Browse Source

Merge branch 'giza' into storage_node_v2_sync5

# Conflicts:
#	types/augment-codec/augment-api-tx.ts
#	types/augment/all/defs.json
#	types/augment/all/types.ts
#	types/augment/augment-api-tx.ts
#	types/src/common.ts
Shamil Gadelshin 3 years ago
parent
commit
afce47dc88
81 changed files with 4531 additions and 1362 deletions
  1. 12 12
      Cargo.lock
  2. 3 0
      devops/infrastructure/node-network/Pulumi.yaml
  3. 12 1
      devops/infrastructure/node-network/README.md
  4. 26 7
      devops/infrastructure/node-network/index.ts
  5. 21 4
      node/src/chain_spec/mod.rs
  6. 1 1
      pioneer/packages/apps-routing/src/joy-roles.ts
  7. 13 22
      pioneer/packages/joy-forum/src/ForumRoot.tsx
  8. 78 14
      pioneer/packages/joy-forum/src/ViewThread.tsx
  9. 6 6
      pioneer/packages/joy-proposals/src/Proposal/Body.tsx
  10. 11 1
      pioneer/packages/joy-proposals/src/forms/GenericWorkingGroupProposalForm.tsx
  11. 12 3
      pioneer/packages/joy-roles/src/tabs/WorkingGroup.controller.tsx
  12. 37 2
      pioneer/packages/joy-roles/src/tabs/WorkingGroup.tsx
  13. 5 2
      pioneer/packages/joy-roles/src/transport.substrate.ts
  14. 12 3
      pioneer/packages/joy-roles/src/working_groups.ts
  15. 62 106
      pioneer/packages/joy-tokenomics/src/Overview/SpendingAndStakeDistributionTable.tsx
  16. 58 83
      pioneer/packages/joy-tokenomics/src/Overview/TokenomicsCharts.tsx
  17. 0 12
      pioneer/packages/joy-tokenomics/src/Overview/index.tsx
  18. 113 0
      pioneer/packages/joy-tokenomics/src/tokenomicsGroupsData.ts
  19. 6 3
      pioneer/packages/joy-utils/src/consts/workingGroups.ts
  20. 3 7
      pioneer/packages/joy-utils/src/transport/proposals.ts
  21. 8 2
      pioneer/packages/joy-utils/src/transport/tokenomics.ts
  22. 4 1
      pioneer/packages/joy-utils/src/types/tokenomics.ts
  23. 8 2
      runtime-modules/common/src/working_group.rs
  24. 1 1
      runtime-modules/content/Cargo.toml
  25. 4 0
      runtime-modules/content/src/errors.rs
  26. 181 243
      runtime-modules/content/src/lib.rs
  27. 7 41
      runtime-modules/content/src/permissions/mod.rs
  28. 105 84
      runtime-modules/content/src/tests/channels.rs
  29. 9 53
      runtime-modules/content/src/tests/mock.rs
  30. 54 33
      runtime-modules/content/src/tests/videos.rs
  31. 1 1
      runtime-modules/forum/Cargo.toml
  32. 1 1
      runtime-modules/governance/Cargo.toml
  33. 5 2
      runtime-modules/governance/src/mock.rs
  34. 1 1
      runtime-modules/hiring/Cargo.toml
  35. 1 1
      runtime-modules/membership/Cargo.toml
  36. 22 40
      runtime-modules/membership/src/lib.rs
  37. 5 2
      runtime-modules/membership/src/mock.rs
  38. 1 1
      runtime-modules/memo/Cargo.toml
  39. 1 1
      runtime-modules/proposals/codex/src/lib.rs
  40. 5 2
      runtime-modules/proposals/codex/src/tests/mock.rs
  41. 1 1
      runtime-modules/proposals/discussion/Cargo.toml
  42. 1 1
      runtime-modules/proposals/discussion/src/lib.rs
  43. 5 2
      runtime-modules/proposals/discussion/src/tests/mock.rs
  44. 1 1
      runtime-modules/proposals/engine/Cargo.toml
  45. 1 1
      runtime-modules/proposals/engine/src/lib.rs
  46. 5 2
      runtime-modules/proposals/engine/src/tests/mock/mod.rs
  47. 1 1
      runtime-modules/recurring-reward/Cargo.toml
  48. 1 1
      runtime-modules/stake/Cargo.toml
  49. 37 26
      runtime-modules/storage/src/lib.rs
  50. 5 4
      runtime-modules/storage/src/tests/mocks.rs
  51. 13 28
      runtime-modules/storage/src/tests/mod.rs
  52. 1 1
      runtime-modules/token-minting/Cargo.toml
  53. 1 1
      runtime-modules/working-group/Cargo.toml
  54. 2 2
      runtime-modules/working-group/src/lib.rs
  55. 5 2
      runtime-modules/working-group/src/tests/mock.rs
  56. 1 1
      runtime/src/integration/proposals/membership_origin_validator.rs
  57. 9 1
      runtime/src/integration/proposals/proposal_encoder.rs
  58. 88 156
      runtime/src/integration/working_group.rs
  59. 45 22
      runtime/src/lib.rs
  60. 0 4
      runtime/src/primitives.rs
  61. 169 45
      runtime/src/tests/proposals_integration/working_group_proposals.rs
  62. 2 2
      types/augment-codec/all.ts
  63. 13 5
      types/augment-codec/augment-api-consts.ts
  64. 948 20
      types/augment-codec/augment-api-errors.ts
  65. 276 12
      types/augment-codec/augment-api-events.ts
  66. 128 2
      types/augment-codec/augment-api-query.ts
  67. 173 14
      types/augment-codec/augment-api-tx.ts
  68. 0 0
      types/augment-codec/augment-types.ts
  69. 29 30
      types/augment/all/defs.json
  70. 26 32
      types/augment/all/types.ts
  71. 13 5
      types/augment/augment-api-consts.ts
  72. 948 20
      types/augment/augment-api-errors.ts
  73. 276 12
      types/augment/augment-api-events.ts
  74. 128 2
      types/augment/augment-api-query.ts
  75. 173 14
      types/augment/augment-api-tx.ts
  76. 0 0
      types/augment/augment-types.ts
  77. 1 1
      types/src/JoyEnum.ts
  78. 18 28
      types/src/common.ts
  79. 20 26
      types/src/content/index.ts
  80. 11 4
      types/src/index.ts
  81. 41 29
      types/src/scripts/generateRegistryJson.ts

+ 12 - 12
Cargo.lock

@@ -3822,7 +3822,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-content"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3859,7 +3859,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-forum"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3876,7 +3876,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-governance"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3919,7 +3919,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-hiring"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3957,7 +3957,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-membership"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3975,7 +3975,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-memo"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -4054,7 +4054,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-proposals-discussion"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -4072,7 +4072,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-proposals-engine"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -4106,7 +4106,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-recurring-reward"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -4157,7 +4157,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-stake"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -4259,7 +4259,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-token-mint"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -4337,7 +4337,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-working-group"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "frame-support",
  "frame-system",

+ 3 - 0
devops/infrastructure/node-network/Pulumi.yaml

@@ -22,3 +22,6 @@ template:
     nodeImage:
       description: Docker image with tag to be used as validator and RPC nodes
       default: 'joystream/node:latest'
+    encryptionKey:
+      description: Key to encrypt the 7z containing secrets with
+      default: '1234'

+ 12 - 1
devops/infrastructure/node-network/README.md

@@ -39,7 +39,7 @@ After cloning this repo, from this working directory, run these commands:
    ```bash
    $ pulumi config set-all --plaintext aws:region=us-east-1 --plaintext aws:profile=joystream-user \
     --plaintext numberOfValidators=2 --plaintext isMinikube=true --plaintext networkSuffix=8122 \
-    --plaintext nodeImage=joystream/node:latest
+    --plaintext nodeImage=joystream/node:latest --plaintext encryptionKey=password
    ```
 
    If you want to build the stack on AWS set the `isMinikube` config to `false`
@@ -67,6 +67,11 @@ After cloning this repo, from this working directory, run these commands:
 
    The ws-rpc endpoint is `https://<ENDPOINT>/ws-rpc` and http-rpc endpoint is `https://<ENDPOINT>/http-rpc`
 
+1. If you are using Minikube, run `minikube service node-network -n $(pulumi stack output namespaceName)`
+
+   This will setup a proxy for your `node-network` service, which can then be accessed at
+   the URL given in the output
+
 1. Access the Kubernetes Cluster using `kubectl`
 
    To access your new Kubernetes cluster using `kubectl`, we need to set up the
@@ -106,6 +111,12 @@ After cloning this repo, from this working directory, run these commands:
    $ kubectl exec --stdin --tty <PODNAME> -c colossus -- /bin/bash
    ```
 
+1. To get the chain-data and secrets, run the below command
+
+   ```bash
+   $ kubectl cp $(kubectl get pods | grep rpc-node | awk '{print $1}'):/chain-data/chain-data.7z ./chain-data.7z
+   ```
+
 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it:
 
    ```bash

+ 26 - 7
devops/infrastructure/node-network/index.ts

@@ -57,6 +57,7 @@ const numberOfValidators = config.getNumber('numberOfValidators') || 1
 const chainDataPath = '/chain-data'
 const chainSpecPath = `${chainDataPath}/chainspec-raw.json`
 const nodeImage = config.get('nodeImage') || 'joystream/node:latest'
+const encryptKey = config.get('encryptionKey') || '1234'
 
 const subkeyContainers = getSubkeyContainers(numberOfValidators, chainDataPath)
 let pvcClaimName: pulumi.Output<any>
@@ -178,6 +179,18 @@ const chainDataPrepareJob = new k8s.batch.v1.Job(
                 },
               ],
             },
+            {
+              name: '7z',
+              image: 'danielwhatmuff/7z-docker',
+              command: ['/bin/sh', '-c'],
+              args: [`7z a -p${encryptKey} ${chainDataPath}/chain-data.7z ${chainDataPath}/*`],
+              volumeMounts: [
+                {
+                  name: 'config-data',
+                  mountPath: chainDataPath,
+                },
+              ],
+            },
           ],
           volumes: [
             {
@@ -289,6 +302,7 @@ const service = new k8s.core.v1.Service(
       name: 'node-network',
     },
     spec: {
+      type: isMinikube ? 'NodePort' : 'ClusterIP',
       ports: [
         { name: 'port-1', port: 9944 },
         { name: 'port-2', port: 9933 },
@@ -313,11 +327,16 @@ const caddyEndpoints = [
 }`,
 ]
 
-const caddy = new CaddyServiceDeployment(
-  'caddy-proxy',
-  { lbReady, namespaceName: namespaceName, isMinikube, caddyEndpoints },
-  resourceOptions
-)
+export let endpoint1: pulumi.Output<string>
+export let endpoint2: pulumi.Output<string>
 
-export const endpoint1 = caddy.primaryEndpoint
-export const endpoint2 = caddy.secondaryEndpoint
+if (!isMinikube) {
+  const caddy = new CaddyServiceDeployment(
+    'caddy-proxy',
+    { lbReady, namespaceName: namespaceName, isMinikube, caddyEndpoints },
+    resourceOptions
+  )
+
+  endpoint1 = pulumi.interpolate`${caddy.primaryEndpoint}`
+  endpoint2 = pulumi.interpolate`${caddy.secondaryEndpoint}`
+}

+ 21 - 4
node/src/chain_spec/mod.rs

@@ -34,9 +34,10 @@ use node_runtime::{
     membership, wasm_binary_unwrap, AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig,
     ContentConfig, ContentWorkingGroupConfig, CouncilConfig, CouncilElectionConfig,
     DistributionWorkingGroupConfig, ElectionParameters, ForumConfig, GatewayWorkingGroupConfig,
-    GrandpaConfig, ImOnlineConfig, MembersConfig, Moment, OperationsWorkingGroupConfig,
-    ProposalsCodexConfig, SessionConfig, SessionKeys, Signature, StakerStatus, StakingConfig,
-    StorageWorkingGroupConfig, SudoConfig, SystemConfig, DAYS,
+    GrandpaConfig, ImOnlineConfig, MembersConfig, Moment, OperationsWorkingGroupAlphaConfig,
+    OperationsWorkingGroupBetaConfig, OperationsWorkingGroupGammaConfig, ProposalsCodexConfig,
+    SessionConfig, SessionKeys, Signature, StakerStatus, StakingConfig, StorageWorkingGroupConfig,
+    SudoConfig, SystemConfig, DAYS,
 };
 
 // Exported to be used by chain-spec-builder
@@ -314,7 +315,7 @@ pub fn testnet_genesis(
             worker_exit_rationale_text_constraint: default_text_constraint,
             worker_storage_size_constraint: default_storage_size_constraint,
         }),
-        working_group_Instance4: Some(OperationsWorkingGroupConfig {
+        working_group_Instance4: Some(OperationsWorkingGroupAlphaConfig {
             phantom: Default::default(),
             working_group_mint_capacity: 0,
             opening_human_readable_text_constraint: default_text_constraint,
@@ -338,6 +339,22 @@ pub fn testnet_genesis(
             worker_exit_rationale_text_constraint: default_text_constraint,
             worker_storage_size_constraint: default_storage_size_constraint,
         }),
+        working_group_Instance7: Some(OperationsWorkingGroupBetaConfig {
+            phantom: Default::default(),
+            working_group_mint_capacity: 0,
+            opening_human_readable_text_constraint: default_text_constraint,
+            worker_application_human_readable_text_constraint: default_text_constraint,
+            worker_exit_rationale_text_constraint: default_text_constraint,
+            worker_storage_size_constraint: default_storage_size_constraint,
+        }),
+        working_group_Instance8: Some(OperationsWorkingGroupGammaConfig {
+            phantom: Default::default(),
+            working_group_mint_capacity: 0,
+            opening_human_readable_text_constraint: default_text_constraint,
+            worker_application_human_readable_text_constraint: default_text_constraint,
+            worker_exit_rationale_text_constraint: default_text_constraint,
+            worker_storage_size_constraint: default_storage_size_constraint,
+        }),
         content: Some({
             ContentConfig {
                 next_curator_group_id: 1,

+ 1 - 1
pioneer/packages/apps-routing/src/joy-roles.ts

@@ -7,7 +7,7 @@ export default function create (t: <T = string> (key: string, text: string, opti
     Component: Roles,
     display: {
       needsApi: [
-        'query.contentDirectoryWorkingGroup.mint',
+        'query.contentWorkingGroup.mint',
         'query.storageWorkingGroup.mint'
       ]
     },

+ 13 - 22
pioneer/packages/joy-forum/src/ForumRoot.tsx

@@ -1,7 +1,6 @@
 import React, { useState, useEffect } from 'react';
 import { Link } from 'react-router-dom';
 import styled from 'styled-components';
-import { orderBy } from 'lodash';
 import BN from 'bn.js';
 
 import { Section } from '@polkadot/joy-utils/react/components';
@@ -63,36 +62,28 @@ const InnerRecentActivity: React.FC<RecentActivityProps> = ({ nextPostId, api })
       if (!nextPostId) return;
 
       const newId = (id: number | BN) => api.createType('PostId', id);
-      const apiCalls: Promise<Post>[] = [];
-      let id = newId(1);
+      let id = newId(nextPostId.toNumber() - 1);
 
-      while (nextPostId.gt(id)) {
-        apiCalls.push(api.query.forum.postById(id) as Promise<Post>);
-        id = newId(id.add(newId(1)));
-      }
+      const threadsIdsLookup = {} as Record<number, boolean>;
+      const recentUniquePosts = new Array<Post>();
 
-      const allPosts = await Promise.all(apiCalls);
-      const sortedPosts = orderBy(
-        allPosts,
-        [(x) => x.id.toNumber()],
-        ['desc']
-      );
+      while (id.gt(newId(0))) {
+        const post = await api.query.forum.postById(id) as Post;
 
-      const threadsIdsLookup = {} as Record<number, boolean>;
-      const postsWithUniqueThreads = sortedPosts.reduce((acc, post) => {
         const threadId = post.thread_id.toNumber();
 
-        if (threadsIdsLookup[threadId]) return acc;
+        id = newId(id.toNumber() - 1);
+
+        if (threadsIdsLookup[threadId]) continue;
 
         threadsIdsLookup[threadId] = true;
 
-        return [
-          ...acc,
-          post
-        ];
-      }, [] as Post[]);
+        recentUniquePosts.push(post);
 
-      const recentUniquePosts = postsWithUniqueThreads.slice(0, RecentActivityPostsCount);
+        if (recentUniquePosts.length === RecentActivityPostsCount) {
+          break;
+        }
+      }
 
       setRecentPosts(recentUniquePosts);
       setLoaded(true);

+ 78 - 14
pioneer/packages/joy-forum/src/ViewThread.tsx

@@ -5,7 +5,7 @@ import styled from 'styled-components';
 import { Table, Button, Label, Icon } from 'semantic-ui-react';
 import BN from 'bn.js';
 
-import { ThreadId } from '@joystream/types/common';
+import { PostId, ThreadId } from '@joystream/types/common';
 import { Category, Thread, Post } from '@joystream/types/forum';
 import { Pagination, RepliesPerPage, CategoryCrumbs, TimeAgoDate, usePagination, useQueryParam, ReplyIdxQueryParam, ReplyEditIdQueryParam } from './utils';
 import { ViewReply } from './ViewReply';
@@ -22,6 +22,7 @@ import MemberPreview from '@polkadot/joy-utils/react/components/MemberByAccountP
 import { formatDate } from '@polkadot/joy-utils/functions/date';
 import { NewReply, EditReply } from './EditReply';
 import { useApi } from '@polkadot/react-hooks';
+import { ApiPromise } from '@polkadot/api/promise';
 
 type ThreadTitleProps = {
   thread: Thread;
@@ -124,6 +125,77 @@ type ViewThreadProps = ApiProps & InnerViewThreadProps & {
   nextPostId?: ThreadId;
 };
 
+const POSTS_THREAD_MAP_CACHE_KEY = 'postsThreadMap';
+
+async function refreshPostsInThreadCache (nextPostId: PostId, api: ApiPromise) {
+  const newId = (id: number | BN) => api.createType('PostId', id);
+  const apiCalls: Promise<Post>[] = [];
+  let idToFetch = newId(1);
+
+  let postsToThread = getPostsIdsInThreadCache();
+  const nextThreadId = await api.query.forum.nextThreadId() as ThreadId;
+
+  if (postsToThread.size >= nextThreadId.toNumber()) { // invalid cache
+    postsToThread = new Map<number, number[]>();
+  }
+
+  if (postsToThread.size > 0) {
+    const lastPostIdInCache = Math.max(...Array.from(postsToThread.values()).flat());
+
+    idToFetch = newId(lastPostIdInCache + 1);
+    const lastPost = await api.query.forum.postById(lastPostIdInCache) as Post;
+
+    if (lastPost) {
+      const postsInThread = postsToThread.get(lastPost.thread_id.toNumber());
+
+      if (!postsInThread || !postsInThread.includes(lastPostIdInCache)) { // cache doesn't match the data in chain
+        postsToThread = new Map<number, number[]>();
+      }
+    } else {
+      postsToThread = new Map<number, number[]>();
+    }
+  }
+
+  const lastPostId = nextPostId.sub(new BN(1));
+
+  while (lastPostId.gte(idToFetch)) {
+    apiCalls.push(api.query.forum.postById(idToFetch) as Promise<Post>);
+    idToFetch = newId(idToFetch.add(newId(1)));
+  }
+
+  const newPosts = await Promise.all<Post>(apiCalls);
+
+  const newPostsToThread = new Map<number, number[]>();
+
+  newPosts.forEach((newPost) => {
+    const previousNewPostIds = newPostsToThread.get(newPost.thread_id.toNumber()) ?? [];
+
+    newPostsToThread.set(newPost.thread_id.toNumber(), [...previousNewPostIds, newPost.id.toNumber()]);
+  });
+
+  if (postsToThread.size > 0) {
+    newPostsToThread.forEach((postIds, threadId) => {
+      const existingPostIds = postsToThread.get(threadId) ?? [];
+
+      postsToThread.set(threadId, [...existingPostIds, ...postIds]);
+    });
+  } else {
+    postsToThread = newPostsToThread;
+  }
+
+  localStorage.setItem(POSTS_THREAD_MAP_CACHE_KEY, JSON.stringify([...postsToThread]));
+}
+
+function getPostsIdsInThreadCache (): Map<number, number[]> {
+  const serializedMap = localStorage.getItem(POSTS_THREAD_MAP_CACHE_KEY);
+
+  if (!serializedMap) {
+    return new Map<number, number[]>();
+  }
+
+  return new Map<number, number[]>(JSON.parse(serializedMap));
+}
+
 function InnerViewThread (props: ViewThreadProps) {
   const [showModerateForm, setShowModerateForm] = useState(false);
   const [displayedPosts, setDisplayedPosts] = useState<Post[]>([]);
@@ -154,20 +226,12 @@ function InnerViewThread (props: ViewThreadProps) {
     const loadPosts = async () => {
       if (!nextPostId || totalPostsInThread === 0 || thread.isEmpty) return;
 
-      const newId = (id: number | BN) => api.createType('PostId', id);
-      const apiCalls: Promise<Post>[] = [];
-      let id = newId(1);
-
-      while (nextPostId.gt(id)) {
-        apiCalls.push(api.query.forum.postById(id) as Promise<Post>);
-        id = newId(id.add(newId(1)));
-      }
+      await refreshPostsInThreadCache(nextPostId, api);
+      const mapPostToThread = getPostsIdsInThreadCache();
+      const postIdsInThread = mapPostToThread.get(thread.id.toNumber()) as number[];
+      const postsInThisThread = await Promise.all(postIdsInThread
+        ? postIdsInThread.map((postId: number) => api.query.forum.postById(postId)) : []) as Post[];
 
-      const allPosts = await Promise.all<Post>(apiCalls);
-      const postsInThisThread = allPosts.filter((item) =>
-        !item.isEmpty &&
-        item.thread_id.eq(thread.id)
-      );
       const sortedPosts = orderBy(
         postsInThisThread,
         [(x) => x.nr_in_thread.toNumber()],

+ 6 - 6
pioneer/packages/joy-proposals/src/Proposal/Body.tsx

@@ -16,7 +16,7 @@ import { formatBalance } from '@polkadot/util';
 import PromiseComponent from '@polkadot/joy-utils/react/components/PromiseComponent';
 import ReactMarkdown from 'react-markdown';
 import { StakingPolicy } from '@joystream/types/hiring';
-import { WorkingGroup } from '@joystream/types/common';
+import { WorkingGroup, WorkingGroupKey } from '@joystream/types/common';
 import { ApplicationsDetailsByOpening } from '@polkadot/joy-utils/react/components/working-groups/ApplicationDetails';
 import { LeadInfoFromId } from '@polkadot/joy-utils/react/components/working-groups/LeadInfo';
 import { formatReward } from '@polkadot/joy-utils/functions/format';
@@ -269,7 +269,7 @@ const paramParsers: { [k in ProposalType]: (params: SpecificProposalDetails<k>,
         : <ApplicationsDetailsByOpening
           openingId={openingId.toNumber()}
           acceptedIds={[succesfulApplicationId.toNumber()]}
-          group={workingGroup.type}/>,
+          group={workingGroup.type as WorkingGroupKey}/>,
       true
     )
   ],
@@ -280,7 +280,7 @@ const paramParsers: { [k in ProposalType]: (params: SpecificProposalDetails<k>,
       'Lead',
       historical
         ? `#${(leadId as WorkerId).toNumber()}`
-        : <LeadInfoFromId group={(group as WorkingGroup).type} leadId={(leadId as WorkerId).toNumber()}/>,
+        : <LeadInfoFromId group={(group as WorkingGroup).type as WorkingGroupKey} leadId={(leadId as WorkerId).toNumber()}/>,
       true
     )
   ],
@@ -291,7 +291,7 @@ const paramParsers: { [k in ProposalType]: (params: SpecificProposalDetails<k>,
       'Lead',
       historical
         ? `#${(leadId as WorkerId).toNumber()}`
-        : <LeadInfoFromId group={(group as WorkingGroup).type} leadId={(leadId as WorkerId).toNumber()}/>,
+        : <LeadInfoFromId group={(group as WorkingGroup).type as WorkingGroupKey} leadId={(leadId as WorkerId).toNumber()}/>,
       true
     )
   ],
@@ -302,7 +302,7 @@ const paramParsers: { [k in ProposalType]: (params: SpecificProposalDetails<k>,
       'Lead',
       historical
         ? `#${(leadId as WorkerId).toNumber()}`
-        : <LeadInfoFromId group={(group as WorkingGroup).type} leadId={(leadId as WorkerId).toNumber()}/>,
+        : <LeadInfoFromId group={(group as WorkingGroup).type as WorkingGroupKey} leadId={(leadId as WorkerId).toNumber()}/>,
       true
     )
   ],
@@ -321,7 +321,7 @@ const paramParsers: { [k in ProposalType]: (params: SpecificProposalDetails<k>,
         'Lead',
         historical
           ? `#${leadId.toNumber()}`
-          : <LeadInfoFromId group={workingGroup.type} leadId={leadId.toNumber()}/>,
+          : <LeadInfoFromId group={workingGroup.type as WorkingGroupKey} leadId={leadId.toNumber()}/>,
         true
       )
     ];

+ 11 - 1
pioneer/packages/joy-proposals/src/forms/GenericWorkingGroupProposalForm.tsx

@@ -45,7 +45,17 @@ export type FormInnerProps = ProposalFormInnerProps<FormContainerProps, FormValu
 
 const availableGroupsOptions = Object.keys(WorkingGroupDef)
   .filter((wgKey) => wgKey !== 'Gateway') // Gateway group not yet supported!
-  .map((wgKey) => ({ text: wgKey + ' Working Group', value: wgKey }));
+  .map((wgKey) => {
+    let text = `${wgKey} Working Group`;
+
+    if (wgKey.toLowerCase().includes('operations')) {
+      const workingGroupType = wgKey.slice('operations'.length);
+
+      text = `Operations Working Group ${workingGroupType}`;
+    }
+
+    return { text, value: wgKey };
+  });
 
 export const GenericWorkingGroupProposalForm: React.FunctionComponent<FormInnerProps> = (props) => {
   const {

+ 12 - 3
pioneer/packages/joy-roles/src/tabs/WorkingGroup.controller.tsx

@@ -9,14 +9,20 @@ import { AvailableGroups } from '../working_groups';
 import { WorkingGroupMembership,
   ContentCurators,
   StorageProviders,
-  OperationsGroup } from './WorkingGroup';
+  OperationsGroupAlpha,
+  OperationsGroupBeta,
+  OperationsGroupGamma,
+  Distribution } from './WorkingGroup';
 
 import styled from 'styled-components';
 
 type State = {
   curators?: WorkingGroupMembership;
   storageProviders?: WorkingGroupMembership;
-  operationsGroup?: WorkingGroupMembership;
+  operationsGroupAlpha?: WorkingGroupMembership;
+  operationsGroupBeta?: WorkingGroupMembership;
+  operationsGroupGamma?: WorkingGroupMembership;
+  distribution?: WorkingGroupMembership;
 }
 
 export class WorkingGroupsController extends Controller<State, ITransport> {
@@ -56,7 +62,10 @@ export const WorkingGroupsView = View<WorkingGroupsController, State>(
     <WorkingGroupsOverview>
       <ContentCurators {...state.curators}/>
       <StorageProviders {...state.storageProviders}/>
-      <OperationsGroup {...state.operationsGroup}/>
+      <OperationsGroupAlpha {...state.operationsGroupAlpha}/>
+      <OperationsGroupBeta {...state.operationsGroupBeta}/>
+      <OperationsGroupGamma {...state.operationsGroupGamma}/>
+      <Distribution {...state.distribution}/>
     </WorkingGroupsOverview>
   )
 );

+ 37 - 2
pioneer/packages/joy-roles/src/tabs/WorkingGroup.tsx

@@ -73,6 +73,10 @@ type GroupOverviewProps = GroupOverviewOuterProps & {
   customBecomeLeadDesc?: string;
 }
 
+interface OperationsGroupProps extends GroupOverviewOuterProps{
+  group: WorkingGroups;
+}
+
 const GroupOverview = Loadable<GroupOverviewProps>(
   ['workers', 'leadStatus'],
   ({
@@ -142,9 +146,8 @@ export const StorageProviders = (props: GroupOverviewOuterProps) => (
   />
 );
 
-export const OperationsGroup = (props: GroupOverviewOuterProps) => (
+export const OperationsGroup = (props: OperationsGroupProps) => (
   <GroupOverview
-    group={WorkingGroups.Operations}
     description={
       <span>
         {"Operations Working Group encompases all the activites that don't require privilages on chain, for example:"}
@@ -159,6 +162,38 @@ export const OperationsGroup = (props: GroupOverviewOuterProps) => (
   />
 );
 
+export const OperationsGroupAlpha = (props: GroupOverviewOuterProps) => (
+  <OperationsGroup
+    group={WorkingGroups.OperationsAlpha}
+    {...props}
+  />
+);
+
+export const OperationsGroupBeta = (props: GroupOverviewOuterProps) => (
+  <OperationsGroup
+    group={WorkingGroups.OperationsBeta}
+    {...props}
+  />
+);
+
+export const OperationsGroupGamma = (props: GroupOverviewOuterProps) => (
+  <OperationsGroup
+    group={WorkingGroups.OperationsGamma}
+    {...props}
+  />
+);
+
+export const Distribution = (props: GroupOverviewOuterProps) => (
+  <GroupOverview
+    group={WorkingGroups.Distribution}
+    description={
+      'Distribution Working Group is responsible for running and maintaining distributor nodes' +
+      ' that deliver large volumes of upstream data to a large number of simultaneous end users.'
+    }
+    {...props}
+  />
+);
+
 const LeadSection = styled.div`
   margin-top: 1rem;
 `;

+ 5 - 2
pioneer/packages/joy-roles/src/transport.substrate.ts

@@ -51,8 +51,11 @@ type StakePair<T = Balance> = {
 
 const apiModuleByGroup = {
   [WorkingGroups.StorageProviders]: 'storageWorkingGroup',
-  [WorkingGroups.ContentCurators]: 'contentDirectoryWorkingGroup',
-  [WorkingGroups.Operations]: 'operationsWorkingGroup'
+  [WorkingGroups.ContentCurators]: 'contentWorkingGroup',
+  [WorkingGroups.OperationsAlpha]: 'operationsWorkingGroupAlpha',
+  [WorkingGroups.OperationsBeta]: 'operationsWorkingGroupBeta',
+  [WorkingGroups.OperationsGamma]: 'operationsWorkingGroupGamma',
+  [WorkingGroups.Distribution]: 'distributionWorkingGroup'
 } as const;
 
 export class Transport extends BaseTransport implements ITransport {

+ 12 - 3
pioneer/packages/joy-roles/src/working_groups.ts

@@ -1,17 +1,26 @@
 export enum WorkingGroups {
   ContentCurators = 'curators',
   StorageProviders = 'storageProviders',
-  Operations = 'operationsGroup'
+  OperationsAlpha = 'operationsGroupAlpha',
+  OperationsBeta = 'operationsGroupBeta',
+  OperationsGamma = 'operationsGroupGamma',
+  Distribution = 'distribution'
 }
 
 export const AvailableGroups: readonly WorkingGroups[] = [
   WorkingGroups.ContentCurators,
   WorkingGroups.StorageProviders,
-  WorkingGroups.Operations
+  WorkingGroups.OperationsAlpha,
+  WorkingGroups.OperationsBeta,
+  WorkingGroups.OperationsGamma,
+  WorkingGroups.Distribution
 ] as const;
 
 export const workerRoleNameByGroup: { [key in WorkingGroups]: string } = {
   [WorkingGroups.ContentCurators]: 'Content Curator',
   [WorkingGroups.StorageProviders]: 'Storage Provider',
-  [WorkingGroups.Operations]: 'Operations Group Worker'
+  [WorkingGroups.OperationsAlpha]: 'Operations Group Alpha Worker',
+  [WorkingGroups.OperationsBeta]: 'Operations Group Beta Worker',
+  [WorkingGroups.OperationsGamma]: 'Operations Group Gamma Worker',
+  [WorkingGroups.Distribution]: 'Distribution'
 };

+ 62 - 106
pioneer/packages/joy-tokenomics/src/Overview/SpendingAndStakeDistributionTable.tsx

@@ -5,7 +5,7 @@ import { useWindowDimensions } from '../../../joy-utils/src/react/hooks';
 
 import { TokenomicsData, StatusServerData } from '@polkadot/joy-utils/src/types/tokenomics';
 
-import { COLORS } from './index';
+import { NON_WORKING_GROUPS, WORKING_GROUPS } from '../tokenomicsGroupsData';
 
 const round = (num: number): number => Math.round((num + Number.EPSILON) * 100) / 100;
 
@@ -121,25 +121,24 @@ const SpendingAndStakeTableRow: React.FC<{
   );
 };
 
-type TokenomicsGroup =
-  'validators' |
-  'council' |
-  'storageProviders' |
-  'contentCurators' |
-  'operations'
+type TokenomicsGroup = typeof WORKING_GROUPS[number]['groupType'] | typeof NON_WORKING_GROUPS[number]['groupType'];
 
 const SpendingAndStakeDistributionTable: React.FC<{data?: TokenomicsData; statusData?: StatusServerData | null}> = ({ data, statusData }) => {
   const { width } = useWindowDimensions();
 
   const displayStatusData = (group: TokenomicsGroup, dataType: 'rewardsPerWeek' | 'totalStake', lead = false): string | undefined => {
-    if ((group === 'storageProviders' || group === 'contentCurators') && lead) {
+    if (WORKING_GROUPS.map(({ groupType }) => groupType).includes(group as any) && lead) {
       return statusData === null
         ? 'Data currently unavailable...'
-        : (data && statusData) && `${(data[group].lead[dataType] * Number(statusData.price)).toFixed(2)}`;
+        : data &&
+            statusData &&
+            `${(
+              data[group as typeof WORKING_GROUPS[number]['groupType']].lead[dataType] * Number(statusData.price)
+            ).toFixed(2)}`;
     } else {
       return statusData === null
         ? 'Data currently unavailable...'
-        : (data && statusData) && `${(data[group][dataType] * Number(statusData.price)).toFixed(2)}`;
+        : data && statusData && `${(data[group][dataType] * Number(statusData.price)).toFixed(2)}`;
     }
   };
 
@@ -160,102 +159,59 @@ const SpendingAndStakeDistributionTable: React.FC<{data?: TokenomicsData; status
       </Table.Header>
 
       <Table.Body>
-        <SpendingAndStakeTableRow
-          role={width <= 1050 ? 'Validators' : 'Validators (Nominators)'}
-          helpContent='The current set of active Validators (and Nominators), and the sum of the sets projected rewards and total stakes (including Nominators).'
-          numberOfActors={data && `${data.validators.number} (${data.validators.nominators.number})`}
-          groupEarning={data && `${Math.round(data.validators.rewardsPerWeek)}`}
-          groupEarningDollar={displayStatusData('validators', 'rewardsPerWeek')}
-          earningShare={data && `${round(data.validators.rewardsShare * 100)}`}
-          groupStake={data && `${data.validators.totalStake}`}
-          groupStakeDollar={displayStatusData('validators', 'totalStake')}
-          stakeShare={data && `${round(data.validators.stakeShare * 100)}`}
-          color={COLORS.VALIDATOR}
-        />
-        <SpendingAndStakeTableRow
-          role={width <= 1015 ? 'Council' : 'Council Members'}
-          helpContent='The current Council Members, and the sum of their projected rewards and total stakes (including voters/backers).'
-          numberOfActors={data && `${data.council.number}`}
-          groupEarning={data && `${Math.round(data.council.rewardsPerWeek)}`}
-          groupEarningDollar={displayStatusData('council', 'rewardsPerWeek')}
-          earningShare={data && `${round(data.council.rewardsShare * 100)}`}
-          groupStake={data && `${data.council.totalStake}`}
-          groupStakeDollar={displayStatusData('council', 'totalStake')}
-          stakeShare={data && `${round(data.council.stakeShare * 100)}`}
-          color={COLORS.COUNCIL_MEMBER}
-        />
-        <SpendingAndStakeTableRow
-          role={width <= 1015 ? 'Storage' : 'Storage Providers'}
-          helpContent='The current Storage Providers, and the sum of their projected rewards and stakes.'
-          numberOfActors={data && `${data.storageProviders.number}`}
-          groupEarning={data && `${Math.round(data.storageProviders.rewardsPerWeek)}`}
-          groupEarningDollar={displayStatusData('storageProviders', 'rewardsPerWeek')}
-          earningShare={data && `${round(data.storageProviders.rewardsShare * 100)}`}
-          groupStake={data && `${data.storageProviders.totalStake}`}
-          groupStakeDollar={displayStatusData('storageProviders', 'totalStake')}
-          stakeShare={data && `${round(data.storageProviders.stakeShare * 100)}`}
-          color={COLORS.STORAGE_PROVIDER}
-        />
-        <SpendingAndStakeTableRow
-          role={width <= 1015 ? 'S. Lead' : width <= 1050 ? 'Storage Lead' : 'Storage Provider Lead'}
-          helpContent='Current Storage Provider Lead, and their projected reward and stake.'
-          numberOfActors={data && `${data.storageProviders.lead.number}`}
-          groupEarning={data && `${Math.round(data.storageProviders.lead.rewardsPerWeek)}`}
-          groupEarningDollar={displayStatusData('storageProviders', 'rewardsPerWeek', true)}
-          earningShare={data && `${round(data.storageProviders.lead.rewardsShare * 100)}`}
-          groupStake={data && `${data.storageProviders.lead.totalStake}`}
-          groupStakeDollar={displayStatusData('storageProviders', 'totalStake', true)}
-          stakeShare={data && `${round(data.storageProviders.lead.stakeShare * 100)}`}
-          color={COLORS.STORAGE_LEAD}
-        />
-        <SpendingAndStakeTableRow
-          role={width <= 1015 ? 'Curators' : 'Content Curators'}
-          helpContent='The current Content Curators, and the sum of their projected rewards and stakes.'
-          numberOfActors={data && `${data.contentCurators.number}`}
-          groupEarning={data && `${Math.round(data.contentCurators.rewardsPerWeek)}`}
-          groupEarningDollar={displayStatusData('contentCurators', 'rewardsPerWeek')}
-          earningShare={data && `${round(data.contentCurators.rewardsShare * 100)}`}
-          groupStake={data && `${data.contentCurators.totalStake}`}
-          groupStakeDollar={displayStatusData('contentCurators', 'totalStake')}
-          stakeShare={data && `${round(data.contentCurators.stakeShare * 100)}`}
-          color={COLORS.CONTENT_CURATOR}
-        />
-        <SpendingAndStakeTableRow
-          role={width <= 1015 ? 'C. Lead' : 'Curators Lead'}
-          helpContent='Current Content Curators Lead, and their projected reward and stake.'
-          numberOfActors={data && `${data.contentCurators.lead.number}`}
-          groupEarning={data && `${Math.round(data.contentCurators.lead.rewardsPerWeek)}`}
-          groupEarningDollar={displayStatusData('contentCurators', 'rewardsPerWeek', true)}
-          earningShare={data && `${round(data.contentCurators.lead.rewardsShare * 100)}`}
-          groupStake={data && `${data.contentCurators.lead.totalStake}`}
-          groupStakeDollar={displayStatusData('contentCurators', 'totalStake', true)}
-          stakeShare={data && `${round(data.contentCurators.lead.stakeShare * 100)}`}
-          color={COLORS.CURATOR_LEAD}
-        />
-        <SpendingAndStakeTableRow
-          role='Operations'
-          helpContent='The current Operations members, and the sum of their projected rewards and stakes.'
-          numberOfActors={data && `${data.operations.number}`}
-          groupEarning={data && `${Math.round(data.operations.rewardsPerWeek)}`}
-          groupEarningDollar={displayStatusData('operations', 'rewardsPerWeek')}
-          earningShare={data && `${round(data.operations.rewardsShare * 100)}`}
-          groupStake={data && `${data.operations.totalStake}`}
-          groupStakeDollar={displayStatusData('operations', 'totalStake')}
-          stakeShare={data && `${round(data.operations.stakeShare * 100)}`}
-          color={COLORS.OPERATIONS}
-        />
-        <SpendingAndStakeTableRow
-          role='Operations Lead'
-          helpContent='Current Operations Lead, and their projected reward and stake.'
-          numberOfActors={data && `${data.operations.lead.number}`}
-          groupEarning={data && `${Math.round(data.operations.lead.rewardsPerWeek)}`}
-          groupEarningDollar={displayStatusData('operations', 'rewardsPerWeek', true)}
-          earningShare={data && `${round(data.operations.lead.rewardsShare * 100)}`}
-          groupStake={data && `${data.operations.lead.totalStake}`}
-          groupStakeDollar={displayStatusData('operations', 'totalStake', true)}
-          stakeShare={data && `${round(data.operations.lead.stakeShare * 100)}`}
-          color={COLORS.OPERATIONS_LEAD}
-        />
+        {NON_WORKING_GROUPS.map(({ groupType, titleCutoff, shortTitle, title, helpText, color }) => {
+          let numberOfActors = data && `${data[groupType].number}`;
+
+          if (groupType === 'validators' && data) {
+            numberOfActors = `${data.validators.number} (${data.validators.nominators.number})`;
+          }
+
+          return (
+            <SpendingAndStakeTableRow
+              key={groupType}
+              role={width <= titleCutoff ? shortTitle : title}
+              helpContent={helpText}
+              numberOfActors={numberOfActors}
+              groupEarning={data && `${Math.round(data[groupType].rewardsPerWeek)}`}
+              groupEarningDollar={displayStatusData(groupType, 'rewardsPerWeek')}
+              earningShare={data && `${round(data[groupType].rewardsShare * 100)}`}
+              groupStake={data && `${data[groupType].totalStake}`}
+              groupStakeDollar={displayStatusData(groupType, 'totalStake')}
+              stakeShare={data && `${round(data[groupType].stakeShare * 100)}`}
+              color={color}
+            />
+          );
+        })}
+        {WORKING_GROUPS.map(({ groupType, titleCutoff, shortTitle, title, helpText, color, lead }) => {
+          return (
+            <React.Fragment key={groupType}>
+              <SpendingAndStakeTableRow
+                role={width <= titleCutoff ? shortTitle : title}
+                helpContent={helpText}
+                numberOfActors={data && `${data[groupType].number}`}
+                groupEarning={data && `${Math.round(data[groupType].rewardsPerWeek)}`}
+                groupEarningDollar={displayStatusData(groupType, 'rewardsPerWeek')}
+                earningShare={data && `${round(data[groupType].rewardsShare * 100)}`}
+                groupStake={data && `${data[groupType].totalStake}`}
+                groupStakeDollar={displayStatusData(groupType, 'totalStake')}
+                stakeShare={data && `${round(data[groupType].stakeShare * 100)}`}
+                color={color}
+              />
+              <SpendingAndStakeTableRow
+                role={width <= lead.titleCutoff ? lead.shortTitle : lead.title}
+                helpContent={lead.helpText}
+                numberOfActors={data && `${data[groupType].lead.number}`}
+                groupEarning={data && `${Math.round(data[groupType].lead.rewardsPerWeek)}`}
+                groupEarningDollar={displayStatusData(groupType, 'rewardsPerWeek', true)}
+                earningShare={data && `${round(data[groupType].lead.rewardsShare * 100)}`}
+                groupStake={data && `${data[groupType].lead.totalStake}`}
+                groupStakeDollar={displayStatusData(groupType, 'totalStake', true)}
+                stakeShare={data && `${round(data[groupType].lead.stakeShare * 100)}`}
+                color={lead.color}
+              />
+            </React.Fragment>
+          );
+        })}
         <SpendingAndStakeTableRow
           role='TOTAL'
           active={true}

+ 58 - 83
pioneer/packages/joy-tokenomics/src/Overview/TokenomicsCharts.tsx

@@ -4,7 +4,8 @@ import PieChart from '../../../react-components/src/Chart/PieChart';
 import styled from 'styled-components';
 
 import { TokenomicsData } from '@polkadot/joy-utils/src/types/tokenomics';
-import { COLORS } from './index';
+
+import { WORKING_GROUPS, NON_WORKING_GROUPS } from '../tokenomicsGroupsData';
 
 const StyledPieChart = styled(PieChart)`
   width:15rem;
@@ -29,88 +30,62 @@ const ChartContainer = styled('div')`
 const TokenomicsCharts: React.FC<{data?: TokenomicsData; className?: string}> = ({ data, className }) => {
   return (
     <div className={className}>
-      {data ? <ChartContainer>
-        <StyledPieChart
-          values={[{
-            colors: [COLORS.VALIDATOR],
-            label: 'Validators',
-            value: data.validators.rewardsShare * 100
-          }, {
-            colors: [COLORS.COUNCIL_MEMBER],
-            label: 'Council',
-            value: data.council.rewardsShare * 100
-          }, {
-            colors: [COLORS.STORAGE_PROVIDER],
-            label: 'Storage Providers',
-            value: data.storageProviders.rewardsShare * 100
-          }, {
-            colors: [COLORS.STORAGE_LEAD],
-            label: 'Storage Lead',
-            value: data.storageProviders.lead.rewardsShare * 100
-          }, {
-            colors: [COLORS.CONTENT_CURATOR],
-            label: 'Content Curators',
-            value: data.contentCurators.rewardsShare * 100
-          }, {
-            colors: [COLORS.CURATOR_LEAD],
-            label: 'Content Curators Lead',
-            value: data.contentCurators.lead.rewardsShare * 100
-          }, {
-            colors: [COLORS.OPERATIONS],
-            label: 'Operations',
-            value: data.operations.rewardsShare * 100
-          }, {
-            colors: [COLORS.OPERATIONS_LEAD],
-            label: 'Operations Lead',
-            value: data.operations.lead.rewardsShare * 100
-          }
-          ]} />
-        <Label as='div'>
-          <Icon name='money' />
-          <span style={{ fontWeight: 600 }}>Spending</span>
-        </Label>
-      </ChartContainer> : <Icon name='circle notched' loading/>}
-      {data ? <ChartContainer>
-        <StyledPieChart
-          values={[{
-            colors: [COLORS.VALIDATOR],
-            label: 'Validators',
-            value: data.validators.stakeShare * 100
-          }, {
-            colors: [COLORS.COUNCIL_MEMBER],
-            label: 'Council',
-            value: data.council.stakeShare * 100
-          }, {
-            colors: [COLORS.STORAGE_PROVIDER],
-            label: 'Storage Providers',
-            value: data.storageProviders.stakeShare * 100
-          }, {
-            colors: [COLORS.STORAGE_LEAD],
-            label: 'Storage Lead',
-            value: data.storageProviders.lead.stakeShare * 100
-          }, {
-            colors: [COLORS.CONTENT_CURATOR],
-            label: 'Content Curators',
-            value: data.contentCurators.stakeShare * 100
-          }, {
-            colors: [COLORS.CURATOR_LEAD],
-            label: 'Content Curators Lead',
-            value: data.contentCurators.lead.stakeShare * 100
-          }, {
-            colors: [COLORS.OPERATIONS],
-            label: 'Operations',
-            value: data.operations.stakeShare * 100
-          }, {
-            colors: [COLORS.OPERATIONS_LEAD],
-            label: 'Operations Lead',
-            value: data.operations.lead.stakeShare * 100
-          }
-          ]} />
-        <Label as='div'>
-          <Icon name='block layout' />
-          <span style={{ fontWeight: 600 }}>Stake</span>
-        </Label>
-      </ChartContainer> : <Icon name='circle notched' loading/>}
+      {data ? (
+        <ChartContainer>
+          <StyledPieChart
+            values={[
+              ...WORKING_GROUPS.map(({ color, title, groupType, lead }) => [{
+                colors: [color],
+                label: title,
+                value: data[groupType].rewardsShare * 100
+              }, {
+                colors: [lead.color],
+                label: lead.title,
+                value: data[groupType].lead.rewardsShare * 100
+              }]).flat(),
+              ...NON_WORKING_GROUPS.map(({ color, shortTitle, groupType }) => ({
+                colors: [color],
+                label: shortTitle,
+                value: data[groupType].rewardsShare * 100
+              }))
+            ]}
+          />
+          <Label as='div'>
+            <Icon name='money' />
+            <span style={{ fontWeight: 600 }}>Spending</span>
+          </Label>
+        </ChartContainer>
+      ) : (
+        <Icon name='circle notched' loading />
+      )}
+      {data ? (
+        <ChartContainer>
+          <StyledPieChart
+            values={[
+              ...WORKING_GROUPS.map(({ color, title, groupType, lead }) => [{
+                colors: [color],
+                label: title,
+                value: data[groupType].stakeShare * 100
+              }, {
+                colors: [lead.color],
+                label: lead.title,
+                value: data[groupType].lead.stakeShare * 100
+              }]).flat(),
+              ...NON_WORKING_GROUPS.map(({ color, shortTitle, groupType }) => ({
+                colors: [color],
+                label: shortTitle,
+                value: data[groupType].stakeShare * 100
+              }))
+            ]}
+          />
+          <Label as='div'>
+            <Icon name='block layout' />
+            <span style={{ fontWeight: 600 }}>Stake</span>
+          </Label>
+        </ChartContainer>
+      ) : (
+        <Icon name='circle notched' loading />
+      )}
     </div>
   );
 };

+ 0 - 12
pioneer/packages/joy-tokenomics/src/Overview/index.tsx

@@ -38,17 +38,6 @@ const StyledTokenomicsCharts = styled(TokenomicsCharts)`
   }
 `;
 
-const COLORS = {
-  VALIDATOR: '#ff9800',
-  COUNCIL_MEMBER: '#ffc107',
-  STORAGE_PROVIDER: '#ffeb3b',
-  STORAGE_LEAD: '#cddc39',
-  CONTENT_CURATOR: '#8bc34a',
-  CURATOR_LEAD: '#4caf50',
-  OPERATIONS: '#009688',
-  OPERATIONS_LEAD: '#00bcd4'
-};
-
 const Overview: React.FC = () => {
   const transport = useTransport();
   const [statusDataValue, statusDataError] = usePromise<StatusServerData | undefined>(() => fetch('https://status.joystream.org/status').then((res) => res.json().then((data) => data as StatusServerData)), undefined, []);
@@ -68,4 +57,3 @@ const Overview: React.FC = () => {
 };
 
 export default Overview;
-export { COLORS };

+ 113 - 0
pioneer/packages/joy-tokenomics/src/tokenomicsGroupsData.ts

@@ -0,0 +1,113 @@
+export const NON_WORKING_GROUPS = [
+  {
+    groupType: 'validators' as const,
+    titleCutoff: 1050,
+    shortTitle: 'Validators',
+    title: 'Validators (Nominators)',
+    helpText:
+      'The current set of active Validators (and Nominators), and the sum of the sets projected rewards and total stakes (including Nominators).',
+    color: '#ff9800'
+  },
+  {
+    groupType: 'council' as const,
+    titleCutoff: 1015,
+    shortTitle: 'Council',
+    title: 'Council Members',
+    helpText:
+      'The current Council Members, and the sum of their projected rewards and total stakes (including voters/backers).',
+    color: '#ffc107'
+  }
+];
+
+export const WORKING_GROUPS = [
+  {
+    groupType: 'storageProviders' as const,
+    titleCutoff: 1015,
+    shortTitle: 'Storage',
+    title: 'Storage Providers',
+    helpText: 'The current Storage Providers, and the sum of their projected rewards and stakes.',
+    color: '#ffeb3b',
+    lead: {
+      titleCutoff: 1015,
+      shortTitle: 'S. Lead',
+      title: 'Storage Lead',
+      helpText: 'Current Storage Provider Lead, and their projected reward and stake.',
+      color: '#cddc39'
+    }
+  },
+  {
+    groupType: 'contentCurators' as const,
+    titleCutoff: 1015,
+    shortTitle: 'Curators',
+    title: 'Content Curators',
+    helpText: 'The current Content Curators, and the sum of their projected rewards and stakes.',
+    color: '#8bc34a',
+    lead: {
+      titleCutoff: 1015,
+      shortTitle: 'C. Lead',
+      title: 'Curators Lead',
+      helpText: 'Current Content Curators Lead, and their projected reward and stake.',
+      color: '#4caf50'
+    }
+  },
+  {
+    groupType: 'operationsAlpha' as const,
+    titleCutoff: 1050,
+    shortTitle: 'Operations A.',
+    title: 'Operations Alpha',
+    helpText: 'The current Operations Group Alpha members, and the sum of their projected rewards and stakes.',
+    color: '#009688',
+    lead: {
+      titleCutoff: 1015,
+      shortTitle: 'Operations A. Lead',
+      title: 'Operations Alpha Lead',
+      helpText: 'Current Operations Group Alpha Lead, and their projected reward and stake.',
+      color: '#00bcd4'
+    }
+  },
+  {
+    groupType: 'operationsBeta' as const,
+    titleCutoff: 1050,
+    shortTitle: 'Operations B.',
+    title: 'Operations Beta',
+    helpText: 'The current Operations Group Beta members, and the sum of their projected rewards and stakes.',
+    color: '#03a9f4',
+    lead: {
+      titleCutoff: 1015,
+      shortTitle: 'Operations B. Lead',
+      title: 'Operations Beta Lead',
+      helpText: 'Current Operations Group Beta Lead, and their projected reward and stake.',
+      color: '#2196f3'
+    }
+  },
+  {
+    groupType: 'operationsGamma' as const,
+    titleCutoff: 1050,
+    shortTitle: 'Operations G.',
+    title: 'Operations Gamma',
+    helpText: 'The current Operations Group Gamma members, and the sum of their projected rewards and stakes.',
+    color: '#3f51b5',
+    lead: {
+      titleCutoff: 1015,
+      shortTitle: 'Operations G. Lead',
+      title: 'Operations Gamma Lead',
+      helpText: 'Current Operations Group Gamma Lead, and their projected reward and stake.',
+      color: '#673ab7'
+    }
+  },
+  {
+    groupType: 'distribution' as const,
+    titleCutoff: 1050,
+    shortTitle: 'Distribution',
+    title: 'Distribution',
+    helpText: 'The current Distribution Group members, and the sum of their projected rewards and stakes.',
+    color: '#9c27b0',
+    lead: {
+      titleCutoff: 1015,
+      shortTitle: 'Distr. Lead',
+      title: 'Distribution Lead',
+      helpText: 'Current Distribution Group Lead, and their projected reward and stake.',
+      color: '#e91e63'
+    }
+  }
+];

+ 6 - 3
pioneer/packages/joy-utils/src/consts/workingGroups.ts

@@ -1,7 +1,10 @@
 import { WorkingGroupKey } from '@joystream/types/common';
 export const apiModuleByGroup: { [k in WorkingGroupKey]: string } = {
   Storage: 'storageWorkingGroup',
-  Content: 'contentDirectoryWorkingGroup',
-  Operations: 'operationsWorkingGroup',
-  Gateway: 'gatewayWorkingGroup'
+  Content: 'contentWorkingGroup',
+  OperationsAlpha: 'operationsWorkingGroupAlpha',
+  OperationsBeta: 'operationsWorkingGroupBeta',
+  OperationsGamma: 'operationsWorkingGroupGamma',
+  Gateway: 'gatewayWorkingGroup',
+  Distribution: 'distributionWorkingGroup'
 };

+ 3 - 7
pioneer/packages/joy-utils/src/transport/proposals.ts

@@ -187,14 +187,10 @@ export default class ProposalsTransport extends BaseTransport {
   }
 
   async voteByProposalAndMember (proposalId: ProposalId, voterId: MemberId): Promise<VoteKind | null> {
-    const votesEntries = await this.api.query.proposalsEngine.voteExistsByProposalByVoter.entries(proposalId);
-    const voteEntry = votesEntries.find((voteEntry) => {
-      const memberId = voteEntry[0].args[1] as MemberId;
+    const vote = (await this.proposalsEngine.voteExistsByProposalByVoter(proposalId, voterId)) as VoteKind;
+    const hasVoted = (await this.api.query.proposalsEngine.voteExistsByProposalByVoter.size(proposalId, voterId)).toNumber();
 
-      return memberId.eq(voterId);
-    });
-
-    return voteEntry ? voteEntry[1] as VoteKind : null;
+    return hasVoted ? vote : null;
   }
 
   async votes (proposalId: ProposalId): Promise<ProposalVotes> {

+ 8 - 2
pioneer/packages/joy-utils/src/transport/tokenomics.ts

@@ -228,7 +228,10 @@ export default class TokenomicsTransport extends BaseTransport {
     const workingGroupsData = {
       storageProviders: await this.getWorkingGroupData('Storage'),
       curators: await this.getWorkingGroupData('Content'),
-      operations: await this.getWorkingGroupData('Operations')
+      operationsAlpha: await this.getWorkingGroupData('OperationsAlpha'),
+      operationsBeta: await this.getWorkingGroupData('OperationsBeta'),
+      operationsGamma: await this.getWorkingGroupData('OperationsGamma'),
+      distribution: await this.getWorkingGroupData('Distribution')
     };
     const { numberOfValidators, numberOfNominators, totalValidatorStake, validatorRewardsPerWeek, totalIssuance } =
       await this.getValidatorData();
@@ -293,7 +296,10 @@ export default class TokenomicsTransport extends BaseTransport {
       },
       storageProviders: resolveGroupData(workingGroupsData.storageProviders),
       contentCurators: resolveGroupData(workingGroupsData.curators),
-      operations: resolveGroupData(workingGroupsData.operations)
+      operationsAlpha: resolveGroupData(workingGroupsData.operationsAlpha),
+      operationsBeta: resolveGroupData(workingGroupsData.operationsBeta),
+      operationsGamma: resolveGroupData(workingGroupsData.operationsGamma),
+      distribution: resolveGroupData(workingGroupsData.distribution)
     };
   }
 }

+ 4 - 1
pioneer/packages/joy-utils/src/types/tokenomics.ts

@@ -37,7 +37,10 @@ export type TokenomicsData = {
   };
   storageProviders: WorkingGroupTokenomicsData;
   contentCurators: WorkingGroupTokenomicsData;
-  operations: WorkingGroupTokenomicsData;
+  operationsAlpha: WorkingGroupTokenomicsData;
+  operationsBeta: WorkingGroupTokenomicsData;
+  operationsGamma: WorkingGroupTokenomicsData;
+  distribution: WorkingGroupTokenomicsData;
 }
 
 export type StatusServerData = {

+ 8 - 2
runtime-modules/common/src/working_group.rs

@@ -26,11 +26,17 @@ pub enum WorkingGroup {
     Content = 3isize,
 
     /// Operations working group: working_group::Instance4.
-    Operations = 4isize,
+    OperationsAlpha = 4isize,
 
     /// Gateway working group: working_group::Instance5.
     Gateway = 5isize,
 
-    /// Distribution working group: working_group::Instance4.
+    /// Distribution working group: working_group::Instance6.
     Distribution = 6isize,
+
+    /// Operations working group: working_group::Instance7.
+    OperationsBeta = 7isize,
+
+    /// Operations working group: working_group::Instance8.
+    OperationsGamma = 8isize,
 }

+ 1 - 1
runtime-modules/content/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-content'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 4 - 0
runtime-modules/content/src/errors.rs

@@ -76,5 +76,9 @@ decl_error! {
         /// Channel Contains Assets
         ChannelContainsAssets,
 
+        /// Bag Size specified is not valid
+        InvalidBagSizeSpecified,
+
+
     }
 }

+ 181 - 243
runtime-modules/content/src/lib.rs

@@ -98,21 +98,11 @@ pub trait Trait:
 
     /// The maximum number of curators per group constraint
     type MaxNumberOfCuratorsPerGroup: Get<MaxNumber>;
-}
 
-/// Specifies how a new asset will be provided on creating and updating
-/// Channels, Videos, Series and Person
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
-pub enum NewAssetsRecord<Balance> {
-    /// Upload to the storage frame_system
-    Upload(CreationUploadParameters<Balance>),
-    /// Multiple url strings pointing at an asset
-    Urls(Vec<AssetUrls>),
+    /// The storage type used
+    type DataObjectStorage: storage::DataObjectStorage<Self>;
 }
 
-type NewAssets<T> = NewAssetsRecord<<T as balances::Trait>::Balance>;
-
 /// The owner of a channel, is the authorized "actor" that can update
 /// or delete or transfer a channel and its contents.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
@@ -127,7 +117,7 @@ pub enum ChannelOwner<MemberId, CuratorGroupId> {
 // simplification type
 pub(crate) type ActorToChannelOwnerResult<T> = Result<
     ChannelOwner<
-        <T as membership::Trait>::MemberId,
+        <T as common::MembershipTypes>::MemberId,
         <T as ContentActorAuthenticator>::CuratorGroupId,
     >,
     Error<T>,
@@ -179,13 +169,11 @@ pub struct ChannelRecord<MemberId, CuratorGroupId, AccountId> {
     reward_account: Option<AccountId>,
     /// Account for withdrawing deletion prize funds
     deletion_prize_source_account_id: AccountId,
-    /// Number of asset held in storage
-    num_assets: u64,
 }
 
 // Channel alias type for simplification.
 pub type Channel<T> = ChannelRecord<
-    <T as membership::Trait>::MemberId,
+    <T as common::MembershipTypes>::MemberId,
     <T as ContentActorAuthenticator>::CuratorGroupId,
     <T as frame_system::Trait>::AccountId,
 >;
@@ -209,7 +197,7 @@ pub struct ChannelOwnershipTransferRequestRecord<
 // ChannelOwnershipTransferRequest type alias for simplification.
 pub type ChannelOwnershipTransferRequest<T> = ChannelOwnershipTransferRequestRecord<
     <T as storage::Trait>::ChannelId,
-    <T as membership::Trait>::MemberId,
+    <T as common::MembershipTypes>::MemberId,
     <T as ContentActorAuthenticator>::CuratorGroupId,
     BalanceOf<T>,
     <T as frame_system::Trait>::AccountId,
@@ -218,32 +206,37 @@ pub type ChannelOwnershipTransferRequest<T> = ChannelOwnershipTransferRequestRec
 /// Information about channel being created.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
-pub struct ChannelCreationParametersRecord<NewAssets, AccountId> {
+pub struct ChannelCreationParametersRecord<StorageAssets, AccountId> {
     /// Asset collection for the channel, referenced by metadata
-    assets: NewAssets,
+    assets: Option<StorageAssets>,
     /// Metadata about the channel.
-    meta: Vec<u8>,
+    meta: Option<Vec<u8>>,
     /// optional reward account
     reward_account: Option<AccountId>,
 }
 
 type ChannelCreationParameters<T> =
-    ChannelCreationParametersRecord<NewAssets<T>, <T as frame_system::Trait>::AccountId>;
+    ChannelCreationParametersRecord<StorageAssets<T>, <T as frame_system::Trait>::AccountId>;
 
 /// Information about channel being updated.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
-pub struct ChannelUpdateParametersRecord<NewAssets, AccountId> {
+pub struct ChannelUpdateParametersRecord<StorageAssets, AccountId, DataObjectId: Ord> {
     /// Asset collection for the channel, referenced by metadata    
-    assets: Option<NewAssets>,
+    assets_to_upload: Option<StorageAssets>,
     /// If set, metadata update for the channel.
     new_meta: Option<Vec<u8>>,
     /// If set, updates the reward account of the channel
     reward_account: Option<Option<AccountId>>,
+    /// assets to be removed from channel
+    assets_to_remove: BTreeSet<DataObjectId>,
 }
 
-type ChannelUpdateParameters<T> =
-    ChannelUpdateParametersRecord<NewAssets<T>, <T as frame_system::Trait>::AccountId>;
+type ChannelUpdateParameters<T> = ChannelUpdateParametersRecord<
+    StorageAssets<T>,
+    <T as frame_system::Trait>::AccountId,
+    DataObjectId<T>,
+>;
 
 /// A category that videos can belong to.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
@@ -272,7 +265,7 @@ pub struct VideoCategoryUpdateParameters {
 /// Information regarding the content being uploaded
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
-pub struct CreationUploadParameters<Balance> {
+pub struct StorageAssetsRecord<Balance> {
     /// Data object parameters.
     pub object_creation_list: Vec<DataObjectCreationParameters>,
 
@@ -280,49 +273,47 @@ pub struct CreationUploadParameters<Balance> {
     pub expected_data_size_fee: Balance,
 }
 
+type StorageAssets<T> = StorageAssetsRecord<<T as balances::Trait>::Balance>;
+
 /// Information about the video being created.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
-pub struct VideoCreationParametersRecord<NewAssets> {
+pub struct VideoCreationParametersRecord<StorageAssets> {
     /// Asset collection for the video
-    assets: NewAssets,
+    assets: Option<StorageAssets>,
     /// Metadata for the video.
-    meta: Vec<u8>,
+    meta: Option<Vec<u8>>,
 }
 
-type VideoCreationParameters<T> = VideoCreationParametersRecord<NewAssets<T>>;
+type VideoCreationParameters<T> = VideoCreationParametersRecord<StorageAssets<T>>;
 
 /// Information about the video being updated
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
-pub struct VideoUpdateParametersRecord<NewAssets> {
+pub struct VideoUpdateParametersRecord<StorageAssets, DataObjectId: Ord> {
     /// Assets referenced by metadata
-    assets: Option<NewAssets>,
+    assets_to_upload: Option<StorageAssets>,
     /// If set, metadata update for the video.
     new_meta: Option<Vec<u8>>,
+    /// video assets to be removed from channel
+    assets_to_remove: BTreeSet<DataObjectId>,
 }
 
-type VideoUpdateParameters<T> = VideoUpdateParametersRecord<NewAssets<T>>;
+type VideoUpdateParameters<T> = VideoUpdateParametersRecord<StorageAssets<T>, DataObjectId<T>>;
 
 /// A video which belongs to a channel. A video may be part of a series or playlist.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
-pub struct VideoRecord<ChannelId, SeriesId, DataObjectId: Ord> {
+pub struct VideoRecord<ChannelId, SeriesId> {
     pub in_channel: ChannelId,
     // keep track of which season the video is in if it is an 'episode'
     // - prevent removing a video if it is in a season (because order is important)
     pub in_series: Option<SeriesId>,
     /// Whether the curators have censored the video or not.
     pub is_censored: bool,
-    /// storage parameters used during deletion
-    pub maybe_data_objects_id_set: Option<BTreeSet<DataObjectId>>,
 }
 
-type Video<T> = VideoRecord<
-    <T as storage::Trait>::ChannelId,
-    <T as Trait>::SeriesId,
-    <T as storage::Trait>::DataObjectId,
->;
+type Video<T> = VideoRecord<<T as storage::Trait>::ChannelId, <T as Trait>::SeriesId>;
 
 /// Information about the plyalist being created.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
@@ -352,9 +343,9 @@ pub struct Playlist<ChannelId> {
 /// Information about the episode being created or updated.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
-pub enum EpisodeParameters<VideoId, NewAssets> {
+pub enum EpisodeParameters<VideoId, StorageAssets> {
     /// A new video is being added as the episode.
-    NewVideo(VideoCreationParametersRecord<NewAssets>),
+    NewVideo(VideoCreationParametersRecord<StorageAssets>),
     /// An existing video is being made into an episode.
     ExistingVideo(VideoId),
 }
@@ -362,15 +353,15 @@ pub enum EpisodeParameters<VideoId, NewAssets> {
 /// Information about the season being created or updated.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
-pub struct SeasonParameters<VideoId, NewAssets> {
+pub struct SeasonParameters<VideoId, StorageAssets> {
     /// Season assets referenced by metadata
-    assets: Option<NewAssets>,
+    assets: Option<StorageAssets>,
     // ?? It might just be more straighforward to always provide full list of episodes at cost of larger tx.
     /// If set, updates the episodes of a season. Extends the number of episodes in a season
     /// when length of new_episodes is greater than previously set. Last elements must all be
     /// 'Some' in that case.
     /// Will truncate existing season when length of new_episodes is less than previously set.
-    episodes: Option<Vec<Option<EpisodeParameters<VideoId, NewAssets>>>>,
+    episodes: Option<Vec<Option<EpisodeParameters<VideoId, StorageAssets>>>>,
 
     meta: Option<Vec<u8>>,
 }
@@ -378,14 +369,14 @@ pub struct SeasonParameters<VideoId, NewAssets> {
 /// Information about the series being created or updated.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
-pub struct SeriesParameters<VideoId, NewAssets> {
+pub struct SeriesParameters<VideoId, StorageAssets> {
     /// Series assets referenced by metadata
-    assets: Option<NewAssets>,
+    assets: Option<StorageAssets>,
     // ?? It might just be more straighforward to always provide full list of seasons at cost of larger tx.
     /// If set, updates the seasons of a series. Extend a series when length of seasons is
     /// greater than previoulsy set. Last elements must all be 'Some' in that case.
     /// Will truncate existing series when length of seasons is less than previously set.
-    seasons: Option<Vec<Option<SeasonParameters<VideoId, NewAssets>>>>,
+    seasons: Option<Vec<Option<SeasonParameters<VideoId, StorageAssets>>>>,
     meta: Option<Vec<u8>>,
 }
 
@@ -433,9 +424,9 @@ impl<MemberId: Default> Default for PersonController<MemberId> {
 /// Information for Person being created.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
-pub struct PersonCreationParameters<NewAssets> {
+pub struct PersonCreationParameters<StorageAssets> {
     /// Assets referenced by metadata
-    assets: NewAssets,
+    assets: StorageAssets,
     /// Metadata for person.
     meta: Vec<u8>,
 }
@@ -443,9 +434,9 @@ pub struct PersonCreationParameters<NewAssets> {
 /// Information for Persion being updated.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
-pub struct PersonUpdateParameters<NewAssets> {
+pub struct PersonUpdateParameters<StorageAssets> {
     /// Assets referenced by metadata
-    assets: Option<NewAssets>,
+    assets: Option<StorageAssets>,
     /// Metadata to update person.
     new_meta: Option<Vec<u8>>,
 }
@@ -458,6 +449,8 @@ pub struct Person<MemberId> {
     controlled_by: PersonController<MemberId>,
 }
 
+type DataObjectId<T> = <T as storage::Trait>::DataObjectId;
+
 decl_storage! {
     trait Store for Module<T: Trait> as Content {
         pub ChannelById get(fn channel_by_id): map hasher(blake2_128_concat) T::ChannelId => Channel<T>;
@@ -651,27 +644,17 @@ decl_module! {
             // The channel owner will be..
             let channel_owner = Self::actor_to_channel_owner(&actor)?;
 
-
             // next channel id
             let channel_id = NextChannelId::<T>::get();
 
-            // get uploading parameters if assets have to be saved on storage
-            let maybe_upload_parameters = Self::pick_upload_parameters_from_assets(
-                &params.assets,
-                &channel_id,
-                &sender,
-            );
-
-            // number of assets succesfully uploaded
-            let num_assets = maybe_upload_parameters
-                .map_or(Ok(0u64), |upload_parameters| {
-                Storage::<T>::upload_data_objects(upload_parameters.clone())
-                    .map(|_| {
-                        upload_parameters
-                        .object_creation_list
-                        .len() as u64
-                })
-            })?;
+            // atomically upload to storage and return the # of uploaded assets
+            if let Some(upload_assets) = params.assets.as_ref() {
+                Self::upload_assets_to_storage(
+                    upload_assets,
+                    &channel_id,
+                    &sender,
+                )?;
+            }
 
             //
             // == MUTATION SAFE ==
@@ -687,8 +670,6 @@ decl_module! {
                 num_videos: 0u64,
                 is_censored: false,
                 reward_account: params.reward_account.clone(),
-                // number of assets uploaded
-                num_assets,
                 // setting the channel owner account as the prize funds account
                 deletion_prize_source_account_id: sender,
             };
@@ -707,8 +688,6 @@ decl_module! {
             channel_id: T::ChannelId,
             params: ChannelUpdateParameters<T>,
         ) {
-            let sender = ensure_signed(origin.clone())?;
-
             // check that channel exists
             let channel = Self::ensure_channel_exists(&channel_id)?;
 
@@ -718,23 +697,17 @@ decl_module! {
                 &channel.owner,
             )?;
 
-            let maybe_upload_parameters = params.assets.clone()
-                .and_then(|assets| {Self::pick_upload_parameters_from_assets(
-                   &assets,
+            Self::remove_assets_from_storage(&params.assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
+
+            // atomically upload to storage and return the # of uploaded assets
+            if let Some(upload_assets) = params.assets_to_upload.as_ref() {
+                Self::upload_assets_to_storage(
+                    upload_assets,
                     &channel_id,
-            &sender,
-            )});
-
-            // number of assets succesfully uploaded
-            let maybe_num_assets = maybe_upload_parameters.as_ref()
-                    .map_or(
-                        Ok(Some(0u64)),
-                        |upload_parameters| {
-                        Storage::<T>::upload_data_objects(upload_parameters.clone())
-                     .map(|_| {
-                        Some(upload_parameters.object_creation_list.len() as u64)
-             })
-            })?;
+                    &channel.deletion_prize_source_account_id
+                )?;
+            }
+
             //
             // == MUTATION SAFE ==
             //
@@ -746,23 +719,19 @@ decl_module! {
                 channel.reward_account = reward_account.clone();
             }
 
-            // Maybe update asset num
-            if let Some(num_assets) = maybe_num_assets {
-                channel.num_assets = channel.num_assets.saturating_add(num_assets);
-            }
-
             // Update the channel
             ChannelById::<T>::insert(channel_id, channel.clone());
 
             Self::deposit_event(RawEvent::ChannelUpdated(actor, channel_id, channel, params));
         }
 
-            // extrinsics for channel deletion
+        // extrinsics for channel deletion
         #[weight = 10_000_000] // TODO: adjust weight
         pub fn delete_channel(
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             channel_id: T::ChannelId,
+            num_objects_to_delete: u64,
         ) -> DispatchResult {
             // check that channel exists
             let channel = Self::ensure_channel_exists(&channel_id)?;
@@ -774,74 +743,49 @@ decl_module! {
                 &channel.owner,
             )?;
 
-            // check that channel assets are 0
-            ensure!(channel.num_assets == 0, Error::<T>::ChannelContainsAssets);
-
             // check that channel videos are 0
             ensure!(channel.num_videos == 0, Error::<T>::ChannelContainsVideos);
 
-            // delete channel dynamic bag
+            // get bag id for the channel
             let dyn_bag = DynamicBagIdType::<T::MemberId, T::ChannelId>::Channel(channel_id);
-            Storage::<T>::delete_dynamic_bag(
-                channel.deletion_prize_source_account_id,
-                dyn_bag
-            )?;
-
-            // remove channel from on chain state
-            ChannelById::<T>::remove(channel_id);
-
-            // deposit event
-            Self::deposit_event(RawEvent::ChannelDeleted(actor, channel_id));
-
-            Ok(())
-        }
-
-        /// Remove assets of a channel from storage
-        #[weight = 10_000_000] // TODO: adjust weight
-        pub fn remove_channel_assets(
-            origin,
-            actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
-            channel_id: T::ChannelId,
-            assets: BTreeSet<<T as storage::Trait>::DataObjectId>,
-        ) {
-            // check that channel exists
-            let channel = Self::ensure_channel_exists(&channel_id)?;
-
-            ensure_actor_authorized_to_update_channel::<T>(
-                origin,
-                &actor,
-                &channel.owner,
-            )?;
-
-            // ensure that the provided assets are not empty
-            ensure!(!assets.is_empty(), Error::<T>::NoAssetsSpecified);
-
-            let num_assets_to_remove = assets.len() as u64;
-
-            // cannot remove more asset than those already present
-            ensure!(
-                num_assets_to_remove <= channel.num_assets,
-                Error::<T>::InvalidAssetsProvided
-            );
+            let bag_id = storage::BagIdType::from(dyn_bag.clone());
+
+            // channel has a dynamic bag associated to it -> remove assets from storage
+            if let Ok(bag) = T::DataObjectStorage::ensure_bag_exists(&bag_id) {
+                // ensure that bag size provided is valid
+                ensure!(
+                    bag.objects_number == num_objects_to_delete,
+                    Error::<T>::InvalidBagSizeSpecified
+                );
+
+                // construct collection of assets to be removed
+                let assets_to_remove = T::DataObjectStorage::get_data_objects_id(&bag_id);
+
+                // remove specified assets from storage
+                Self::remove_assets_from_storage(
+                    &assets_to_remove,
+                    &channel_id,
+                    &channel.deletion_prize_source_account_id
+                )?;
 
-            // remove assets from storage
-            Storage::<T>::delete_data_objects(
-                channel.deletion_prize_source_account_id.clone(),
-                Self::bag_id_for_channel(&channel_id),
-                assets.clone(),
-            )?;
+                // delete channel dynamic bag
+                Storage::<T>::delete_dynamic_bag(
+                    channel.deletion_prize_source_account_id,
+                    dyn_bag
+                )?;
+            }
 
             //
             // == MUTATION SAFE ==
             //
 
-            // update onchain channel status
-            let mut channel = channel;
-            channel.num_assets = channel.num_assets.saturating_sub(num_assets_to_remove);
-            ChannelById::<T>::insert(channel_id, channel.clone());
+            // remove channel from on chain state
+            ChannelById::<T>::remove(channel_id);
 
+            // deposit event
+            Self::deposit_event(RawEvent::ChannelDeleted(actor, channel_id));
 
-            Self::deposit_event(RawEvent::ChannelAssetsRemoved(actor, channel_id, assets, channel));
+            Ok(())
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -974,8 +918,6 @@ decl_module! {
             params: VideoCreationParameters<T>,
         ) {
 
-            let sender = ensure_signed(origin.clone())?;
-
             // check that channel exists
             let channel = Self::ensure_channel_exists(&channel_id)?;
 
@@ -988,26 +930,14 @@ decl_module! {
             // next video id
             let video_id = NextVideoId::<T>::get();
 
-            // adding the content to storage node if uploading is needed
-            let maybe_upload_parameters = Self::pick_upload_parameters_from_assets(
-                &params.assets,
-                &channel_id,
-        &sender,
-            );
-
-            // if storaged uploading is required save t he object id for the video
-            let maybe_data_objects_ids = maybe_upload_parameters
-                .map_or(
-                    Ok(None),
-                    |upload_parameters| {
-                     // beginning object id
-                        let beg = Storage::<T>::next_data_object_id();
-
-                        // upload objects and return their indexes
-                        Storage::<T>::upload_data_objects(upload_parameters)
-                        .map(|_| Storage::<T>::next_data_object_id()) // ending index
-                        .map(|end| Some((beg..end).collect::<BTreeSet<_>>())) // create collection
-                })?;
+            // atomically upload to storage and return the # of uploaded assets
+            if let Some(upload_assets) = params.assets.as_ref() {
+                Self::upload_assets_to_storage(
+                    upload_assets,
+                    &channel_id,
+                    &channel.deletion_prize_source_account_id
+                )?;
+            }
 
             //
             // == MUTATION SAFE ==
@@ -1021,8 +951,6 @@ decl_module! {
                 in_series: None,
                 /// Whether the curators have censored the video or not.
                 is_censored: false,
-                /// storage parameters for later storage deletion
-                maybe_data_objects_id_set: maybe_data_objects_ids,
             };
 
             // add it to the onchain state
@@ -1047,40 +975,34 @@ decl_module! {
             video_id: T::VideoId,
             params: VideoUpdateParameters<T>,
         ) {
-            let sender = ensure_signed(origin.clone())?;
-
             // check that video exists, retrieve corresponding channel id.
-            let channel_id = Self::ensure_video_exists(&video_id)?.in_channel;
+            let video = Self::ensure_video_exists(&video_id)?;
+
+            let channel_id = video.in_channel;
+            let channel = ChannelById::<T>::get(&channel_id);
 
             ensure_actor_authorized_to_update_channel::<T>(
                 origin,
                 &actor,
-                &Self::channel_by_id(channel_id).owner,
+                &channel.owner,
             )?;
 
-            // Pick the assets to be uploaded to storage frame_system out
-            if let Some(assets) = &params.assets {
-                // adding content to storage if needed
-               let maybe_upload_parameters = Self::pick_upload_parameters_from_assets(
-                   assets,
-                   &channel_id,
-                   &sender,
-               );
-
-              if let Some(upload_parameters) = maybe_upload_parameters{
-                 Storage::<T>::upload_data_objects(upload_parameters)?;
-              }
+            // remove specified assets from channel bag in storage
+            Self::remove_assets_from_storage(&params.assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
+
+            // atomically upload to storage and return the # of uploaded assets
+            if let Some(upload_assets) = params.assets_to_upload.as_ref() {
+                Self::upload_assets_to_storage(
+                    upload_assets,
+                    &channel_id,
+                    &channel.deletion_prize_source_account_id
+                )?;
             }
 
             //
             // == MUTATION SAFE ==
             //
 
-            // increase the number of video the selected channel by 1
-            ChannelById::<T>::mutate(channel_id, |channel| {
-                channel.num_videos = channel.num_videos.saturating_add(1);
-            });
-
             Self::deposit_event(RawEvent::VideoUpdated(actor, video_id, params));
         }
 
@@ -1089,6 +1011,7 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             video_id: T::VideoId,
+            assets_to_remove: BTreeSet<DataObjectId<T>>,
         ) {
 
             // check that video exists
@@ -1106,16 +1029,11 @@ decl_module! {
                 &channel.owner,
             )?;
 
+            // ensure video can be removed
             Self::ensure_video_can_be_removed(&video)?;
 
-            // If video is on storage, remove it
-            if let Some(data_objects_id_set) = video.maybe_data_objects_id_set {
-                Storage::<T>::delete_data_objects(
-                    channel.deletion_prize_source_account_id,
-                    Self::bag_id_for_channel(&channel_id),
-                    data_objects_id_set,
-                )?;
-            }
+            // remove specified assets from channel bag in storage
+            Self::remove_assets_from_storage(&assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
 
             //
             // == MUTATION SAFE ==
@@ -1244,7 +1162,7 @@ decl_module! {
         pub fn create_person(
             _origin,
             _actor: PersonActor<T::MemberId, T::CuratorId>,
-            _params: PersonCreationParameters<NewAssets<T>>,
+            _params: PersonCreationParameters<StorageAssets<T>>,
         ) {
             Self::not_implemented()?;
         }
@@ -1254,7 +1172,7 @@ decl_module! {
             _origin,
             _actor: PersonActor<T::MemberId, T::CuratorId>,
             _person: T::PersonId,
-            _params: PersonUpdateParameters<NewAssets<T>>,
+            _params: PersonUpdateParameters<StorageAssets<T>>,
         ) {
             Self::not_implemented()?;
         }
@@ -1326,7 +1244,7 @@ decl_module! {
             _origin,
             _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             _channel_id: T::ChannelId,
-            _params: SeriesParameters<T::VideoId, NewAssets<T>>
+            _params: SeriesParameters<T::VideoId, StorageAssets<T>>
         ) {
             Self::not_implemented()?;
         }
@@ -1336,7 +1254,7 @@ decl_module! {
             _origin,
             _actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             _channel_id: T::ChannelId,
-            _params: SeriesParameters<T::VideoId, NewAssets<T>>
+            _params: SeriesParameters<T::VideoId, StorageAssets<T>>
         ) {
             Self::not_implemented()?;
         }
@@ -1415,28 +1333,24 @@ impl<T: Trait> Module<T> {
     }
 
     fn pick_upload_parameters_from_assets(
-        assets: &NewAssets<T>,
+        assets: &StorageAssets<T>,
         channel_id: &T::ChannelId,
-        sender: &T::AccountId,
-    ) -> Option<UploadParameters<T>> {
+        prize_source_account: &T::AccountId,
+    ) -> UploadParameters<T> {
         // dynamic bag for a media object
         let dyn_bag = DynamicBagIdType::<T::MemberId, T::ChannelId>::Channel(*channel_id);
         let bag_id = BagIdType::from(dyn_bag.clone());
 
-        if !storage::Bags::<T>::contains_key(bag_id.clone()) {
+        if T::DataObjectStorage::ensure_bag_exists(&bag_id).is_err() {
             // create_dynamic_bag checks automatically satifsfied with None as second parameter
             Storage::<T>::create_dynamic_bag(dyn_bag, None).unwrap();
         }
 
-        if let NewAssets::<T>::Upload(creation_upload_params) = assets {
-            Some(UploadParametersRecord {
-                bag_id,
-                object_creation_list: creation_upload_params.object_creation_list.clone(),
-                deletion_prize_source_account_id: sender.clone(),
-                expected_data_size_fee: creation_upload_params.expected_data_size_fee,
-            })
-        } else {
-            None
+        UploadParametersRecord {
+            bag_id,
+            object_creation_list: assets.object_creation_list.clone(),
+            deletion_prize_source_account_id: prize_source_account.clone(),
+            expected_data_size_fee: assets.expected_data_size_fee,
         }
     }
 
@@ -1446,17 +1360,10 @@ impl<T: Trait> Module<T> {
         match actor {
             // Lead should use their member or curator role to create channels
             ContentActor::Lead => Err(Error::<T>::ActorCannotOwnChannel),
-            ContentActor::Curator(
-                curator_group_id,
-                _curator_id
-            ) => {
+            ContentActor::Curator(curator_group_id, _curator_id) => {
                 Ok(ChannelOwner::CuratorGroup(*curator_group_id))
             }
-            ContentActor::Member(member_id) => {
-                Ok(ChannelOwner::Member(*member_id))
-            }
-            // TODO:
-            // ContentActor::Dao(id) => Ok(ChannelOwner::Dao(id)),
+            ContentActor::Member(member_id) => Ok(ChannelOwner::Member(*member_id)),
         }
     }
 
@@ -1469,6 +1376,37 @@ impl<T: Trait> Module<T> {
     fn not_implemented() -> DispatchResult {
         Err(Error::<T>::FeatureNotImplemented.into())
     }
+
+    fn upload_assets_to_storage(
+        assets: &StorageAssets<T>,
+        channel_id: &T::ChannelId,
+        prize_source_account: &T::AccountId,
+    ) -> DispatchResult {
+        // construct upload params
+        let upload_params =
+            Self::pick_upload_parameters_from_assets(assets, channel_id, prize_source_account);
+
+        // attempt to upload objects att
+        Storage::<T>::upload_data_objects(upload_params.clone())?;
+
+        Ok(())
+    }
+
+    fn remove_assets_from_storage(
+        assets: &BTreeSet<DataObjectId<T>>,
+        channel_id: &T::ChannelId,
+        prize_source_account: &T::AccountId,
+    ) -> DispatchResult {
+        // remove assets if any
+        if !assets.is_empty() {
+            Storage::<T>::delete_data_objects(
+                prize_source_account.clone(),
+                Self::bag_id_for_channel(&channel_id),
+                assets.clone(),
+            )?;
+        }
+        Ok(())
+    }
 }
 
 decl_event!(
@@ -1477,7 +1415,7 @@ decl_event!(
         ContentActor = ContentActor<
             <T as ContentActorAuthenticator>::CuratorGroupId,
             <T as ContentActorAuthenticator>::CuratorId,
-            <T as membership::Trait>::MemberId,
+            <T as common::MembershipTypes>::MemberId,
         >,
         CuratorGroupId = <T as ContentActorAuthenticator>::CuratorGroupId,
         CuratorId = <T as ContentActorAuthenticator>::CuratorId,
@@ -1492,13 +1430,13 @@ decl_event!(
         ChannelOwnershipTransferRequest = ChannelOwnershipTransferRequest<T>,
         Series = Series<<T as storage::Trait>::ChannelId, <T as Trait>::VideoId>,
         Channel = Channel<T>,
-        DataObjectId = <T as storage::Trait>::DataObjectId,
+        DataObjectId = DataObjectId<T>,
         IsCensored = bool,
         ChannelCreationParameters = ChannelCreationParameters<T>,
         ChannelUpdateParameters = ChannelUpdateParameters<T>,
         VideoCreationParameters = VideoCreationParameters<T>,
         VideoUpdateParameters = VideoUpdateParameters<T>,
-        NewAssets = NewAssets<T>,
+        StorageAssets = StorageAssets<T>,
     {
         // Curators
         CuratorGroupCreated(CuratorGroupId),
@@ -1572,15 +1510,15 @@ decl_event!(
         SeriesCreated(
             ContentActor,
             SeriesId,
-            NewAssets,
-            SeriesParameters<VideoId, NewAssets>,
+            StorageAssets,
+            SeriesParameters<VideoId, StorageAssets>,
             Series,
         ),
         SeriesUpdated(
             ContentActor,
             SeriesId,
-            NewAssets,
-            SeriesParameters<VideoId, NewAssets>,
+            StorageAssets,
+            SeriesParameters<VideoId, StorageAssets>,
             Series,
         ),
         SeriesDeleted(ContentActor, SeriesId),
@@ -1589,14 +1527,14 @@ decl_event!(
         PersonCreated(
             ContentActor,
             PersonId,
-            NewAssets,
-            PersonCreationParameters<NewAssets>,
+            StorageAssets,
+            PersonCreationParameters<StorageAssets>,
         ),
         PersonUpdated(
             ContentActor,
             PersonId,
-            NewAssets,
-            PersonUpdateParameters<NewAssets>,
+            StorageAssets,
+            PersonUpdateParameters<StorageAssets>,
         ),
         PersonDeleted(ContentActor, PersonId),
         ChannelDeleted(ContentActor, ChannelId),

+ 7 - 41
runtime-modules/content/src/permissions/mod.rs

@@ -11,7 +11,6 @@ use frame_support::{ensure, Parameter};
 pub use serde::{Deserialize, Serialize};
 use sp_arithmetic::traits::BaseArithmetic;
 use sp_runtime::traits::{MaybeSerializeDeserialize, Member};
-// use frame_system::ensure_root;
 
 /// Model of authentication manager.
 pub trait ContentActorAuthenticator: frame_system::Trait + membership::Trait {
@@ -104,26 +103,18 @@ pub fn ensure_actor_authorized_to_create_channel<T: Trait>(
 ) -> DispatchResult {
     match actor {
         // Lead should use their member or curator role to create or update channel assets.
-        ContentActor::Lead => {
-            Err(Error::<T>::ActorCannotOwnChannel.into())
-        }
+        ContentActor::Lead => Err(Error::<T>::ActorCannotOwnChannel.into()),
         ContentActor::Curator(curator_group_id, curator_id) => {
             let sender = ensure_signed(origin)?;
 
             // Authorize curator, performing all checks to ensure curator can act
-            CuratorGroup::<T>::perform_curator_in_group_auth(
-                curator_id,
-                curator_group_id,
-                &sender,
-            )
+            CuratorGroup::<T>::perform_curator_in_group_auth(curator_id, curator_group_id, &sender)
         }
         ContentActor::Member(member_id) => {
             let sender = ensure_signed(origin)?;
 
             ensure_member_auth_success::<T>(member_id, &sender)
         }
-        // TODO:
-        // ContentActor::Dao(_daoId) => ...,
     }
 }
 
@@ -176,8 +167,6 @@ pub fn ensure_actor_authorized_to_update_channel<T: Trait>(
 
             Ok(())
         }
-        // TODO:
-        // ContentActor::Dao(_daoId) => ...,
     }
 }
 
@@ -206,7 +195,7 @@ pub fn ensure_actor_authorized_to_censor<T: Trait>(
         ContentActor::Lead => {
             let sender = ensure_signed(origin)?;
             ensure_lead_auth_success::<T>(&sender)
-        },
+        }
         ContentActor::Curator(curator_group_id, curator_id) => {
             let sender = ensure_signed(origin)?;
 
@@ -223,13 +212,11 @@ pub fn ensure_actor_authorized_to_censor<T: Trait>(
             } else {
                 Ok(())
             }
-        },
+        }
         ContentActor::Member(_) => {
             // Members cannot censore channels!
             Err(Error::<T>::ActorNotAuthorized.into())
         }
-        // TODO:
-        // ContentActor::Dao(_daoId) => ...,
     }
 }
 
@@ -242,40 +229,20 @@ pub fn ensure_actor_authorized_to_manage_categories<T: Trait>(
         ContentActor::Lead => {
             let sender = ensure_signed(origin)?;
             ensure_lead_auth_success::<T>(&sender)
-        },
+        }
         ContentActor::Curator(curator_group_id, curator_id) => {
             let sender = ensure_signed(origin)?;
 
             // Authorize curator, performing all checks to ensure curator can act
-            CuratorGroup::<T>::perform_curator_in_group_auth(
-                curator_id,
-                curator_group_id,
-                &sender,
-            )
-        },
+            CuratorGroup::<T>::perform_curator_in_group_auth(curator_id, curator_group_id, &sender)
+        }
         ContentActor::Member(_) => {
             // Members cannot censore channels!
             Err(Error::<T>::ActorNotAuthorized.into())
         }
-        // TODO:
-        // ContentActor::Dao(_daoId) => ...,
     }
 }
 
-// pub fn ensure_actor_authorized_to_delete_stale_assets<T: Trait>(
-//     origin: T::Origin,
-//     actor: &ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
-// ) -> DispatchResult {
-//     // Only Lead and (sudo) can delete assets no longer associated with a channel or person.
-//     if let ContentActor::Lead = actor {
-//         let sender = ensure_signed(origin)?;
-//         ensure_lead_auth_success::<T>(&sender)
-//     } else {
-//         ensure_root(origin)?;
-//         Ok(())
-//     }
-// }
-
 /// Enum, representing all possible `Actor`s
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Eq, PartialEq, Clone, Copy, Debug)]
@@ -287,7 +254,6 @@ pub enum ContentActor<
     Curator(CuratorGroupId, CuratorId),
     Member(MemberId),
     Lead,
-    // Dao,
 }
 
 impl<

+ 105 - 84
runtime-modules/content/src/tests/channels.rs

@@ -18,8 +18,8 @@ fn successful_channel_deletion() {
             <Test as balances::Trait>::Balance::from(100u32),
         );
 
-        // 3 assets
-        let assets = NewAssets::<Test>::Upload(CreationUploadParameters {
+        // 3 assets added at creation
+        let assets = StorageAssetsRecord {
             object_creation_list: vec![
                 DataObjectCreationParameters {
                     size: 3,
@@ -35,8 +35,7 @@ fn successful_channel_deletion() {
                 },
             ],
             expected_data_size_fee: storage::DataObjectPerMegabyteFee::<Test>::get(),
-        });
-
+        };
         let channel_id = NextChannelId::<Test>::get();
 
         // create channel
@@ -44,41 +43,49 @@ fn successful_channel_deletion() {
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: assets,
-                meta: vec![],
+                assets: Some(assets),
+                meta: None,
                 reward_account: None,
             },
             Ok(()),
         );
 
-        // attempt to delete channel with non zero assets
+        // attempt to delete channel with non zero assets should result in error: objects
+        // are misspecified
         delete_channel_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             channel_id,
-            Err(Error::<Test>::ChannelContainsAssets.into()),
+            2u64,
+            Err(Error::<Test>::InvalidBagSizeSpecified.into()),
         );
 
-        // delete assets
-        let assets_to_delete = [0u64, 1u64, 2u64]
-            .iter()
-            .map(|&x| x)
-            .collect::<BTreeSet<_>>();
-
-        // delete channel assets
-        delete_channel_assets_mock(
+        // successful deletion because we empty the bag first
+        delete_channel_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             channel_id,
-            assets_to_delete,
+            3u64,
             Ok(()),
         );
 
-        // successful deletion
+        // create a channel with no assets:
+        let empty_channel_id = Content::next_channel_id();
+        create_channel_mock(
+            FIRST_MEMBER_ORIGIN,
+            ContentActor::Member(FIRST_MEMBER_ID),
+            ChannelCreationParametersRecord {
+                assets: None,
+                meta: None,
+                reward_account: None,
+            },
+            Ok(()),
+        );
         delete_channel_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
-            channel_id,
+            empty_channel_id,
+            43u64, // this param will be discarded if channel has no assets
             Ok(()),
         );
     })
@@ -97,7 +104,7 @@ fn successful_channel_assets_deletion() {
         );
 
         // 3 assets
-        let assets = NewAssets::<Test>::Upload(CreationUploadParameters {
+        let assets = StorageAssetsRecord {
             object_creation_list: vec![
                 DataObjectCreationParameters {
                     size: 3,
@@ -113,7 +120,7 @@ fn successful_channel_assets_deletion() {
                 },
             ],
             expected_data_size_fee: storage::DataObjectPerMegabyteFee::<Test>::get(),
-        });
+        };
 
         let channel_id = NextChannelId::<Test>::get();
         // create channel
@@ -121,24 +128,28 @@ fn successful_channel_assets_deletion() {
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: assets,
-                meta: vec![],
+                assets: Some(assets),
+                meta: Some(vec![]),
                 reward_account: None,
             },
             Ok(()),
         );
 
         // delete assets
-        let assets_to_delete = [0u64, 1u64].iter().map(|&x| x).collect::<BTreeSet<_>>();
+        let assets_to_remove = [0u64, 1u64].iter().map(|&x| x).collect::<BTreeSet<_>>();
 
         // delete channel assets
-        delete_channel_assets_mock(
-            FIRST_MEMBER_ORIGIN,
+        assert_ok!(Content::update_channel(
+            Origin::signed(FIRST_MEMBER_ORIGIN),
             ContentActor::Member(FIRST_MEMBER_ID),
             channel_id,
-            assets_to_delete,
-            Ok(()),
-        );
+            ChannelUpdateParametersRecord {
+                assets_to_upload: None,
+                new_meta: None,
+                reward_account: None,
+                assets_to_remove: assets_to_remove,
+            },
+        ));
     })
 }
 
@@ -155,7 +166,8 @@ fn succesful_channel_update() {
         );
 
         // 2 + 1 assets to be uploaded
-        let assets = NewAssets::<Test>::Upload(CreationUploadParameters {
+        let first_obj_id = Storage::<Test>::next_data_object_id();
+        let first_batch = StorageAssetsRecord {
             object_creation_list: vec![
                 DataObjectCreationParameters {
                     size: 3,
@@ -167,9 +179,11 @@ fn succesful_channel_update() {
                 },
             ],
             expected_data_size_fee: storage::DataObjectPerMegabyteFee::<Test>::get(),
-        });
+        };
+        let first_batch_ids =
+            (first_obj_id..Storage::<Test>::next_data_object_id()).collect::<BTreeSet<_>>();
 
-        let new_assets = NewAssets::<Test>::Upload(CreationUploadParameters {
+        let second_batch = StorageAssetsRecord {
             object_creation_list: vec![
                 DataObjectCreationParameters {
                     size: 3,
@@ -181,43 +195,46 @@ fn succesful_channel_update() {
                 },
             ],
             expected_data_size_fee: storage::DataObjectPerMegabyteFee::<Test>::get(),
-        });
+        };
 
         let channel_id = NextChannelId::<Test>::get();
-        // create channel
+
+        // create channel with first batch of assets
         create_channel_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: assets,
-                meta: vec![],
+                assets: Some(first_batch),
+                meta: Some(vec![]),
                 reward_account: None,
             },
             Ok(()),
         );
 
-        // update channel
+        // update channel by adding the second batch of assets
         update_channel_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             channel_id,
             ChannelUpdateParametersRecord {
-                assets: Some(new_assets),
-                new_meta: None,
+                assets_to_upload: Some(second_batch),
+                new_meta: Some(vec![]),
                 reward_account: None,
+                assets_to_remove: BTreeSet::new(),
             },
             Ok(()),
         );
 
-        // update with 0 assets
+        // update channel by removing the first batch of assets
         update_channel_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             channel_id,
             ChannelUpdateParametersRecord {
-                assets: None,
+                assets_to_upload: None,
                 new_meta: None,
                 reward_account: None,
+                assets_to_remove: first_batch_ids,
             },
             Ok(()),
         );
@@ -237,7 +254,7 @@ fn succesful_channel_creation() {
         );
 
         // 3 assets to be uploaded
-        let assets = NewAssets::<Test>::Upload(CreationUploadParameters {
+        let assets = StorageAssetsRecord {
             object_creation_list: vec![
                 DataObjectCreationParameters {
                     size: 3,
@@ -253,15 +270,15 @@ fn succesful_channel_creation() {
                 },
             ],
             expected_data_size_fee: storage::DataObjectPerMegabyteFee::<Test>::get(),
-        });
+        };
 
         // create channel
         create_channel_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: assets,
-                meta: vec![],
+                assets: Some(assets),
+                meta: Some(vec![]),
                 reward_account: None,
             },
             Ok(()),
@@ -277,8 +294,8 @@ fn lead_cannot_create_channel() {
                 Origin::signed(LEAD_ORIGIN),
                 ContentActor::Lead,
                 ChannelCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: Some(vec![]),
                     reward_account: None,
                 }
             ),
@@ -299,8 +316,8 @@ fn curator_owned_channels() {
                 Origin::signed(FIRST_CURATOR_ORIGIN),
                 ContentActor::Curator(FIRST_CURATOR_GROUP_ID, FIRST_CURATOR_ID),
                 ChannelCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: Some(vec![]),
                     reward_account: None,
                 }
             ),
@@ -316,8 +333,8 @@ fn curator_owned_channels() {
                 Origin::signed(SECOND_CURATOR_ORIGIN),
                 ContentActor::Curator(FIRST_CURATOR_GROUP_ID, SECOND_CURATOR_ID),
                 ChannelCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: Some(vec![]),
                     reward_account: None,
                 }
             ),
@@ -330,8 +347,8 @@ fn curator_owned_channels() {
                 Origin::signed(SECOND_CURATOR_ORIGIN),
                 ContentActor::Curator(FIRST_CURATOR_GROUP_ID, FIRST_CURATOR_ID),
                 ChannelCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: Some(vec![]),
                     reward_account: None,
                 }
             ),
@@ -345,8 +362,8 @@ fn curator_owned_channels() {
             Origin::signed(FIRST_CURATOR_ORIGIN),
             ContentActor::Curator(FIRST_CURATOR_GROUP_ID, FIRST_CURATOR_ID),
             ChannelCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![]),
-                meta: vec![],
+                assets: None,
+                meta: Some(vec![]),
                 reward_account: None,
             }
         ));
@@ -361,12 +378,11 @@ fn curator_owned_channels() {
                     is_censored: false,
                     reward_account: None,
                     deletion_prize_source_account_id: FIRST_CURATOR_ORIGIN,
-                    num_assets: 0,
                     num_videos: 0,
                 },
                 ChannelCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: Some(vec![]),
                     reward_account: None,
                 }
             ))
@@ -378,10 +394,11 @@ fn curator_owned_channels() {
             ContentActor::Curator(FIRST_CURATOR_GROUP_ID, FIRST_CURATOR_ID),
             channel_id,
             ChannelUpdateParametersRecord {
-                assets: None,
+                assets_to_upload: None,
                 new_meta: None,
                 reward_account: None,
-            }
+                assets_to_remove: BTreeSet::new(),
+            },
         ));
 
         // Lead can update curator owned channels
@@ -390,10 +407,11 @@ fn curator_owned_channels() {
             ContentActor::Lead,
             channel_id,
             ChannelUpdateParametersRecord {
-                assets: None,
+                assets_to_upload: None,
                 new_meta: None,
                 reward_account: None,
-            }
+                assets_to_remove: BTreeSet::new(),
+            },
         ));
     })
 }
@@ -410,8 +428,8 @@ fn member_owned_channels() {
                 Origin::signed(UNKNOWN_ORIGIN),
                 ContentActor::Member(MEMBERS_COUNT + 1),
                 ChannelCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: Some(vec![]),
                     reward_account: None,
                 }
             ),
@@ -425,8 +443,8 @@ fn member_owned_channels() {
             Origin::signed(FIRST_MEMBER_ORIGIN),
             ContentActor::Member(FIRST_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![]),
-                meta: vec![],
+                assets: None,
+                meta: Some(vec![]),
                 reward_account: None,
             }
         ));
@@ -441,12 +459,12 @@ fn member_owned_channels() {
                     is_censored: false,
                     reward_account: None,
                     deletion_prize_source_account_id: FIRST_MEMBER_ORIGIN,
-                    num_assets: 0,
+
                     num_videos: 0,
                 },
                 ChannelCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: Some(vec![]),
                     reward_account: None,
                 }
             ))
@@ -459,8 +477,8 @@ fn member_owned_channels() {
             Origin::signed(SECOND_MEMBER_ORIGIN),
             ContentActor::Member(SECOND_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![]),
-                meta: vec![],
+                assets: None,
+                meta: Some(vec![]),
                 reward_account: None,
             }
         ));
@@ -475,12 +493,12 @@ fn member_owned_channels() {
                     is_censored: false,
                     reward_account: None,
                     deletion_prize_source_account_id: SECOND_MEMBER_ORIGIN,
-                    num_assets: 0,
+
                     num_videos: 0,
                 },
                 ChannelCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: Some(vec![]),
                     reward_account: None,
                 }
             ))
@@ -492,10 +510,11 @@ fn member_owned_channels() {
             ContentActor::Member(FIRST_MEMBER_ID),
             channel_id_1,
             ChannelUpdateParametersRecord {
-                assets: None,
+                assets_to_upload: None,
                 new_meta: None,
                 reward_account: None,
-            }
+                assets_to_remove: BTreeSet::new(),
+            },
         ));
 
         assert_eq!(
@@ -508,13 +527,14 @@ fn member_owned_channels() {
                     is_censored: false,
                     reward_account: None,
                     deletion_prize_source_account_id: FIRST_MEMBER_ORIGIN,
-                    num_assets: 0,
+
                     num_videos: 0,
                 },
                 ChannelUpdateParametersRecord {
-                    assets: None,
+                    assets_to_upload: None,
                     new_meta: None,
                     reward_account: None,
+                    assets_to_remove: BTreeSet::new(),
                 }
             ))
         );
@@ -526,10 +546,11 @@ fn member_owned_channels() {
                 ContentActor::Member(FIRST_MEMBER_ID),
                 channel_id_2,
                 ChannelUpdateParametersRecord {
-                    assets: None,
+                    assets_to_upload: None,
                     new_meta: None,
                     reward_account: None,
-                }
+                    assets_to_remove: BTreeSet::new(),
+                },
             ),
             Error::<Test>::ActorNotAuthorized
         );
@@ -547,8 +568,8 @@ fn channel_censoring() {
             Origin::signed(FIRST_MEMBER_ORIGIN),
             ContentActor::Member(FIRST_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![]),
-                meta: vec![],
+                assets: None,
+                meta: Some(vec![]),
                 reward_account: None,
             }
         ));
@@ -623,8 +644,8 @@ fn channel_censoring() {
             Origin::signed(FIRST_CURATOR_ORIGIN),
             ContentActor::Curator(group_id, FIRST_CURATOR_ID),
             ChannelCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![]),
-                meta: vec![],
+                assets: None,
+                meta: Some(vec![]),
                 reward_account: None,
             }
         ));

+ 9 - 53
runtime-modules/content/src/tests/mock.rs

@@ -153,10 +153,8 @@ parameter_types! {
 
 impl membership::Trait for Test {
     type Event = MetaEvent;
-    type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
-    type ActorId = u64;
     type ScreenedMemberMaxInitialBalance = ();
 }
 
@@ -223,7 +221,6 @@ impl storage::Trait for Test {
     type DistributionBucketFamilyId = u64;
     type DistributionBucketOperatorId = u64;
     type ChannelId = u64;
-    type MaxNumberOfDataObjectsPerBag = MaxNumberOfDataObjectsPerBag;
     type DataObjectDeletionPrize = DataObjectDeletionPrize;
     type BlacklistSizeLimit = BlacklistSizeLimit;
     type ModuleId = StorageModuleId;
@@ -360,6 +357,9 @@ impl Trait for Test {
 
     /// The maximum number of curators per group constraint
     type MaxNumberOfCuratorsPerGroup = MaxNumberOfCuratorsPerGroup;
+
+    /// The data object used in storage
+    type DataObjectStorage = storage::Module<Self>;
 }
 
 pub type System = frame_system::Module<Test>;
@@ -447,10 +447,6 @@ pub fn create_channel_mock(
     );
 
     if result.is_ok() {
-        let num_assets = match params.assets.clone() {
-            NewAssets::<Test>::Urls(v) => v.len() as u64,
-            NewAssets::<Test>::Upload(c) => c.object_creation_list.len() as u64,
-        };
         let owner = Content::actor_to_channel_owner(&actor).unwrap();
 
         assert_eq!(
@@ -463,7 +459,6 @@ pub fn create_channel_mock(
                     is_censored: false,
                     reward_account: params.reward_account,
                     deletion_prize_source_account_id: sender,
-                    num_assets: num_assets,
                     num_videos: 0,
                 },
                 params.clone(),
@@ -486,16 +481,12 @@ pub fn update_channel_mock(
             Origin::signed(sender),
             actor.clone(),
             channel_id.clone(),
-            params.clone()
+            params.clone(),
         ),
         result.clone(),
     );
 
     if result.is_ok() {
-        let maybe_num_assets = params.assets.clone().map_or(None, |assets| match assets {
-            NewAssets::<Test>::Urls(v) => Some(v.len() as u64),
-            NewAssets::<Test>::Upload(c) => Some(c.object_creation_list.len() as u64),
-        });
         assert_eq!(
             System::events().last().unwrap().event,
             MetaEvent::content(RawEvent::ChannelUpdated(
@@ -506,7 +497,6 @@ pub fn update_channel_mock(
                     is_censored: channel_pre.is_censored,
                     reward_account: channel_pre.reward_account.clone(),
                     deletion_prize_source_account_id: sender,
-                    num_assets: channel_pre.num_assets + maybe_num_assets.unwrap_or(0),
                     num_videos: channel_pre.num_videos,
                 },
                 params.clone(),
@@ -515,57 +505,23 @@ pub fn update_channel_mock(
     }
 }
 
-pub fn delete_channel_assets_mock(
+pub fn delete_channel_mock(
     sender: u64,
     actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
     channel_id: ChannelId,
-    assets: BTreeSet<<Test as storage::Trait>::DataObjectId>,
+    objects_num: u64,
     result: DispatchResult,
 ) {
-    let channel_pre = ChannelById::<Test>::get(channel_id.clone());
-
     assert_eq!(
-        Content::remove_channel_assets(
+        Content::delete_channel(
             Origin::signed(sender),
             actor.clone(),
             channel_id.clone(),
-            assets.clone(),
+            objects_num,
         ),
         result.clone(),
     );
 
-    if result.is_ok() {
-        let num_assets_removed = assets.len();
-        assert_eq!(
-            System::events().last().unwrap().event,
-            MetaEvent::content(RawEvent::ChannelAssetsRemoved(
-                actor.clone(),
-                channel_id,
-                assets.clone(),
-                ChannelRecord {
-                    owner: channel_pre.owner.clone(),
-                    is_censored: channel_pre.is_censored,
-                    reward_account: channel_pre.reward_account.clone(),
-                    deletion_prize_source_account_id: sender,
-                    num_assets: channel_pre.num_assets - (num_assets_removed as u64),
-                    num_videos: channel_pre.num_videos,
-                },
-            ))
-        );
-    }
-}
-
-pub fn delete_channel_mock(
-    sender: u64,
-    actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
-    channel_id: ChannelId,
-    result: DispatchResult,
-) {
-    assert_eq!(
-        Content::delete_channel(Origin::signed(sender), actor.clone(), channel_id.clone()),
-        result.clone(),
-    );
-
     if result.is_ok() {
         assert_eq!(
             System::events().last().unwrap().event,
@@ -625,7 +581,7 @@ pub fn update_video_mock(
             Origin::signed(sender),
             actor.clone(),
             video_id.clone(),
-            params.clone()
+            params.clone(),
         ),
         result.clone(),
     );

+ 54 - 33
runtime-modules/content/src/tests/videos.rs

@@ -14,8 +14,8 @@ fn create_member_channel() -> ChannelId {
         Origin::signed(FIRST_MEMBER_ORIGIN),
         ContentActor::Member(FIRST_MEMBER_ID),
         ChannelCreationParametersRecord {
-            assets: NewAssets::<Test>::Urls(vec![]),
-            meta: vec![],
+            assets: None,
+            meta: Some(vec![]),
             reward_account: None,
         }
     ));
@@ -40,15 +40,15 @@ fn video_creation_successful() {
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![]),
-                meta: vec![],
+                assets: None,
+                meta: Some(vec![]),
                 reward_account: None,
             },
             Ok(()),
         );
 
         let params = VideoCreationParametersRecord {
-            assets: NewAssets::<Test>::Upload(CreationUploadParameters {
+            assets: Some(StorageAssetsRecord {
                 object_creation_list: vec![
                     DataObjectCreationParameters {
                         size: 3,
@@ -65,7 +65,7 @@ fn video_creation_successful() {
                 ],
                 expected_data_size_fee: storage::DataObjectPerMegabyteFee::<Test>::get(),
             }),
-            meta: b"test".to_vec(),
+            meta: Some(b"test".to_vec()),
         };
 
         create_video_mock(
@@ -94,15 +94,16 @@ fn video_update_successful() {
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
             ChannelCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![]),
-                meta: vec![],
+                assets: None,
+                meta: Some(vec![]),
                 reward_account: None,
             },
             Ok(()),
         );
 
+        // create video with 3 assets
         let params = VideoCreationParametersRecord {
-            assets: NewAssets::<Test>::Upload(CreationUploadParameters {
+            assets: Some(StorageAssetsRecord {
                 object_creation_list: vec![
                     DataObjectCreationParameters {
                         size: 3,
@@ -119,11 +120,13 @@ fn video_update_successful() {
                 ],
                 expected_data_size_fee: storage::DataObjectPerMegabyteFee::<Test>::get(),
             }),
-            meta: b"test".to_vec(),
+            meta: Some(b"test".to_vec()),
         };
 
         let video_id = Content::next_video_id();
 
+        let first_obj_id = Storage::<Test>::next_data_object_id();
+
         create_video_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
@@ -132,17 +135,21 @@ fn video_update_successful() {
             Ok(()),
         );
 
+        // add 1 asset
         let update_params = VideoUpdateParametersRecord {
-            assets: Some(NewAssets::<Test>::Upload(CreationUploadParameters {
+            assets_to_upload: Some(StorageAssetsRecord {
                 object_creation_list: vec![DataObjectCreationParameters {
                     size: 3,
                     ipfs_content_id: b"first".to_vec(),
                 }],
                 expected_data_size_fee: storage::DataObjectPerMegabyteFee::<Test>::get(),
-            })),
+            }),
             new_meta: None,
+            assets_to_remove: BTreeSet::new(),
         };
 
+        let last_obj_id = Storage::<Test>::next_data_object_id();
+
         update_video_mock(
             FIRST_MEMBER_ORIGIN,
             ContentActor::Member(FIRST_MEMBER_ID),
@@ -150,6 +157,19 @@ fn video_update_successful() {
             update_params,
             Ok(()),
         );
+
+        // remove all assets from the channel the video is in
+        update_video_mock(
+            FIRST_MEMBER_ORIGIN,
+            ContentActor::Member(FIRST_MEMBER_ID),
+            video_id,
+            VideoUpdateParametersRecord {
+                assets_to_upload: None,
+                new_meta: None,
+                assets_to_remove: (first_obj_id..last_obj_id).collect::<BTreeSet<_>>(),
+            },
+            Ok(()),
+        );
     })
 }
 
@@ -166,8 +186,8 @@ fn member_can_create_videos() {
             ContentActor::Member(FIRST_MEMBER_ID),
             channel_id,
             VideoCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![vec![b"https://somewhere.com/".to_vec()]]),
-                meta: b"metablob".to_vec(),
+                assets: None,
+                meta: None,
             }
         ));
 
@@ -178,8 +198,8 @@ fn member_can_create_videos() {
                 channel_id,
                 video_id,
                 VideoCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![vec![b"https://somewhere.com/".to_vec()]]),
-                    meta: b"metablob".to_vec(),
+                    assets: None,
+                    meta: None,
                 }
             ))
         );
@@ -194,11 +214,10 @@ fn member_can_create_videos() {
             ContentActor::Member(FIRST_MEMBER_ID),
             video_id,
             VideoUpdateParametersRecord {
-                assets: Some(NewAssets::<Test>::Urls(vec![vec![
-                    b"https://somewhere-else.com/".to_vec()
-                ]])),
-                new_meta: Some(b"newmetablob".to_vec()),
-            }
+                assets_to_upload: None,
+                new_meta: None,
+                assets_to_remove: BTreeSet::new(),
+            },
         ));
 
         assert_eq!(
@@ -207,10 +226,9 @@ fn member_can_create_videos() {
                 ContentActor::Member(FIRST_MEMBER_ID),
                 video_id,
                 VideoUpdateParametersRecord {
-                    assets: Some(NewAssets::<Test>::Urls(vec![vec![
-                        b"https://somewhere-else.com/".to_vec()
-                    ]])),
-                    new_meta: Some(b"newmetablob".to_vec()),
+                    assets_to_upload: None,
+                    new_meta: None,
+                    assets_to_remove: BTreeSet::new(),
                 }
             ))
         );
@@ -222,8 +240,8 @@ fn member_can_create_videos() {
                 ContentActor::Member(SECOND_MEMBER_ID),
                 channel_id,
                 VideoCreationParametersRecord {
-                    assets: NewAssets::<Test>::Urls(vec![]),
-                    meta: vec![],
+                    assets: None,
+                    meta: None,
                 }
             ),
             Error::<Test>::ActorNotAuthorized
@@ -236,9 +254,10 @@ fn member_can_create_videos() {
                 ContentActor::Member(SECOND_MEMBER_ID),
                 video_id,
                 VideoUpdateParametersRecord {
-                    assets: None,
+                    assets_to_upload: None,
                     new_meta: None,
-                }
+                    assets_to_remove: BTreeSet::new(),
+                },
             ),
             Error::<Test>::ActorNotAuthorized
         );
@@ -248,7 +267,8 @@ fn member_can_create_videos() {
             Content::delete_video(
                 Origin::signed(SECOND_MEMBER_ORIGIN),
                 ContentActor::Member(SECOND_MEMBER_ID),
-                video_id
+                video_id,
+                BTreeSet::new(),
             ),
             Error::<Test>::ActorNotAuthorized
         );
@@ -257,7 +277,8 @@ fn member_can_create_videos() {
         assert_ok!(Content::delete_video(
             Origin::signed(FIRST_MEMBER_ORIGIN),
             ContentActor::Member(FIRST_MEMBER_ID),
-            video_id
+            video_id,
+            BTreeSet::new(),
         ));
 
         assert_eq!(
@@ -283,8 +304,8 @@ fn curators_can_censor_videos() {
             ContentActor::Member(FIRST_MEMBER_ID),
             channel_id,
             VideoCreationParametersRecord {
-                assets: NewAssets::<Test>::Urls(vec![vec![b"https://somewhere.com/".to_vec()]]),
-                meta: b"metablob".to_vec(),
+                assets: None,
+                meta: None,
             }
         ));
 

+ 1 - 1
runtime-modules/forum/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-forum'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 1 - 1
runtime-modules/governance/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-governance'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 5 - 2
runtime-modules/governance/src/mock.rs

@@ -76,12 +76,15 @@ parameter_types! {
     pub const ScreenedMemberMaxInitialBalance: u64 = 500;
 }
 
+impl common::MembershipTypes for Test {
+    type MemberId = u64;
+    type ActorId = u64;
+}
+
 impl membership::Trait for Test {
     type Event = ();
-    type MemberId = u64;
     type SubscriptionId = u32;
     type PaidTermId = u32;
-    type ActorId = u32;
     type ScreenedMemberMaxInitialBalance = ScreenedMemberMaxInitialBalance;
 }
 impl minting::Trait for Test {

+ 1 - 1
runtime-modules/hiring/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-hiring'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 1 - 1
runtime-modules/membership/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-membership'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 22 - 40
runtime-modules/membership/src/lib.rs

@@ -23,18 +23,11 @@ use sp_std::vec;
 use sp_std::vec::Vec;
 
 use common::currency::{BalanceOf, GovernanceCurrency};
-pub trait Trait: frame_system::Trait + GovernanceCurrency + pallet_timestamp::Trait {
+pub trait Trait:
+    frame_system::Trait + GovernanceCurrency + pallet_timestamp::Trait + common::MembershipTypes
+{
     type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
 
-    type MemberId: Parameter
-        + Member
-        + BaseArithmetic
-        + Codec
-        + Default
-        + Copy
-        + MaybeSerialize
-        + PartialEq;
-
     type PaidTermId: Parameter
         + Member
         + BaseArithmetic
@@ -53,17 +46,6 @@ pub trait Trait: frame_system::Trait + GovernanceCurrency + pallet_timestamp::Tr
         + MaybeSerialize
         + PartialEq;
 
-    /// Describes the common type for the working group members (workers).
-    type ActorId: Parameter
-        + Member
-        + BaseArithmetic
-        + Codec
-        + Default
-        + Copy
-        + MaybeSerialize
-        + PartialEq
-        + Ord;
-
     /// The maximum amount of initial funds that may be endowed to new members added by
     /// screening authority. If set to zero, no initial balance can be given.
     type ScreenedMemberMaxInitialBalance: Get<BalanceOf<Self>>;
@@ -246,13 +228,13 @@ decl_storage! {
 decl_event! {
     pub enum Event<T> where
       <T as frame_system::Trait>::AccountId,
-      <T as Trait>::MemberId,
+      <T as common::MembershipTypes>::MemberId,
       <T as Trait>::PaidTermId,
     {
         MemberRegistered(MemberId, AccountId, EntryMethod<PaidTermId, AccountId>),
-        MemberUpdatedAboutText(MemberId),
-        MemberUpdatedAvatar(MemberId),
-        MemberUpdatedHandle(MemberId),
+        MemberUpdatedAboutText(MemberId, Vec<u8>),
+        MemberUpdatedAvatar(MemberId, Vec<u8>),
+        MemberUpdatedHandle(MemberId, Vec<u8>),
         MemberSetRootAccount(MemberId, AccountId),
         MemberSetControllerAccount(MemberId, AccountId),
     }
@@ -312,7 +294,7 @@ decl_module! {
 
             ensure!(membership.controller_account == sender, Error::<T>::ControllerAccountRequired);
 
-            Self::_change_member_about_text(member_id, &text)?;
+            Self::_change_member_about_text(member_id, text)?;
         }
 
         /// Change member's avatar
@@ -324,7 +306,7 @@ decl_module! {
 
             ensure!(membership.controller_account == sender, Error::<T>::ControllerAccountRequired);
 
-            Self::_change_member_avatar(member_id, &uri)?;
+            Self::_change_member_avatar(member_id, uri)?;
         }
 
         /// Change member's handle. Will ensure new handle is unique and old one will be available
@@ -356,10 +338,10 @@ decl_module! {
             ensure!(membership.controller_account == sender, Error::<T>::ControllerAccountRequired);
 
             if let Some(uri) = avatar_uri {
-                Self::_change_member_avatar(member_id, &uri)?;
+                Self::_change_member_avatar(member_id, uri)?;
             }
             if let Some(about) = about {
-                Self::_change_member_about_text(member_id, &about)?;
+                Self::_change_member_about_text(member_id, about)?;
             }
             if let Some(handle) = handle {
                 Self::_change_member_handle(member_id, handle)?;
@@ -588,8 +570,8 @@ impl<T: Trait> Module<T> {
         Ok(())
     }
 
-    fn validate_text(text: &[u8]) -> Vec<u8> {
-        let mut text = text.to_owned();
+    fn validate_text(text: Vec<u8>) -> Vec<u8> {
+        let mut text = text;
         text.truncate(Self::max_about_text_length() as usize);
         text
     }
@@ -612,7 +594,7 @@ impl<T: Trait> Module<T> {
         let handle = handle.ok_or(Error::<T>::HandleMustBeProvidedDuringRegistration)?;
         Self::validate_handle(&handle)?;
 
-        let about = Self::validate_text(&about.unwrap_or_default());
+        let about = Self::validate_text(about.unwrap_or_default());
         let avatar_uri = avatar_uri.unwrap_or_default();
         Self::validate_avatar(&avatar_uri)?;
 
@@ -662,20 +644,20 @@ impl<T: Trait> Module<T> {
         Ok(new_member_id)
     }
 
-    fn _change_member_about_text(id: T::MemberId, text: &[u8]) -> DispatchResult {
+    fn _change_member_about_text(id: T::MemberId, text: Vec<u8>) -> DispatchResult {
         let mut membership = Self::ensure_membership(id)?;
         let text = Self::validate_text(text);
-        membership.about = text;
-        Self::deposit_event(RawEvent::MemberUpdatedAboutText(id));
+        membership.about = text.clone();
+        Self::deposit_event(RawEvent::MemberUpdatedAboutText(id, text));
         <MembershipById<T>>::insert(id, membership);
         Ok(())
     }
 
-    fn _change_member_avatar(id: T::MemberId, uri: &[u8]) -> DispatchResult {
+    fn _change_member_avatar(id: T::MemberId, uri: Vec<u8>) -> DispatchResult {
         let mut membership = Self::ensure_membership(id)?;
-        Self::validate_avatar(uri)?;
+        Self::validate_avatar(&uri)?;
         membership.avatar_uri = uri.to_owned();
-        Self::deposit_event(RawEvent::MemberUpdatedAvatar(id));
+        Self::deposit_event(RawEvent::MemberUpdatedAvatar(id, uri));
         <MembershipById<T>>::insert(id, membership);
         Ok(())
     }
@@ -686,8 +668,8 @@ impl<T: Trait> Module<T> {
         Self::ensure_unique_handle(&handle)?;
         <MemberIdByHandle<T>>::remove(&membership.handle);
         <MemberIdByHandle<T>>::insert(handle.clone(), id);
-        membership.handle = handle;
-        Self::deposit_event(RawEvent::MemberUpdatedHandle(id));
+        membership.handle = handle.clone();
+        Self::deposit_event(RawEvent::MemberUpdatedHandle(id, handle));
         <MembershipById<T>>::insert(id, membership);
         Ok(())
     }

+ 5 - 2
runtime-modules/membership/src/mock.rs

@@ -86,12 +86,15 @@ parameter_types! {
     pub const ScreenedMemberMaxInitialBalance: u64 = 500;
 }
 
+impl common::MembershipTypes for Test {
+    type MemberId = u64;
+    type ActorId = u64;
+}
+
 impl Trait for Test {
     type Event = ();
-    type MemberId = u64;
     type PaidTermId = u32;
     type SubscriptionId = u32;
-    type ActorId = u32;
     type ScreenedMemberMaxInitialBalance = ScreenedMemberMaxInitialBalance;
 }
 

+ 1 - 1
runtime-modules/memo/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-memo'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 1 - 1
runtime-modules/proposals/codex/src/lib.rs

@@ -181,7 +181,7 @@ pub type NegativeImbalance<T> = <<T as stake::Trait>::Currency as Currency<
     <T as frame_system::Trait>::AccountId,
 >>::NegativeImbalance;
 
-type MemberId<T> = <T as membership::Trait>::MemberId;
+type MemberId<T> = <T as common::MembershipTypes>::MemberId;
 
 decl_error! {
     /// Codex module predefined errors

+ 5 - 2
runtime-modules/proposals/codex/src/tests/mock.rs

@@ -50,12 +50,15 @@ parameter_types! {
     pub const ScreenedMemberMaxInitialBalance: u64 = 500;
 }
 
+impl common::MembershipTypes for Test {
+    type MemberId = u64;
+    type ActorId = u64;
+}
+
 impl membership::Trait for Test {
     type Event = ();
-    type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
-    type ActorId = u64;
     type ScreenedMemberMaxInitialBalance = ScreenedMemberMaxInitialBalance;
 }
 

+ 1 - 1
runtime-modules/proposals/discussion/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-proposals-discussion'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 1 - 1
runtime-modules/proposals/discussion/src/lib.rs

@@ -59,7 +59,7 @@ use sp_std::vec::Vec;
 use common::origin::ActorOriginValidator;
 use types::{DiscussionPost, DiscussionThread, ThreadCounter};
 
-type MemberId<T> = <T as membership::Trait>::MemberId;
+type MemberId<T> = <T as common::MembershipTypes>::MemberId;
 
 decl_event!(
     /// Proposals engine events

+ 5 - 2
runtime-modules/proposals/discussion/src/tests/mock.rs

@@ -77,12 +77,15 @@ parameter_types! {
     pub const ScreenedMemberMaxInitialBalance: u64 = 500;
 }
 
+impl common::MembershipTypes for Test {
+    type MemberId = u64;
+    type ActorId = u64;
+}
+
 impl membership::Trait for Test {
     type Event = TestEvent;
-    type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
-    type ActorId = u64;
     type ScreenedMemberMaxInitialBalance = ScreenedMemberMaxInitialBalance;
 }
 

+ 1 - 1
runtime-modules/proposals/engine/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-proposals-engine'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 1 - 1
runtime-modules/proposals/engine/src/lib.rs

@@ -143,7 +143,7 @@ use sp_std::vec::Vec;
 
 use common::origin::ActorOriginValidator;
 
-type MemberId<T> = <T as membership::Trait>::MemberId;
+type MemberId<T> = <T as common::MembershipTypes>::MemberId;
 
 /// Proposals engine trait.
 pub trait Trait:

+ 5 - 2
runtime-modules/proposals/engine/src/tests/mock/mod.rs

@@ -90,12 +90,15 @@ parameter_types! {
     pub const ScreenedMemberMaxInitialBalance: u64 = 500;
 }
 
+impl common::MembershipTypes for Test {
+    type MemberId = u64;
+    type ActorId = u64;
+}
+
 impl membership::Trait for Test {
     type Event = TestEvent;
-    type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
-    type ActorId = u64;
     type ScreenedMemberMaxInitialBalance = ScreenedMemberMaxInitialBalance;
 }
 

+ 1 - 1
runtime-modules/recurring-reward/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-recurring-reward'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 1 - 1
runtime-modules/stake/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-stake'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 37 - 26
runtime-modules/storage/src/lib.rs

@@ -99,7 +99,6 @@
 //! - create_dynamic_bag
 //!
 //! ### Pallet constants
-//! - MaxNumberOfDataObjectsPerBag
 //! - DataObjectDeletionPrize
 //! - BlacklistSizeLimit
 //! - StorageBucketsPerBagValueConstraint
@@ -211,6 +210,12 @@ pub trait DataObjectStorage<T: Trait> {
         bag_id: &DynamicBagId<T>,
         deletion_prize: &Option<DynamicBagDeletionPrize<T>>,
     ) -> DispatchResult;
+
+    /// Checks if a bag does exists and returns it. Static Always exists
+    fn ensure_bag_exists(bag_id: &BagId<T>) -> Result<Bag<T>, DispatchError>;
+
+    /// Get all objects id in a bag, without checking its existence
+    fn get_data_objects_id(bag_id: &BagId<T>) -> BTreeSet<T::DataObjectId>;
 }
 
 /// Storage trait.
@@ -283,9 +288,6 @@ pub trait Trait: frame_system::Trait + balances::Trait + membership::Trait {
         + MaybeSerialize
         + PartialEq;
 
-    /// Defines max number of data objects per bag.
-    type MaxNumberOfDataObjectsPerBag: Get<u64>;
-
     /// Defines a prize for a data object deletion.
     type DataObjectDeletionPrize: Get<BalanceOf<Self>>;
 
@@ -452,10 +454,10 @@ pub type Cid = Vec<u8>;
 type Balances<T> = balances::Module<T>;
 
 /// Alias for the member id.
-pub type MemberId<T> = <T as membership::Trait>::MemberId;
+pub type MemberId<T> = <T as common::MembershipTypes>::MemberId;
 
 /// Type identifier for worker role, which must be same as membership actor identifier
-pub type WorkerId<T> = <T as membership::Trait>::ActorId;
+pub type WorkerId<T> = <T as common::MembershipTypes>::ActorId;
 
 /// Balance alias for `balances` module.
 pub type BalanceOf<T> = <T as balances::Trait>::Balance;
@@ -1012,7 +1014,8 @@ decl_event! {
         /// Params
         /// - data objects IDs
         /// - initial uploading parameters
-        DataObjectsUploaded(Vec<DataObjectId>, UploadParameters),
+        /// - deletion prize for objects
+        DataObjectsUploaded(Vec<DataObjectId>, UploadParameters, Balance),
 
         /// Emits on setting the storage operator metadata.
         /// Params
@@ -1109,7 +1112,14 @@ decl_event! {
         /// Params
         /// - dynamic bag ID
         /// - optional DynamicBagDeletionPrize instance
-        DynamicBagCreated(DynamicBagId, Option<DynamicBagDeletionPrizeRecord<AccountId, Balance>>),
+        /// - assigned storage buckets' IDs
+        /// - assigned distribution buckets' IDs
+        DynamicBagCreated(
+            DynamicBagId,
+            Option<DynamicBagDeletionPrizeRecord<AccountId, Balance>>,
+            BTreeSet<StorageBucketId>,
+            BTreeSet<DistributionBucketId>,
+        ),
 
         /// Emits on changing the voucher for a storage bucket.
         /// Params
@@ -1308,9 +1318,6 @@ decl_error! {
         /// Upload data error: invalid deletion prize source account.
         InvalidDeletionPrizeSourceAccount,
 
-        /// Upload data error: data objects per bag limit exceeded.
-        DataObjectsPerBagLimitExceeded,
-
         /// Invalid storage provider for bucket.
         InvalidStorageProvider,
 
@@ -1451,9 +1458,6 @@ decl_module! {
         /// Predefined errors.
         type Error = Error<T>;
 
-        /// Exports const - max number of data objects per bag.
-        const MaxNumberOfDataObjectsPerBag: u64 = T::MaxNumberOfDataObjectsPerBag::get();
-
         /// Exports const - a prize for a data object deletion.
         const DataObjectDeletionPrize: BalanceOf<T> = T::DataObjectDeletionPrize::get();
 
@@ -2574,6 +2578,7 @@ impl<T: Trait> DataObjectStorage<T> for Module<T> {
         Self::deposit_event(RawEvent::DataObjectsUploaded(
             data.data_objects_map.keys().cloned().collect(),
             params,
+            T::DataObjectDeletionPrize::get(),
         ));
 
         Ok(())
@@ -2722,9 +2727,9 @@ impl<T: Trait> DataObjectStorage<T> for Module<T> {
         let distribution_buckets = Self::pick_distribution_buckets_for_dynamic_bag(bag_type);
 
         let bag = Bag::<T> {
-            stored_by: storage_buckets,
+            stored_by: storage_buckets.clone(),
             deletion_prize: deletion_prize.clone().map(|dp| dp.prize),
-            distributed_by: distribution_buckets,
+            distributed_by: distribution_buckets.clone(),
             ..Default::default()
         };
 
@@ -2732,7 +2737,12 @@ impl<T: Trait> DataObjectStorage<T> for Module<T> {
 
         <Bags<T>>::insert(&bag_id, bag);
 
-        Self::deposit_event(RawEvent::DynamicBagCreated(dynamic_bag_id, deletion_prize));
+        Self::deposit_event(RawEvent::DynamicBagCreated(
+            dynamic_bag_id,
+            deletion_prize,
+            storage_buckets,
+            distribution_buckets,
+        ));
 
         Ok(())
     }
@@ -2743,6 +2753,16 @@ impl<T: Trait> DataObjectStorage<T> for Module<T> {
     ) -> DispatchResult {
         Self::validate_create_dynamic_bag_params(bag_id, deletion_prize)
     }
+
+    fn ensure_bag_exists(bag_id: &BagId<T>) -> Result<Bag<T>, DispatchError> {
+        Self::ensure_bag_exists(bag_id)
+    }
+
+    fn get_data_objects_id(bag_id: &BagId<T>) -> BTreeSet<T::DataObjectId> {
+        DataObjectsById::<T>::iter_prefix(&bag_id)
+            .map(|x| x.0)
+            .collect()
+    }
 }
 
 impl<T: Trait> Module<T> {
@@ -3211,15 +3231,6 @@ impl<T: Trait> Module<T> {
 
         let bag = Self::ensure_bag_exists(&params.bag_id)?;
 
-        let new_objects_number: u64 = params.object_creation_list.len().saturated_into();
-        let total_possible_data_objects_number: u64 = new_objects_number + bag.objects_number;
-
-        // Check bag capacity.
-        ensure!(
-            total_possible_data_objects_number <= T::MaxNumberOfDataObjectsPerBag::get(),
-            Error::<T>::DataObjectsPerBagLimitExceeded
-        );
-
         // Check data size fee change.
         ensure!(
             params.expected_data_size_fee == Self::data_object_per_mega_byte_fee(),

+ 5 - 4
runtime-modules/storage/src/tests/mocks.rs

@@ -50,7 +50,6 @@ impl balances::Trait for Test {
 }
 
 parameter_types! {
-    pub const MaxNumberOfDataObjectsPerBag: u64 = 4;
     pub const MaxDistributionBucketFamilyNumber: u64 = 4;
     pub const MaxDistributionBucketNumberPerFamily: u64 = 10;
     pub const DataObjectDeletionPrize: u64 = 10;
@@ -85,7 +84,6 @@ impl crate::Trait for Test {
     type DistributionBucketFamilyId = u64;
     type DistributionBucketOperatorId = u64;
     type ChannelId = u64;
-    type MaxNumberOfDataObjectsPerBag = MaxNumberOfDataObjectsPerBag;
     type DataObjectDeletionPrize = DataObjectDeletionPrize;
     type BlacklistSizeLimit = BlacklistSizeLimit;
     type ModuleId = StorageModuleId;
@@ -189,12 +187,15 @@ parameter_types! {
     pub const ScreenedMemberMaxInitialBalance: u64 = 5000;
 }
 
+impl common::MembershipTypes for Test {
+    type MemberId = u64;
+    type ActorId = u64;
+}
+
 impl membership::Trait for Test {
     type Event = TestEvent;
-    type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
-    type ActorId = u64;
     type ScreenedMemberMaxInitialBalance = ();
 }
 

+ 13 - 28
runtime-modules/storage/src/tests/mod.rs

@@ -7,7 +7,6 @@ use frame_support::dispatch::DispatchError;
 use frame_support::traits::Currency;
 use frame_support::{StorageDoubleMap, StorageMap, StorageValue};
 use frame_system::RawOrigin;
-use sp_runtime::SaturatedConversion;
 use sp_std::collections::btree_map::BTreeMap;
 use sp_std::collections::btree_set::BTreeSet;
 use sp_std::iter::{repeat, FromIterator};
@@ -25,8 +24,8 @@ use mocks::{
     build_test_externalities, Balances, DataObjectDeletionPrize,
     DefaultChannelDynamicBagNumberOfStorageBuckets, DefaultMemberDynamicBagNumberOfStorageBuckets,
     InitialStorageBucketsNumberForDynamicBag, MaxDataObjectSize, MaxDistributionBucketFamilyNumber,
-    MaxDistributionBucketNumberPerFamily, MaxNumberOfDataObjectsPerBag, MaxRandomIterationNumber,
-    Storage, Test, ANOTHER_DISTRIBUTION_PROVIDER_ID, ANOTHER_STORAGE_PROVIDER_ID,
+    MaxDistributionBucketNumberPerFamily, MaxRandomIterationNumber, Storage, Test,
+    ANOTHER_DISTRIBUTION_PROVIDER_ID, ANOTHER_STORAGE_PROVIDER_ID,
     DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID, DEFAULT_DISTRIBUTION_PROVIDER_ID,
     DEFAULT_MEMBER_ACCOUNT_ID, DEFAULT_MEMBER_ID, DEFAULT_STORAGE_PROVIDER_ACCOUNT_ID,
     DEFAULT_STORAGE_PROVIDER_ID, DISTRIBUTION_WG_LEADER_ACCOUNT_ID, STORAGE_WG_LEADER_ACCOUNT_ID,
@@ -712,6 +711,7 @@ fn upload_succeeded() {
         EventFixture::assert_last_crate_event(RawEvent::DataObjectsUploaded(
             vec![data_object_id],
             upload_params,
+            DataObjectDeletionPrize::get(),
         ));
     });
 }
@@ -1013,25 +1013,6 @@ fn upload_fails_with_empty_object_cid() {
     });
 }
 
-#[test]
-fn upload_fails_with_max_data_object_size_exceeded() {
-    build_test_externalities().execute_with(|| {
-        let max_object_size = MaxNumberOfDataObjectsPerBag::get();
-        let invalid_object_number: u8 = (max_object_size + 1).saturated_into();
-
-        let upload_params = UploadParameters::<Test> {
-            bag_id: BagId::<Test>::Static(StaticBagId::Council),
-            deletion_prize_source_account_id: DEFAULT_MEMBER_ACCOUNT_ID,
-            object_creation_list: create_data_object_candidates(1, invalid_object_number),
-            expected_data_size_fee: Storage::data_object_per_mega_byte_fee(),
-        };
-
-        UploadFixture::default()
-            .with_params(upload_params)
-            .call_and_assert(Err(Error::<Test>::DataObjectsPerBagLimitExceeded.into()));
-    });
-}
-
 #[test]
 fn upload_fails_with_insufficient_balance_for_deletion_prize() {
     build_test_externalities().execute_with(|| {
@@ -3098,19 +3079,16 @@ fn create_dynamic_bag_succeeded() {
             .with_deletion_prize(deletion_prize.clone())
             .call_and_assert(Ok(()));
 
-        EventFixture::assert_last_crate_event(RawEvent::DynamicBagCreated(
-            dynamic_bag_id.clone(),
-            Some(deletion_prize),
-        ));
-
         let bag = Storage::dynamic_bag(&dynamic_bag_id);
+
         // Check that IDs are within possible range.
         assert!(bag
             .stored_by
             .iter()
             .all(|id| { *id < Storage::next_storage_bucket_id() }));
 
-        let creation_policy = Storage::get_dynamic_bag_creation_policy(dynamic_bag_id.into());
+        let creation_policy =
+            Storage::get_dynamic_bag_creation_policy(dynamic_bag_id.clone().into());
         assert_eq!(
             bag.stored_by.len(),
             creation_policy.number_of_storage_buckets as usize
@@ -3127,6 +3105,13 @@ fn create_dynamic_bag_succeeded() {
             Balances::usable_balance(&<StorageTreasury<Test>>::module_account_id()),
             deletion_prize_value
         );
+
+        EventFixture::assert_last_crate_event(RawEvent::DynamicBagCreated(
+            dynamic_bag_id,
+            Some(deletion_prize),
+            BTreeSet::from_iter(bag.stored_by),
+            BTreeSet::from_iter(bag.distributed_by),
+        ));
     });
 }
 

+ 1 - 1
runtime-modules/token-minting/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-token-mint'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 1 - 1
runtime-modules/working-group/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-working-group'
-version = '3.1.1'
+version = '3.2.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 2 - 2
runtime-modules/working-group/src/lib.rs

@@ -78,7 +78,7 @@ pub use types::{
 pub type StakeId<T> = <T as stake::Trait>::StakeId;
 
 /// Member identifier in membership::member module
-pub type MemberId<T> = <T as membership::Trait>::MemberId;
+pub type MemberId<T> = <T as common::MembershipTypes>::MemberId;
 
 /// Workaround for BTreeSet type
 pub type ApplicationIdSet<T> = BTreeSet<ApplicationId<T>>;
@@ -109,7 +109,7 @@ pub type NegativeImbalance<T> = <<T as stake::Trait>::Currency as Currency<
 pub type ApplicationIdToWorkerIdMap<T> = BTreeMap<ApplicationId<T>, WorkerId<T>>;
 
 /// Type identifier for worker role, which must be same as membership actor identifier
-pub type WorkerId<T> = <T as membership::Trait>::ActorId;
+pub type WorkerId<T> = <T as common::MembershipTypes>::ActorId;
 
 /// Alias for the application id from the hiring module.
 pub type HiringApplicationId<T> = <T as hiring::Trait>::ApplicationId;

+ 5 - 2
runtime-modules/working-group/src/tests/mock.rs

@@ -101,12 +101,15 @@ parameter_types! {
     pub const ScreenedMemberMaxInitialBalance: u64 = 500;
 }
 
+impl common::MembershipTypes for Test {
+    type MemberId = u64;
+    type ActorId = u64;
+}
+
 impl membership::Trait for Test {
     type Event = TestEvent;
-    type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
-    type ActorId = u64;
     type ScreenedMemberMaxInitialBalance = ScreenedMemberMaxInitialBalance;
 }
 

+ 1 - 1
runtime/src/integration/proposals/membership_origin_validator.rs

@@ -6,7 +6,7 @@ use common::origin::ActorOriginValidator;
 use frame_system::ensure_signed;
 
 /// Member of the Joystream organization
-pub type MemberId<T> = <T as membership::Trait>::MemberId;
+pub type MemberId<T> = <T as common::MembershipTypes>::MemberId;
 
 /// Default membership actor origin validator.
 pub struct MembershipOriginValidator<T> {

+ 9 - 1
runtime/src/integration/proposals/proposal_encoder.rs

@@ -23,7 +23,15 @@ macro_rules! wrap_working_group_call {
             WorkingGroup::Distribution => {
                 Call::DistributionWorkingGroup($working_group_instance_call)
             }
-            WorkingGroup::Operations => Call::OperationsWorkingGroup($working_group_instance_call),
+            WorkingGroup::OperationsAlpha => {
+                Call::OperationsWorkingGroupAlpha($working_group_instance_call)
+            }
+            WorkingGroup::OperationsBeta => {
+                Call::OperationsWorkingGroupBeta($working_group_instance_call)
+            }
+            WorkingGroup::OperationsGamma => {
+                Call::OperationsWorkingGroupGamma($working_group_instance_call)
+            }
             WorkingGroup::Gateway => Call::GatewayWorkingGroup($working_group_instance_call),
         }
     }};

+ 88 - 156
runtime/src/integration/working_group.rs

@@ -2,185 +2,117 @@ use frame_support::StorageMap;
 use sp_std::marker::PhantomData;
 
 use crate::{
-    ContentWorkingGroupInstance, GatewayWorkingGroupInstance, OperationsWorkingGroupInstance,
-    StorageWorkingGroupInstance,
+    ContentWorkingGroupInstance, DistributionWorkingGroupInstance, GatewayWorkingGroupInstance,
+    OperationsWorkingGroupInstanceAlpha, OperationsWorkingGroupInstanceBeta,
+    OperationsWorkingGroupInstanceGamma, StorageWorkingGroupInstance,
 };
 use stake::{BalanceOf, NegativeImbalance};
 
+macro_rules! wg_staking_event_impl {
+    ($operation_wg_instance:ident, $operation_wg_staking_event_handler:ty) => {
+        impl<T: stake::Trait + working_group::Trait<$operation_wg_instance>>
+            stake::StakingEventsHandler<T> for $operation_wg_staking_event_handler
+        {
+            /// Unstake remaining sum back to the source_account_id
+            fn unstaked(
+                stake_id: &<T as stake::Trait>::StakeId,
+                _unstaked_amount: BalanceOf<T>,
+                remaining_imbalance: NegativeImbalance<T>,
+            ) -> NegativeImbalance<T> {
+                // Stake not related to a staked role managed by the hiring module.
+                if !hiring::ApplicationIdByStakingId::<T>::contains_key(*stake_id) {
+                return remaining_imbalance;
+            }
+
+            let hiring_application_id = hiring::ApplicationIdByStakingId::<T>::get(*stake_id);
+
+            if working_group::MemberIdByHiringApplicationId::<T, $operation_wg_instance>::contains_key(
+                hiring_application_id,
+            ) {
+                return <working_group::Module<T, $operation_wg_instance>>::refund_working_group_stake(
+                *stake_id,
+                remaining_imbalance,
+                );
+            }
+
+                remaining_imbalance
+            }
+
+            /// Empty handler for the slashing.
+            fn slashed(
+                _: &<T as stake::Trait>::StakeId,
+                _: Option<<T as stake::Trait>::SlashId>,
+                _: BalanceOf<T>,
+                _: BalanceOf<T>,
+                remaining_imbalance: NegativeImbalance<T>,
+            ) -> NegativeImbalance<T> {
+                remaining_imbalance
+            }
+        }
+    }
+}
+
 // Will be removed in the next releases.
 #[allow(clippy::upper_case_acronyms)]
 pub struct ContentDirectoryWgStakingEventsHandler<T> {
     pub marker: PhantomData<T>,
 }
 
-impl<T: stake::Trait + working_group::Trait<ContentWorkingGroupInstance>>
-    stake::StakingEventsHandler<T> for ContentDirectoryWgStakingEventsHandler<T>
-{
-    /// Unstake remaining sum back to the source_account_id
-    fn unstaked(
-        stake_id: &<T as stake::Trait>::StakeId,
-        _unstaked_amount: BalanceOf<T>,
-        remaining_imbalance: NegativeImbalance<T>,
-    ) -> NegativeImbalance<T> {
-        // Stake not related to a staked role managed by the hiring module.
-        if !hiring::ApplicationIdByStakingId::<T>::contains_key(*stake_id) {
-            return remaining_imbalance;
-        }
-
-        let hiring_application_id = hiring::ApplicationIdByStakingId::<T>::get(*stake_id);
-
-        if working_group::MemberIdByHiringApplicationId::<T, ContentWorkingGroupInstance>::contains_key(
-            hiring_application_id,
-        ) {
-            return <working_group::Module<T, ContentWorkingGroupInstance>>::refund_working_group_stake(
-				*stake_id,
-				remaining_imbalance,
-			);
-        }
-
-        remaining_imbalance
-    }
-
-    /// Empty handler for the slashing.
-    fn slashed(
-        _: &<T as stake::Trait>::StakeId,
-        _: Option<<T as stake::Trait>::SlashId>,
-        _: BalanceOf<T>,
-        _: BalanceOf<T>,
-        remaining_imbalance: NegativeImbalance<T>,
-    ) -> NegativeImbalance<T> {
-        remaining_imbalance
-    }
-}
-
 pub struct StorageWgStakingEventsHandler<T> {
     pub marker: PhantomData<T>,
 }
 
-impl<T: stake::Trait + working_group::Trait<StorageWorkingGroupInstance>>
-    stake::StakingEventsHandler<T> for StorageWgStakingEventsHandler<T>
-{
-    /// Unstake remaining sum back to the source_account_id
-    fn unstaked(
-        stake_id: &<T as stake::Trait>::StakeId,
-        _unstaked_amount: BalanceOf<T>,
-        remaining_imbalance: NegativeImbalance<T>,
-    ) -> NegativeImbalance<T> {
-        // Stake not related to a staked role managed by the hiring module.
-        if !hiring::ApplicationIdByStakingId::<T>::contains_key(*stake_id) {
-            return remaining_imbalance;
-        }
-
-        let hiring_application_id = hiring::ApplicationIdByStakingId::<T>::get(*stake_id);
-
-        if working_group::MemberIdByHiringApplicationId::<T, StorageWorkingGroupInstance>::contains_key(
-            hiring_application_id,
-        ) {
-            return <working_group::Module<T, StorageWorkingGroupInstance>>::refund_working_group_stake(
-				*stake_id,
-				remaining_imbalance,
-			);
-        }
-
-        remaining_imbalance
-    }
-
-    /// Empty handler for the slashing.
-    fn slashed(
-        _: &<T as stake::Trait>::StakeId,
-        _: Option<<T as stake::Trait>::SlashId>,
-        _: BalanceOf<T>,
-        _: BalanceOf<T>,
-        remaining_imbalance: NegativeImbalance<T>,
-    ) -> NegativeImbalance<T> {
-        remaining_imbalance
-    }
+pub struct OperationsWgStakingEventsHandlerAlpha<T> {
+    pub marker: PhantomData<T>,
 }
 
-pub struct OperationsWgStakingEventsHandler<T> {
+pub struct OperationsWgStakingEventsHandlerBeta<T> {
     pub marker: PhantomData<T>,
 }
 
-impl<T: stake::Trait + working_group::Trait<OperationsWorkingGroupInstance>>
-    stake::StakingEventsHandler<T> for OperationsWgStakingEventsHandler<T>
-{
-    /// Unstake remaining sum back to the source_account_id
-    fn unstaked(
-        stake_id: &<T as stake::Trait>::StakeId,
-        _unstaked_amount: BalanceOf<T>,
-        remaining_imbalance: NegativeImbalance<T>,
-    ) -> NegativeImbalance<T> {
-        // Stake not related to a staked role managed by the hiring module.
-        if !hiring::ApplicationIdByStakingId::<T>::contains_key(*stake_id) {
-            return remaining_imbalance;
-        }
-
-        let hiring_application_id = hiring::ApplicationIdByStakingId::<T>::get(*stake_id);
-
-        if working_group::MemberIdByHiringApplicationId::<T, OperationsWorkingGroupInstance>::contains_key(
-            hiring_application_id,
-        ) {
-            return <working_group::Module<T, OperationsWorkingGroupInstance>>::refund_working_group_stake(
-				*stake_id,
-				remaining_imbalance,
-			);
-        }
-
-        remaining_imbalance
-    }
-
-    /// Empty handler for the slashing.
-    fn slashed(
-        _: &<T as stake::Trait>::StakeId,
-        _: Option<<T as stake::Trait>::SlashId>,
-        _: BalanceOf<T>,
-        _: BalanceOf<T>,
-        remaining_imbalance: NegativeImbalance<T>,
-    ) -> NegativeImbalance<T> {
-        remaining_imbalance
-    }
+pub struct OperationsWgStakingEventsHandlerGamma<T> {
+    pub marker: PhantomData<T>,
 }
 
 pub struct GatewayWgStakingEventsHandler<T> {
     pub marker: PhantomData<T>,
 }
 
-impl<T: stake::Trait + working_group::Trait<GatewayWorkingGroupInstance>>
-    stake::StakingEventsHandler<T> for GatewayWgStakingEventsHandler<T>
-{
-    /// Unstake remaining sum back to the source_account_id
-    fn unstaked(
-        stake_id: &<T as stake::Trait>::StakeId,
-        _unstaked_amount: BalanceOf<T>,
-        remaining_imbalance: NegativeImbalance<T>,
-    ) -> NegativeImbalance<T> {
-        // Stake not related to a staked role managed by the hiring module.
-        if !hiring::ApplicationIdByStakingId::<T>::contains_key(*stake_id) {
-            return remaining_imbalance;
-        }
-
-        let hiring_application_id = hiring::ApplicationIdByStakingId::<T>::get(*stake_id);
-
-        if working_group::MemberIdByHiringApplicationId::<T, GatewayWorkingGroupInstance>::contains_key(
-            hiring_application_id,
-        ) {
-            return <working_group::Module<T, GatewayWorkingGroupInstance>>::refund_working_group_stake(
-				*stake_id,
-				remaining_imbalance,
-			);
-        }
+pub struct DistributionWgStakingEventsHandler<T> {
+    pub marker: PhantomData<T>,
+}
 
-        remaining_imbalance
-    }
+wg_staking_event_impl!(
+    ContentWorkingGroupInstance,
+    ContentDirectoryWgStakingEventsHandler<T>
+);
 
-    /// Empty handler for the slashing.
-    fn slashed(
-        _: &<T as stake::Trait>::StakeId,
-        _: Option<<T as stake::Trait>::SlashId>,
-        _: BalanceOf<T>,
-        _: BalanceOf<T>,
-        remaining_imbalance: NegativeImbalance<T>,
-    ) -> NegativeImbalance<T> {
-        remaining_imbalance
-    }
-}
+wg_staking_event_impl!(
+    StorageWorkingGroupInstance,
+    StorageWgStakingEventsHandler<T>
+);
+
+wg_staking_event_impl!(
+    GatewayWorkingGroupInstance,
+    GatewayWgStakingEventsHandler<T>
+);
+
+wg_staking_event_impl!(
+    OperationsWorkingGroupInstanceAlpha,
+    OperationsWgStakingEventsHandlerAlpha<T>
+);
+
+wg_staking_event_impl!(
+    OperationsWorkingGroupInstanceBeta,
+    OperationsWgStakingEventsHandlerBeta<T>
+);
+
+wg_staking_event_impl!(
+    OperationsWorkingGroupInstanceGamma,
+    OperationsWgStakingEventsHandlerGamma<T>
+);
+
+wg_staking_event_impl!(
+    DistributionWorkingGroupInstance,
+    DistributionWgStakingEventsHandler<T>
+);

+ 45 - 22
runtime/src/lib.rs

@@ -442,6 +442,7 @@ impl content::Trait for Runtime {
     type SeriesId = SeriesId;
     type ChannelOwnershipTransferRequestId = ChannelOwnershipTransferRequestId;
     type MaxNumberOfCuratorsPerGroup = MaxNumberOfCuratorsPerGroup;
+    type DataObjectStorage = Storage;
 }
 
 impl hiring::Trait for Runtime {
@@ -471,15 +472,24 @@ impl stake::Trait for Runtime {
     type Currency = <Self as common::currency::GovernanceCurrency>::Currency;
     type StakePoolId = StakePoolId;
     type StakingEventsHandler = (
-        crate::integration::proposals::StakingEventsHandler<Self>,
         (
             (
+                crate::integration::proposals::StakingEventsHandler<Self>,
                 crate::integration::working_group::ContentDirectoryWgStakingEventsHandler<Self>,
+            ),
+            (
                 crate::integration::working_group::StorageWgStakingEventsHandler<Self>,
+                crate::integration::working_group::OperationsWgStakingEventsHandlerAlpha<Self>,
+            ),
+        ),
+        (
+            (
+                crate::integration::working_group::OperationsWgStakingEventsHandlerBeta<Self>,
+                crate::integration::working_group::OperationsWgStakingEventsHandlerGamma<Self>,
             ),
             (
-                crate::integration::working_group::OperationsWgStakingEventsHandler<Self>,
                 crate::integration::working_group::GatewayWgStakingEventsHandler<Self>,
+                crate::integration::working_group::DistributionWgStakingEventsHandler<Self>,
             ),
         ),
     );
@@ -522,10 +532,8 @@ parameter_types! {
 
 impl membership::Trait for Runtime {
     type Event = Event;
-    type MemberId = MemberId;
     type PaidTermId = u64;
     type SubscriptionId = u64;
-    type ActorId = ActorId;
     type ScreenedMemberMaxInitialBalance = ScreenedMemberMaxInitialBalance;
 }
 
@@ -545,12 +553,18 @@ pub type ContentWorkingGroupInstance = working_group::Instance3;
 // The distribution working group instance alias.
 pub type DistributionWorkingGroupInstance = working_group::Instance6;
 
-// The builder working group instance alias.
-pub type OperationsWorkingGroupInstance = working_group::Instance4;
-
 // The gateway working group instance alias.
 pub type GatewayWorkingGroupInstance = working_group::Instance5;
 
+// The operation working group alpha instance alias.
+pub type OperationsWorkingGroupInstanceAlpha = working_group::Instance4;
+
+// The operation working group beta instance alias .
+pub type OperationsWorkingGroupInstanceBeta = working_group::Instance7;
+
+// The operation working group gamma instance alias .
+pub type OperationsWorkingGroupInstanceGamma = working_group::Instance8;
+
 parameter_types! {
     pub const MaxWorkerNumberLimit: u32 = 100;
 }
@@ -570,7 +584,7 @@ impl working_group::Trait<DistributionWorkingGroupInstance> for Runtime {
     type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
 }
 
-impl working_group::Trait<OperationsWorkingGroupInstance> for Runtime {
+impl working_group::Trait<OperationsWorkingGroupInstanceAlpha> for Runtime {
     type Event = Event;
     type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
 }
@@ -580,6 +594,16 @@ impl working_group::Trait<GatewayWorkingGroupInstance> for Runtime {
     type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
 }
 
+impl working_group::Trait<OperationsWorkingGroupInstanceBeta> for Runtime {
+    type Event = Event;
+    type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
+}
+
+impl working_group::Trait<OperationsWorkingGroupInstanceGamma> for Runtime {
+    type Event = Event;
+    type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
+}
+
 parameter_types! {
     pub const ProposalCancellationFee: u64 = 10000;
     pub const ProposalRejectionFee: u64 = 5000;
@@ -646,20 +670,19 @@ parameter_types! {
 }
 
 parameter_types! {
-    pub const MaxDistributionBucketNumberPerFamily: u64 = 20; //TODO: adjust value
-    pub const MaxDistributionBucketFamilyNumber: u64 = 20; //TODO: adjust value
-    pub const MaxNumberOfDataObjectsPerBag: u64 = 1000; //TODO: adjust value
-    pub const DataObjectDeletionPrize: Balance = 10; //TODO: adjust value
+    pub const MaxDistributionBucketNumberPerFamily: u64 = 500;
+    pub const MaxDistributionBucketFamilyNumber: u64 = 200;
+    pub const DataObjectDeletionPrize: Balance = 1; //TODO: Change during Olympia release
     pub const BlacklistSizeLimit: u64 = 10000; //TODO: adjust value
-    pub const MaxRandomIterationNumber: u64 = 30; //TODO: adjust value
-    pub const MaxNumberOfPendingInvitationsPerDistributionBucket: u64 = 30; //TODO: adjust value
+    pub const MaxRandomIterationNumber: u64 = 10; //TODO: adjust value
+    pub const MaxNumberOfPendingInvitationsPerDistributionBucket: u64 = 20; //TODO: adjust value
     pub const StorageModuleId: ModuleId = ModuleId(*b"mstorage"); // module storage
     pub const StorageBucketsPerBagValueConstraint: storage::StorageBucketsPerBagValueConstraint =
-        storage::StorageBucketsPerBagValueConstraint {min: 3, max_min_diff: 7}; //TODO: adjust value
-    pub const DefaultMemberDynamicBagNumberOfStorageBuckets: u64 = 4; //TODO: adjust value
-    pub const DefaultChannelDynamicBagNumberOfStorageBuckets: u64 = 4; //TODO: adjust value
+        storage::StorageBucketsPerBagValueConstraint {min: 5, max_min_diff: 15}; //TODO: adjust value
+    pub const DefaultMemberDynamicBagNumberOfStorageBuckets: u64 = 5; //TODO: adjust value
+    pub const DefaultChannelDynamicBagNumberOfStorageBuckets: u64 = 5; //TODO: adjust value
     pub const DistributionBucketsPerBagValueConstraint: storage::DistributionBucketsPerBagValueConstraint =
-        storage::DistributionBucketsPerBagValueConstraint {min: 3, max_min_diff: 7}; //TODO: adjust value
+        storage::DistributionBucketsPerBagValueConstraint {min: 1, max_min_diff: 100}; //TODO: adjust value
     pub const MaxDataObjectSize: u64 = 10 * 1024 * 1024 * 1024; // 10 GB
 }
 
@@ -670,7 +693,6 @@ impl storage::Trait for Runtime {
     type DistributionBucketId = DistributionBucketId;
     type DistributionBucketFamilyId = DistributionBucketFamilyId;
     type ChannelId = ChannelId;
-    type MaxNumberOfDataObjectsPerBag = MaxNumberOfDataObjectsPerBag;
     type DataObjectDeletionPrize = DataObjectDeletionPrize;
     type BlacklistSizeLimit = BlacklistSizeLimit;
     type ModuleId = StorageModuleId;
@@ -779,14 +801,15 @@ construct_runtime!(
         ProposalsEngine: proposals_engine::{Module, Call, Storage, Event<T>},
         ProposalsDiscussion: proposals_discussion::{Module, Call, Storage, Event<T>},
         ProposalsCodex: proposals_codex::{Module, Call, Storage, Config<T>},
+        Storage: storage::{Module, Call, Storage, Event<T>},
         // --- Working groups
         // reserved for the future use: ForumWorkingGroup: working_group::<Instance1>::{Module, Call, Storage, Config<T>, Event<T>},
         StorageWorkingGroup: working_group::<Instance2>::{Module, Call, Storage, Config<T>, Event<T>},
         ContentWorkingGroup: working_group::<Instance3>::{Module, Call, Storage, Config<T>, Event<T>},
-        OperationsWorkingGroup: working_group::<Instance4>::{Module, Call, Storage, Config<T>, Event<T>},
+        OperationsWorkingGroupAlpha: working_group::<Instance4>::{Module, Call, Storage, Config<T>, Event<T>},
         GatewayWorkingGroup: working_group::<Instance5>::{Module, Call, Storage, Config<T>, Event<T>},
         DistributionWorkingGroup: working_group::<Instance6>::{Module, Call, Storage, Config<T>, Event<T>},
-        //
-        Storage: storage::{Module, Call, Storage, Event<T>},
+        OperationsWorkingGroupBeta: working_group::<Instance7>::{Module, Call, Storage, Config<T>, Event<T>},
+        OperationsWorkingGroupGamma: working_group::<Instance8>::{Module, Call, Storage, Config<T>, Event<T>},
     }
 );

+ 0 - 4
runtime/src/primitives.rs

@@ -14,10 +14,6 @@ pub type TransactionPriority = u64;
 /// Alias for ContentId, used in various places.
 pub type ContentId = sp_core::H256;
 
-#[allow(clippy::upper_case_acronyms)]
-/// Alias for DAOId, used in various places.
-pub type DAOId = u64;
-
 /// Alias for DataObjectTypeId, used in various places.
 pub type DataObjectTypeId = u64;
 

+ 169 - 45
runtime/src/tests/proposals_integration/working_group_proposals.rs

@@ -13,8 +13,10 @@ use working_group::{OpeningPolicyCommitment, RewardPolicy};
 use crate::{
     Balance, BlockNumber, ContentWorkingGroup, ContentWorkingGroupInstance,
     DistributionWorkingGroup, DistributionWorkingGroupInstance, GatewayWorkingGroup,
-    GatewayWorkingGroupInstance, OperationsWorkingGroup, OperationsWorkingGroupInstance,
-    StorageWorkingGroup, StorageWorkingGroupInstance,
+    GatewayWorkingGroupInstance, OperationsWorkingGroupAlpha, OperationsWorkingGroupBeta,
+    OperationsWorkingGroupGamma, OperationsWorkingGroupInstanceAlpha,
+    OperationsWorkingGroupInstanceBeta, OperationsWorkingGroupInstanceGamma, StorageWorkingGroup,
+    StorageWorkingGroupInstance,
 };
 use sp_std::collections::btree_set::BTreeSet;
 
@@ -62,11 +64,27 @@ fn add_opening(
             >>::contains_key(opening_id));
             opening_id
         }
-        WorkingGroup::Operations => {
-            let opening_id = OperationsWorkingGroup::next_opening_id();
+        WorkingGroup::OperationsAlpha => {
+            let opening_id = OperationsWorkingGroupAlpha::next_opening_id();
             assert!(!<working_group::OpeningById<
                 Runtime,
-                OperationsWorkingGroupInstance,
+                OperationsWorkingGroupInstanceAlpha,
+            >>::contains_key(opening_id));
+            opening_id
+        }
+        WorkingGroup::OperationsBeta => {
+            let opening_id = OperationsWorkingGroupBeta::next_opening_id();
+            assert!(!<working_group::OpeningById<
+                Runtime,
+                OperationsWorkingGroupInstanceBeta,
+            >>::contains_key(opening_id));
+            opening_id
+        }
+        WorkingGroup::OperationsGamma => {
+            let opening_id = OperationsWorkingGroupGamma::next_opening_id();
+            assert!(!<working_group::OpeningById<
+                Runtime,
+                OperationsWorkingGroupInstanceGamma,
             >>::contains_key(opening_id));
             opening_id
         }
@@ -362,10 +380,22 @@ fn create_add_working_group_leader_opening_proposal_execution_succeeds() {
                     DistributionWorkingGroupInstance,
                 >(group);
             }
-            WorkingGroup::Operations => {
+            WorkingGroup::OperationsAlpha => {
                 run_create_add_working_group_leader_opening_proposal_execution_succeeds::<
                     Runtime,
-                    OperationsWorkingGroupInstance,
+                    OperationsWorkingGroupInstanceAlpha,
+                >(group);
+            }
+            WorkingGroup::OperationsBeta => {
+                run_create_add_working_group_leader_opening_proposal_execution_succeeds::<
+                    Runtime,
+                    OperationsWorkingGroupInstanceBeta,
+                >(group);
+            }
+            WorkingGroup::OperationsGamma => {
+                run_create_add_working_group_leader_opening_proposal_execution_succeeds::<
+                    Runtime,
+                    OperationsWorkingGroupInstanceGamma,
                 >(group);
             }
             WorkingGroup::Gateway => {
@@ -384,7 +414,7 @@ fn run_create_add_working_group_leader_opening_proposal_execution_succeeds<
 >(
     working_group: WorkingGroup,
 ) where
-    <T as membership::Trait>::MemberId: From<u64>,
+    <T as common::MembershipTypes>::MemberId: From<u64>,
     <T as hiring::Trait>::OpeningId: From<u64>,
 {
     initial_test_ext().execute_with(|| {
@@ -434,16 +464,29 @@ fn create_begin_review_working_group_leader_applications_proposal_execution_succ
             }
             WorkingGroup::Distribution => {
                 run_create_begin_review_working_group_leader_applications_proposal_execution_succeeds::<
-                Runtime,
+                    Runtime,
                     DistributionWorkingGroupInstance,
+                >(group);
+            }
+            WorkingGroup::OperationsAlpha => {
+                run_create_begin_review_working_group_leader_applications_proposal_execution_succeeds::<
+                Runtime,
+                OperationsWorkingGroupInstanceAlpha,
+            >(group);
+            }
+            WorkingGroup::OperationsBeta => {
+                run_create_begin_review_working_group_leader_applications_proposal_execution_succeeds::<
+                Runtime,
+                OperationsWorkingGroupInstanceBeta,
             >(group);
             }
-            WorkingGroup::Operations => {
+            WorkingGroup::OperationsGamma => {
                 run_create_begin_review_working_group_leader_applications_proposal_execution_succeeds::<
                 Runtime,
-                OperationsWorkingGroupInstance,
+                OperationsWorkingGroupInstanceGamma,
             >(group);
             }
+
             WorkingGroup::Gateway => {
                 run_create_begin_review_working_group_leader_applications_proposal_execution_succeeds::<
                 Runtime,
@@ -536,12 +579,25 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
                     DistributionWorkingGroupInstance,
                 >(group);
             }
-            WorkingGroup::Operations => {
+            WorkingGroup::OperationsAlpha => {
+                run_create_fill_working_group_leader_opening_proposal_execution_succeeds::<
+                    Runtime,
+                    OperationsWorkingGroupInstanceAlpha,
+                >(group);
+            }
+            WorkingGroup::OperationsBeta => {
+                run_create_fill_working_group_leader_opening_proposal_execution_succeeds::<
+                    Runtime,
+                    OperationsWorkingGroupInstanceBeta,
+                >(group);
+            }
+            WorkingGroup::OperationsGamma => {
                 run_create_fill_working_group_leader_opening_proposal_execution_succeeds::<
                     Runtime,
-                    OperationsWorkingGroupInstance,
+                    OperationsWorkingGroupInstanceGamma,
                 >(group);
             }
+
             WorkingGroup::Gateway => {
                 run_create_fill_working_group_leader_opening_proposal_execution_succeeds::<
                     Runtime,
@@ -558,7 +614,7 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
         working_group: WorkingGroup,
     ) where
         <T as frame_system::Trait>::AccountId: From<[u8; 32]>,
-        <T as membership::Trait>::MemberId: From<u64>,
+        <T as common::MembershipTypes>::MemberId: From<u64>,
         <T as hiring::Trait>::OpeningId: From<u64>,
     {
         initial_test_ext().execute_with(|| {
@@ -631,12 +687,25 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
                         DistributionWorkingGroupInstance,
                     >(group);
                 }
-                WorkingGroup::Operations => {
+                WorkingGroup::OperationsAlpha => {
+                    run_create_decrease_group_leader_stake_proposal_execution_succeeds::<
+                        Runtime,
+                        OperationsWorkingGroupInstanceAlpha,
+                    >(group);
+                }
+                WorkingGroup::OperationsBeta => {
+                    run_create_decrease_group_leader_stake_proposal_execution_succeeds::<
+                        Runtime,
+                        OperationsWorkingGroupInstanceBeta,
+                    >(group);
+                }
+                WorkingGroup::OperationsGamma => {
                     run_create_decrease_group_leader_stake_proposal_execution_succeeds::<
                         Runtime,
-                        OperationsWorkingGroupInstance,
+                        OperationsWorkingGroupInstanceGamma,
                     >(group);
                 }
+
                 WorkingGroup::Gateway => {
                     run_create_decrease_group_leader_stake_proposal_execution_succeeds::<
                         Runtime,
@@ -655,8 +724,8 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
     ) where
         <T as frame_system::Trait>::AccountId: From<[u8; 32]>,
         <T as hiring::Trait>::OpeningId: From<u64>,
-        <T as membership::Trait>::MemberId: From<u64>,
-        <T as membership::Trait>::ActorId: Into<u64>,
+        <T as common::MembershipTypes>::MemberId: From<u64>,
+        <T as common::MembershipTypes>::ActorId: Into<u64>,
         <<T as stake::Trait>::Currency as traits::Currency<
             <T as frame_system::Trait>::AccountId,
         >>::Balance: From<u128>,
@@ -766,10 +835,22 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
                         DistributionWorkingGroupInstance,
                     >(group)
                 }
-                WorkingGroup::Operations => {
+                WorkingGroup::OperationsAlpha => {
+                    run_create_slash_group_leader_stake_proposal_execution_succeeds::<
+                        Runtime,
+                        OperationsWorkingGroupInstanceAlpha,
+                    >(group)
+                }
+                WorkingGroup::OperationsBeta => {
+                    run_create_slash_group_leader_stake_proposal_execution_succeeds::<
+                        Runtime,
+                        OperationsWorkingGroupInstanceBeta,
+                    >(group)
+                }
+                WorkingGroup::OperationsGamma => {
                     run_create_slash_group_leader_stake_proposal_execution_succeeds::<
                         Runtime,
-                        OperationsWorkingGroupInstance,
+                        OperationsWorkingGroupInstanceGamma,
                     >(group)
                 }
                 WorkingGroup::Gateway => {
@@ -790,8 +871,8 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
     ) where
         <T as frame_system::Trait>::AccountId: From<[u8; 32]>,
         <T as hiring::Trait>::OpeningId: From<u64>,
-        <T as membership::Trait>::MemberId: From<u64>,
-        <T as membership::Trait>::ActorId: Into<u64>,
+        <T as common::MembershipTypes>::MemberId: From<u64>,
+        <T as common::MembershipTypes>::ActorId: Into<u64>,
         <<T as stake::Trait>::Currency as traits::Currency<
             <T as frame_system::Trait>::AccountId,
         >>::Balance: From<u128>,
@@ -902,11 +983,23 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
                         DistributionWorkingGroupInstance,
                     >(group);
                 }
-                WorkingGroup::Operations => {
+                WorkingGroup::OperationsAlpha => {
                     run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
                         Runtime,
-                        OperationsWorkingGroupInstance,
-                    >(group);
+                        OperationsWorkingGroupInstanceAlpha,
+                    >(group)
+                }
+                WorkingGroup::OperationsBeta => {
+                    run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
+                        Runtime,
+                        OperationsWorkingGroupInstanceBeta,
+                    >(group)
+                }
+                WorkingGroup::OperationsGamma => {
+                    run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
+                        Runtime,
+                        OperationsWorkingGroupInstanceGamma,
+                    >(group)
                 }
                 WorkingGroup::Gateway => {
                     run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
@@ -924,7 +1017,7 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
             working_group: WorkingGroup,
         ) where
             <T as frame_system::Trait>::AccountId: From<[u8; 32]>,
-            <T as membership::Trait>::MemberId: From<u64>,
+            <T as common::MembershipTypes>::MemberId: From<u64>,
             <T as minting::Trait>::MintId: From<u64>,
             <<T as minting::Trait>::Currency as traits::Currency<
                 <T as frame_system::Trait>::AccountId,
@@ -959,31 +1052,43 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
             for group in WorkingGroup::iter() {
                 match group {
                     WorkingGroup::Content => {
-                        run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
+                        run_create_set_group_leader_reward_proposal_execution_succeeds::<
                             Runtime,
                             ContentWorkingGroupInstance,
                         >(group);
                     }
                     WorkingGroup::Storage => {
-                        run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
+                        run_create_set_group_leader_reward_proposal_execution_succeeds::<
                             Runtime,
                             StorageWorkingGroupInstance,
                         >(group);
                     }
                     WorkingGroup::Distribution => {
-                        run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
+                        run_create_set_group_leader_reward_proposal_execution_succeeds::<
                             Runtime,
                             DistributionWorkingGroupInstance,
                         >(group);
                     }
-                    WorkingGroup::Operations => {
-                        run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
+                    WorkingGroup::OperationsAlpha => {
+                        run_create_set_group_leader_reward_proposal_execution_succeeds::<
                             Runtime,
-                            OperationsWorkingGroupInstance,
-                        >(group);
+                            OperationsWorkingGroupInstanceAlpha,
+                        >(group)
+                    }
+                    WorkingGroup::OperationsBeta => {
+                        run_create_set_group_leader_reward_proposal_execution_succeeds::<
+                            Runtime,
+                            OperationsWorkingGroupInstanceBeta,
+                        >(group)
+                    }
+                    WorkingGroup::OperationsGamma => {
+                        run_create_set_group_leader_reward_proposal_execution_succeeds::<
+                            Runtime,
+                            OperationsWorkingGroupInstanceGamma,
+                        >(group)
                     }
                     WorkingGroup::Gateway => {
-                        run_create_set_working_group_mint_capacity_proposal_execution_succeeds::<
+                        run_create_set_group_leader_reward_proposal_execution_succeeds::<
                             Runtime,
                             GatewayWorkingGroupInstance,
                         >(group);
@@ -999,8 +1104,8 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
             working_group: WorkingGroup,
         ) where
             <T as frame_system::Trait>::AccountId: From<[u8; 32]>,
-            <T as membership::Trait>::MemberId: From<u64>,
-            <T as membership::Trait>::ActorId: Into<u64>,
+            <T as common::MembershipTypes>::MemberId: From<u64>,
+            <T as common::MembershipTypes>::ActorId: Into<u64>,
             <T as minting::Trait>::MintId: From<u64>,
             <T as hiring::Trait>::OpeningId: From<u64>,
             <<T as minting::Trait>::Currency as traits::Currency<
@@ -1117,12 +1222,25 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
                             DistributionWorkingGroupInstance,
                         >(group);
                     }
-                    WorkingGroup::Operations => {
+                    WorkingGroup::OperationsAlpha => {
                         run_create_terminate_group_leader_role_proposal_execution_succeeds::<
                             Runtime,
-                            OperationsWorkingGroupInstance,
-                        >(group);
+                            OperationsWorkingGroupInstanceAlpha,
+                        >(group)
+                    }
+                    WorkingGroup::OperationsBeta => {
+                        run_create_terminate_group_leader_role_proposal_execution_succeeds::<
+                            Runtime,
+                            OperationsWorkingGroupInstanceBeta,
+                        >(group)
+                    }
+                    WorkingGroup::OperationsGamma => {
+                        run_create_terminate_group_leader_role_proposal_execution_succeeds::<
+                            Runtime,
+                            OperationsWorkingGroupInstanceGamma,
+                        >(group)
                     }
+
                     WorkingGroup::Gateway => {
                         run_create_terminate_group_leader_role_proposal_execution_succeeds::<
                             Runtime,
@@ -1140,8 +1258,8 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
             working_group: WorkingGroup,
         ) where
             <T as frame_system::Trait>::AccountId: From<[u8; 32]>,
-            <T as membership::Trait>::MemberId: From<u64>,
-            <T as membership::Trait>::ActorId: Into<u64>,
+            <T as common::MembershipTypes>::MemberId: From<u64>,
+            <T as common::MembershipTypes>::ActorId: Into<u64>,
             <T as minting::Trait>::MintId: From<u64>,
             <T as hiring::Trait>::OpeningId: From<u64>,
             <<T as stake::Trait>::Currency as traits::Currency<
@@ -1251,8 +1369,14 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
                     WorkingGroup::Distribution => {
                         run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds::<Runtime, DistributionWorkingGroupInstance>(group);
                     }
-                    WorkingGroup::Operations => {
-                        run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds::<Runtime, OperationsWorkingGroupInstance>(group);
+                    WorkingGroup::OperationsAlpha => {
+                        run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds::<Runtime, OperationsWorkingGroupInstanceAlpha>(group);
+                    }
+                    WorkingGroup::OperationsBeta => {
+                        run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds::<Runtime, OperationsWorkingGroupInstanceBeta>(group);
+                    }
+                    WorkingGroup::OperationsGamma => {
+                        run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds::<Runtime, OperationsWorkingGroupInstanceGamma>(group);
                     }
                     WorkingGroup::Gateway => {
                         run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds::<Runtime, GatewayWorkingGroupInstance>(group);
@@ -1268,8 +1392,8 @@ fn create_fill_working_group_leader_opening_proposal_execution_succeeds() {
             working_group: WorkingGroup,
         ) where
             <T as frame_system::Trait>::AccountId: From<[u8; 32]>,
-            <T as membership::Trait>::MemberId: From<u64>,
-            <T as membership::Trait>::ActorId: Into<u64>,
+            <T as common::MembershipTypes>::MemberId: From<u64>,
+            <T as common::MembershipTypes>::ActorId: Into<u64>,
             <T as minting::Trait>::MintId: From<u64>,
             <T as hiring::Trait>::OpeningId: From<u64>,
             <<T as stake::Trait>::Currency as traits::Currency<

File diff suppressed because it is too large
+ 2 - 2
types/augment-codec/all.ts


+ 13 - 5
types/augment-codec/augment-api-consts.ts

@@ -69,7 +69,19 @@ declare module '@polkadot/api/types/consts' {
     members: {
       screenedMemberMaxInitialBalance: BalanceOf & AugmentedConst<ApiType>;
     };
-    operationsWorkingGroup: {
+    operationsWorkingGroupAlpha: {
+      /**
+       * Exports const -  max simultaneous active worker number.
+       **/
+      maxWorkerNumberLimit: u32 & AugmentedConst<ApiType>;
+    };
+    operationsWorkingGroupBeta: {
+      /**
+       * Exports const -  max simultaneous active worker number.
+       **/
+      maxWorkerNumberLimit: u32 & AugmentedConst<ApiType>;
+    };
+    operationsWorkingGroupGamma: {
       /**
        * Exports const -  max simultaneous active worker number.
        **/
@@ -205,10 +217,6 @@ declare module '@polkadot/api/types/consts' {
        * 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.
        **/

File diff suppressed because it is too large
+ 948 - 20
types/augment-codec/augment-api-errors.ts


+ 276 - 12
types/augment-codec/augment-api-events.ts

@@ -2,7 +2,7 @@
 /* eslint-disable */
 
 import type { BTreeMap, BTreeSet, Bytes, Option, Vec, bool, u32, u64 } from '@polkadot/types';
-import type { ApplicationId, ApplicationIdToWorkerIdMap, BagId, CategoryId, Channel, ChannelCategory, ChannelCategoryCreationParameters, ChannelCategoryId, ChannelCategoryUpdateParameters, ChannelCreationParameters, ChannelId, ChannelOwnershipTransferRequest, ChannelOwnershipTransferRequestId, ChannelUpdateParameters, Cid, ContentActor, ContentId, CuratorGroupId, CuratorId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrizeRecord, DynamicBagId, DynamicBagType, EntryMethod, IsCensored, MemberId, MintBalanceOf, MintId, NewAsset, OpeningId, PersonCreationParameters, PersonId, PersonUpdateParameters, PlaylistCreationParameters, PlaylistId, PlaylistUpdateParameters, PostId, ProposalId, ProposalStatus, RationaleText, Series, SeriesId, SeriesParameters, StorageBucketId, ThreadId, UploadParameters, VideoCategoryCreationParameters, VideoCategoryId, VideoCategoryUpdateParameters, VideoCreationParameters, VideoId, VideoUpdateParameters, VoteKind, Voucher, WorkerId } from './all';
+import type { ApplicationId, ApplicationIdToWorkerIdMap, BagId, CategoryId, Channel, ChannelCategory, ChannelCategoryCreationParameters, ChannelCategoryId, ChannelCategoryUpdateParameters, ChannelCreationParameters, ChannelId, ChannelOwnershipTransferRequest, ChannelOwnershipTransferRequestId, ChannelUpdateParameters, Cid, ContentActor, CuratorGroupId, CuratorId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrizeRecord, DynamicBagId, DynamicBagType, EntryMethod, IsCensored, MemberId, MintBalanceOf, MintId, OpeningId, PersonCreationParameters, PersonId, PersonUpdateParameters, PlaylistCreationParameters, PlaylistId, PlaylistUpdateParameters, PostId, ProposalId, ProposalStatus, RationaleText, Series, SeriesId, SeriesParameters, StorageAssets, StorageBucketId, ThreadId, UploadParameters, VideoCategoryCreationParameters, VideoCategoryId, VideoCategoryUpdateParameters, VideoCreationParameters, VideoId, VideoUpdateParameters, 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';
@@ -53,12 +53,13 @@ declare module '@polkadot/api/types/events' {
       Unreserved: AugmentedEvent<ApiType, [AccountId, Balance]>;
     };
     content: {
-      ChannelAssetsRemoved: AugmentedEvent<ApiType, [ContentActor, ChannelId, Vec<ContentId>]>;
+      ChannelAssetsRemoved: AugmentedEvent<ApiType, [ContentActor, ChannelId, BTreeSet<DataObjectId>, Channel]>;
       ChannelCategoryCreated: AugmentedEvent<ApiType, [ChannelCategoryId, ChannelCategory, ChannelCategoryCreationParameters]>;
       ChannelCategoryDeleted: AugmentedEvent<ApiType, [ContentActor, ChannelCategoryId]>;
       ChannelCategoryUpdated: AugmentedEvent<ApiType, [ContentActor, ChannelCategoryId, ChannelCategoryUpdateParameters]>;
       ChannelCensorshipStatusUpdated: AugmentedEvent<ApiType, [ContentActor, ChannelId, IsCensored, Bytes]>;
       ChannelCreated: AugmentedEvent<ApiType, [ContentActor, ChannelId, Channel, ChannelCreationParameters]>;
+      ChannelDeleted: AugmentedEvent<ApiType, [ContentActor, ChannelId]>;
       ChannelOwnershipTransferred: AugmentedEvent<ApiType, [ContentActor, ChannelOwnershipTransferRequestId]>;
       ChannelOwnershipTransferRequested: AugmentedEvent<ApiType, [ContentActor, ChannelOwnershipTransferRequestId, ChannelOwnershipTransferRequest]>;
       ChannelOwnershipTransferRequestWithdrawn: AugmentedEvent<ApiType, [ContentActor, ChannelOwnershipTransferRequestId]>;
@@ -68,15 +69,15 @@ declare module '@polkadot/api/types/events' {
       CuratorGroupStatusSet: AugmentedEvent<ApiType, [CuratorGroupId, bool]>;
       CuratorRemoved: AugmentedEvent<ApiType, [CuratorGroupId, CuratorId]>;
       FeaturedVideosSet: AugmentedEvent<ApiType, [ContentActor, Vec<VideoId>]>;
-      PersonCreated: AugmentedEvent<ApiType, [ContentActor, PersonId, Vec<NewAsset>, PersonCreationParameters]>;
+      PersonCreated: AugmentedEvent<ApiType, [ContentActor, PersonId, StorageAssets, PersonCreationParameters]>;
       PersonDeleted: AugmentedEvent<ApiType, [ContentActor, PersonId]>;
-      PersonUpdated: AugmentedEvent<ApiType, [ContentActor, PersonId, Vec<NewAsset>, PersonUpdateParameters]>;
+      PersonUpdated: AugmentedEvent<ApiType, [ContentActor, PersonId, StorageAssets, PersonUpdateParameters]>;
       PlaylistCreated: AugmentedEvent<ApiType, [ContentActor, PlaylistId, PlaylistCreationParameters]>;
       PlaylistDeleted: AugmentedEvent<ApiType, [ContentActor, PlaylistId]>;
       PlaylistUpdated: AugmentedEvent<ApiType, [ContentActor, PlaylistId, PlaylistUpdateParameters]>;
-      SeriesCreated: AugmentedEvent<ApiType, [ContentActor, SeriesId, Vec<NewAsset>, SeriesParameters, Series]>;
+      SeriesCreated: AugmentedEvent<ApiType, [ContentActor, SeriesId, StorageAssets, SeriesParameters, Series]>;
       SeriesDeleted: AugmentedEvent<ApiType, [ContentActor, SeriesId]>;
-      SeriesUpdated: AugmentedEvent<ApiType, [ContentActor, SeriesId, Vec<NewAsset>, SeriesParameters, Series]>;
+      SeriesUpdated: AugmentedEvent<ApiType, [ContentActor, SeriesId, StorageAssets, SeriesParameters, Series]>;
       VideoCategoryCreated: AugmentedEvent<ApiType, [ContentActor, VideoCategoryId, VideoCategoryCreationParameters]>;
       VideoCategoryDeleted: AugmentedEvent<ApiType, [ContentActor, VideoCategoryId]>;
       VideoCategoryUpdated: AugmentedEvent<ApiType, [ContentActor, VideoCategoryId, VideoCategoryUpdateParameters]>;
@@ -564,9 +565,9 @@ declare module '@polkadot/api/types/events' {
       MemberRegistered: AugmentedEvent<ApiType, [MemberId, AccountId, EntryMethod]>;
       MemberSetControllerAccount: AugmentedEvent<ApiType, [MemberId, AccountId]>;
       MemberSetRootAccount: AugmentedEvent<ApiType, [MemberId, AccountId]>;
-      MemberUpdatedAboutText: AugmentedEvent<ApiType, [MemberId]>;
-      MemberUpdatedAvatar: AugmentedEvent<ApiType, [MemberId]>;
-      MemberUpdatedHandle: AugmentedEvent<ApiType, [MemberId]>;
+      MemberUpdatedAboutText: AugmentedEvent<ApiType, [MemberId, Bytes]>;
+      MemberUpdatedAvatar: AugmentedEvent<ApiType, [MemberId, Bytes]>;
+      MemberUpdatedHandle: AugmentedEvent<ApiType, [MemberId, Bytes]>;
     };
     memo: {
       MemoUpdated: AugmentedEvent<ApiType, [AccountId]>;
@@ -580,7 +581,267 @@ declare module '@polkadot/api/types/events' {
        **/
       Offence: AugmentedEvent<ApiType, [Kind, OpaqueTimeSlot, bool]>;
     };
-    operationsWorkingGroup: {
+    operationsWorkingGroupAlpha: {
+      /**
+       * Emits on accepting application for the worker opening.
+       * Params:
+       * - Opening id
+       **/
+      AcceptedApplications: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on terminating the application for the worker/lead opening.
+       * Params:
+       * - Worker application id
+       **/
+      ApplicationTerminated: AugmentedEvent<ApiType, [ApplicationId]>;
+      /**
+       * Emits on withdrawing the application for the worker/lead opening.
+       * Params:
+       * - Worker application id
+       **/
+      ApplicationWithdrawn: AugmentedEvent<ApiType, [ApplicationId]>;
+      /**
+       * Emits on adding the application for the worker opening.
+       * Params:
+       * - Opening id
+       * - Application id
+       **/
+      AppliedOnOpening: AugmentedEvent<ApiType, [OpeningId, ApplicationId]>;
+      /**
+       * Emits on beginning the application review for the worker/lead opening.
+       * Params:
+       * - Opening id
+       **/
+      BeganApplicationReview: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on setting the leader.
+       * Params:
+       * - Worker id.
+       **/
+      LeaderSet: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on un-setting the leader.
+       * Params:
+       **/
+      LeaderUnset: AugmentedEvent<ApiType, []>;
+      /**
+       * Emits on changing working group mint capacity.
+       * Params:
+       * - mint id.
+       * - new mint balance.
+       **/
+      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 updating the reward amount of the worker.
+       * Params:
+       * - Id of the worker.
+       **/
+      WorkerRewardAmountUpdated: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on updating the role account of the worker.
+       * Params:
+       * - Id of the worker.
+       * - Role account id of the worker.
+       **/
+      WorkerRoleAccountUpdated: AugmentedEvent<ApiType, [WorkerId, AccountId]>;
+      /**
+       * Emits on updating the worker storage role.
+       * Params:
+       * - Id of the worker.
+       * - Raw storage field.
+       **/
+      WorkerStorageUpdated: AugmentedEvent<ApiType, [WorkerId, Bytes]>;
+    };
+    operationsWorkingGroupBeta: {
+      /**
+       * Emits on accepting application for the worker opening.
+       * Params:
+       * - Opening id
+       **/
+      AcceptedApplications: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on terminating the application for the worker/lead opening.
+       * Params:
+       * - Worker application id
+       **/
+      ApplicationTerminated: AugmentedEvent<ApiType, [ApplicationId]>;
+      /**
+       * Emits on withdrawing the application for the worker/lead opening.
+       * Params:
+       * - Worker application id
+       **/
+      ApplicationWithdrawn: AugmentedEvent<ApiType, [ApplicationId]>;
+      /**
+       * Emits on adding the application for the worker opening.
+       * Params:
+       * - Opening id
+       * - Application id
+       **/
+      AppliedOnOpening: AugmentedEvent<ApiType, [OpeningId, ApplicationId]>;
+      /**
+       * Emits on beginning the application review for the worker/lead opening.
+       * Params:
+       * - Opening id
+       **/
+      BeganApplicationReview: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on setting the leader.
+       * Params:
+       * - Worker id.
+       **/
+      LeaderSet: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on un-setting the leader.
+       * Params:
+       **/
+      LeaderUnset: AugmentedEvent<ApiType, []>;
+      /**
+       * Emits on changing working group mint capacity.
+       * Params:
+       * - mint id.
+       * - new mint balance.
+       **/
+      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 updating the reward amount of the worker.
+       * Params:
+       * - Id of the worker.
+       **/
+      WorkerRewardAmountUpdated: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on updating the role account of the worker.
+       * Params:
+       * - Id of the worker.
+       * - Role account id of the worker.
+       **/
+      WorkerRoleAccountUpdated: AugmentedEvent<ApiType, [WorkerId, AccountId]>;
+      /**
+       * Emits on updating the worker storage role.
+       * Params:
+       * - Id of the worker.
+       * - Raw storage field.
+       **/
+      WorkerStorageUpdated: AugmentedEvent<ApiType, [WorkerId, Bytes]>;
+    };
+    operationsWorkingGroupGamma: {
       /**
        * Emits on accepting application for the worker opening.
        * Params:
@@ -837,8 +1098,9 @@ declare module '@polkadot/api/types/events' {
        * Params
        * - data objects IDs
        * - initial uploading parameters
+       * - deletion prize for objects
        **/
-      DataObjectsUploaded: AugmentedEvent<ApiType, [Vec<DataObjectId>, UploadParameters]>;
+      DataObjectsUploaded: AugmentedEvent<ApiType, [Vec<DataObjectId>, UploadParameters, Balance]>;
       /**
        * Emits on creating distribution bucket.
        * Params
@@ -949,8 +1211,10 @@ declare module '@polkadot/api/types/events' {
        * Params
        * - dynamic bag ID
        * - optional DynamicBagDeletionPrize instance
+       * - assigned storage buckets' IDs
+       * - assigned distribution buckets' IDs
        **/
-      DynamicBagCreated: AugmentedEvent<ApiType, [DynamicBagId, Option<DynamicBagDeletionPrizeRecord>]>;
+      DynamicBagCreated: AugmentedEvent<ApiType, [DynamicBagId, Option<DynamicBagDeletionPrizeRecord>, BTreeSet<StorageBucketId>, BTreeSet<DistributionBucketId>]>;
       /**
        * Emits on deleting a dynamic bag.
        * Params

+ 128 - 2
types/augment-codec/augment-api-query.ts

@@ -583,7 +583,133 @@ declare module '@polkadot/api/types/storage' {
        **/
       reportsByKindIndex: AugmentedQuery<ApiType, (arg: Kind | string | Uint8Array) => Observable<Bytes>, [Kind]>;
     };
-    operationsWorkingGroup: {
+    operationsWorkingGroupAlpha: {
+      /**
+       * Count of active workers.
+       **/
+      activeWorkerCount: AugmentedQuery<ApiType, () => Observable<u32>, []>;
+      /**
+       * Maps identifier to worker application on opening.
+       **/
+      applicationById: AugmentedQuery<ApiType, (arg: ApplicationId | AnyNumber | Uint8Array) => Observable<ApplicationOf>, [ApplicationId]>;
+      /**
+       * The current lead.
+       **/
+      currentLead: AugmentedQuery<ApiType, () => Observable<Option<WorkerId>>, []>;
+      /**
+       * Map member id by hiring application id.
+       * Required by StakingEventsHandler callback call to refund the balance on unstaking.
+       **/
+      memberIdByHiringApplicationId: AugmentedQuery<ApiType, (arg: HiringApplicationId | AnyNumber | Uint8Array) => Observable<MemberId>, [HiringApplicationId]>;
+      /**
+       * The mint currently funding the rewards for this module.
+       **/
+      mint: AugmentedQuery<ApiType, () => Observable<MintId>, []>;
+      /**
+       * Next identifier value for new worker application.
+       **/
+      nextApplicationId: AugmentedQuery<ApiType, () => Observable<ApplicationId>, []>;
+      /**
+       * Next identifier value for new worker opening.
+       **/
+      nextOpeningId: AugmentedQuery<ApiType, () => Observable<OpeningId>, []>;
+      /**
+       * Next identifier for new worker.
+       **/
+      nextWorkerId: AugmentedQuery<ApiType, () => Observable<WorkerId>, []>;
+      /**
+       * Maps identifier to worker opening.
+       **/
+      openingById: AugmentedQuery<ApiType, (arg: OpeningId | AnyNumber | Uint8Array) => Observable<OpeningOf>, [OpeningId]>;
+      /**
+       * Opening human readable text length limits
+       **/
+      openingHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Worker application human readable text length limits
+       **/
+      workerApplicationHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Maps identifier to corresponding worker.
+       **/
+      workerById: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<WorkerOf>, [WorkerId]>;
+      /**
+       * Worker exit rationale text length limits.
+       **/
+      workerExitRationaleText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Maps identifier to corresponding worker storage.
+       **/
+      workerStorage: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<Bytes>, [WorkerId]>;
+      /**
+       * Worker storage size upper bound.
+       **/
+      workerStorageSize: AugmentedQuery<ApiType, () => Observable<u16>, []>;
+    };
+    operationsWorkingGroupBeta: {
+      /**
+       * Count of active workers.
+       **/
+      activeWorkerCount: AugmentedQuery<ApiType, () => Observable<u32>, []>;
+      /**
+       * Maps identifier to worker application on opening.
+       **/
+      applicationById: AugmentedQuery<ApiType, (arg: ApplicationId | AnyNumber | Uint8Array) => Observable<ApplicationOf>, [ApplicationId]>;
+      /**
+       * The current lead.
+       **/
+      currentLead: AugmentedQuery<ApiType, () => Observable<Option<WorkerId>>, []>;
+      /**
+       * Map member id by hiring application id.
+       * Required by StakingEventsHandler callback call to refund the balance on unstaking.
+       **/
+      memberIdByHiringApplicationId: AugmentedQuery<ApiType, (arg: HiringApplicationId | AnyNumber | Uint8Array) => Observable<MemberId>, [HiringApplicationId]>;
+      /**
+       * The mint currently funding the rewards for this module.
+       **/
+      mint: AugmentedQuery<ApiType, () => Observable<MintId>, []>;
+      /**
+       * Next identifier value for new worker application.
+       **/
+      nextApplicationId: AugmentedQuery<ApiType, () => Observable<ApplicationId>, []>;
+      /**
+       * Next identifier value for new worker opening.
+       **/
+      nextOpeningId: AugmentedQuery<ApiType, () => Observable<OpeningId>, []>;
+      /**
+       * Next identifier for new worker.
+       **/
+      nextWorkerId: AugmentedQuery<ApiType, () => Observable<WorkerId>, []>;
+      /**
+       * Maps identifier to worker opening.
+       **/
+      openingById: AugmentedQuery<ApiType, (arg: OpeningId | AnyNumber | Uint8Array) => Observable<OpeningOf>, [OpeningId]>;
+      /**
+       * Opening human readable text length limits
+       **/
+      openingHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Worker application human readable text length limits
+       **/
+      workerApplicationHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Maps identifier to corresponding worker.
+       **/
+      workerById: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<WorkerOf>, [WorkerId]>;
+      /**
+       * Worker exit rationale text length limits.
+       **/
+      workerExitRationaleText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Maps identifier to corresponding worker storage.
+       **/
+      workerStorage: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<Bytes>, [WorkerId]>;
+      /**
+       * Worker storage size upper bound.
+       **/
+      workerStorageSize: AugmentedQuery<ApiType, () => Observable<u16>, []>;
+    };
+    operationsWorkingGroupGamma: {
       /**
        * Count of active workers.
        **/
@@ -1137,7 +1263,7 @@ declare module '@polkadot/api/types/storage' {
        **/
       uploadingBlocked: AugmentedQuery<ApiType, () => Observable<bool>, []>;
       /**
-       * "Max objects number for a storage bucket voucher" number limit.
+       * "Max objects number for a storage  bucket voucher" number limit.
        **/
       voucherMaxObjectsNumberLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
       /**

+ 173 - 14
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 } from '@polkadot/types/types';
-import type { ActivateOpeningAt, AddOpeningParameters, ApplicationId, ApplicationIdSet, BagId, BalanceOfMint, CategoryId, ChannelCategoryCreationParameters, ChannelCategoryId, ChannelCategoryUpdateParameters, ChannelCreationParameters, ChannelId, ChannelOwnershipTransferRequest, ChannelOwnershipTransferRequestId, ChannelUpdateParameters, Cid, ContentActor, ContentId, CuratorGroupId, CuratorId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrize, DynamicBagId, DynamicBagType, ElectionParameters, FillOpeningParameters, MemberId, MemoText, OpeningId, OpeningPolicyCommitment, OpeningType, PaidTermId, PersonActor, PersonCreationParameters, PersonId, PersonUpdateParameters, PlaylistCreationParameters, PlaylistId, PlaylistUpdateParameters, PostId, ProposalId, RewardPolicy, SeriesId, SeriesParameters, StorageBucketId, TerminateRoleParameters, ThreadId, UploadParameters, VideoCategoryCreationParameters, VideoCategoryId, VideoCategoryUpdateParameters, VideoCreationParameters, VideoId, VideoUpdateParameters, VoteKind, WorkerId, WorkingGroup } from './all';
+import type { ActivateOpeningAt, AddOpeningParameters, ApplicationId, ApplicationIdSet, BagId, BalanceOfMint, CategoryId, ChannelCategoryCreationParameters, ChannelCategoryId, ChannelCategoryUpdateParameters, ChannelCreationParameters, ChannelId, ChannelOwnershipTransferRequest, ChannelOwnershipTransferRequestId, ChannelUpdateParameters, Cid, ContentActor, CuratorGroupId, CuratorId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrize, DynamicBagId, DynamicBagType, ElectionParameters, FillOpeningParameters, MemberId, MemoText, OpeningId, OpeningPolicyCommitment, OpeningType, PaidTermId, PersonActor, PersonCreationParameters, PersonId, PersonUpdateParameters, PlaylistCreationParameters, PlaylistId, PlaylistUpdateParameters, PostId, ProposalId, RewardPolicy, SeriesId, SeriesParameters, StorageBucketId, TerminateRoleParameters, ThreadId, UploadParameters, VideoCategoryCreationParameters, VideoCategoryId, VideoCategoryUpdateParameters, VideoCreationParameters, VideoId, VideoUpdateParameters, 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';
@@ -137,16 +137,13 @@ declare module '@polkadot/api/types/submittable' {
       createSeries: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: SeriesParameters | { assets?: any; seasons?: any; meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, SeriesParameters]>;
       createVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: VideoCreationParameters | { assets?: any; meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, VideoCreationParameters]>;
       createVideoCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, params: VideoCategoryCreationParameters | { meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoCategoryCreationParameters]>;
+      deleteChannel: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, numObjectsToDelete: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, u64]>;
       deleteChannelCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, categoryId: ChannelCategoryId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelCategoryId]>;
       deletePerson: AugmentedSubmittable<(actor: PersonActor | { Member: any } | { Curator: any } | string | Uint8Array, person: PersonId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PersonActor, PersonId]>;
       deletePlaylist: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, playlist: PlaylistId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, PlaylistId]>;
       deleteSeries: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, series: SeriesId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, SeriesId]>;
-      deleteVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId]>;
+      deleteVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array, assetsToRemove: BTreeSet<DataObjectId>) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId, BTreeSet<DataObjectId>]>;
       deleteVideoCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, categoryId: VideoCategoryId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoCategoryId]>;
-      /**
-       * Remove assets of a channel from storage
-       **/
-      removeChannelAssets: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, assets: Vec<ContentId> | (ContentId | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, Vec<ContentId>]>;
       /**
        * Remove curator from a given curator group
        **/
@@ -158,13 +155,13 @@ declare module '@polkadot/api/types/submittable' {
        **/
       setCuratorGroupStatus: AugmentedSubmittable<(curatorGroupId: CuratorGroupId | AnyNumber | Uint8Array, isActive: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [CuratorGroupId, bool]>;
       setFeaturedVideos: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, list: Vec<VideoId> | (VideoId | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [ContentActor, Vec<VideoId>]>;
-      updateChannel: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: ChannelUpdateParameters | { assets?: any; new_meta?: any; reward_account?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, ChannelUpdateParameters]>;
+      updateChannel: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: ChannelUpdateParameters | { assets_to_upload?: any; new_meta?: any; reward_account?: any; assets_to_remove?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, ChannelUpdateParameters]>;
       updateChannelCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, categoryId: ChannelCategoryId | AnyNumber | Uint8Array, params: ChannelCategoryUpdateParameters | { new_meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelCategoryId, ChannelCategoryUpdateParameters]>;
       updateChannelCensorshipStatus: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, isCensored: bool | boolean | Uint8Array, rationale: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, bool, Bytes]>;
       updatePerson: AugmentedSubmittable<(actor: PersonActor | { Member: any } | { Curator: any } | string | Uint8Array, person: PersonId | AnyNumber | Uint8Array, params: PersonUpdateParameters | { assets?: any; meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [PersonActor, PersonId, PersonUpdateParameters]>;
       updatePlaylist: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, playlist: PlaylistId | AnyNumber | Uint8Array, params: PlaylistUpdateParameters | { new_meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, PlaylistId, PlaylistUpdateParameters]>;
       updateSeries: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: SeriesParameters | { assets?: any; seasons?: any; meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, SeriesParameters]>;
-      updateVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array, params: VideoUpdateParameters | { assets?: any; new_meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId, VideoUpdateParameters]>;
+      updateVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array, params: VideoUpdateParameters | { assets_to_upload?: any; new_meta?: any; assets_to_remove?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId, VideoUpdateParameters]>;
       updateVideoCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, categoryId: VideoCategoryId | AnyNumber | Uint8Array, params: VideoCategoryUpdateParameters | { new_meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoCategoryId, VideoCategoryUpdateParameters]>;
       updateVideoCensorshipStatus: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array, isCensored: bool | boolean | Uint8Array, rationale: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId, bool, Bytes]>;
     };
@@ -586,7 +583,169 @@ declare module '@polkadot/api/types/submittable' {
     memo: {
       updateMemo: AugmentedSubmittable<(memo: MemoText | string) => SubmittableExtrinsic<ApiType>, [MemoText]>;
     };
-    operationsWorkingGroup: {
+    operationsWorkingGroupAlpha: {
+      /**
+       * Begin accepting worker applications to an opening that is active.
+       * Require signed leader origin or the root (to accept applications for the leader position).
+       **/
+      acceptApplications: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
+      /**
+       * Add an opening for a worker role.
+       * Require signed leader origin or the root (to add opening for the leader position).
+       **/
+      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_application_stake_unstaking_period?: any; terminate_role_stake_unstaking_period?: any; exit_role_application_stake_unstaking_period?: any; exit_role_stake_unstaking_period?: any } | string | Uint8Array, humanReadableText: Bytes | string | Uint8Array, openingType: OpeningType | 'Leader' | 'Worker' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [ActivateOpeningAt, OpeningPolicyCommitment, Bytes, OpeningType]>;
+      /**
+       * Apply on a worker opening.
+       **/
+      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]>;
+      /**
+       * Begin reviewing, and therefore not accepting new applications.
+       * Require signed leader origin or the root (to begin review applications for the leader position).
+       **/
+      beginApplicantReview: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
+      /**
+       * 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).
+       **/
+      decreaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Fill opening for worker/lead.
+       * Require signed leader origin or the root (to fill opening for the leader position).
+       **/
+      fillOpening: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array, successfulApplicationIds: ApplicationIdSet, rewardPolicy: Option<RewardPolicy> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId, ApplicationIdSet, Option<RewardPolicy>]>;
+      /**
+       * 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.
+       **/
+      increaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Leave the role by the active worker.
+       **/
+      leaveRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
+      /**
+       * Sets the capacity to enable working group budget. Requires root origin.
+       **/
+      setMintCapacity: AugmentedSubmittable<(newCapacity: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BalanceOf]>;
+      /**
+       * 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).
+       **/
+      slashStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Terminate the worker application. Can be done by the lead only.
+       **/
+      terminateApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
+      /**
+       * Terminate the active worker by the lead.
+       * Require signed leader origin or the root (to terminate the leader role).
+       **/
+      terminateRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array, slashStake: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes, bool]>;
+      /**
+       * Update the reward account associated with a set reward relationship for the active worker.
+       **/
+      updateRewardAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRewardAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
+      /**
+       * 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).
+       **/
+      updateRewardAmount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newAmount: BalanceOfMint | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOfMint]>;
+      /**
+       * Update the associated role account of the active worker/lead.
+       **/
+      updateRoleAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRoleAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
+      /**
+       * Update the associated role storage.
+       **/
+      updateRoleStorage: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storage: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
+      /**
+       * Withdraw the worker application. Can be done by the worker itself only.
+       **/
+      withdrawApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
+    };
+    operationsWorkingGroupBeta: {
+      /**
+       * Begin accepting worker applications to an opening that is active.
+       * Require signed leader origin or the root (to accept applications for the leader position).
+       **/
+      acceptApplications: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
+      /**
+       * Add an opening for a worker role.
+       * Require signed leader origin or the root (to add opening for the leader position).
+       **/
+      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_application_stake_unstaking_period?: any; terminate_role_stake_unstaking_period?: any; exit_role_application_stake_unstaking_period?: any; exit_role_stake_unstaking_period?: any } | string | Uint8Array, humanReadableText: Bytes | string | Uint8Array, openingType: OpeningType | 'Leader' | 'Worker' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [ActivateOpeningAt, OpeningPolicyCommitment, Bytes, OpeningType]>;
+      /**
+       * Apply on a worker opening.
+       **/
+      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]>;
+      /**
+       * Begin reviewing, and therefore not accepting new applications.
+       * Require signed leader origin or the root (to begin review applications for the leader position).
+       **/
+      beginApplicantReview: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
+      /**
+       * 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).
+       **/
+      decreaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Fill opening for worker/lead.
+       * Require signed leader origin or the root (to fill opening for the leader position).
+       **/
+      fillOpening: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array, successfulApplicationIds: ApplicationIdSet, rewardPolicy: Option<RewardPolicy> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId, ApplicationIdSet, Option<RewardPolicy>]>;
+      /**
+       * 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.
+       **/
+      increaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Leave the role by the active worker.
+       **/
+      leaveRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
+      /**
+       * Sets the capacity to enable working group budget. Requires root origin.
+       **/
+      setMintCapacity: AugmentedSubmittable<(newCapacity: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BalanceOf]>;
+      /**
+       * 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).
+       **/
+      slashStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Terminate the worker application. Can be done by the lead only.
+       **/
+      terminateApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
+      /**
+       * Terminate the active worker by the lead.
+       * Require signed leader origin or the root (to terminate the leader role).
+       **/
+      terminateRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array, slashStake: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes, bool]>;
+      /**
+       * Update the reward account associated with a set reward relationship for the active worker.
+       **/
+      updateRewardAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRewardAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
+      /**
+       * 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).
+       **/
+      updateRewardAmount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newAmount: BalanceOfMint | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOfMint]>;
+      /**
+       * Update the associated role account of the active worker/lead.
+       **/
+      updateRoleAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRoleAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
+      /**
+       * Update the associated role storage.
+       **/
+      updateRoleStorage: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storage: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
+      /**
+       * Withdraw the worker application. Can be done by the worker itself only.
+       **/
+      withdrawApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
+    };
+    operationsWorkingGroupGamma: {
       /**
        * Begin accepting worker applications to an opening that is active.
        * Require signed leader origin or the root (to accept applications for the leader position).
@@ -677,12 +836,12 @@ declare module '@polkadot/api/types/submittable' {
        * Create 'Begin review working group leader applications' proposal type.
        * This proposal uses `begin_applicant_review()` extrinsic from the Joystream `working group` module.
        **/
-      createBeginReviewWorkingGroupLeaderApplicationsProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, openingId: OpeningId | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, OpeningId, WorkingGroup]>;
+      createBeginReviewWorkingGroupLeaderApplicationsProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, openingId: OpeningId | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, OpeningId, WorkingGroup]>;
       /**
        * Create 'decrease working group leader stake' proposal type.
        * This proposal uses `decrease_stake()` extrinsic from the `working-group`  module.
        **/
-      createDecreaseWorkingGroupLeaderStakeProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, decreasingStake: BalanceOf | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOf, WorkingGroup]>;
+      createDecreaseWorkingGroupLeaderStakeProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, decreasingStake: BalanceOf | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOf, WorkingGroup]>;
       /**
        * Create 'Fill working group leader opening' proposal type.
        * This proposal uses `fill_opening()` extrinsic from the Joystream `working group` module.
@@ -707,17 +866,17 @@ declare module '@polkadot/api/types/submittable' {
        * Create 'set working group leader reward' proposal type.
        * This proposal uses `update_reward_amount()` extrinsic from the `working-group`  module.
        **/
-      createSetWorkingGroupLeaderRewardProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, rewardAmount: BalanceOfMint | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOfMint, WorkingGroup]>;
+      createSetWorkingGroupLeaderRewardProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, rewardAmount: BalanceOfMint | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOfMint, WorkingGroup]>;
       /**
        * Create 'Set working group mint capacity' proposal type.
        * This proposal uses `set_mint_capacity()` extrinsic from the `working-group`  module.
        **/
-      createSetWorkingGroupMintCapacityProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, mintBalance: BalanceOfMint | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, BalanceOfMint, WorkingGroup]>;
+      createSetWorkingGroupMintCapacityProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, mintBalance: BalanceOfMint | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, BalanceOfMint, WorkingGroup]>;
       /**
        * Create 'slash working group leader stake' proposal type.
        * This proposal uses `slash_stake()` extrinsic from the `working-group`  module.
        **/
-      createSlashWorkingGroupLeaderStakeProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, slashingStake: BalanceOf | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOf, WorkingGroup]>;
+      createSlashWorkingGroupLeaderStakeProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, slashingStake: BalanceOf | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOf, WorkingGroup]>;
       /**
        * Create 'Spending' proposal type.
        * This proposal uses `spend_from_council_mint()` extrinsic from the `governance::council`  module.

File diff suppressed because it is too large
+ 0 - 0
types/augment-codec/augment-types.ts


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

@@ -82,12 +82,15 @@
     },
     "WorkingGroup": {
         "_enum": [
-            "Reserved",
-            "Forum",
+            "_Reserved0",
+            "_Reserved1",
             "Storage",
             "Content",
-            "Operations",
-            "Gateway"
+            "OperationsAlpha",
+            "Gateway",
+            "Distribution",
+            "OperationsBeta",
+            "OperationsGamma"
         ]
     },
     "SlashingTerms": {
@@ -104,7 +107,6 @@
     "Address": "AccountId",
     "LookupSource": "AccountId",
     "ChannelId": "u64",
-    "DAOId": "u64",
     "Url": "Text",
     "EntryMethod": {
         "_enum": {
@@ -763,25 +765,21 @@
             "Lead": "Null"
         }
     },
-    "NewAsset": {
-        "_enum": {
-            "Upload": "u64",
-            "Urls": "Vec<Url>"
-        }
+    "StorageAssets": {
+        "object_creation_list": "Vec<DataObjectCreationParameters>",
+        "expected_data_size_fee": "u128"
     },
     "Channel": {
         "owner": "ChannelOwner",
-        "videos": "Vec<VideoId>",
-        "playlists": "Vec<PlaylistId>",
-        "series": "Vec<SeriesId>",
+        "num_videos": "u64",
         "is_censored": "bool",
-        "reward_account": "Option<GenericAccountId>"
+        "reward_account": "Option<GenericAccountId>",
+        "deletion_prize_source_account_id": "GenericAccountId"
     },
     "ChannelOwner": {
         "_enum": {
             "Member": "MemberId",
-            "Curators": "CuratorGroupId",
-            "Dao": "DAOId"
+            "Curators": "CuratorGroupId"
         }
     },
     "ChannelCategoryId": "u64",
@@ -793,14 +791,15 @@
         "new_meta": "Bytes"
     },
     "ChannelCreationParameters": {
-        "assets": "Vec<NewAsset>",
-        "meta": "Bytes",
+        "assets": "Option<StorageAssets>",
+        "meta": "Option<Bytes>",
         "reward_account": "Option<GenericAccountId>"
     },
     "ChannelUpdateParameters": {
-        "assets": "Option<Vec<NewAsset>>",
+        "assets_to_upload": "Option<StorageAssets>",
         "new_meta": "Option<Bytes>",
-        "reward_account": "Option<Option<GenericAccountId>>"
+        "reward_account": "Option<Option<GenericAccountId>>",
+        "assets_to_remove": "Vec<DataObjectId>"
     },
     "ChannelOwnershipTransferRequestId": "u64",
     "ChannelOwnershipTransferRequest": {
@@ -824,12 +823,13 @@
         "new_meta": "Bytes"
     },
     "VideoCreationParameters": {
-        "assets": "Vec<NewAsset>",
-        "meta": "Bytes"
+        "assets": "Option<StorageAssets>",
+        "meta": "Option<Bytes>"
     },
     "VideoUpdateParameters": {
-        "assets": "Option<Vec<NewAsset>>",
-        "new_meta": "Option<Bytes>"
+        "assets_to_upload": "Option<StorageAssets>",
+        "new_meta": "Option<Bytes>",
+        "assets_to_remove": "Vec<DataObjectId>"
     },
     "Person": {
         "controlled_by": "PersonController"
@@ -848,11 +848,11 @@
         }
     },
     "PersonCreationParameters": {
-        "assets": "Vec<NewAsset>",
+        "assets": "StorageAssets",
         "meta": "Bytes"
     },
     "PersonUpdateParameters": {
-        "assets": "Option<Vec<NewAsset>>",
+        "assets": "Option<StorageAssets>",
         "meta": "Option<Bytes>"
     },
     "Playlist": {
@@ -874,12 +874,12 @@
         "episodes": "Vec<VideoId>"
     },
     "SeriesParameters": {
-        "assets": "Option<Vec<NewAsset>>",
+        "assets": "Option<StorageAssets>",
         "seasons": "Option<Vec<Option<SeasonParameters>>>",
         "meta": "Option<Bytes>"
     },
     "SeasonParameters": {
-        "assets": "Option<Vec<NewAsset>>",
+        "assets": "Option<StorageAssets>",
         "episodes": "Option<Vec<Option<EpisodeParemters>>>",
         "meta": "Option<Bytes>"
     },
@@ -890,6 +890,5 @@
         }
     },
     "MaxNumber": "u32",
-    "IsCensored": "bool",
-    "ContentId": "u64"
+    "IsCensored": "bool"
 }

+ 26 - 32
types/augment/all/types.ts

@@ -202,11 +202,10 @@ export interface CategoryId extends u64 {}
 /** @name Channel */
 export interface Channel extends Struct {
   readonly owner: ChannelOwner;
-  readonly videos: Vec<VideoId>;
-  readonly playlists: Vec<PlaylistId>;
-  readonly series: Vec<SeriesId>;
+  readonly num_videos: u64;
   readonly is_censored: bool;
   readonly reward_account: Option<GenericAccountId>;
+  readonly deletion_prize_source_account_id: GenericAccountId;
 }
 
 /** @name ChannelCategory */
@@ -230,8 +229,8 @@ export interface ChannelContentType extends Null {}
 
 /** @name ChannelCreationParameters */
 export interface ChannelCreationParameters extends Struct {
-  readonly assets: Vec<NewAsset>;
-  readonly meta: Bytes;
+  readonly assets: Option<StorageAssets>;
+  readonly meta: Option<Bytes>;
   readonly reward_account: Option<GenericAccountId>;
 }
 
@@ -247,8 +246,6 @@ export interface ChannelOwner extends Enum {
   readonly asMember: MemberId;
   readonly isCurators: boolean;
   readonly asCurators: CuratorGroupId;
-  readonly isDao: boolean;
-  readonly asDao: DAOId;
 }
 
 /** @name ChannelOwnershipTransferRequest */
@@ -267,9 +264,10 @@ export interface ChannelPublicationStatus extends Null {}
 
 /** @name ChannelUpdateParameters */
 export interface ChannelUpdateParameters extends Struct {
-  readonly assets: Option<Vec<NewAsset>>;
+  readonly assets_to_upload: Option<StorageAssets>;
   readonly new_meta: Option<Bytes>;
   readonly reward_account: Option<Option<GenericAccountId>>;
+  readonly assets_to_remove: Vec<DataObjectId>;
 }
 
 /** @name ChildPositionInParentCategory */
@@ -308,9 +306,6 @@ export interface ContentActor extends Enum {
   readonly isLead: boolean;
 }
 
-/** @name ContentId */
-export interface ContentId extends u64 {}
-
 /** @name ContentIdSet */
 export interface ContentIdSet extends BTreeSet<Cid> {}
 
@@ -359,9 +354,6 @@ export interface CuratorOpening extends Null {}
 /** @name CuratorOpeningId */
 export interface CuratorOpeningId extends Null {}
 
-/** @name DAOId */
-export interface DAOId extends u64 {}
-
 /** @name DataObject */
 export interface DataObject extends Struct {
   readonly accepted: bool;
@@ -654,14 +646,6 @@ export interface ModerationAction extends Struct {
   readonly rationale: Text;
 }
 
-/** @name NewAsset */
-export interface NewAsset extends Enum {
-  readonly isUpload: boolean;
-  readonly asUpload: u64;
-  readonly isUrls: boolean;
-  readonly asUrls: Vec<Url>;
-}
-
 /** @name NextAdjustment */
 export interface NextAdjustment extends Struct {
   readonly adjustment: AdjustOnInterval;
@@ -781,7 +765,7 @@ export interface PersonController extends Enum {
 
 /** @name PersonCreationParameters */
 export interface PersonCreationParameters extends Struct {
-  readonly assets: Vec<NewAsset>;
+  readonly assets: StorageAssets;
   readonly meta: Bytes;
 }
 
@@ -790,7 +774,7 @@ export interface PersonId extends u64 {}
 
 /** @name PersonUpdateParameters */
 export interface PersonUpdateParameters extends Struct {
-  readonly assets: Option<Vec<NewAsset>>;
+  readonly assets: Option<StorageAssets>;
   readonly meta: Option<Bytes>;
 }
 
@@ -1079,7 +1063,7 @@ export interface Season extends Struct {
 
 /** @name SeasonParameters */
 export interface SeasonParameters extends Struct {
-  readonly assets: Option<Vec<NewAsset>>;
+  readonly assets: Option<StorageAssets>;
   readonly episodes: Option<Vec<Option<EpisodeParemters>>>;
   readonly meta: Option<Bytes>;
 }
@@ -1105,7 +1089,7 @@ export interface SeriesId extends u64 {}
 
 /** @name SeriesParameters */
 export interface SeriesParameters extends Struct {
-  readonly assets: Option<Vec<NewAsset>>;
+  readonly assets: Option<StorageAssets>;
   readonly seasons: Option<Vec<Option<SeasonParameters>>>;
   readonly meta: Option<Bytes>;
 }
@@ -1205,6 +1189,12 @@ export interface StaticBagId extends Enum {
 /** @name Status */
 export interface Status extends Null {}
 
+/** @name StorageAssets */
+export interface StorageAssets extends Struct {
+  readonly object_creation_list: Vec<DataObjectCreationParameters>;
+  readonly expected_data_size_fee: u128;
+}
+
 /** @name StorageBucket */
 export interface StorageBucket extends Struct {
   readonly operator_status: StorageBucketOperatorStatus;
@@ -1349,8 +1339,8 @@ export interface VideoCategoryUpdateParameters extends Struct {
 
 /** @name VideoCreationParameters */
 export interface VideoCreationParameters extends Struct {
-  readonly assets: Vec<NewAsset>;
-  readonly meta: Bytes;
+  readonly assets: Option<StorageAssets>;
+  readonly meta: Option<Bytes>;
 }
 
 /** @name VideoId */
@@ -1358,8 +1348,9 @@ export interface VideoId extends u64 {}
 
 /** @name VideoUpdateParameters */
 export interface VideoUpdateParameters extends Struct {
-  readonly assets: Option<Vec<NewAsset>>;
+  readonly assets_to_upload: Option<StorageAssets>;
   readonly new_meta: Option<Bytes>;
+  readonly assets_to_remove: Vec<DataObjectId>;
 }
 
 /** @name VoteKind */
@@ -1404,12 +1395,15 @@ export interface WorkerOf extends Struct {
 
 /** @name WorkingGroup */
 export interface WorkingGroup extends Enum {
-  readonly isReserved: boolean;
-  readonly isForum: boolean;
+  readonly isReserved0: boolean;
+  readonly isReserved1: boolean;
   readonly isStorage: boolean;
   readonly isContent: boolean;
-  readonly isOperations: boolean;
+  readonly isOperationsAlpha: boolean;
   readonly isGateway: boolean;
+  readonly isDistribution: boolean;
+  readonly isOperationsBeta: boolean;
+  readonly isOperationsGamma: boolean;
 }
 
 /** @name WorkingGroupUnstaker */

+ 13 - 5
types/augment/augment-api-consts.ts

@@ -69,7 +69,19 @@ declare module '@polkadot/api/types/consts' {
     members: {
       screenedMemberMaxInitialBalance: BalanceOf & AugmentedConst<ApiType>;
     };
-    operationsWorkingGroup: {
+    operationsWorkingGroupAlpha: {
+      /**
+       * Exports const -  max simultaneous active worker number.
+       **/
+      maxWorkerNumberLimit: u32 & AugmentedConst<ApiType>;
+    };
+    operationsWorkingGroupBeta: {
+      /**
+       * Exports const -  max simultaneous active worker number.
+       **/
+      maxWorkerNumberLimit: u32 & AugmentedConst<ApiType>;
+    };
+    operationsWorkingGroupGamma: {
       /**
        * Exports const -  max simultaneous active worker number.
        **/
@@ -205,10 +217,6 @@ declare module '@polkadot/api/types/consts' {
        * 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.
        **/

File diff suppressed because it is too large
+ 948 - 20
types/augment/augment-api-errors.ts


+ 276 - 12
types/augment/augment-api-events.ts

@@ -2,7 +2,7 @@
 /* eslint-disable */
 
 import type { BTreeMap, BTreeSet, Bytes, Option, Vec, bool, u32, u64 } from '@polkadot/types';
-import type { ApplicationId, ApplicationIdToWorkerIdMap, BagId, CategoryId, Channel, ChannelCategory, ChannelCategoryCreationParameters, ChannelCategoryId, ChannelCategoryUpdateParameters, ChannelCreationParameters, ChannelId, ChannelOwnershipTransferRequest, ChannelOwnershipTransferRequestId, ChannelUpdateParameters, Cid, ContentActor, ContentId, CuratorGroupId, CuratorId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrizeRecord, DynamicBagId, DynamicBagType, EntryMethod, IsCensored, MemberId, MintBalanceOf, MintId, NewAsset, OpeningId, PersonCreationParameters, PersonId, PersonUpdateParameters, PlaylistCreationParameters, PlaylistId, PlaylistUpdateParameters, PostId, ProposalId, ProposalStatus, RationaleText, Series, SeriesId, SeriesParameters, StorageBucketId, ThreadId, UploadParameters, VideoCategoryCreationParameters, VideoCategoryId, VideoCategoryUpdateParameters, VideoCreationParameters, VideoId, VideoUpdateParameters, VoteKind, Voucher, WorkerId } from './all';
+import type { ApplicationId, ApplicationIdToWorkerIdMap, BagId, CategoryId, Channel, ChannelCategory, ChannelCategoryCreationParameters, ChannelCategoryId, ChannelCategoryUpdateParameters, ChannelCreationParameters, ChannelId, ChannelOwnershipTransferRequest, ChannelOwnershipTransferRequestId, ChannelUpdateParameters, Cid, ContentActor, CuratorGroupId, CuratorId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrizeRecord, DynamicBagId, DynamicBagType, EntryMethod, IsCensored, MemberId, MintBalanceOf, MintId, OpeningId, PersonCreationParameters, PersonId, PersonUpdateParameters, PlaylistCreationParameters, PlaylistId, PlaylistUpdateParameters, PostId, ProposalId, ProposalStatus, RationaleText, Series, SeriesId, SeriesParameters, StorageAssets, StorageBucketId, ThreadId, UploadParameters, VideoCategoryCreationParameters, VideoCategoryId, VideoCategoryUpdateParameters, VideoCreationParameters, VideoId, VideoUpdateParameters, 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';
@@ -53,12 +53,13 @@ declare module '@polkadot/api/types/events' {
       Unreserved: AugmentedEvent<ApiType, [AccountId, Balance]>;
     };
     content: {
-      ChannelAssetsRemoved: AugmentedEvent<ApiType, [ContentActor, ChannelId, Vec<ContentId>]>;
+      ChannelAssetsRemoved: AugmentedEvent<ApiType, [ContentActor, ChannelId, BTreeSet<DataObjectId>, Channel]>;
       ChannelCategoryCreated: AugmentedEvent<ApiType, [ChannelCategoryId, ChannelCategory, ChannelCategoryCreationParameters]>;
       ChannelCategoryDeleted: AugmentedEvent<ApiType, [ContentActor, ChannelCategoryId]>;
       ChannelCategoryUpdated: AugmentedEvent<ApiType, [ContentActor, ChannelCategoryId, ChannelCategoryUpdateParameters]>;
       ChannelCensorshipStatusUpdated: AugmentedEvent<ApiType, [ContentActor, ChannelId, IsCensored, Bytes]>;
       ChannelCreated: AugmentedEvent<ApiType, [ContentActor, ChannelId, Channel, ChannelCreationParameters]>;
+      ChannelDeleted: AugmentedEvent<ApiType, [ContentActor, ChannelId]>;
       ChannelOwnershipTransferred: AugmentedEvent<ApiType, [ContentActor, ChannelOwnershipTransferRequestId]>;
       ChannelOwnershipTransferRequested: AugmentedEvent<ApiType, [ContentActor, ChannelOwnershipTransferRequestId, ChannelOwnershipTransferRequest]>;
       ChannelOwnershipTransferRequestWithdrawn: AugmentedEvent<ApiType, [ContentActor, ChannelOwnershipTransferRequestId]>;
@@ -68,15 +69,15 @@ declare module '@polkadot/api/types/events' {
       CuratorGroupStatusSet: AugmentedEvent<ApiType, [CuratorGroupId, bool]>;
       CuratorRemoved: AugmentedEvent<ApiType, [CuratorGroupId, CuratorId]>;
       FeaturedVideosSet: AugmentedEvent<ApiType, [ContentActor, Vec<VideoId>]>;
-      PersonCreated: AugmentedEvent<ApiType, [ContentActor, PersonId, Vec<NewAsset>, PersonCreationParameters]>;
+      PersonCreated: AugmentedEvent<ApiType, [ContentActor, PersonId, StorageAssets, PersonCreationParameters]>;
       PersonDeleted: AugmentedEvent<ApiType, [ContentActor, PersonId]>;
-      PersonUpdated: AugmentedEvent<ApiType, [ContentActor, PersonId, Vec<NewAsset>, PersonUpdateParameters]>;
+      PersonUpdated: AugmentedEvent<ApiType, [ContentActor, PersonId, StorageAssets, PersonUpdateParameters]>;
       PlaylistCreated: AugmentedEvent<ApiType, [ContentActor, PlaylistId, PlaylistCreationParameters]>;
       PlaylistDeleted: AugmentedEvent<ApiType, [ContentActor, PlaylistId]>;
       PlaylistUpdated: AugmentedEvent<ApiType, [ContentActor, PlaylistId, PlaylistUpdateParameters]>;
-      SeriesCreated: AugmentedEvent<ApiType, [ContentActor, SeriesId, Vec<NewAsset>, SeriesParameters, Series]>;
+      SeriesCreated: AugmentedEvent<ApiType, [ContentActor, SeriesId, StorageAssets, SeriesParameters, Series]>;
       SeriesDeleted: AugmentedEvent<ApiType, [ContentActor, SeriesId]>;
-      SeriesUpdated: AugmentedEvent<ApiType, [ContentActor, SeriesId, Vec<NewAsset>, SeriesParameters, Series]>;
+      SeriesUpdated: AugmentedEvent<ApiType, [ContentActor, SeriesId, StorageAssets, SeriesParameters, Series]>;
       VideoCategoryCreated: AugmentedEvent<ApiType, [ContentActor, VideoCategoryId, VideoCategoryCreationParameters]>;
       VideoCategoryDeleted: AugmentedEvent<ApiType, [ContentActor, VideoCategoryId]>;
       VideoCategoryUpdated: AugmentedEvent<ApiType, [ContentActor, VideoCategoryId, VideoCategoryUpdateParameters]>;
@@ -564,9 +565,9 @@ declare module '@polkadot/api/types/events' {
       MemberRegistered: AugmentedEvent<ApiType, [MemberId, AccountId, EntryMethod]>;
       MemberSetControllerAccount: AugmentedEvent<ApiType, [MemberId, AccountId]>;
       MemberSetRootAccount: AugmentedEvent<ApiType, [MemberId, AccountId]>;
-      MemberUpdatedAboutText: AugmentedEvent<ApiType, [MemberId]>;
-      MemberUpdatedAvatar: AugmentedEvent<ApiType, [MemberId]>;
-      MemberUpdatedHandle: AugmentedEvent<ApiType, [MemberId]>;
+      MemberUpdatedAboutText: AugmentedEvent<ApiType, [MemberId, Bytes]>;
+      MemberUpdatedAvatar: AugmentedEvent<ApiType, [MemberId, Bytes]>;
+      MemberUpdatedHandle: AugmentedEvent<ApiType, [MemberId, Bytes]>;
     };
     memo: {
       MemoUpdated: AugmentedEvent<ApiType, [AccountId]>;
@@ -580,7 +581,267 @@ declare module '@polkadot/api/types/events' {
        **/
       Offence: AugmentedEvent<ApiType, [Kind, OpaqueTimeSlot, bool]>;
     };
-    operationsWorkingGroup: {
+    operationsWorkingGroupAlpha: {
+      /**
+       * Emits on accepting application for the worker opening.
+       * Params:
+       * - Opening id
+       **/
+      AcceptedApplications: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on terminating the application for the worker/lead opening.
+       * Params:
+       * - Worker application id
+       **/
+      ApplicationTerminated: AugmentedEvent<ApiType, [ApplicationId]>;
+      /**
+       * Emits on withdrawing the application for the worker/lead opening.
+       * Params:
+       * - Worker application id
+       **/
+      ApplicationWithdrawn: AugmentedEvent<ApiType, [ApplicationId]>;
+      /**
+       * Emits on adding the application for the worker opening.
+       * Params:
+       * - Opening id
+       * - Application id
+       **/
+      AppliedOnOpening: AugmentedEvent<ApiType, [OpeningId, ApplicationId]>;
+      /**
+       * Emits on beginning the application review for the worker/lead opening.
+       * Params:
+       * - Opening id
+       **/
+      BeganApplicationReview: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on setting the leader.
+       * Params:
+       * - Worker id.
+       **/
+      LeaderSet: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on un-setting the leader.
+       * Params:
+       **/
+      LeaderUnset: AugmentedEvent<ApiType, []>;
+      /**
+       * Emits on changing working group mint capacity.
+       * Params:
+       * - mint id.
+       * - new mint balance.
+       **/
+      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 updating the reward amount of the worker.
+       * Params:
+       * - Id of the worker.
+       **/
+      WorkerRewardAmountUpdated: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on updating the role account of the worker.
+       * Params:
+       * - Id of the worker.
+       * - Role account id of the worker.
+       **/
+      WorkerRoleAccountUpdated: AugmentedEvent<ApiType, [WorkerId, AccountId]>;
+      /**
+       * Emits on updating the worker storage role.
+       * Params:
+       * - Id of the worker.
+       * - Raw storage field.
+       **/
+      WorkerStorageUpdated: AugmentedEvent<ApiType, [WorkerId, Bytes]>;
+    };
+    operationsWorkingGroupBeta: {
+      /**
+       * Emits on accepting application for the worker opening.
+       * Params:
+       * - Opening id
+       **/
+      AcceptedApplications: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on terminating the application for the worker/lead opening.
+       * Params:
+       * - Worker application id
+       **/
+      ApplicationTerminated: AugmentedEvent<ApiType, [ApplicationId]>;
+      /**
+       * Emits on withdrawing the application for the worker/lead opening.
+       * Params:
+       * - Worker application id
+       **/
+      ApplicationWithdrawn: AugmentedEvent<ApiType, [ApplicationId]>;
+      /**
+       * Emits on adding the application for the worker opening.
+       * Params:
+       * - Opening id
+       * - Application id
+       **/
+      AppliedOnOpening: AugmentedEvent<ApiType, [OpeningId, ApplicationId]>;
+      /**
+       * Emits on beginning the application review for the worker/lead opening.
+       * Params:
+       * - Opening id
+       **/
+      BeganApplicationReview: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on setting the leader.
+       * Params:
+       * - Worker id.
+       **/
+      LeaderSet: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on un-setting the leader.
+       * Params:
+       **/
+      LeaderUnset: AugmentedEvent<ApiType, []>;
+      /**
+       * Emits on changing working group mint capacity.
+       * Params:
+       * - mint id.
+       * - new mint balance.
+       **/
+      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 updating the reward amount of the worker.
+       * Params:
+       * - Id of the worker.
+       **/
+      WorkerRewardAmountUpdated: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on updating the role account of the worker.
+       * Params:
+       * - Id of the worker.
+       * - Role account id of the worker.
+       **/
+      WorkerRoleAccountUpdated: AugmentedEvent<ApiType, [WorkerId, AccountId]>;
+      /**
+       * Emits on updating the worker storage role.
+       * Params:
+       * - Id of the worker.
+       * - Raw storage field.
+       **/
+      WorkerStorageUpdated: AugmentedEvent<ApiType, [WorkerId, Bytes]>;
+    };
+    operationsWorkingGroupGamma: {
       /**
        * Emits on accepting application for the worker opening.
        * Params:
@@ -837,8 +1098,9 @@ declare module '@polkadot/api/types/events' {
        * Params
        * - data objects IDs
        * - initial uploading parameters
+       * - deletion prize for objects
        **/
-      DataObjectsUploaded: AugmentedEvent<ApiType, [Vec<DataObjectId>, UploadParameters]>;
+      DataObjectsUploaded: AugmentedEvent<ApiType, [Vec<DataObjectId>, UploadParameters, Balance]>;
       /**
        * Emits on creating distribution bucket.
        * Params
@@ -949,8 +1211,10 @@ declare module '@polkadot/api/types/events' {
        * Params
        * - dynamic bag ID
        * - optional DynamicBagDeletionPrize instance
+       * - assigned storage buckets' IDs
+       * - assigned distribution buckets' IDs
        **/
-      DynamicBagCreated: AugmentedEvent<ApiType, [DynamicBagId, Option<DynamicBagDeletionPrizeRecord>]>;
+      DynamicBagCreated: AugmentedEvent<ApiType, [DynamicBagId, Option<DynamicBagDeletionPrizeRecord>, BTreeSet<StorageBucketId>, BTreeSet<DistributionBucketId>]>;
       /**
        * Emits on deleting a dynamic bag.
        * Params

+ 128 - 2
types/augment/augment-api-query.ts

@@ -583,7 +583,133 @@ declare module '@polkadot/api/types/storage' {
        **/
       reportsByKindIndex: AugmentedQuery<ApiType, (arg: Kind | string | Uint8Array) => Observable<Bytes>, [Kind]>;
     };
-    operationsWorkingGroup: {
+    operationsWorkingGroupAlpha: {
+      /**
+       * Count of active workers.
+       **/
+      activeWorkerCount: AugmentedQuery<ApiType, () => Observable<u32>, []>;
+      /**
+       * Maps identifier to worker application on opening.
+       **/
+      applicationById: AugmentedQuery<ApiType, (arg: ApplicationId | AnyNumber | Uint8Array) => Observable<ApplicationOf>, [ApplicationId]>;
+      /**
+       * The current lead.
+       **/
+      currentLead: AugmentedQuery<ApiType, () => Observable<Option<WorkerId>>, []>;
+      /**
+       * Map member id by hiring application id.
+       * Required by StakingEventsHandler callback call to refund the balance on unstaking.
+       **/
+      memberIdByHiringApplicationId: AugmentedQuery<ApiType, (arg: HiringApplicationId | AnyNumber | Uint8Array) => Observable<MemberId>, [HiringApplicationId]>;
+      /**
+       * The mint currently funding the rewards for this module.
+       **/
+      mint: AugmentedQuery<ApiType, () => Observable<MintId>, []>;
+      /**
+       * Next identifier value for new worker application.
+       **/
+      nextApplicationId: AugmentedQuery<ApiType, () => Observable<ApplicationId>, []>;
+      /**
+       * Next identifier value for new worker opening.
+       **/
+      nextOpeningId: AugmentedQuery<ApiType, () => Observable<OpeningId>, []>;
+      /**
+       * Next identifier for new worker.
+       **/
+      nextWorkerId: AugmentedQuery<ApiType, () => Observable<WorkerId>, []>;
+      /**
+       * Maps identifier to worker opening.
+       **/
+      openingById: AugmentedQuery<ApiType, (arg: OpeningId | AnyNumber | Uint8Array) => Observable<OpeningOf>, [OpeningId]>;
+      /**
+       * Opening human readable text length limits
+       **/
+      openingHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Worker application human readable text length limits
+       **/
+      workerApplicationHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Maps identifier to corresponding worker.
+       **/
+      workerById: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<WorkerOf>, [WorkerId]>;
+      /**
+       * Worker exit rationale text length limits.
+       **/
+      workerExitRationaleText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Maps identifier to corresponding worker storage.
+       **/
+      workerStorage: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<Bytes>, [WorkerId]>;
+      /**
+       * Worker storage size upper bound.
+       **/
+      workerStorageSize: AugmentedQuery<ApiType, () => Observable<u16>, []>;
+    };
+    operationsWorkingGroupBeta: {
+      /**
+       * Count of active workers.
+       **/
+      activeWorkerCount: AugmentedQuery<ApiType, () => Observable<u32>, []>;
+      /**
+       * Maps identifier to worker application on opening.
+       **/
+      applicationById: AugmentedQuery<ApiType, (arg: ApplicationId | AnyNumber | Uint8Array) => Observable<ApplicationOf>, [ApplicationId]>;
+      /**
+       * The current lead.
+       **/
+      currentLead: AugmentedQuery<ApiType, () => Observable<Option<WorkerId>>, []>;
+      /**
+       * Map member id by hiring application id.
+       * Required by StakingEventsHandler callback call to refund the balance on unstaking.
+       **/
+      memberIdByHiringApplicationId: AugmentedQuery<ApiType, (arg: HiringApplicationId | AnyNumber | Uint8Array) => Observable<MemberId>, [HiringApplicationId]>;
+      /**
+       * The mint currently funding the rewards for this module.
+       **/
+      mint: AugmentedQuery<ApiType, () => Observable<MintId>, []>;
+      /**
+       * Next identifier value for new worker application.
+       **/
+      nextApplicationId: AugmentedQuery<ApiType, () => Observable<ApplicationId>, []>;
+      /**
+       * Next identifier value for new worker opening.
+       **/
+      nextOpeningId: AugmentedQuery<ApiType, () => Observable<OpeningId>, []>;
+      /**
+       * Next identifier for new worker.
+       **/
+      nextWorkerId: AugmentedQuery<ApiType, () => Observable<WorkerId>, []>;
+      /**
+       * Maps identifier to worker opening.
+       **/
+      openingById: AugmentedQuery<ApiType, (arg: OpeningId | AnyNumber | Uint8Array) => Observable<OpeningOf>, [OpeningId]>;
+      /**
+       * Opening human readable text length limits
+       **/
+      openingHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Worker application human readable text length limits
+       **/
+      workerApplicationHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Maps identifier to corresponding worker.
+       **/
+      workerById: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<WorkerOf>, [WorkerId]>;
+      /**
+       * Worker exit rationale text length limits.
+       **/
+      workerExitRationaleText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
+      /**
+       * Maps identifier to corresponding worker storage.
+       **/
+      workerStorage: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<Bytes>, [WorkerId]>;
+      /**
+       * Worker storage size upper bound.
+       **/
+      workerStorageSize: AugmentedQuery<ApiType, () => Observable<u16>, []>;
+    };
+    operationsWorkingGroupGamma: {
       /**
        * Count of active workers.
        **/
@@ -1137,7 +1263,7 @@ declare module '@polkadot/api/types/storage' {
        **/
       uploadingBlocked: AugmentedQuery<ApiType, () => Observable<bool>, []>;
       /**
-       * "Max objects number for a storage bucket voucher" number limit.
+       * "Max objects number for a storage  bucket voucher" number limit.
        **/
       voucherMaxObjectsNumberLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
       /**

+ 173 - 14
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 } from '@polkadot/types/types';
-import type { ActivateOpeningAt, AddOpeningParameters, ApplicationId, ApplicationIdSet, BagId, BalanceOfMint, CategoryId, ChannelCategoryCreationParameters, ChannelCategoryId, ChannelCategoryUpdateParameters, ChannelCreationParameters, ChannelId, ChannelOwnershipTransferRequest, ChannelOwnershipTransferRequestId, ChannelUpdateParameters, Cid, ContentActor, ContentId, CuratorGroupId, CuratorId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrize, DynamicBagId, DynamicBagType, ElectionParameters, FillOpeningParameters, MemberId, MemoText, OpeningId, OpeningPolicyCommitment, OpeningType, PaidTermId, PersonActor, PersonCreationParameters, PersonId, PersonUpdateParameters, PlaylistCreationParameters, PlaylistId, PlaylistUpdateParameters, PostId, ProposalId, RewardPolicy, SeriesId, SeriesParameters, StorageBucketId, TerminateRoleParameters, ThreadId, UploadParameters, VideoCategoryCreationParameters, VideoCategoryId, VideoCategoryUpdateParameters, VideoCreationParameters, VideoId, VideoUpdateParameters, VoteKind, WorkerId, WorkingGroup } from './all';
+import type { ActivateOpeningAt, AddOpeningParameters, ApplicationId, ApplicationIdSet, BagId, BalanceOfMint, CategoryId, ChannelCategoryCreationParameters, ChannelCategoryId, ChannelCategoryUpdateParameters, ChannelCreationParameters, ChannelId, ChannelOwnershipTransferRequest, ChannelOwnershipTransferRequestId, ChannelUpdateParameters, Cid, ContentActor, CuratorGroupId, CuratorId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrize, DynamicBagId, DynamicBagType, ElectionParameters, FillOpeningParameters, MemberId, MemoText, OpeningId, OpeningPolicyCommitment, OpeningType, PaidTermId, PersonActor, PersonCreationParameters, PersonId, PersonUpdateParameters, PlaylistCreationParameters, PlaylistId, PlaylistUpdateParameters, PostId, ProposalId, RewardPolicy, SeriesId, SeriesParameters, StorageBucketId, TerminateRoleParameters, ThreadId, UploadParameters, VideoCategoryCreationParameters, VideoCategoryId, VideoCategoryUpdateParameters, VideoCreationParameters, VideoId, VideoUpdateParameters, 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';
@@ -137,16 +137,13 @@ declare module '@polkadot/api/types/submittable' {
       createSeries: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: SeriesParameters | { assets?: any; seasons?: any; meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, SeriesParameters]>;
       createVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: VideoCreationParameters | { assets?: any; meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, VideoCreationParameters]>;
       createVideoCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, params: VideoCategoryCreationParameters | { meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoCategoryCreationParameters]>;
+      deleteChannel: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, numObjectsToDelete: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, u64]>;
       deleteChannelCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, categoryId: ChannelCategoryId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelCategoryId]>;
       deletePerson: AugmentedSubmittable<(actor: PersonActor | { Member: any } | { Curator: any } | string | Uint8Array, person: PersonId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PersonActor, PersonId]>;
       deletePlaylist: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, playlist: PlaylistId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, PlaylistId]>;
       deleteSeries: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, series: SeriesId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, SeriesId]>;
-      deleteVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId]>;
+      deleteVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array, assetsToRemove: BTreeSet<DataObjectId>) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId, BTreeSet<DataObjectId>]>;
       deleteVideoCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, categoryId: VideoCategoryId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoCategoryId]>;
-      /**
-       * Remove assets of a channel from storage
-       **/
-      removeChannelAssets: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, assets: Vec<ContentId> | (ContentId | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, Vec<ContentId>]>;
       /**
        * Remove curator from a given curator group
        **/
@@ -158,13 +155,13 @@ declare module '@polkadot/api/types/submittable' {
        **/
       setCuratorGroupStatus: AugmentedSubmittable<(curatorGroupId: CuratorGroupId | AnyNumber | Uint8Array, isActive: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [CuratorGroupId, bool]>;
       setFeaturedVideos: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, list: Vec<VideoId> | (VideoId | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [ContentActor, Vec<VideoId>]>;
-      updateChannel: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: ChannelUpdateParameters | { assets?: any; new_meta?: any; reward_account?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, ChannelUpdateParameters]>;
+      updateChannel: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: ChannelUpdateParameters | { assets_to_upload?: any; new_meta?: any; reward_account?: any; assets_to_remove?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, ChannelUpdateParameters]>;
       updateChannelCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, categoryId: ChannelCategoryId | AnyNumber | Uint8Array, params: ChannelCategoryUpdateParameters | { new_meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelCategoryId, ChannelCategoryUpdateParameters]>;
       updateChannelCensorshipStatus: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, isCensored: bool | boolean | Uint8Array, rationale: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, bool, Bytes]>;
       updatePerson: AugmentedSubmittable<(actor: PersonActor | { Member: any } | { Curator: any } | string | Uint8Array, person: PersonId | AnyNumber | Uint8Array, params: PersonUpdateParameters | { assets?: any; meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [PersonActor, PersonId, PersonUpdateParameters]>;
       updatePlaylist: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, playlist: PlaylistId | AnyNumber | Uint8Array, params: PlaylistUpdateParameters | { new_meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, PlaylistId, PlaylistUpdateParameters]>;
       updateSeries: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, channelId: ChannelId | AnyNumber | Uint8Array, params: SeriesParameters | { assets?: any; seasons?: any; meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, ChannelId, SeriesParameters]>;
-      updateVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array, params: VideoUpdateParameters | { assets?: any; new_meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId, VideoUpdateParameters]>;
+      updateVideo: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array, params: VideoUpdateParameters | { assets_to_upload?: any; new_meta?: any; assets_to_remove?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId, VideoUpdateParameters]>;
       updateVideoCategory: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, categoryId: VideoCategoryId | AnyNumber | Uint8Array, params: VideoCategoryUpdateParameters | { new_meta?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoCategoryId, VideoCategoryUpdateParameters]>;
       updateVideoCensorshipStatus: AugmentedSubmittable<(actor: ContentActor | { Curator: any } | { Member: any } | { Lead: any } | string | Uint8Array, videoId: VideoId | AnyNumber | Uint8Array, isCensored: bool | boolean | Uint8Array, rationale: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentActor, VideoId, bool, Bytes]>;
     };
@@ -586,7 +583,169 @@ declare module '@polkadot/api/types/submittable' {
     memo: {
       updateMemo: AugmentedSubmittable<(memo: MemoText | string) => SubmittableExtrinsic<ApiType>, [MemoText]>;
     };
-    operationsWorkingGroup: {
+    operationsWorkingGroupAlpha: {
+      /**
+       * Begin accepting worker applications to an opening that is active.
+       * Require signed leader origin or the root (to accept applications for the leader position).
+       **/
+      acceptApplications: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
+      /**
+       * Add an opening for a worker role.
+       * Require signed leader origin or the root (to add opening for the leader position).
+       **/
+      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_application_stake_unstaking_period?: any; terminate_role_stake_unstaking_period?: any; exit_role_application_stake_unstaking_period?: any; exit_role_stake_unstaking_period?: any } | string | Uint8Array, humanReadableText: Bytes | string | Uint8Array, openingType: OpeningType | 'Leader' | 'Worker' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [ActivateOpeningAt, OpeningPolicyCommitment, Bytes, OpeningType]>;
+      /**
+       * Apply on a worker opening.
+       **/
+      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]>;
+      /**
+       * Begin reviewing, and therefore not accepting new applications.
+       * Require signed leader origin or the root (to begin review applications for the leader position).
+       **/
+      beginApplicantReview: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
+      /**
+       * 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).
+       **/
+      decreaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Fill opening for worker/lead.
+       * Require signed leader origin or the root (to fill opening for the leader position).
+       **/
+      fillOpening: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array, successfulApplicationIds: ApplicationIdSet, rewardPolicy: Option<RewardPolicy> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId, ApplicationIdSet, Option<RewardPolicy>]>;
+      /**
+       * 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.
+       **/
+      increaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Leave the role by the active worker.
+       **/
+      leaveRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
+      /**
+       * Sets the capacity to enable working group budget. Requires root origin.
+       **/
+      setMintCapacity: AugmentedSubmittable<(newCapacity: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BalanceOf]>;
+      /**
+       * 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).
+       **/
+      slashStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Terminate the worker application. Can be done by the lead only.
+       **/
+      terminateApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
+      /**
+       * Terminate the active worker by the lead.
+       * Require signed leader origin or the root (to terminate the leader role).
+       **/
+      terminateRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array, slashStake: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes, bool]>;
+      /**
+       * Update the reward account associated with a set reward relationship for the active worker.
+       **/
+      updateRewardAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRewardAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
+      /**
+       * 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).
+       **/
+      updateRewardAmount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newAmount: BalanceOfMint | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOfMint]>;
+      /**
+       * Update the associated role account of the active worker/lead.
+       **/
+      updateRoleAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRoleAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
+      /**
+       * Update the associated role storage.
+       **/
+      updateRoleStorage: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storage: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
+      /**
+       * Withdraw the worker application. Can be done by the worker itself only.
+       **/
+      withdrawApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
+    };
+    operationsWorkingGroupBeta: {
+      /**
+       * Begin accepting worker applications to an opening that is active.
+       * Require signed leader origin or the root (to accept applications for the leader position).
+       **/
+      acceptApplications: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
+      /**
+       * Add an opening for a worker role.
+       * Require signed leader origin or the root (to add opening for the leader position).
+       **/
+      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_application_stake_unstaking_period?: any; terminate_role_stake_unstaking_period?: any; exit_role_application_stake_unstaking_period?: any; exit_role_stake_unstaking_period?: any } | string | Uint8Array, humanReadableText: Bytes | string | Uint8Array, openingType: OpeningType | 'Leader' | 'Worker' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [ActivateOpeningAt, OpeningPolicyCommitment, Bytes, OpeningType]>;
+      /**
+       * Apply on a worker opening.
+       **/
+      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]>;
+      /**
+       * Begin reviewing, and therefore not accepting new applications.
+       * Require signed leader origin or the root (to begin review applications for the leader position).
+       **/
+      beginApplicantReview: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
+      /**
+       * 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).
+       **/
+      decreaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Fill opening for worker/lead.
+       * Require signed leader origin or the root (to fill opening for the leader position).
+       **/
+      fillOpening: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array, successfulApplicationIds: ApplicationIdSet, rewardPolicy: Option<RewardPolicy> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId, ApplicationIdSet, Option<RewardPolicy>]>;
+      /**
+       * 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.
+       **/
+      increaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Leave the role by the active worker.
+       **/
+      leaveRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
+      /**
+       * Sets the capacity to enable working group budget. Requires root origin.
+       **/
+      setMintCapacity: AugmentedSubmittable<(newCapacity: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BalanceOf]>;
+      /**
+       * 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).
+       **/
+      slashStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
+      /**
+       * Terminate the worker application. Can be done by the lead only.
+       **/
+      terminateApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
+      /**
+       * Terminate the active worker by the lead.
+       * Require signed leader origin or the root (to terminate the leader role).
+       **/
+      terminateRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array, slashStake: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes, bool]>;
+      /**
+       * Update the reward account associated with a set reward relationship for the active worker.
+       **/
+      updateRewardAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRewardAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
+      /**
+       * 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).
+       **/
+      updateRewardAmount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newAmount: BalanceOfMint | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOfMint]>;
+      /**
+       * Update the associated role account of the active worker/lead.
+       **/
+      updateRoleAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRoleAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
+      /**
+       * Update the associated role storage.
+       **/
+      updateRoleStorage: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storage: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
+      /**
+       * Withdraw the worker application. Can be done by the worker itself only.
+       **/
+      withdrawApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
+    };
+    operationsWorkingGroupGamma: {
       /**
        * Begin accepting worker applications to an opening that is active.
        * Require signed leader origin or the root (to accept applications for the leader position).
@@ -677,12 +836,12 @@ declare module '@polkadot/api/types/submittable' {
        * Create 'Begin review working group leader applications' proposal type.
        * This proposal uses `begin_applicant_review()` extrinsic from the Joystream `working group` module.
        **/
-      createBeginReviewWorkingGroupLeaderApplicationsProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, openingId: OpeningId | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, OpeningId, WorkingGroup]>;
+      createBeginReviewWorkingGroupLeaderApplicationsProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, openingId: OpeningId | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, OpeningId, WorkingGroup]>;
       /**
        * Create 'decrease working group leader stake' proposal type.
        * This proposal uses `decrease_stake()` extrinsic from the `working-group`  module.
        **/
-      createDecreaseWorkingGroupLeaderStakeProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, decreasingStake: BalanceOf | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOf, WorkingGroup]>;
+      createDecreaseWorkingGroupLeaderStakeProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, decreasingStake: BalanceOf | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOf, WorkingGroup]>;
       /**
        * Create 'Fill working group leader opening' proposal type.
        * This proposal uses `fill_opening()` extrinsic from the Joystream `working group` module.
@@ -707,17 +866,17 @@ declare module '@polkadot/api/types/submittable' {
        * Create 'set working group leader reward' proposal type.
        * This proposal uses `update_reward_amount()` extrinsic from the `working-group`  module.
        **/
-      createSetWorkingGroupLeaderRewardProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, rewardAmount: BalanceOfMint | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOfMint, WorkingGroup]>;
+      createSetWorkingGroupLeaderRewardProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, rewardAmount: BalanceOfMint | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOfMint, WorkingGroup]>;
       /**
        * Create 'Set working group mint capacity' proposal type.
        * This proposal uses `set_mint_capacity()` extrinsic from the `working-group`  module.
        **/
-      createSetWorkingGroupMintCapacityProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, mintBalance: BalanceOfMint | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, BalanceOfMint, WorkingGroup]>;
+      createSetWorkingGroupMintCapacityProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, mintBalance: BalanceOfMint | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, BalanceOfMint, WorkingGroup]>;
       /**
        * Create 'slash working group leader stake' proposal type.
        * This proposal uses `slash_stake()` extrinsic from the `working-group`  module.
        **/
-      createSlashWorkingGroupLeaderStakeProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, slashingStake: BalanceOf | AnyNumber | Uint8Array, workingGroup: WorkingGroup | 'Reserved' | 'Forum' | 'Storage' | 'Content' | 'Operations' | 'Gateway' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOf, WorkingGroup]>;
+      createSlashWorkingGroupLeaderStakeProposal: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, title: Bytes | string | Uint8Array, description: Bytes | string | Uint8Array, stakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, workerId: WorkerId | AnyNumber | Uint8Array, slashingStake: BalanceOf | AnyNumber | Uint8Array, workingGroup: WorkingGroup | '_Reserved0' | '_Reserved1' | 'Storage' | 'Content' | 'OperationsAlpha' | 'Gateway' | 'Distribution' | 'OperationsBeta' | 'OperationsGamma' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, Bytes, Bytes, Option<BalanceOf>, WorkerId, BalanceOf, WorkingGroup]>;
       /**
        * Create 'Spending' proposal type.
        * This proposal uses `spend_from_council_mint()` extrinsic from the `governance::council`  module.

File diff suppressed because it is too large
+ 0 - 0
types/augment/augment-types.ts


+ 1 - 1
types/src/JoyEnum.ts

@@ -33,7 +33,7 @@ export function JoyEnum<Types extends Record<string, Constructor>>(types: Types)
     }
 
     // eslint-disable-next-line no-useless-constructor
-    constructor(registry: Registry, value?: any, index?: number) {
+    constructor(registry: Registry, value?: unknown, index?: number) {
       super(registry, value, index)
     }
 

+ 18 - 28
types/src/common.ts

@@ -1,7 +1,6 @@
 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'
 // we get 'moment' because it is a dependency of @polkadot/util, via @polkadot/keyring
 import moment from 'moment'
 import { JoyStructCustom, JoyStructDecorated } from './JoyStruct'
@@ -16,30 +15,16 @@ export { JoyEnum, JoyStructCustom, JoyStructDecorated }
 export interface ExtendedBTreeSet<V extends UInt> extends BTreeSet<V> {
   toArray(): V[]
 }
+
 export function JoyBTreeSet<V extends UInt>(valType: Constructor<V>): Constructor<ExtendedBTreeSet<V>> {
   return class extends BTreeSet.with(valType) {
-    public toArray(): V[] {
-      return Array.from(this)
-    }
-
-    public toU8a(isBare?: boolean): Uint8Array {
-      const encoded = new Array<Uint8Array>()
-
-      if (!isBare) {
-        encoded.push(compactToU8a(this.size))
-      }
-
-      const sorted = Array.from(this).sort((a, b) => (a.lt(b) ? -1 : 1))
-
-      sorted.forEach((v: V) => {
-        encoded.push(v.toU8a(isBare))
-      })
-
-      return u8aConcat(...encoded)
+    public forEach(callbackFn: (value: V, value2: V, set: Set<V>) => void, thisArg?: unknown): void {
+      const sorted = this.toArray()
+      return new Set(sorted).forEach(callbackFn, thisArg)
     }
 
-    public toHex(): string {
-      return u8aToHex(this.toU8a())
+    public toArray() {
+      return Array.from(this).sort((a, b) => (a.lt(b) ? -1 : 1))
     }
   }
 }
@@ -47,7 +32,6 @@ export function JoyBTreeSet<V extends UInt>(valType: Constructor<V>): Constructo
 export class Url extends Text {}
 
 export class ChannelId extends u64 {}
-export class DAOId extends u64 {}
 
 // common types between Forum and Proposal Discussions modules
 export class ThreadId extends u64 {}
@@ -106,17 +90,24 @@ export class InputValidationLengthConstraint
   }
 }
 
+// Reserved keys are not part of the exported definition const, since they are not intented to be used
 export const WorkingGroupDef = {
-  Reserved: Null,
-  Forum: Null,
+  // _Reserved0
+  // _Reserved1
   Storage: Null,
   Content: Null,
-  Operations: Null,
+  OperationsAlpha: Null,
   Gateway: Null,
-  // TODO: Distribution
+  Distribution: Null,
+  OperationsBeta: Null,
+  OperationsGamma: Null,
 } as const
 export type WorkingGroupKey = keyof typeof WorkingGroupDef
-export class WorkingGroup extends JoyEnum(WorkingGroupDef) {}
+export class WorkingGroup extends JoyEnum({
+  _Reserved0: Null,
+  _Reserved1: Null,
+  ...WorkingGroupDef,
+}) {}
 
 // Temporarly in "common", because used both by /working-group and /content-working-group:
 export type ISlashableTerms = {
@@ -159,7 +150,6 @@ export const commonTypes: RegistryTypes = {
   Address,
   LookupSource,
   ChannelId,
-  DAOId,
   Url,
 }
 

+ 20 - 26
types/src/content/index.ts

@@ -1,8 +1,9 @@
 import { Vec, Option, Tuple } from '@polkadot/types'
 import { bool, u64, u32, u128, Null, Bytes } from '@polkadot/types/primitive'
 import { MemberId } from '../members'
-import { JoyStructDecorated, JoyEnum, ChannelId, JoyBTreeSet, DAOId, Url } from '../common'
+import { JoyStructDecorated, JoyEnum, ChannelId, JoyBTreeSet } from '../common'
 import { GenericAccountId as AccountId } from '@polkadot/types/generic/AccountId'
+import { DataObjectId, DataObjectCreationParameters } from '../storage'
 
 export class CuratorId extends u64 {}
 export class CuratorGroupId extends u64 {}
@@ -16,15 +17,9 @@ export class ChannelOwnershipTransferRequestId extends u64 {}
 export class MaxNumber extends u32 {}
 export class IsCensored extends bool {}
 
-// TODO: Remove after the storage-content integration.
-export class ContentId extends u64 {}
-
-// TODO: Remove after the storage-content integration.
-export class ContentParameters extends u64 {}
-
-export class NewAsset extends JoyEnum({
-  Upload: ContentParameters,
-  Urls: Vec.with(Url),
+export class StorageAssets extends JoyStructDecorated({
+  object_creation_list: Vec.with(DataObjectCreationParameters),
+  expected_data_size_fee: u128,
 }) {}
 
 export class CuratorGroup extends JoyStructDecorated({
@@ -41,28 +36,27 @@ export class ContentActor extends JoyEnum({
 export class ChannelOwner extends JoyEnum({
   Member: MemberId,
   Curators: CuratorGroupId,
-  Dao: DAOId,
 }) {}
 
 export class Channel extends JoyStructDecorated({
   owner: ChannelOwner,
-  videos: Vec.with(VideoId),
-  playlists: Vec.with(PlaylistId),
-  series: Vec.with(SeriesId),
+  num_videos: u64,
   is_censored: bool,
   reward_account: Option.with(AccountId),
+  deletion_prize_source_account_id: AccountId,
 }) {}
 
 export class ChannelCreationParameters extends JoyStructDecorated({
-  assets: Vec.with(NewAsset),
-  meta: Bytes,
+  assets: Option.with(StorageAssets),
+  meta: Option.with(Bytes),
   reward_account: Option.with(AccountId),
 }) {}
 
 export class ChannelUpdateParameters extends JoyStructDecorated({
-  assets: Option.with(Vec.with(NewAsset)),
+  assets_to_upload: Option.with(StorageAssets),
   new_meta: Option.with(Bytes),
   reward_account: Option.with(Option.with(AccountId)),
+  assets_to_remove: JoyBTreeSet(DataObjectId),
 }) {}
 
 export class ChannelOwnershipTransferRequest extends JoyStructDecorated({
@@ -103,13 +97,14 @@ export class Video extends JoyStructDecorated({
 }) {}
 
 export class VideoCreationParameters extends JoyStructDecorated({
-  assets: Vec.with(NewAsset),
-  meta: Bytes,
+  assets: Option.with(StorageAssets),
+  meta: Option.with(Bytes),
 }) {}
 
 export class VideoUpdateParameters extends JoyStructDecorated({
-  assets: Option.with(Vec.with(NewAsset)),
+  assets_to_upload: Option.with(StorageAssets),
   new_meta: Option.with(Bytes),
+  assets_to_remove: JoyBTreeSet(DataObjectId),
 }) {}
 
 export class Playlist extends JoyStructDecorated({
@@ -134,7 +129,7 @@ export class Season extends JoyStructDecorated({
 }) {}
 
 export class SeasonParameters extends JoyStructDecorated({
-  assets: Option.with(Vec.with(NewAsset)),
+  assets: Option.with(StorageAssets),
   episodes: Option.with(Vec.with(Option.with(EpisodeParemters))),
   meta: Option.with(Bytes),
 }) {}
@@ -145,7 +140,7 @@ export class Series extends JoyStructDecorated({
 }) {}
 
 export class SeriesParameters extends JoyStructDecorated({
-  assets: Option.with(Vec.with(NewAsset)),
+  assets: Option.with(StorageAssets),
   seasons: Option.with(Vec.with(Option.with(SeasonParameters))),
   meta: Option.with(Bytes),
 }) {}
@@ -160,12 +155,12 @@ export class Person extends JoyStructDecorated({
 }) {}
 
 export class PersonCreationParameters extends JoyStructDecorated({
-  assets: Vec.with(NewAsset),
+  assets: StorageAssets,
   meta: Bytes,
 }) {}
 
 export class PersonUpdateParameters extends JoyStructDecorated({
-  assets: Option.with(Vec.with(NewAsset)),
+  assets: Option.with(StorageAssets),
   meta: Option.with(Bytes),
 }) {}
 
@@ -179,7 +174,7 @@ export const contentTypes = {
   CuratorGroupId,
   CuratorGroup,
   ContentActor,
-  NewAsset,
+  StorageAssets,
   Channel,
   ChannelOwner,
   ChannelCategoryId,
@@ -216,7 +211,6 @@ export const contentTypes = {
   EpisodeParemters,
   MaxNumber,
   IsCensored,
-  ContentId, // TODO: Remove after the content integration
 }
 
 export default contentTypes

+ 11 - 4
types/src/index.ts

@@ -1,4 +1,4 @@
-import { Codec, RegistryTypes } from '@polkadot/types/types'
+import { Codec, Constructor, RegistryTypes } from '@polkadot/types/types'
 import common from './common'
 import members from './members'
 import council from './council'
@@ -62,8 +62,8 @@ registry.register(types)
 // will create a type like: { a: string } | { b: number } | { c: Null } | "c"
 type EnumVariant<T> = keyof T extends infer K
   ? K extends keyof T
-    ? T[K] extends Null
-      ? K
+    ? T[K] extends Null | null
+      ? K | { [I in K]: T[I] }
       : { [I in K]: T[I] }
     : never
   : never
@@ -86,7 +86,9 @@ type CreateInterface_NoOption<T extends Codec> =
       ? CreateInterface<S>[]
       : T extends BTreeMap<infer K, infer V>
       ? Map<K, V>
-      : any)
+      : T extends Null
+      ? null
+      : unknown)
 
 // Wrapper for CreateInterface_NoOption that includes resolving an Option
 // (nested Options like Option<Option<Codec>> will resolve to Option<any>, but there are very edge case)
@@ -102,3 +104,8 @@ export function createType<TN extends AnyTypeName, T extends InterfaceTypes[TN]
 ): InterfaceTypes[TN] {
   return registry.createType(type, value)
 }
+
+// FIXME: Backward-compatibility. Use only one createType in the future!
+export function createTypeFromConstructor<T extends Codec>(type: Constructor<T>, value: CreateInterface<T>): T {
+  return registry.createType(type.name as AnyTypeName, value) as T
+}

+ 41 - 29
types/src/scripts/generateRegistryJson.ts

@@ -5,62 +5,74 @@ import { Constructor, Codec, RegistryTypes, Registry } from '@polkadot/types/typ
 import { TypeRegistry } from '@polkadot/types'
 import fs from 'fs'
 import path from 'path'
+import _ from 'lodash'
 
 const OUTPUT_PATH = path.join(__dirname, '../../augment/all/defs.json')
 
-function normalizeDef(registry: Registry, defOrConstructor: any, typeName: string): RegistryTypes[string] {
+function normalizeDef(registry: Registry, defOrConstructor: unknown, typeName: string): RegistryTypes[string] {
   if (typeof defOrConstructor === 'string') {
+    let typeName: string = defOrConstructor
     // Replace unhandled BTreeSet with Vec
-    defOrConstructor = defOrConstructor.replace('BTreeSet<', 'Vec<')
+    // FIXME: Remove after updating @polkadot/api!
+    typeName = typeName.replace('BTreeSet<', 'Vec<')
     // Workaround for "Unhandled type VecFixed"
-    defOrConstructor = defOrConstructor.replace('[u8;32]', 'Hash')
-    return defOrConstructor
-  } else if (typeof defOrConstructor === 'function') {
-    const defString = new (defOrConstructor as Constructor<Codec>)(registry).toRawType().toString()
-    let obj: any
+    typeName = typeName.replace('[u8;32]', 'Hash')
+    return typeName
+  }
+
+  if (typeof defOrConstructor === 'function') {
+    const TypeConstructor = defOrConstructor as Constructor<Codec>
+    const defString = new TypeConstructor(registry).toRawType().toString()
+    let obj: RegistryTypes[string]
 
     try {
       obj = JSON.parse(defString)
     } catch (e) {
-      // def if just a type name:
+      // def is a string (type name)
       return defString
     }
 
-    // def is an object:
-    const normalizedObj: any = {}
-    if (obj._enum && Array.isArray(obj._enum)) {
-      // Enum as array - No need to normalize
+    // String (type name) - no need to normalize
+    if (typeof obj === 'string') {
       return obj
-    } else if (obj._enum && !Array.isArray(obj._enum)) {
-      // Enum as object - normalize properties
-      normalizedObj._enum = {}
-      Object.entries(obj._enum).forEach(([key, value]) => {
+    }
+
+    // Enum as array - no need to normalize
+    if (typeof obj === 'object' && '_enum' in obj && Array.isArray(obj._enum)) {
+      return obj
+    }
+
+    // Enum as object - normalize properties
+    if (typeof obj === 'object' && '_enum' in obj && typeof obj._enum === 'object' && !Array.isArray(obj._enum)) {
+      const normalizedEnumDef = _.mapValues(obj._enum, (value, key) => {
         const normalizedValue = normalizeDef(registry, value, `${typeName}[${key}]`)
         if (typeof normalizedValue !== 'string') {
           throw new Error(
             `Too many nested definitions in ${typeName} enum. Did you forget to expose some types in the registry?`
           )
         }
-        normalizedObj._enum[key] = normalizedValue
-      })
-    } else if (obj._set) {
-      // Set - we don't need those now, but perhaps worth looking into at some point
+        return normalizedValue
+      }) as Record<string, string>
+      return { _enum: normalizedEnumDef }
+    }
+
+    // Set - not supported now
+    if ('_set' in obj) {
       throw new Error('_set definitions are not supported yet!')
-    } else {
-      // Struct - normalize properties
-      for (const [key, value] of Object.entries(obj)) {
-        // Prevent interface clashes
+    }
+
+    // Struct - normalize properties
+    if (typeof obj === 'object' && !('_enum' in obj) && !('_set' in obj)) {
+      return _.mapValues(obj, (value, key) => {
         const normalizedValue = normalizeDef(registry, value, `${typeName}[${key}]`)
         if (typeof normalizedValue !== 'string') {
           throw new Error(
             `Too many nested definitions in ${typeName} struct. Did you forget to expose some types in the registry?`
           )
         }
-        normalizedObj[key] = normalizedValue
-      }
+        return normalizedValue
+      })
     }
-
-    return normalizedObj
   }
 
   throw new Error(`Unkown type entry for ${typeName} found in registry!`)
@@ -71,7 +83,7 @@ function defsFromTypes(types: RegistryTypes) {
   registry.setKnownTypes({ types })
   registry.register(types)
   const defs: RegistryTypes = {}
-  Object.entries(registry.knownTypes.types as any).forEach(([typeName, defOrConstructor]) => {
+  Object.entries(registry.knownTypes.types as Omit<RegistryTypes, string>).forEach(([typeName, defOrConstructor]) => {
     const def = normalizeDef(registry, defOrConstructor, typeName)
     defs[typeName] = def
   })

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