Browse Source

Merge remote-tracking branch 'shamilRepo/migrate_runtime_module4' into master

ondratra 4 years ago
parent
commit
3429493d32
100 changed files with 19091 additions and 1985 deletions
  1. 14 0
      .editorconfig
  2. 39 0
      .github/workflows/joystream-cli.yml
  3. 4 0
      .github/workflows/pioneer.yml
  4. 529 245
      Cargo.lock
  5. 2 2
      Cargo.toml
  6. 7 0
      cli/.eslintrc.js
  7. 2 1
      cli/.prettierignore
  8. 13 7
      cli/package.json
  9. 435 80
      cli/src/Api.ts
  10. 11 10
      cli/src/ExitCodes.ts
  11. 352 44
      cli/src/Types.ts
  12. 215 206
      cli/src/base/AccountsCommandBase.ts
  13. 394 15
      cli/src/base/ApiCommandBase.ts
  14. 98 7
      cli/src/base/DefaultCommandBase.ts
  15. 94 79
      cli/src/base/StateAwareCommandBase.ts
  16. 271 0
      cli/src/base/WorkingGroupsCommandBase.ts
  17. 24 16
      cli/src/commands/account/choose.ts
  18. 35 35
      cli/src/commands/account/create.ts
  19. 34 34
      cli/src/commands/account/current.ts
  20. 62 61
      cli/src/commands/account/export.ts
  21. 23 21
      cli/src/commands/account/forget.ts
  22. 34 36
      cli/src/commands/account/import.ts
  23. 53 54
      cli/src/commands/account/transferTokens.ts
  24. 7 8
      cli/src/commands/api/getUri.ts
  25. 208 251
      cli/src/commands/api/inspect.ts
  26. 22 22
      cli/src/commands/api/setUri.ts
  27. 48 49
      cli/src/commands/council/info.ts
  28. 39 0
      cli/src/commands/working-groups/application.ts
  29. 89 0
      cli/src/commands/working-groups/createOpening.ts
  30. 56 0
      cli/src/commands/working-groups/decreaseWorkerStake.ts
  31. 56 0
      cli/src/commands/working-groups/evictWorker.ts
  32. 52 0
      cli/src/commands/working-groups/fillOpening.ts
  33. 46 0
      cli/src/commands/working-groups/increaseStake.ts
  34. 28 0
      cli/src/commands/working-groups/leaveRole.ts
  35. 80 0
      cli/src/commands/working-groups/opening.ts
  36. 23 0
      cli/src/commands/working-groups/openings.ts
  37. 40 0
      cli/src/commands/working-groups/overview.ts
  38. 55 0
      cli/src/commands/working-groups/slashWorker.ts
  39. 40 0
      cli/src/commands/working-groups/startAcceptingApplications.ts
  40. 38 0
      cli/src/commands/working-groups/startReviewPeriod.ts
  41. 38 0
      cli/src/commands/working-groups/terminateApplication.ts
  42. 48 0
      cli/src/commands/working-groups/updateRewardAccount.ts
  43. 58 0
      cli/src/commands/working-groups/updateRoleAccount.ts
  44. 67 0
      cli/src/commands/working-groups/updateWorkerReward.ts
  45. 64 25
      cli/src/helpers/display.ts
  46. 30 0
      cli/src/helpers/promptOptions.ts
  47. 14 14
      cli/src/helpers/validation.ts
  48. 1 1
      cli/src/index.ts
  49. 44 0
      cli/src/promptOptions/addWorkerOpening.ts
  50. 51 0
      cli/src/validators/common.ts
  51. 7 7
      cli/test/commands/council/info.test.ts
  52. 1 3
      cli/test/tsconfig.json
  53. 3 1
      cli/tsconfig.json
  54. 12 0
      devops/ansible/build-and-run-tests-single-node-playbook.yml
  55. 4 0
      devops/ansible/build-image-tasklist.yml
  56. 34 0
      devops/ansible/docker-compose.yml
  57. 2 0
      devops/ansible/hosts
  58. 15 0
      devops/ansible/install-dependencies-playbook.yml
  59. 24 0
      devops/ansible/run-tests-single-node-playbook.yml
  60. 24 0
      devops/ansible/run-tests-two-nodes-playbook.yml
  61. 37 0
      devops/dockerfiles/ansible-node/Dockerfile
  62. 4 0
      devops/eslint-config/index.js
  63. 766 0
      devops/vstore/classes.json
  64. 12694 0
      devops/vstore/entities.json
  65. 245 138
      node/Cargo.toml
  66. 3 20
      node/bin/main.rs
  67. 196 71
      node/src/chain_spec.rs
  68. 45 125
      node/src/cli.rs
  69. 100 0
      node/src/command.rs
  70. 2 2
      node/src/forum_config/from_serialized.rs
  71. 1 1
      node/src/forum_config/mod.rs
  72. 4 0
      node/src/lib.rs
  73. 1 13
      node/src/members_config.rs
  74. 10 0
      node/src/node_executor.rs
  75. 191 0
      node/src/node_rpc.rs
  76. 529 225
      node/src/service.rs
  77. 4 1
      package.json
  78. 1 0
      pioneer/.eslintrc.js
  79. 1 1
      pioneer/package.json
  80. 0 2
      pioneer/packages/apps-routing/src/index.ts
  81. 2 1
      pioneer/packages/apps-routing/src/joy-roles.ts
  82. 0 17
      pioneer/packages/apps-routing/src/joy-storage.ts
  83. 1 1
      pioneer/packages/apps/src/SideBar/Item.tsx
  84. 1 1
      pioneer/packages/joy-election/src/Applicant.tsx
  85. 1 1
      pioneer/packages/joy-election/src/ApplyForm.tsx
  86. 1 1
      pioneer/packages/joy-election/src/Council.tsx
  87. 1 1
      pioneer/packages/joy-election/src/Dashboard.tsx
  88. 1 1
      pioneer/packages/joy-election/src/SealedVote.tsx
  89. 1 1
      pioneer/packages/joy-election/src/index.tsx
  90. 2 1
      pioneer/packages/joy-forum/src/CategoryList.tsx
  91. 4 3
      pioneer/packages/joy-forum/src/Context.tsx
  92. 2 1
      pioneer/packages/joy-forum/src/EditReply.tsx
  93. 2 1
      pioneer/packages/joy-forum/src/EditThread.tsx
  94. 2 1
      pioneer/packages/joy-forum/src/ForumRoot.tsx
  95. 2 1
      pioneer/packages/joy-forum/src/Moderate.tsx
  96. 2 1
      pioneer/packages/joy-forum/src/ViewThread.tsx
  97. 2 1
      pioneer/packages/joy-forum/src/utils.tsx
  98. 1 1
      pioneer/packages/joy-forum/src/validation.tsx
  99. 5 5
      pioneer/packages/joy-media/src/DiscoveryProvider.tsx
  100. 11 11
      pioneer/packages/joy-media/src/Upload.tsx

+ 14 - 0
.editorconfig

@@ -0,0 +1,14 @@
+# In case prettier plugin or eslint with autofix is not enabled in IDE
+# The fallback settings here should match with our prettierrc config
+# so we get consistency!
+root = true
+
+[*]
+indent_style=space
+indent_size=2
+tab_width=2
+end_of_line=lf
+charset=utf-8
+trim_trailing_whitespace=true
+max_line_length=120
+insert_final_newline=true

+ 39 - 0
.github/workflows/joystream-cli.yml

@@ -0,0 +1,39 @@
+name: joystream-cli
+on: [pull_request, push]
+
+jobs:
+  cli_build_ubuntu:
+    name: Ubuntu Checks
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        node-version: [12.x]
+    steps:
+    - uses: actions/checkout@v1
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v1
+      with:
+        node-version: ${{ matrix.node-version }}
+    - name: checks
+      run: |
+        yarn install --frozen-lockfile
+        yarn madge --circular types/
+        yarn workspace joystream-cli checks
+
+  cli_build_osx:
+    name: MacOS Checks
+    runs-on: macos-latest
+    strategy:
+      matrix:
+        node-version: [12.x]
+    steps:
+    - uses: actions/checkout@v1
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v1
+      with:
+        node-version: ${{ matrix.node-version }}
+    - name: checks
+      run: |
+        yarn install --frozen-lockfile --network-timeout 120000
+        yarn madge --circular types/
+        yarn workspace joystream-cli checks

+ 4 - 0
.github/workflows/pioneer-pr.yml → .github/workflows/pioneer.yml

@@ -17,6 +17,7 @@ jobs:
     - name: build
     - name: build
       run: |
       run: |
         yarn install --frozen-lockfile
         yarn install --frozen-lockfile
+        yarn madge --circular types/
         yarn workspace pioneer build
         yarn workspace pioneer build
 
 
   pioneer_build_osx:
   pioneer_build_osx:
@@ -34,6 +35,7 @@ jobs:
     - name: build
     - name: build
       run: |
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
         yarn install --frozen-lockfile --network-timeout 120000
+        yarn madge --circular types/
         yarn workspace pioneer build
         yarn workspace pioneer build
 
 
   pioneer_lint_ubuntu:
   pioneer_lint_ubuntu:
@@ -51,6 +53,7 @@ jobs:
     - name: lint
     - name: lint
       run: |
       run: |
         yarn install --frozen-lockfile
         yarn install --frozen-lockfile
+        yarn madge --circular types/
         yarn workspace pioneer lint
         yarn workspace pioneer lint
 
 
   pioneer_lint_osx:
   pioneer_lint_osx:
@@ -68,4 +71,5 @@ jobs:
     - name: lint
     - name: lint
       run: |
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
         yarn install --frozen-lockfile --network-timeout 120000
+        yarn madge --circular types/
         yarn workspace pioneer lint
         yarn workspace pioneer lint

File diff suppressed because it is too large
+ 529 - 245
Cargo.lock


+ 2 - 2
Cargo.toml

@@ -12,15 +12,15 @@ members = [
 	"runtime-modules/membership",
 	"runtime-modules/membership",
 	"runtime-modules/memo",
 	"runtime-modules/memo",
 	"runtime-modules/recurring-reward",
 	"runtime-modules/recurring-reward",
-	"runtime-modules/roles",
 	"runtime-modules/service-discovery",
 	"runtime-modules/service-discovery",
 	"runtime-modules/stake",
 	"runtime-modules/stake",
 	"runtime-modules/storage",
 	"runtime-modules/storage",
 	"runtime-modules/token-minting",
 	"runtime-modules/token-minting",
 	"runtime-modules/versioned-store",
 	"runtime-modules/versioned-store",
 	"runtime-modules/versioned-store-permissions",
 	"runtime-modules/versioned-store-permissions",
+	"runtime-modules/working-group",
 	"node",
 	"node",
-	"utils/chain-spec-builder/"
+#	"utils/chain-spec-builder/"
 ]
 ]
 
 
 [profile.release]
 [profile.release]

+ 7 - 0
cli/.eslintrc.js

@@ -1,4 +1,7 @@
 module.exports = {
 module.exports = {
+  env: {
+    mocha: true,
+  },
   extends: [
   extends: [
     // The oclif rules have some code-style/formatting rules which may conflict with
     // The oclif rules have some code-style/formatting rules which may conflict with
     // our prettier global settings. Disabling for now
     // our prettier global settings. Disabling for now
@@ -7,4 +10,8 @@ module.exports = {
     // "oclif",
     // "oclif",
     // "oclif-typescript",
     // "oclif-typescript",
   ],
   ],
+  rules: {
+    "no-unused-vars": "off", // Required by the typescript rule below
+    "@typescript-eslint/no-unused-vars": ["error"]
+  }
 }
 }

+ 2 - 1
cli/.prettierignore

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

+ 13 - 7
cli/package.json

@@ -8,7 +8,7 @@
   },
   },
   "bugs": "https://github.com/Joystream/substrate-runtime-joystream/issues",
   "bugs": "https://github.com/Joystream/substrate-runtime-joystream/issues",
   "dependencies": {
   "dependencies": {
-    "@joystream/types": "^0.10.0",
+    "@joystream/types": "^0.11.0",
     "@oclif/command": "^1.5.19",
     "@oclif/command": "^1.5.19",
     "@oclif/config": "^1.14.0",
     "@oclif/config": "^1.14.0",
     "@oclif/plugin-help": "^2.2.3",
     "@oclif/plugin-help": "^2.2.3",
@@ -21,11 +21,13 @@
     "moment": "^2.24.0",
     "moment": "^2.24.0",
     "proper-lockfile": "^4.1.1",
     "proper-lockfile": "^4.1.1",
     "slug": "^2.1.1",
     "slug": "^2.1.1",
-    "tslib": "^1.11.1"
+    "tslib": "^1.11.1",
+    "ajv": "^6.11.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "@oclif/dev-cli": "^1.22.2",
     "@oclif/dev-cli": "^1.22.2",
     "@oclif/test": "^1.2.5",
     "@oclif/test": "^1.2.5",
+    "@polkadot/ts": "^0.1.56",
     "@types/chai": "^4.2.11",
     "@types/chai": "^4.2.11",
     "@types/mocha": "^5.2.7",
     "@types/mocha": "^5.2.7",
     "@types/node": "^10.17.18",
     "@types/node": "^10.17.18",
@@ -37,8 +39,7 @@
     "mocha": "^5.2.0",
     "mocha": "^5.2.0",
     "nyc": "^14.1.1",
     "nyc": "^14.1.1",
     "ts-node": "^8.8.2",
     "ts-node": "^8.8.2",
-    "typescript": "^3.8.3",
-    "@polkadot/ts": "^0.1.56"
+    "typescript": "^3.8.3"
   },
   },
   "engines": {
   "engines": {
     "node": ">=8.0.0"
     "node": ">=8.0.0"
@@ -71,6 +72,9 @@
       },
       },
       "api": {
       "api": {
         "description": "Inspect the substrate node api, perform lower-level api calls or change the current api provider uri"
         "description": "Inspect the substrate node api, perform lower-level api calls or change the current api provider uri"
+      },
+      "working-groups": {
+        "description": "Working group lead and worker actions"
       }
       }
     }
     }
   },
   },
@@ -81,12 +85,14 @@
   },
   },
   "scripts": {
   "scripts": {
     "postpack": "rm -f oclif.manifest.json",
     "postpack": "rm -f oclif.manifest.json",
-    "posttest": "eslint . --ext .ts",
+    "posttest": "yarn lint",
     "prepack": "rm -rf lib && tsc -b && oclif-dev manifest && oclif-dev readme",
     "prepack": "rm -rf lib && tsc -b && oclif-dev manifest && oclif-dev readme",
     "test": "nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
     "test": "nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
+    "build": "tsc --build tsconfig.json",
     "version": "oclif-dev readme && git add README.md",
     "version": "oclif-dev readme && git add README.md",
-    "lint": "eslint ./src/ --quiet --ext .ts",
-    "prettier-write": "prettier --write ."
+    "lint": "eslint ./ --quiet --ext .ts",
+    "checks": "yarn lint && tsc --noEmit --pretty && prettier ./ --check",
+    "format": "prettier ./ --write"
   },
   },
   "types": "lib/index.d.ts"
   "types": "lib/index.d.ts"
 }
 }

+ 435 - 80
cli/src/Api.ts

@@ -1,114 +1,469 @@
-import BN from 'bn.js';
-import { registerJoystreamTypes } from '@joystream/types/';
-import { ApiPromise, WsProvider } from '@polkadot/api';
-import { QueryableStorageMultiArg } from '@polkadot/api/types';
-import { formatBalance } from '@polkadot/util';
-import { Hash } from '@polkadot/types/interfaces';
-import { KeyringPair } from '@polkadot/keyring/types';
-import { Codec } from '@polkadot/types/types';
-import { AccountSummary, CouncilInfoObj, CouncilInfoTuple, createCouncilInfoObj } from './Types';
-import { DerivedFees, DerivedBalances } from '@polkadot/api-derive/types';
-import { CLIError } from '@oclif/errors';
-import ExitCodes from './ExitCodes';
-
-export const DEFAULT_API_URI = 'wss://rome-rpc-endpoint.joystream.org:9944/';
-export const TOKEN_SYMBOL = 'JOY';
+import BN from 'bn.js'
+import { registerJoystreamTypes } from '@joystream/types/'
+import { ApiPromise, WsProvider } from '@polkadot/api'
+import { QueryableStorageMultiArg } from '@polkadot/api/types'
+import { formatBalance } from '@polkadot/util'
+import { Hash, Balance, Moment } from '@polkadot/types/interfaces'
+import { KeyringPair } from '@polkadot/keyring/types'
+import { Codec } from '@polkadot/types/types'
+import { Option, Vec } from '@polkadot/types'
+import { u32 } from '@polkadot/types/primitive'
+import {
+  AccountSummary,
+  CouncilInfoObj,
+  CouncilInfoTuple,
+  createCouncilInfoObj,
+  WorkingGroups,
+  Reward,
+  GroupMember,
+  OpeningStatus,
+  GroupOpeningStage,
+  GroupOpening,
+  GroupApplication,
+} from './Types'
+import { DerivedFees, DerivedBalances } from '@polkadot/api-derive/types'
+import { CLIError } from '@oclif/errors'
+import ExitCodes from './ExitCodes'
+import {
+  Worker,
+  WorkerId,
+  RoleStakeProfile,
+  Opening as WGOpening,
+  Application as WGApplication,
+} from '@joystream/types/working-group'
+import {
+  Opening,
+  Application,
+  OpeningStage,
+  ApplicationStageKeys,
+  ApplicationId,
+  OpeningId,
+} from '@joystream/types/hiring'
+import { MemberId, Profile } from '@joystream/types/members'
+import { RewardRelationship, RewardRelationshipId } from '@joystream/types/recurring-rewards'
+import { Stake, StakeId } from '@joystream/types/stake'
+import { LinkageResult } from '@polkadot/types/codec/Linkage'
 
 
-// Api wrapper for handling most common api calls and allowing easy API implementation switch in the future
+import { InputValidationLengthConstraint } from '@joystream/types/common'
+
+export const DEFAULT_API_URI = 'wss://rome-rpc-endpoint.joystream.org:9944/'
+const DEFAULT_DECIMALS = new u32(12)
 
 
+// Mapping of working group to api module
+export const apiModuleByGroup: { [key in WorkingGroups]: string } = {
+  [WorkingGroups.StorageProviders]: 'storageWorkingGroup',
+}
+
+// Api wrapper for handling most common api calls and allowing easy API implementation switch in the future
 export default class Api {
 export default class Api {
-    private _api: ApiPromise;
+  private _api: ApiPromise
+
+  private constructor(originalApi: ApiPromise) {
+    this._api = originalApi
+  }
+
+  public getOriginalApi(): ApiPromise {
+    return this._api
+  }
+
+  private static async initApi(apiUri: string = DEFAULT_API_URI): Promise<ApiPromise> {
+    const wsProvider: WsProvider = new WsProvider(apiUri)
+    registerJoystreamTypes()
+    const api = await ApiPromise.create({ provider: wsProvider })
+
+    // Initializing some api params based on pioneer/packages/react-api/Api.tsx
+    const [properties] = await Promise.all([api.rpc.system.properties()])
+
+    const tokenSymbol = properties.tokenSymbol.unwrapOr('DEV').toString()
+    const tokenDecimals = properties.tokenDecimals.unwrapOr(DEFAULT_DECIMALS).toNumber()
+
+    // formatBlanace config
+    formatBalance.setDefaults({
+      decimals: tokenDecimals,
+      unit: tokenSymbol,
+    })
+
+    return api
+  }
+
+  static async create(apiUri: string = DEFAULT_API_URI): Promise<Api> {
+    const originalApi: ApiPromise = await Api.initApi(apiUri)
+    return new Api(originalApi)
+  }
+
+  private async queryMultiOnce(queries: Parameters<typeof ApiPromise.prototype.queryMulti>[0]): Promise<Codec[]> {
+    let results: Codec[] = []
+
+    const unsub = await this._api.queryMulti(queries, (res) => {
+      results = res
+    })
+    unsub()
+
+    if (!results.length || results.length !== queries.length) {
+      throw new CLIError('API querying issue', { exit: ExitCodes.ApiError })
+    }
+
+    return results
+  }
+
+  async getAccountsBalancesInfo(accountAddresses: string[]): Promise<DerivedBalances[]> {
+    const accountsBalances: DerivedBalances[] = await this._api.derive.balances.votingBalances(accountAddresses)
+
+    return accountsBalances
+  }
+
+  // Get on-chain data related to given account.
+  // For now it's just account balances
+  async getAccountSummary(accountAddresses: string): Promise<AccountSummary> {
+    const balances: DerivedBalances = (await this.getAccountsBalancesInfo([accountAddresses]))[0]
+    // TODO: Some more information can be fetched here in the future
+
+    return { balances }
+  }
+
+  async getCouncilInfo(): Promise<CouncilInfoObj> {
+    const queries: { [P in keyof CouncilInfoObj]: QueryableStorageMultiArg<'promise'> } = {
+      activeCouncil: this._api.query.council.activeCouncil,
+      termEndsAt: this._api.query.council.termEndsAt,
+      autoStart: this._api.query.councilElection.autoStart,
+      newTermDuration: this._api.query.councilElection.newTermDuration,
+      candidacyLimit: this._api.query.councilElection.candidacyLimit,
+      councilSize: this._api.query.councilElection.councilSize,
+      minCouncilStake: this._api.query.councilElection.minCouncilStake,
+      minVotingStake: this._api.query.councilElection.minVotingStake,
+      announcingPeriod: this._api.query.councilElection.announcingPeriod,
+      votingPeriod: this._api.query.councilElection.votingPeriod,
+      revealingPeriod: this._api.query.councilElection.revealingPeriod,
+      round: this._api.query.councilElection.round,
+      stage: this._api.query.councilElection.stage,
+    }
+    const results: CouncilInfoTuple = (await this.queryMultiOnce(Object.values(queries))) as CouncilInfoTuple
+
+    return createCouncilInfoObj(...results)
+  }
+
+  // TODO: This formula is probably not too good, so some better implementation will be required in the future
+  async estimateFee(account: KeyringPair, recipientAddr: string, amount: BN): Promise<BN> {
+    const transfer = this._api.tx.balances.transfer(recipientAddr, amount)
+    const signature = account.sign(transfer.toU8a())
+    const transactionByteSize: BN = new BN(transfer.encodedLength + signature.length)
+
+    const fees: DerivedFees = await this._api.derive.balances.fees()
+
+    const estimatedFee = fees.transactionBaseFee.add(fees.transactionByteFee.mul(transactionByteSize))
+
+    return estimatedFee
+  }
+
+  async transfer(account: KeyringPair, recipientAddr: string, amount: BN): Promise<Hash> {
+    const txHash = await this._api.tx.balances.transfer(recipientAddr, amount).signAndSend(account)
+    return txHash
+  }
+
+  // Working groups
+  // TODO: This is a lot of repeated logic from "/pioneer/joy-roles/src/transport.substrate.ts"
+  // (although simplified a little bit)
+  // Hopefully this will be refactored to "joystream-js" soon
+  protected singleLinkageResult<T extends Codec>(result: LinkageResult) {
+    return result[0] as T
+  }
+
+  protected multiLinkageResult<K extends Codec, V extends Codec>(result: LinkageResult): [Vec<K>, Vec<V>] {
+    return [result[0] as Vec<K>, result[1] as Vec<V>]
+  }
+
+  protected async blockHash(height: number): Promise<string> {
+    const blockHash = await this._api.rpc.chain.getBlockHash(height)
+
+    return blockHash.toString()
+  }
+
+  protected async blockTimestamp(height: number): Promise<Date> {
+    const blockTime = (await this._api.query.timestamp.now.at(await this.blockHash(height))) as Moment
+
+    return new Date(blockTime.toNumber())
+  }
+
+  protected workingGroupApiQuery(group: WorkingGroups) {
+    const module = apiModuleByGroup[group]
+    return this._api.query[module]
+  }
+
+  protected async memberProfileById(memberId: MemberId): Promise<Profile | null> {
+    const profile = (await this._api.query.members.memberProfile(memberId)) as Option<Profile>
+
+    return profile.unwrapOr(null)
+  }
+
+  async groupLead(group: WorkingGroups): Promise<GroupMember | null> {
+    const optLeadId = (await this.workingGroupApiQuery(group).currentLead()) as Option<WorkerId>
 
 
-    private constructor(originalApi:ApiPromise) {
-        this._api = originalApi;
+    if (!optLeadId.isSome) {
+      return null
     }
     }
 
 
-    public getOriginalApi(): ApiPromise {
-        return this._api;
+    const leadWorkerId = optLeadId.unwrap()
+    const leadWorker = await this.workerByWorkerId(group, leadWorkerId.toNumber())
+
+    return await this.parseGroupMember(leadWorkerId, leadWorker)
+  }
+
+  protected async stakeValue(stakeId: StakeId): Promise<Balance> {
+    const stake = this.singleLinkageResult<Stake>((await this._api.query.stake.stakes(stakeId)) as LinkageResult)
+    return stake.value
+  }
+
+  protected async workerStake(stakeProfile: RoleStakeProfile): Promise<Balance> {
+    return this.stakeValue(stakeProfile.stake_id)
+  }
+
+  protected async workerReward(relationshipId: RewardRelationshipId): Promise<Reward> {
+    const rewardRelationship = this.singleLinkageResult<RewardRelationship>(
+      (await this._api.query.recurringRewards.rewardRelationships(relationshipId)) as LinkageResult
+    )
+
+    return {
+      totalRecieved: rewardRelationship.total_reward_received,
+      value: rewardRelationship.amount_per_payout,
+      interval: rewardRelationship.payout_interval.unwrapOr(undefined)?.toNumber(),
+      nextPaymentBlock: rewardRelationship.next_payment_at_block.unwrapOr(new BN(0)).toNumber(),
+    }
+  }
+
+  protected async parseGroupMember(id: WorkerId, worker: Worker): Promise<GroupMember> {
+    const roleAccount = worker.role_account_id
+    const memberId = worker.member_id
+
+    const profile = await this.memberProfileById(memberId)
+
+    if (!profile) {
+      throw new Error(`Group member profile not found! (member id: ${memberId.toNumber()})`)
+    }
+
+    let stake: Balance | undefined
+    if (worker.role_stake_profile && worker.role_stake_profile.isSome) {
+      stake = await this.workerStake(worker.role_stake_profile.unwrap())
+    }
+
+    let reward: Reward | undefined
+    if (worker.reward_relationship && worker.reward_relationship.isSome) {
+      reward = await this.workerReward(worker.reward_relationship.unwrap())
+    }
+
+    return {
+      workerId: id,
+      roleAccount,
+      memberId,
+      profile,
+      stake,
+      reward,
+    }
+  }
+
+  async workerByWorkerId(group: WorkingGroups, workerId: number): Promise<Worker> {
+    const nextId = (await this.workingGroupApiQuery(group).nextWorkerId()) as WorkerId
+
+    // This is chain specfic, but if next id is still 0, it means no workers have been added yet
+    if (workerId < 0 || workerId >= nextId.toNumber()) {
+      throw new CLIError('Invalid worker id!')
+    }
+
+    const worker = this.singleLinkageResult<Worker>(
+      (await this.workingGroupApiQuery(group).workerById(workerId)) as LinkageResult
+    )
+
+    if (!worker.is_active) {
+      throw new CLIError('This worker is not active anymore')
+    }
+
+    return worker
+  }
+
+  async groupMember(group: WorkingGroups, workerId: number) {
+    const worker = await this.workerByWorkerId(group, workerId)
+    return await this.parseGroupMember(new WorkerId(workerId), worker)
+  }
+
+  async groupMembers(group: WorkingGroups): Promise<GroupMember[]> {
+    const nextId = (await this.workingGroupApiQuery(group).nextWorkerId()) as WorkerId
+
+    // This is chain specfic, but if next id is still 0, it means no workers have been added yet
+    if (nextId.eq(0)) {
+      return []
     }
     }
 
 
-    private static async initApi(apiUri: string = DEFAULT_API_URI): Promise<ApiPromise> {
-        formatBalance.setDefaults({ unit: TOKEN_SYMBOL });
-        const wsProvider:WsProvider = new WsProvider(apiUri);
-        registerJoystreamTypes();
+    const [workerIds, workers] = this.multiLinkageResult<WorkerId, Worker>(
+      (await this.workingGroupApiQuery(group).workerById()) as LinkageResult
+    )
+
+    const groupMembers: GroupMember[] = []
+    for (const [index, worker] of Object.entries(workers.toArray())) {
+      const workerId = workerIds[parseInt(index)]
+      if (worker.is_active) {
+        groupMembers.push(await this.parseGroupMember(workerId, worker))
+      }
+    }
+
+    return groupMembers.reverse()
+  }
+
+  async openingsByGroup(group: WorkingGroups): Promise<GroupOpening[]> {
+    const openings: GroupOpening[] = []
+    const nextId = (await this.workingGroupApiQuery(group).nextOpeningId()) as OpeningId
 
 
-        return await ApiPromise.create({ provider: wsProvider });
+    // This is chain specfic, but if next id is still 0, it means no openings have been added yet
+    if (!nextId.eq(0)) {
+      const highestId = nextId.toNumber() - 1
+      for (let i = highestId; i >= 0; i--) {
+        openings.push(await this.groupOpening(group, i))
+      }
     }
     }
 
 
-    static async create(apiUri: string = DEFAULT_API_URI): Promise<Api> {
-        const originalApi: ApiPromise = await Api.initApi(apiUri);
-        return new Api(originalApi);
+    return openings
+  }
+
+  protected async hiringOpeningById(id: number | OpeningId): Promise<Opening> {
+    const result = (await this._api.query.hiring.openingById(id)) as LinkageResult
+    return this.singleLinkageResult<Opening>(result)
+  }
+
+  protected async hiringApplicationById(id: number | ApplicationId): Promise<Application> {
+    const result = (await this._api.query.hiring.applicationById(id)) as LinkageResult
+    return this.singleLinkageResult<Application>(result)
+  }
+
+  async wgApplicationById(group: WorkingGroups, wgApplicationId: number): Promise<WGApplication> {
+    const nextAppId = (await this.workingGroupApiQuery(group).nextApplicationId()) as ApplicationId
+
+    if (wgApplicationId < 0 || wgApplicationId >= nextAppId.toNumber()) {
+      throw new CLIError('Invalid working group application ID!')
     }
     }
 
 
-    private async queryMultiOnce(queries: Parameters<typeof ApiPromise.prototype.queryMulti>[0]): Promise<Codec[]> {
-        let results: Codec[] = [];
+    return this.singleLinkageResult<WGApplication>(
+      (await this.workingGroupApiQuery(group).applicationById(wgApplicationId)) as LinkageResult
+    )
+  }
 
 
-        const unsub = await this._api.queryMulti(
-            queries,
-            (res) => { results = res }
-        );
-        unsub();
+  protected async parseApplication(wgApplicationId: number, wgApplication: WGApplication): Promise<GroupApplication> {
+    const appId = wgApplication.application_id
+    const application = await this.hiringApplicationById(appId)
 
 
-        if (!results.length || results.length !== queries.length) {
-            throw new CLIError('API querying issue', { exit: ExitCodes.ApiError });
-        }
+    const { active_role_staking_id: roleStakingId, active_application_staking_id: appStakingId } = application
 
 
-        return results;
+    return {
+      wgApplicationId,
+      applicationId: appId.toNumber(),
+      wgOpeningId: wgApplication.opening_id.toNumber(),
+      member: await this.memberProfileById(wgApplication.member_id),
+      roleAccout: wgApplication.role_account_id,
+      stakes: {
+        application: appStakingId.isSome ? (await this.stakeValue(appStakingId.unwrap())).toNumber() : 0,
+        role: roleStakingId.isSome ? (await this.stakeValue(roleStakingId.unwrap())).toNumber() : 0,
+      },
+      humanReadableText: application.human_readable_text.toString(),
+      stage: application.stage.type as ApplicationStageKeys,
     }
     }
+  }
+
+  async groupApplication(group: WorkingGroups, wgApplicationId: number): Promise<GroupApplication> {
+    const wgApplication = await this.wgApplicationById(group, wgApplicationId)
+    return await this.parseApplication(wgApplicationId, wgApplication)
+  }
 
 
-    async getAccountsBalancesInfo(accountAddresses:string[]): Promise<DerivedBalances[]> {
-        let accountsBalances: DerivedBalances[] = await this._api.derive.balances.votingBalances(accountAddresses);
+  protected async groupOpeningApplications(group: WorkingGroups, wgOpeningId: number): Promise<GroupApplication[]> {
+    const applications: GroupApplication[] = []
 
 
-        return accountsBalances;
+    const nextAppId = (await this.workingGroupApiQuery(group).nextApplicationId()) as ApplicationId
+    for (let i = 0; i < nextAppId.toNumber(); i++) {
+      const wgApplication = await this.wgApplicationById(group, i)
+      if (wgApplication.opening_id.toNumber() !== wgOpeningId) {
+        continue
+      }
+      applications.push(await this.parseApplication(i, wgApplication))
     }
     }
 
 
-    // Get on-chain data related to given account.
-    // For now it's just account balances
-    async getAccountSummary(accountAddresses:string): Promise<AccountSummary> {
-        const balances: DerivedBalances = (await this.getAccountsBalancesInfo([accountAddresses]))[0];
-        // TODO: Some more information can be fetched here in the future
+    return applications
+  }
 
 
-        return { balances };
+  async groupOpening(group: WorkingGroups, wgOpeningId: number): Promise<GroupOpening> {
+    const nextId = ((await this.workingGroupApiQuery(group).nextOpeningId()) as OpeningId).toNumber()
+
+    if (wgOpeningId < 0 || wgOpeningId >= nextId) {
+      throw new CLIError('Invalid working group opening ID!')
     }
     }
 
 
-    async getCouncilInfo(): Promise<CouncilInfoObj> {
-        const queries: { [P in keyof CouncilInfoObj]: QueryableStorageMultiArg<"promise"> } = {
-            activeCouncil:    this._api.query.council.activeCouncil,
-            termEndsAt:       this._api.query.council.termEndsAt,
-            autoStart:        this._api.query.councilElection.autoStart,
-            newTermDuration:  this._api.query.councilElection.newTermDuration,
-            candidacyLimit:   this._api.query.councilElection.candidacyLimit,
-            councilSize:      this._api.query.councilElection.councilSize,
-            minCouncilStake:  this._api.query.councilElection.minCouncilStake,
-            minVotingStake:   this._api.query.councilElection.minVotingStake,
-            announcingPeriod: this._api.query.councilElection.announcingPeriod,
-            votingPeriod:     this._api.query.councilElection.votingPeriod,
-            revealingPeriod:  this._api.query.councilElection.revealingPeriod,
-            round:            this._api.query.councilElection.round,
-            stage:            this._api.query.councilElection.stage
-        }
-        const results: CouncilInfoTuple = <CouncilInfoTuple> await this.queryMultiOnce(Object.values(queries));
+    const groupOpening = this.singleLinkageResult<WGOpening>(
+      (await this.workingGroupApiQuery(group).openingById(wgOpeningId)) as LinkageResult
+    )
 
 
-        return createCouncilInfoObj(...results);
+    const openingId = groupOpening.hiring_opening_id.toNumber()
+    const opening = await this.hiringOpeningById(openingId)
+    const applications = await this.groupOpeningApplications(group, wgOpeningId)
+    const stage = await this.parseOpeningStage(opening.stage)
+    const type = groupOpening.opening_type
+    const stakes = {
+      application: opening.application_staking_policy.unwrapOr(undefined),
+      role: opening.role_staking_policy.unwrapOr(undefined),
     }
     }
 
 
-    // TODO: This formula is probably not too good, so some better implementation will be required in the future
-    async estimateFee(account: KeyringPair, recipientAddr: string, amount: BN): Promise<BN> {
-        const transfer = this._api.tx.balances.transfer(recipientAddr, amount);
-        const signature = account.sign(transfer.toU8a());
-        const transactionByteSize:BN = new BN(transfer.encodedLength + signature.length);
+    return {
+      wgOpeningId,
+      openingId,
+      opening,
+      stage,
+      stakes,
+      applications,
+      type,
+    }
+  }
 
 
-        const fees: DerivedFees = await this._api.derive.balances.fees();
+  async parseOpeningStage(stage: OpeningStage): Promise<GroupOpeningStage> {
+    let status: OpeningStatus | undefined, stageBlock: number | undefined, stageDate: Date | undefined
 
 
-        const estimatedFee = fees.transactionBaseFee.add(fees.transactionByteFee.mul(transactionByteSize));
+    if (stage.isOfType('WaitingToBegin')) {
+      const stageData = stage.asType('WaitingToBegin')
+      const currentBlockNumber = (await this._api.derive.chain.bestNumber()).toNumber()
+      const expectedBlockTime = (this._api.consts.babe.expectedBlockTime as Moment).toNumber()
+      status = OpeningStatus.WaitingToBegin
+      stageBlock = stageData.begins_at_block.toNumber()
+      stageDate = new Date(Date.now() + (stageBlock - currentBlockNumber) * expectedBlockTime)
+    }
 
 
-        return estimatedFee;
+    if (stage.isOfType('Active')) {
+      const stageData = stage.asType('Active')
+      const substage = stageData.stage
+      if (substage.isOfType('AcceptingApplications')) {
+        status = OpeningStatus.AcceptingApplications
+        stageBlock = substage.asType('AcceptingApplications').started_accepting_applicants_at_block.toNumber()
+      }
+      if (substage.isOfType('ReviewPeriod')) {
+        status = OpeningStatus.InReview
+        stageBlock = substage.asType('ReviewPeriod').started_review_period_at_block.toNumber()
+      }
+      if (substage.isOfType('Deactivated')) {
+        status = substage.asType('Deactivated').cause.isOfType('Filled')
+          ? OpeningStatus.Complete
+          : OpeningStatus.Cancelled
+        stageBlock = substage.asType('Deactivated').deactivated_at_block.toNumber()
+      }
+      if (stageBlock) {
+        stageDate = new Date(await this.blockTimestamp(stageBlock))
+      }
     }
     }
 
 
-    async transfer(account: KeyringPair, recipientAddr: string, amount: BN): Promise<Hash> {
-        const txHash = await this._api.tx.balances
-            .transfer(recipientAddr, amount)
-            .signAndSend(account);
-        return txHash;
+    return {
+      status: status || OpeningStatus.Unknown,
+      block: stageBlock,
+      date: stageDate,
     }
     }
+  }
+
+  async getMemberIdsByControllerAccount(address: string): Promise<MemberId[]> {
+    const ids = (await this._api.query.members.memberIdsByControllerAccountId(address)) as Vec<MemberId>
+    return ids.toArray()
+  }
+
+  async workerExitRationaleConstraint(group: WorkingGroups): Promise<InputValidationLengthConstraint> {
+    return (await this.workingGroupApiQuery(group).workerExitRationaleText()) as InputValidationLengthConstraint
+  }
 }
 }

+ 11 - 10
cli/src/ExitCodes.ts

@@ -1,14 +1,15 @@
 enum ExitCodes {
 enum ExitCodes {
-    OK = 0,
+  OK = 0,
 
 
-    InvalidInput = 400,
-    FileNotFound = 401,
-    InvalidFile = 402,
-    NoAccountFound = 403,
-    NoAccountSelected = 404,
+  InvalidInput = 400,
+  FileNotFound = 401,
+  InvalidFile = 402,
+  NoAccountFound = 403,
+  NoAccountSelected = 404,
+  AccessDenied = 405,
 
 
-    UnexpectedException = 500,
-    FsOperationFailed = 501,
-    ApiError = 502,
+  UnexpectedException = 500,
+  FsOperationFailed = 501,
+  ApiError = 502,
 }
 }
-export = ExitCodes;
+export = ExitCodes

+ 352 - 44
cli/src/Types.ts

@@ -1,63 +1,371 @@
-import BN from 'bn.js';
-import { ElectionStage, Seat } from '@joystream/types/';
-import { Option } from '@polkadot/types';
-import { BlockNumber, Balance } from '@polkadot/types/interfaces';
-import { DerivedBalances } from '@polkadot/api-derive/types';
-import { KeyringPair } from '@polkadot/keyring/types';
+import BN from 'bn.js'
+import { ElectionStage, Seat } from '@joystream/types/council'
+import { Option, Text } from '@polkadot/types'
+import { Constructor, Codec } from '@polkadot/types/types'
+import { Struct, Vec } from '@polkadot/types/codec'
+import { u32 } from '@polkadot/types/primitive'
+import { BlockNumber, Balance, AccountId } from '@polkadot/types/interfaces'
+import { DerivedBalances } from '@polkadot/api-derive/types'
+import { KeyringPair } from '@polkadot/keyring/types'
+import { WorkerId, OpeningType } from '@joystream/types/working-group'
+import { Profile, MemberId } from '@joystream/types/members'
+import {
+  GenericJoyStreamRoleSchema,
+  JobSpecifics,
+  ApplicationDetails,
+  QuestionSections,
+  QuestionSection,
+  QuestionsFields,
+  QuestionField,
+  EntryInMembershipModuke,
+  HiringProcess,
+  AdditionalRolehiringProcessDetails,
+  CreatorDetails,
+} from '@joystream/types/hiring/schemas/role.schema.typings'
+import ajv from 'ajv'
+import { Opening, StakingPolicy, ApplicationStageKeys } from '@joystream/types/hiring'
+import { Validator } from 'inquirer'
 
 
 // KeyringPair type extended with mandatory "meta.name"
 // KeyringPair type extended with mandatory "meta.name"
 // It's used for accounts/keys management within CLI.
 // It's used for accounts/keys management within CLI.
 // If not provided in the account json file, the meta.name value is set to "Unnamed Account"
 // If not provided in the account json file, the meta.name value is set to "Unnamed Account"
 export type NamedKeyringPair = KeyringPair & {
 export type NamedKeyringPair = KeyringPair & {
-    meta: {
-        name: string
-    }
+  meta: {
+    name: string
+  }
 }
 }
 
 
 // Summary of the account information fetched from the api for "account:current" purposes (currently just balances)
 // Summary of the account information fetched from the api for "account:current" purposes (currently just balances)
 export type AccountSummary = {
 export type AccountSummary = {
-    balances: DerivedBalances
+  balances: DerivedBalances
 }
 }
 
 
-// Object/Tuple containing council/councilElection information (council:info).
-// The tuple is useful, because that's how api.queryMulti returns the results.
-export type CouncilInfoTuple = Parameters<typeof createCouncilInfoObj>;
-export type CouncilInfoObj = ReturnType<typeof createCouncilInfoObj>;
 // This function allows us to easily transform the tuple into the object
 // This function allows us to easily transform the tuple into the object
-// and simplifies the creation of consitent Object and Tuple types (seen above).
+// and simplifies the creation of consitent Object and Tuple types (seen below).
 export function createCouncilInfoObj(
 export function createCouncilInfoObj(
-    activeCouncil: Seat[],
-    termEndsAt: BlockNumber,
-    autoStart: Boolean,
-    newTermDuration: BN,
-    candidacyLimit: BN,
-    councilSize: BN,
-    minCouncilStake: Balance,
-    minVotingStake: Balance,
-    announcingPeriod: BlockNumber,
-    votingPeriod: BlockNumber,
-    revealingPeriod: BlockNumber,
-    round: BN,
-    stage: Option<ElectionStage>
+  activeCouncil: Seat[],
+  termEndsAt: BlockNumber,
+  autoStart: boolean,
+  newTermDuration: BN,
+  candidacyLimit: BN,
+  councilSize: BN,
+  minCouncilStake: Balance,
+  minVotingStake: Balance,
+  announcingPeriod: BlockNumber,
+  votingPeriod: BlockNumber,
+  revealingPeriod: BlockNumber,
+  round: BN,
+  stage: Option<ElectionStage>
 ) {
 ) {
-    return {
-        activeCouncil,
-        termEndsAt,
-        autoStart,
-        newTermDuration,
-        candidacyLimit,
-        councilSize,
-        minCouncilStake,
-        minVotingStake,
-        announcingPeriod,
-        votingPeriod,
-        revealingPeriod,
-        round,
-        stage
-    };
+  return {
+    activeCouncil,
+    termEndsAt,
+    autoStart,
+    newTermDuration,
+    candidacyLimit,
+    councilSize,
+    minCouncilStake,
+    minVotingStake,
+    announcingPeriod,
+    votingPeriod,
+    revealingPeriod,
+    round,
+    stage,
+  }
 }
 }
+// Object/Tuple containing council/councilElection information (council:info).
+// The tuple is useful, because that's how api.queryMulti returns the results.
+export type CouncilInfoTuple = Parameters<typeof createCouncilInfoObj>
+export type CouncilInfoObj = ReturnType<typeof createCouncilInfoObj>
 
 
 // Object with "name" and "value" properties, used for rendering simple CLI tables like:
 // Object with "name" and "value" properties, used for rendering simple CLI tables like:
 // Total balance:   100 JOY
 // Total balance:   100 JOY
 // Free calance:     50 JOY
 // Free calance:     50 JOY
-export type NameValueObj = { name: string, value: string };
+export type NameValueObj = { name: string; value: string }
+
+// Working groups related types
+export enum WorkingGroups {
+  StorageProviders = 'storageProviders',
+}
+
+// In contrast to Pioneer, currently only StorageProviders group is available in CLI
+export const AvailableGroups: readonly WorkingGroups[] = [WorkingGroups.StorageProviders] as const
+
+export type Reward = {
+  totalRecieved: Balance
+  value: Balance
+  interval?: number
+  nextPaymentBlock: number // 0 = no incoming payment
+}
+
+// Compound working group types
+export type GroupMember = {
+  workerId: WorkerId
+  memberId: MemberId
+  roleAccount: AccountId
+  profile: Profile
+  stake?: Balance
+  reward?: Reward
+}
+
+export type GroupApplication = {
+  wgApplicationId: number
+  applicationId: number
+  wgOpeningId: number
+  member: Profile | null
+  roleAccout: AccountId
+  stakes: {
+    application: number
+    role: number
+  }
+  humanReadableText: string
+  stage: ApplicationStageKeys
+}
+
+export enum OpeningStatus {
+  WaitingToBegin = 'WaitingToBegin',
+  AcceptingApplications = 'AcceptingApplications',
+  InReview = 'InReview',
+  Complete = 'Complete',
+  Cancelled = 'Cancelled',
+  Unknown = 'Unknown',
+}
+
+export type GroupOpeningStage = {
+  status: OpeningStatus
+  block?: number
+  date?: Date
+}
+
+export type GroupOpeningStakes = {
+  application?: StakingPolicy
+  role?: StakingPolicy
+}
+
+export type GroupOpening = {
+  wgOpeningId: number
+  openingId: number
+  stage: GroupOpeningStage
+  opening: Opening
+  stakes: GroupOpeningStakes
+  applications: GroupApplication[]
+  type: OpeningType
+}
+
+// Some helper structs for generating human_readable_text in working group opening extrinsic
+// Note those types are not part of the runtime etc., we just use them to simplify prompting for values
+// (since there exists functionality that handles that for substrate types like: Struct, Vec etc.)
+interface WithJSONable<T> {
+  toJSON: () => T
+}
+export class HRTJobSpecificsStruct extends Struct implements WithJSONable<JobSpecifics> {
+  constructor(value?: JobSpecifics) {
+    super(
+      {
+        title: 'Text',
+        description: 'Text',
+      },
+      value
+    )
+  }
+  get title(): string {
+    return (this.get('title') as Text).toString()
+  }
+  get description(): string {
+    return (this.get('description') as Text).toString()
+  }
+  toJSON(): JobSpecifics {
+    const { title, description } = this
+    return { title, description }
+  }
+}
+export class HRTEntryInMembershipModukeStruct extends Struct implements WithJSONable<EntryInMembershipModuke> {
+  constructor(value?: EntryInMembershipModuke) {
+    super(
+      {
+        handle: 'Text',
+      },
+      value
+    )
+  }
+  get handle(): string {
+    return (this.get('handle') as Text).toString()
+  }
+  toJSON(): EntryInMembershipModuke {
+    const { handle } = this
+    return { handle }
+  }
+}
+export class HRTCreatorDetailsStruct extends Struct implements WithJSONable<CreatorDetails> {
+  constructor(value?: CreatorDetails) {
+    super(
+      {
+        membership: HRTEntryInMembershipModukeStruct,
+      },
+      value
+    )
+  }
+  get membership(): EntryInMembershipModuke {
+    return (this.get('membership') as HRTEntryInMembershipModukeStruct).toJSON()
+  }
+  toJSON(): CreatorDetails {
+    const { membership } = this
+    return { membership }
+  }
+}
+export class HRTHiringProcessStruct extends Struct implements WithJSONable<HiringProcess> {
+  constructor(value?: HiringProcess) {
+    super(
+      {
+        details: 'Vec<Text>',
+      },
+      value
+    )
+  }
+  get details(): AdditionalRolehiringProcessDetails {
+    return (this.get('details') as Vec<Text>).toArray().map((v) => v.toString())
+  }
+  toJSON(): HiringProcess {
+    const { details } = this
+    return { details }
+  }
+}
+export class HRTQuestionFieldStruct extends Struct implements WithJSONable<QuestionField> {
+  constructor(value?: QuestionField) {
+    super(
+      {
+        title: 'Text',
+        type: 'Text',
+      },
+      value
+    )
+  }
+  get title(): string {
+    return (this.get('title') as Text).toString()
+  }
+  get type(): string {
+    return (this.get('type') as Text).toString()
+  }
+  toJSON(): QuestionField {
+    const { title, type } = this
+    return { title, type }
+  }
+}
+class HRTQuestionsFieldsVec extends Vec.with(HRTQuestionFieldStruct) implements WithJSONable<QuestionsFields> {
+  toJSON(): QuestionsFields {
+    return this.toArray().map((v) => v.toJSON())
+  }
+}
+export class HRTQuestionSectionStruct extends Struct implements WithJSONable<QuestionSection> {
+  constructor(value?: QuestionSection) {
+    super(
+      {
+        title: 'Text',
+        questions: HRTQuestionsFieldsVec,
+      },
+      value
+    )
+  }
+  get title(): string {
+    return (this.get('title') as Text).toString()
+  }
+  get questions(): QuestionsFields {
+    return (this.get('questions') as HRTQuestionsFieldsVec).toJSON()
+  }
+  toJSON(): QuestionSection {
+    const { title, questions } = this
+    return { title, questions }
+  }
+}
+export class HRTQuestionSectionsVec extends Vec.with(HRTQuestionSectionStruct)
+  implements WithJSONable<QuestionSections> {
+  toJSON(): QuestionSections {
+    return this.toArray().map((v) => v.toJSON())
+  }
+}
+export class HRTApplicationDetailsStruct extends Struct implements WithJSONable<ApplicationDetails> {
+  constructor(value?: ApplicationDetails) {
+    super(
+      {
+        sections: HRTQuestionSectionsVec,
+      },
+      value
+    )
+  }
+  get sections(): QuestionSections {
+    return (this.get('sections') as HRTQuestionSectionsVec).toJSON()
+  }
+  toJSON(): ApplicationDetails {
+    const { sections } = this
+    return { sections }
+  }
+}
+export class HRTStruct extends Struct implements WithJSONable<GenericJoyStreamRoleSchema> {
+  constructor(value?: GenericJoyStreamRoleSchema) {
+    super(
+      {
+        version: 'u32',
+        headline: 'Text',
+        job: HRTJobSpecificsStruct,
+        application: HRTApplicationDetailsStruct,
+        reward: 'Text',
+        creator: HRTCreatorDetailsStruct,
+        process: HRTHiringProcessStruct,
+      },
+      value
+    )
+  }
+  get version(): number {
+    return (this.get('version') as u32).toNumber()
+  }
+  get headline(): string {
+    return (this.get('headline') as Text).toString()
+  }
+  get job(): JobSpecifics {
+    return (this.get('job') as HRTJobSpecificsStruct).toJSON()
+  }
+  get application(): ApplicationDetails {
+    return (this.get('application') as HRTApplicationDetailsStruct).toJSON()
+  }
+  get reward(): string {
+    return (this.get('reward') as Text).toString()
+  }
+  get creator(): CreatorDetails {
+    return (this.get('creator') as HRTCreatorDetailsStruct).toJSON()
+  }
+  get process(): HiringProcess {
+    return (this.get('process') as HRTHiringProcessStruct).toJSON()
+  }
+  toJSON(): GenericJoyStreamRoleSchema {
+    const { version, headline, job, application, reward, creator, process } = this
+    return { version, headline, job, application, reward, creator, process }
+  }
+}
+
+// Api-related
+
+// Additional options that can be passed to ApiCommandBase.promptForParam in order to override
+// its default behaviour, change param name, add validation etc.
+export type ApiParamOptions<ParamType = Codec> = {
+  forcedName?: string
+  value?: {
+    default: ParamType
+    locked?: boolean
+  }
+  jsonSchema?: {
+    struct: Constructor<Struct>
+    schemaValidator: ajv.ValidateFunction
+  }
+  validator?: Validator
+  nestedOptions?: ApiParamsOptions // For more complex params, like structs
+}
+export type ApiParamsOptions = {
+  [paramName: string]: ApiParamOptions
+}
+
+export type ApiMethodArg = Codec
+export type ApiMethodNamedArg = {
+  name: string
+  value: ApiMethodArg
+}
+export type ApiMethodNamedArgs = ApiMethodNamedArg[]

+ 215 - 206
cli/src/base/AccountsCommandBase.ts

@@ -1,217 +1,226 @@
-import fs from 'fs';
-import path from 'path';
-import slug from 'slug';
-import inquirer from 'inquirer';
-import ExitCodes from '../ExitCodes';
-import { CLIError } from '@oclif/errors';
-import ApiCommandBase from './ApiCommandBase';
-import { Keyring } from '@polkadot/api';
-import { formatBalance } from '@polkadot/util';
-import { NamedKeyringPair } from '../Types';
-import { DerivedBalances } from '@polkadot/api-derive/types';
-import { toFixedLength } from '../helpers/display';
-
-const ACCOUNTS_DIRNAME = '/accounts';
+import fs from 'fs'
+import path from 'path'
+import slug from 'slug'
+import inquirer from 'inquirer'
+import ExitCodes from '../ExitCodes'
+import { CLIError } from '@oclif/errors'
+import ApiCommandBase from './ApiCommandBase'
+import { Keyring } from '@polkadot/api'
+import { formatBalance } from '@polkadot/util'
+import { NamedKeyringPair } from '../Types'
+import { DerivedBalances } from '@polkadot/api-derive/types'
+import { toFixedLength } from '../helpers/display'
+
+const ACCOUNTS_DIRNAME = 'accounts'
+const SPECIAL_ACCOUNT_POSTFIX = '__DEV'
 
 
 /**
 /**
  * Abstract base class for account-related commands.
  * Abstract base class for account-related commands.
  *
  *
  * All the accounts available in the CLI are stored in the form of json backup files inside:
  * All the accounts available in the CLI are stored in the form of json backup files inside:
- * { this.config.dataDir }/{ ACCOUNTS_DIRNAME } (ie. ~/.local/share/joystream-cli/accounts on Ubuntu)
- * Where: this.config.dataDir is provided by oclif and ACCOUNTS_DIRNAME is a const (see above).
+ * { APP_DATA_PATH }/{ ACCOUNTS_DIRNAME } (ie. ~/.local/share/joystream-cli/accounts on Ubuntu)
+ * Where: APP_DATA_PATH is provided by StateAwareCommandBase and ACCOUNTS_DIRNAME is a const (see above).
  */
  */
 export default abstract class AccountsCommandBase extends ApiCommandBase {
 export default abstract class AccountsCommandBase extends ApiCommandBase {
-    getAccountsDirPath(): string {
-        return path.join(this.config.dataDir, ACCOUNTS_DIRNAME);
+  getAccountsDirPath(): string {
+    return path.join(this.getAppDataPath(), ACCOUNTS_DIRNAME)
+  }
+
+  getAccountFilePath(account: NamedKeyringPair, isSpecial = false): string {
+    return path.join(this.getAccountsDirPath(), this.generateAccountFilename(account, isSpecial))
+  }
+
+  generateAccountFilename(account: NamedKeyringPair, isSpecial = false): string {
+    return `${slug(account.meta.name, '_')}__${account.address}${isSpecial ? SPECIAL_ACCOUNT_POSTFIX : ''}.json`
+  }
+
+  private initAccountsFs(): void {
+    if (!fs.existsSync(this.getAccountsDirPath())) {
+      fs.mkdirSync(this.getAccountsDirPath())
+    }
+  }
+
+  saveAccount(account: NamedKeyringPair, password: string, isSpecial = false): void {
+    try {
+      const destPath = this.getAccountFilePath(account, isSpecial)
+      fs.writeFileSync(destPath, JSON.stringify(account.toJson(password)))
+    } catch (e) {
+      throw this.createDataWriteError()
+    }
+  }
+
+  // Add dev "Alice" and "Bob" accounts
+  initSpecialAccounts() {
+    const keyring = new Keyring({ type: 'sr25519' })
+    keyring.addFromUri('//Alice', { name: 'Alice' })
+    keyring.addFromUri('//Bob', { name: 'Bob' })
+    keyring.getPairs().forEach((pair) => this.saveAccount({ ...pair, meta: { name: pair.meta.name } }, '', true))
+  }
+
+  fetchAccountFromJsonFile(jsonBackupFilePath: string): NamedKeyringPair {
+    if (!fs.existsSync(jsonBackupFilePath)) {
+      throw new CLIError('Input file does not exist!', { exit: ExitCodes.FileNotFound })
     }
     }
-
-    getAccountFilePath(account: NamedKeyringPair): string {
-        return path.join(this.getAccountsDirPath(), this.generateAccountFilename(account));
-    }
-
-    generateAccountFilename(account: NamedKeyringPair): string {
-        return `${ slug(account.meta.name, '_') }__${ account.address }.json`;
-    }
-
-    private initAccountsFs(): void {
-        if (!fs.existsSync(this.getAccountsDirPath())) {
-            fs.mkdirSync(this.getAccountsDirPath());
-        }
-    }
-
-    saveAccount(account: NamedKeyringPair, password: string): void {
-        try {
-            fs.writeFileSync(this.getAccountFilePath(account), JSON.stringify(account.toJson(password)));
-        } catch(e) {
-            throw this.createDataWriteError();
-        }
-    }
-
-    fetchAccountFromJsonFile(jsonBackupFilePath: string): NamedKeyringPair {
-        if (!fs.existsSync(jsonBackupFilePath)) {
-            throw new CLIError('Input file does not exist!', { exit: ExitCodes.FileNotFound });
-        }
-        if (path.extname(jsonBackupFilePath) !== '.json') {
-            throw new CLIError('Invalid input file: File extension should be .json', { exit: ExitCodes.InvalidFile });
-        }
-        let accountJsonObj: any;
-        try {
-            accountJsonObj = require(jsonBackupFilePath);
-        } catch (e) {
-            throw new CLIError('Provided backup file is not valid or cannot be accessed', { exit: ExitCodes.InvalidFile });
-        }
-        if (typeof accountJsonObj !== 'object' || accountJsonObj === null) {
-            throw new CLIError('Provided backup file is not valid', { exit: ExitCodes.InvalidFile });
-        }
-
-        // Force some default account name if none is provided in the original backup
-        if (!accountJsonObj.meta) accountJsonObj.meta = {};
-        if (!accountJsonObj.meta.name) accountJsonObj.meta.name = 'Unnamed Account';
-
-        let keyring = new Keyring();
-        let account:NamedKeyringPair;
-        try {
-            // Try adding and retrieving the keys in order to validate that the backup file is correct
-            keyring.addFromJson(accountJsonObj);
-            account = <NamedKeyringPair> keyring.getPair(accountJsonObj.address); // We can be sure it's named, because we forced it before
-        } catch (e) {
-            throw new CLIError('Provided backup file is not valid', { exit: ExitCodes.InvalidFile });
-        }
-
-        return account;
-    }
-
-    private fetchAccountOrNullFromFile(jsonFilePath: string): NamedKeyringPair | null {
-        try {
-            return this.fetchAccountFromJsonFile(jsonFilePath);
-        } catch (e) {
-            // Here in case of a typical CLIError we just return null (otherwise we throw)
-            if (!(e instanceof CLIError)) throw e;
-            return null;
-        }
-    }
-
-    fetchAccounts(): NamedKeyringPair[] {
-        let files: string[] = [];
-        const accountDir = this.getAccountsDirPath();
-        try {
-            files = fs.readdirSync(accountDir);
-        }
-        catch(e) {
-        }
-
-        // We have to assert the type, because TS is not aware that we're filtering out the nulls at the end
-        return <NamedKeyringPair[]> files
-            .map(fileName => {
-                const filePath = path.join(accountDir, fileName);
-                return this.fetchAccountOrNullFromFile(filePath);
-            })
-            .filter(accObj => accObj !== null);
-    }
-
-    getSelectedAccountFilename(): string {
-        return this.getPreservedState().selectedAccountFilename;
-    }
-
-    getSelectedAccount(): NamedKeyringPair | null {
-        const selectedAccountFilename = this.getSelectedAccountFilename();
-
-        if (!selectedAccountFilename) {
-            return null;
-        }
-
-        const account = this.fetchAccountOrNullFromFile(
-            path.join(this.getAccountsDirPath(), selectedAccountFilename)
-        );
-
-        return account;
-    }
-
-    // Use when account usage is required in given command
-    async getRequiredSelectedAccount(promptIfMissing: boolean = true): Promise<NamedKeyringPair> {
-        let selectedAccount: NamedKeyringPair | null = this.getSelectedAccount();
-        if (!selectedAccount) {
-            this.warn('No default account selected! Use account:choose to set the default account!');
-            if (!promptIfMissing) this.exit(ExitCodes.NoAccountSelected);
-            const accounts: NamedKeyringPair[] = this.fetchAccounts();
-            if (!accounts.length) {
-                this.error('There are no accounts available!', { exit: ExitCodes.NoAccountFound });
-            }
-
-            selectedAccount = await this.promptForAccount(accounts);
-        }
-
-        return selectedAccount;
+    if (path.extname(jsonBackupFilePath) !== '.json') {
+      throw new CLIError('Invalid input file: File extension should be .json', { exit: ExitCodes.InvalidFile })
     }
     }
-
-    async setSelectedAccount(account: NamedKeyringPair): Promise<void> {
-        await this.setPreservedState({ selectedAccountFilename: this.generateAccountFilename(account) });
-    }
-
-    async promptForPassword(message:string = 'Your account\'s password') {
-        const { password } = await inquirer.prompt([
-            { name: 'password', type: 'password', message }
-        ]);
-
-        return password;
-    }
-
-    async requireConfirmation(message: string = 'Are you sure you want to execute this action?'): Promise<void> {
-        const { confirmed } = await inquirer.prompt([
-            { type: 'confirm', name: 'confirmed', message, default: false }
-        ]);
-        if (!confirmed) this.exit(ExitCodes.OK);
-    }
-
-    async promptForAccount(
-        accounts: NamedKeyringPair[],
-        defaultAccount: NamedKeyringPair | null = null,
-        message: string = 'Select an account',
-        showBalances: boolean = true
-    ): Promise<NamedKeyringPair> {
-        let balances: DerivedBalances[];
-        if (showBalances) {
-            balances = await this.getApi().getAccountsBalancesInfo(accounts.map(acc => acc.address));
-        }
-        const longestAccNameLength: number = accounts.reduce((prev, curr) => Math.max(curr.meta.name.length, prev), 0);
-        const accNameColLength: number = Math.min(longestAccNameLength + 1, 20);
-        const { chosenAccountFilename } = await inquirer.prompt([{
-            name: 'chosenAccountFilename',
-            message,
-            type: 'list',
-            choices: accounts.map((account: NamedKeyringPair, i) => ({
-                name: (
-                    `${ toFixedLength(account.meta.name, accNameColLength) } | `+
-                    `${ account.address } | ` +
-                    ((showBalances || '') && (
-                        `${ formatBalance(balances[i].availableBalance) } / `+
-                        `${ formatBalance(balances[i].votingBalance) }`
-                    ))
-                ),
-                value: this.generateAccountFilename(account),
-                short: `${ account.meta.name } (${ account.address })`
-            })),
-            default: defaultAccount && this.generateAccountFilename(defaultAccount)
-        }]);
-
-        return <NamedKeyringPair> accounts.find(acc => this.generateAccountFilename(acc) === chosenAccountFilename);
-    }
-
-    async requestAccountDecoding(account: NamedKeyringPair): Promise<void> {
-        const password: string = await this.promptForPassword();
-        try {
-            account.decodePkcs8(password);
-        } catch (e) {
-            this.error('Invalid password!', { exit: ExitCodes.InvalidInput });
-        }
-    }
-
-    async init() {
-        await super.init();
-        try {
-            this.initAccountsFs();
-        } catch (e) {
-            throw this.createDataDirInitError();
-        }
+    let accountJsonObj: any
+    try {
+      accountJsonObj = require(jsonBackupFilePath)
+    } catch (e) {
+      throw new CLIError('Provided backup file is not valid or cannot be accessed', { exit: ExitCodes.InvalidFile })
+    }
+    if (typeof accountJsonObj !== 'object' || accountJsonObj === null) {
+      throw new CLIError('Provided backup file is not valid', { exit: ExitCodes.InvalidFile })
     }
     }
+
+    // Force some default account name if none is provided in the original backup
+    if (!accountJsonObj.meta) accountJsonObj.meta = {}
+    if (!accountJsonObj.meta.name) accountJsonObj.meta.name = 'Unnamed Account'
+
+    const keyring = new Keyring()
+    let account: NamedKeyringPair
+    try {
+      // Try adding and retrieving the keys in order to validate that the backup file is correct
+      keyring.addFromJson(accountJsonObj)
+      account = keyring.getPair(accountJsonObj.address) as NamedKeyringPair // We can be sure it's named, because we forced it before
+    } catch (e) {
+      throw new CLIError('Provided backup file is not valid', { exit: ExitCodes.InvalidFile })
+    }
+
+    return account
+  }
+
+  private fetchAccountOrNullFromFile(jsonFilePath: string): NamedKeyringPair | null {
+    try {
+      return this.fetchAccountFromJsonFile(jsonFilePath)
+    } catch (e) {
+      // Here in case of a typical CLIError we just return null (otherwise we throw)
+      if (!(e instanceof CLIError)) throw e
+      return null
+    }
+  }
+
+  fetchAccounts(includeSpecial = false): NamedKeyringPair[] {
+    let files: string[] = []
+    const accountDir = this.getAccountsDirPath()
+    try {
+      files = fs.readdirSync(accountDir)
+    } catch (e) {
+      // Do nothing
+    }
+
+    // We have to assert the type, because TS is not aware that we're filtering out the nulls at the end
+    return files
+      .map((fileName) => {
+        const filePath = path.join(accountDir, fileName)
+        if (!includeSpecial && filePath.includes(SPECIAL_ACCOUNT_POSTFIX + '.')) return null
+        return this.fetchAccountOrNullFromFile(filePath)
+      })
+      .filter((accObj) => accObj !== null) as NamedKeyringPair[]
+  }
+
+  getSelectedAccountFilename(): string {
+    return this.getPreservedState().selectedAccountFilename
+  }
+
+  getSelectedAccount(): NamedKeyringPair | null {
+    const selectedAccountFilename = this.getSelectedAccountFilename()
+
+    if (!selectedAccountFilename) {
+      return null
+    }
+
+    const account = this.fetchAccountOrNullFromFile(path.join(this.getAccountsDirPath(), selectedAccountFilename))
+
+    return account
+  }
+
+  // Use when account usage is required in given command
+  async getRequiredSelectedAccount(promptIfMissing = true): Promise<NamedKeyringPair> {
+    let selectedAccount: NamedKeyringPair | null = this.getSelectedAccount()
+    if (!selectedAccount) {
+      this.warn('No default account selected! Use account:choose to set the default account!')
+      if (!promptIfMissing) this.exit(ExitCodes.NoAccountSelected)
+      const accounts: NamedKeyringPair[] = this.fetchAccounts()
+      if (!accounts.length) {
+        this.error('There are no accounts available!', { exit: ExitCodes.NoAccountFound })
+      }
+
+      selectedAccount = await this.promptForAccount(accounts)
+    }
+
+    return selectedAccount
+  }
+
+  async setSelectedAccount(account: NamedKeyringPair): Promise<void> {
+    const accountFilename = fs.existsSync(this.getAccountFilePath(account, true))
+      ? this.generateAccountFilename(account, true)
+      : this.generateAccountFilename(account)
+
+    await this.setPreservedState({ selectedAccountFilename: accountFilename })
+  }
+
+  async promptForPassword(message = "Your account's password") {
+    const { password } = await inquirer.prompt([{ name: 'password', type: 'password', message }])
+
+    return password
+  }
+
+  async requireConfirmation(message = 'Are you sure you want to execute this action?'): Promise<void> {
+    const { confirmed } = await inquirer.prompt([{ type: 'confirm', name: 'confirmed', message, default: false }])
+    if (!confirmed) this.exit(ExitCodes.OK)
+  }
+
+  async promptForAccount(
+    accounts: NamedKeyringPair[],
+    defaultAccount: NamedKeyringPair | null = null,
+    message = 'Select an account',
+    showBalances = true
+  ): Promise<NamedKeyringPair> {
+    let balances: DerivedBalances[]
+    if (showBalances) {
+      balances = await this.getApi().getAccountsBalancesInfo(accounts.map((acc) => acc.address))
+    }
+    const longestAccNameLength: number = accounts.reduce((prev, curr) => Math.max(curr.meta.name.length, prev), 0)
+    const accNameColLength: number = Math.min(longestAccNameLength + 1, 20)
+    const { chosenAccountFilename } = await inquirer.prompt([
+      {
+        name: 'chosenAccountFilename',
+        message,
+        type: 'list',
+        choices: accounts.map((account: NamedKeyringPair, i) => ({
+          name:
+            `${toFixedLength(account.meta.name, accNameColLength)} | ` +
+            `${account.address} | ` +
+            ((showBalances || '') &&
+              `${formatBalance(balances[i].availableBalance)} / ` + `${formatBalance(balances[i].votingBalance)}`),
+          value: this.generateAccountFilename(account),
+          short: `${account.meta.name} (${account.address})`,
+        })),
+        default: defaultAccount && this.generateAccountFilename(defaultAccount),
+      },
+    ])
+
+    return accounts.find((acc) => this.generateAccountFilename(acc) === chosenAccountFilename) as NamedKeyringPair
+  }
+
+  async requestAccountDecoding(account: NamedKeyringPair): Promise<void> {
+    const password: string = await this.promptForPassword()
+    try {
+      account.decodePkcs8(password)
+    } catch (e) {
+      this.error('Invalid password!', { exit: ExitCodes.InvalidInput })
+    }
+  }
+
+  async init() {
+    await super.init()
+    try {
+      this.initAccountsFs()
+      this.initSpecialAccounts()
+    } catch (e) {
+      throw this.createDataDirInitError()
+    }
+  }
 }
 }

+ 394 - 15
cli/src/base/ApiCommandBase.ts

@@ -1,28 +1,407 @@
-import ExitCodes from '../ExitCodes';
-import { CLIError } from '@oclif/errors';
-import StateAwareCommandBase from './StateAwareCommandBase';
-import Api from '../Api';
+import ExitCodes from '../ExitCodes'
+import { CLIError } from '@oclif/errors'
+import StateAwareCommandBase from './StateAwareCommandBase'
+import Api from '../Api'
+import { getTypeDef, createType, Option, Tuple, Bytes } from '@polkadot/types'
+import { Codec, TypeDef, TypeDefInfo, Constructor } from '@polkadot/types/types'
+import { Vec, Struct, Enum } from '@polkadot/types/codec'
 import { ApiPromise } from '@polkadot/api'
 import { ApiPromise } from '@polkadot/api'
+import { KeyringPair } from '@polkadot/keyring/types'
+import chalk from 'chalk'
+import { SubmittableResultImpl } from '@polkadot/api/types'
+import ajv from 'ajv'
+import { ApiMethodArg, ApiMethodNamedArgs, ApiParamsOptions, ApiParamOptions } from '../Types'
+import { createParamOptions } from '../helpers/promptOptions'
+
+class ExtrinsicFailedError extends Error {}
 
 
 /**
 /**
  * Abstract base class for commands that require access to the API.
  * Abstract base class for commands that require access to the API.
  */
  */
 export default abstract class ApiCommandBase extends StateAwareCommandBase {
 export default abstract class ApiCommandBase extends StateAwareCommandBase {
-    private api: Api | null = null;
+  private api: Api | null = null
+
+  getApi(): Api {
+    if (!this.api) throw new CLIError('Tried to get API before initialization.', { exit: ExitCodes.ApiError })
+    return this.api
+  }
+
+  // Get original api for lower-level api calls
+  getOriginalApi(): ApiPromise {
+    return this.getApi().getOriginalApi()
+  }
+
+  async init() {
+    await super.init()
+    const apiUri: string = this.getPreservedState().apiUri
+    this.api = await Api.create(apiUri)
+  }
+
+  // This is needed to correctly handle some structs, enums etc.
+  // Where the main typeDef doesn't provide enough information
+  protected getRawTypeDef(type: string) {
+    const instance = createType(type as any)
+    return getTypeDef(instance.toRawType())
+  }
+
+  // Prettifier for type names which are actually JSON strings
+  protected prettifyJsonTypeName(json: string) {
+    const obj = JSON.parse(json) as { [key: string]: string }
+    return (
+      '{\n' +
+      Object.keys(obj)
+        .map((prop) => `  ${prop}${chalk.white(':' + obj[prop])}`)
+        .join('\n') +
+      '\n}'
+    )
+  }
+
+  // Get param name based on TypeDef object
+  protected paramName(typeDef: TypeDef) {
+    return chalk.green(
+      typeDef.displayName ||
+        typeDef.name ||
+        (typeDef.type.startsWith('{') ? this.prettifyJsonTypeName(typeDef.type) : typeDef.type)
+    )
+  }
+
+  // Prompt for simple/plain value (provided as string) of given type
+  async promptForSimple(typeDef: TypeDef, paramOptions?: ApiParamOptions): Promise<Codec> {
+    const providedValue = await this.simplePrompt({
+      message: `Provide value for ${this.paramName(typeDef)}`,
+      type: 'input',
+      // If not default provided - show default value resulting from providing empty string
+      default: paramOptions?.value?.default?.toString() || createType(typeDef.type as any, '').toString(),
+      validate: paramOptions?.validator,
+    })
+    return createType(typeDef.type as any, providedValue)
+  }
+
+  // Prompt for Option<Codec> value
+  async promptForOption(typeDef: TypeDef, paramOptions?: ApiParamOptions): Promise<Option<Codec>> {
+    const subtype = typeDef.sub as TypeDef // We assume that Opion always has a single subtype
+    const defaultValue = paramOptions?.value?.default as Option<Codec> | undefined
+    const confirmed = await this.simplePrompt({
+      message: `Do you want to provide the optional ${this.paramName(typeDef)} parameter?`,
+      type: 'confirm',
+      default: defaultValue ? defaultValue.isSome : false,
+    })
+
+    if (confirmed) {
+      this.openIndentGroup()
+      const value = await this.promptForParam(
+        subtype.type,
+        createParamOptions(subtype.name, defaultValue?.unwrapOr(undefined))
+      )
+      this.closeIndentGroup()
+      return new Option(subtype.type as any, value)
+    }
+
+    return new Option(subtype.type as any, null)
+  }
+
+  // Prompt for Tuple
+  // TODO: Not well tested yet
+  async promptForTuple(typeDef: TypeDef, paramOptions?: ApiParamOptions): Promise<Tuple> {
+    console.log(chalk.grey(`Providing values for ${this.paramName(typeDef)} tuple:`))
+
+    this.openIndentGroup()
+    const result: ApiMethodArg[] = []
+    // We assume that for Tuple there is always at least 1 subtype (pethaps it's even always an array?)
+    const subtypes: TypeDef[] = Array.isArray(typeDef.sub) ? typeDef.sub! : [typeDef.sub!]
+    const defaultValue = paramOptions?.value?.default as Tuple | undefined
 
 
-    getApi(): Api {
-        if (!this.api) throw new CLIError('Tried to get API before initialization.', { exit: ExitCodes.ApiError });
-        return this.api;
+    for (const [index, subtype] of Object.entries(subtypes)) {
+      const entryDefaultVal = defaultValue && defaultValue[parseInt(index)]
+      const inputParam = await this.promptForParam(subtype.type, createParamOptions(subtype.name, entryDefaultVal))
+      result.push(inputParam)
     }
     }
+    this.closeIndentGroup()
 
 
-    // Get original api for lower-level api calls
-    getOriginalApi(): ApiPromise {
-        return this.getApi().getOriginalApi();
+    return new Tuple(subtypes.map((subtype) => subtype.type) as any, result)
+  }
+
+  // Prompt for Struct
+  async promptForStruct(typeDef: TypeDef, paramOptions?: ApiParamOptions): Promise<ApiMethodArg> {
+    console.log(chalk.grey(`Providing values for ${this.paramName(typeDef)} struct:`))
+
+    this.openIndentGroup()
+    const structType = typeDef.type
+    const rawTypeDef = this.getRawTypeDef(structType)
+    // We assume struct typeDef always has array of typeDefs inside ".sub"
+    const structSubtypes = rawTypeDef.sub as TypeDef[]
+    const structDefault = paramOptions?.value?.default as Struct | undefined
+
+    const structValues: { [key: string]: ApiMethodArg } = {}
+    for (const subtype of structSubtypes) {
+      const fieldOptions = paramOptions?.nestedOptions && paramOptions.nestedOptions[subtype.name!]
+      const fieldDefaultValue = fieldOptions?.value?.default || (structDefault && structDefault.get(subtype.name!))
+      const finalFieldOptions: ApiParamOptions = {
+        ...fieldOptions,
+        forcedName: subtype.name,
+        value: fieldDefaultValue && { ...fieldOptions?.value, default: fieldDefaultValue },
+      }
+      structValues[subtype.name!] = await this.promptForParam(subtype.type, finalFieldOptions)
+    }
+    this.closeIndentGroup()
+
+    return createType(structType as any, structValues)
+  }
+
+  // Prompt for Vec
+  async promptForVec(typeDef: TypeDef, paramOptions?: ApiParamOptions): Promise<Vec<Codec>> {
+    console.log(chalk.grey(`Providing values for ${this.paramName(typeDef)} vector:`))
+
+    this.openIndentGroup()
+    // We assume Vec always has one TypeDef as ".sub"
+    const subtype = typeDef.sub as TypeDef
+    const defaultValue = paramOptions?.value?.default as Vec<Codec> | undefined
+    const entries: Codec[] = []
+    let addAnother = false
+    do {
+      addAnother = await this.simplePrompt({
+        message: `Do you want to add another entry to ${this.paramName(typeDef)} vector (currently: ${
+          entries.length
+        })?`,
+        type: 'confirm',
+        default: defaultValue ? entries.length < defaultValue.length : false,
+      })
+      const defaultEntryValue = defaultValue && defaultValue[entries.length]
+      if (addAnother) {
+        entries.push(await this.promptForParam(subtype.type, createParamOptions(subtype.name, defaultEntryValue)))
+      }
+    } while (addAnother)
+    this.closeIndentGroup()
+
+    return new Vec(subtype.type as any, entries)
+  }
+
+  // Prompt for Enum
+  async promptForEnum(typeDef: TypeDef, paramOptions?: ApiParamOptions): Promise<Enum> {
+    const enumType = typeDef.type
+    const rawTypeDef = this.getRawTypeDef(enumType)
+    // We assume enum always has array on TypeDefs inside ".sub"
+    const enumSubtypes = rawTypeDef.sub as TypeDef[]
+    const defaultValue = paramOptions?.value?.default as Enum | undefined
+
+    const enumSubtypeName = await this.simplePrompt({
+      message: `Choose value for ${this.paramName(typeDef)}:`,
+      type: 'list',
+      choices: enumSubtypes.map((subtype) => ({
+        name: subtype.name,
+        value: subtype.name,
+      })),
+      default: defaultValue?.type,
+    })
+
+    const enumSubtype = enumSubtypes.find((st) => st.name === enumSubtypeName)!
+
+    if (enumSubtype.type !== 'Null') {
+      const subtypeOptions = createParamOptions(enumSubtype.name, defaultValue?.value)
+      return createType(enumType as any, {
+        [enumSubtype.name!]: await this.promptForParam(enumSubtype.type, subtypeOptions),
+      })
     }
     }
 
 
-    async init() {
-        await super.init();
-        const apiUri: string = this.getPreservedState().apiUri;
-        this.api = await Api.create(apiUri);
+    return createType(enumType as any, enumSubtype.name)
+  }
+
+  // Prompt for param based on "paramType" string (ie. Option<MemeberId>)
+  // TODO: This may not yet work for all possible types
+  async promptForParam(
+    paramType: string,
+    paramOptions?: ApiParamOptions // TODO: This is not fully implemented for all types yet
+  ): Promise<ApiMethodArg> {
+    const typeDef = getTypeDef(paramType)
+    const rawTypeDef = this.getRawTypeDef(paramType)
+
+    if (paramOptions?.forcedName) {
+      typeDef.name = paramOptions.forcedName
     }
     }
+
+    if (paramOptions?.value?.locked) {
+      return paramOptions.value.default
+    }
+
+    if (paramOptions?.jsonSchema) {
+      const { struct, schemaValidator } = paramOptions.jsonSchema
+      return await this.promptForJsonBytes(
+        struct,
+        typeDef.name,
+        paramOptions.value?.default as Bytes | undefined,
+        schemaValidator
+      )
+    }
+
+    if (rawTypeDef.info === TypeDefInfo.Option) {
+      return await this.promptForOption(typeDef, paramOptions)
+    } else if (rawTypeDef.info === TypeDefInfo.Tuple) {
+      return await this.promptForTuple(typeDef, paramOptions)
+    } else if (rawTypeDef.info === TypeDefInfo.Struct) {
+      return await this.promptForStruct(typeDef, paramOptions)
+    } else if (rawTypeDef.info === TypeDefInfo.Enum) {
+      return await this.promptForEnum(typeDef, paramOptions)
+    } else if (rawTypeDef.info === TypeDefInfo.Vec) {
+      return await this.promptForVec(typeDef, paramOptions)
+    } else {
+      return await this.promptForSimple(typeDef, paramOptions)
+    }
+  }
+
+  async promptForJsonBytes(
+    JsonStruct: Constructor<Struct>,
+    argName?: string,
+    defaultValue?: Bytes,
+    schemaValidator?: ajv.ValidateFunction
+  ) {
+    const rawType = new JsonStruct().toRawType()
+    const typeDef = getTypeDef(rawType)
+
+    const defaultStruct =
+      defaultValue && new JsonStruct(JSON.parse(Buffer.from(defaultValue.toHex().replace('0x', ''), 'hex').toString()))
+
+    if (argName) {
+      typeDef.name = argName
+    }
+
+    let isValid = true,
+      jsonText: string
+    do {
+      const structVal = await this.promptForStruct(typeDef, createParamOptions(typeDef.name, defaultStruct))
+      jsonText = JSON.stringify(structVal.toJSON())
+      if (schemaValidator) {
+        isValid = Boolean(schemaValidator(JSON.parse(jsonText)))
+        if (!isValid) {
+          this.log('\n')
+          this.warn(
+            'Schema validation failed with:\n' +
+              schemaValidator.errors?.map((e) => chalk.red(`${chalk.bold(e.dataPath)}: ${e.message}`)).join('\n') +
+              '\nTry again...'
+          )
+          this.log('\n')
+        }
+      }
+    } while (!isValid)
+
+    return new Bytes('0x' + Buffer.from(jsonText, 'ascii').toString('hex'))
+  }
+
+  async promptForExtrinsicParams(
+    module: string,
+    method: string,
+    paramsOptions?: ApiParamsOptions
+  ): Promise<ApiMethodArg[]> {
+    const extrinsicMethod = this.getOriginalApi().tx[module][method]
+    const values: ApiMethodArg[] = []
+
+    this.openIndentGroup()
+    for (const arg of extrinsicMethod.meta.args.toArray()) {
+      const argName = arg.name.toString()
+      const argType = arg.type.toString()
+      let argOptions = paramsOptions && paramsOptions[argName]
+      if (!argOptions?.forcedName) {
+        argOptions = { ...argOptions, forcedName: argName }
+      }
+      values.push(await this.promptForParam(argType, argOptions))
+    }
+    this.closeIndentGroup()
+
+    return values
+  }
+
+  sendExtrinsic(account: KeyringPair, module: string, method: string, params: Codec[]) {
+    return new Promise((resolve, reject) => {
+      const extrinsicMethod = this.getOriginalApi().tx[module][method]
+      let unsubscribe: () => void
+      extrinsicMethod(...params)
+        .signAndSend(account, {}, (result: SubmittableResultImpl) => {
+          // Implementation loosely based on /pioneer/packages/react-signer/src/Modal.tsx
+          if (!result || !result.status) {
+            return
+          }
+
+          if (result.status.isFinalized) {
+            unsubscribe()
+            result.events
+              .filter(({ event: { section } }): boolean => section === 'system')
+              .forEach(({ event: { method } }): void => {
+                if (method === 'ExtrinsicFailed') {
+                  reject(new ExtrinsicFailedError('Extrinsic execution error!'))
+                } else if (method === 'ExtrinsicSuccess') {
+                  resolve()
+                }
+              })
+          } else if (result.isError) {
+            reject(new ExtrinsicFailedError('Extrinsic execution error!'))
+          }
+        })
+        .then((unsubFunc) => (unsubscribe = unsubFunc))
+        .catch((e) =>
+          reject(new ExtrinsicFailedError(`Cannot send the extrinsic: ${e.message ? e.message : JSON.stringify(e)}`))
+        )
+    })
+  }
+
+  async sendAndFollowExtrinsic(
+    account: KeyringPair,
+    module: string,
+    method: string,
+    params: Codec[],
+    warnOnly = false // If specified - only warning will be displayed (instead of error beeing thrown)
+  ) {
+    try {
+      this.log(chalk.white(`\nSending ${module}.${method} extrinsic...`))
+      await this.sendExtrinsic(account, module, method, params)
+      this.log(chalk.green(`Extrinsic successful!`))
+    } catch (e) {
+      if (e instanceof ExtrinsicFailedError && warnOnly) {
+        this.warn(`${module}.${method} extrinsic failed! ${e.message}`)
+      } else if (e instanceof ExtrinsicFailedError) {
+        throw new CLIError(`${module}.${method} extrinsic failed! ${e.message}`, { exit: ExitCodes.ApiError })
+      } else {
+        throw e
+      }
+    }
+  }
+
+  async buildAndSendExtrinsic(
+    account: KeyringPair,
+    module: string,
+    method: string,
+    paramsOptions: ApiParamsOptions,
+    warnOnly = false // If specified - only warning will be displayed (instead of error beeing thrown)
+  ): Promise<ApiMethodArg[]> {
+    const params = await this.promptForExtrinsicParams(module, method, paramsOptions)
+    await this.sendAndFollowExtrinsic(account, module, method, params, warnOnly)
+
+    return params
+  }
+
+  extrinsicArgsFromDraft(module: string, method: string, draftFilePath: string): ApiMethodNamedArgs {
+    let draftJSONObj
+    const parsedArgs: ApiMethodNamedArgs = []
+    const extrinsicMethod = this.getOriginalApi().tx[module][method]
+    try {
+      // eslint-disable-next-line @typescript-eslint/no-var-requires
+      draftJSONObj = require(draftFilePath)
+    } catch (e) {
+      throw new CLIError(`Could not load draft from: ${draftFilePath}`, { exit: ExitCodes.InvalidFile })
+    }
+    if (!draftJSONObj || !Array.isArray(draftJSONObj) || draftJSONObj.length !== extrinsicMethod.meta.args.length) {
+      throw new CLIError(`The draft file at ${draftFilePath} is invalid!`, { exit: ExitCodes.InvalidFile })
+    }
+    for (const [index, arg] of Object.entries(extrinsicMethod.meta.args.toArray())) {
+      const argName = arg.name.toString()
+      const argType = arg.type.toString()
+      try {
+        parsedArgs.push({ name: argName, value: createType(argType as any, draftJSONObj[parseInt(index)]) })
+      } catch (e) {
+        throw new CLIError(`Couldn't parse ${argName} value from draft at ${draftFilePath}!`, {
+          exit: ExitCodes.InvalidFile,
+        })
+      }
+    }
+
+    return parsedArgs
+  }
 }
 }

+ 98 - 7
cli/src/base/DefaultCommandBase.ts

@@ -1,15 +1,106 @@
-import ExitCodes from '../ExitCodes';
-import Command from '@oclif/command';
+import ExitCodes from '../ExitCodes'
+import Command from '@oclif/command'
+import inquirer, { DistinctQuestion } from 'inquirer'
+import chalk from 'chalk'
 
 
 /**
 /**
  * Abstract base class for pretty much all commands
  * Abstract base class for pretty much all commands
  * (prevents console.log from hanging the process and unifies the default exit code)
  * (prevents console.log from hanging the process and unifies the default exit code)
  */
  */
 export default abstract class DefaultCommandBase extends Command {
 export default abstract class DefaultCommandBase extends Command {
-    async finally(err: any) {
-        // called after run and catch regardless of whether or not the command errored
-        // We'll force exit here, in case there is no error, to prevent console.log from hanging the process
-        if (!err) this.exit(ExitCodes.OK);
-        super.finally(err);
+  protected indentGroupsOpened = 0
+  protected jsonPrettyIdent = ''
+
+  openIndentGroup() {
+    console.group()
+    ++this.indentGroupsOpened
+  }
+
+  closeIndentGroup() {
+    console.groupEnd()
+    --this.indentGroupsOpened
+  }
+
+  async simplePrompt(question: DistinctQuestion) {
+    const { result } = await inquirer.prompt([
+      {
+        ...question,
+        name: 'result',
+        // prefix = 2 spaces for each group - 1 (because 1 is always added by default)
+        prefix: Array.from(new Array(this.indentGroupsOpened))
+          .map(() => '  ')
+          .join('')
+          .slice(1),
+      },
+    ])
+
+    return result
+  }
+
+  private jsonPrettyIndented(line: string) {
+    return `${this.jsonPrettyIdent}${line}`
+  }
+
+  private jsonPrettyOpen(char: '{' | '[') {
+    this.jsonPrettyIdent += '    '
+    return chalk.gray(char) + '\n'
+  }
+
+  private jsonPrettyClose(char: '}' | ']') {
+    this.jsonPrettyIdent = this.jsonPrettyIdent.slice(0, -4)
+    return this.jsonPrettyIndented(chalk.gray(char))
+  }
+
+  private jsonPrettyKeyVal(key: string, val: any): string {
+    return this.jsonPrettyIndented(chalk.white(`${key}: ${this.jsonPrettyAny(val)}`))
+  }
+
+  private jsonPrettyObj(obj: { [key: string]: any }): string {
+    return (
+      this.jsonPrettyOpen('{') +
+      Object.keys(obj)
+        .map((k) => this.jsonPrettyKeyVal(k, obj[k]))
+        .join(',\n') +
+      '\n' +
+      this.jsonPrettyClose('}')
+    )
+  }
+
+  private jsonPrettyArr(arr: any[]): string {
+    return (
+      this.jsonPrettyOpen('[') +
+      arr.map((v) => this.jsonPrettyIndented(this.jsonPrettyAny(v))).join(',\n') +
+      '\n' +
+      this.jsonPrettyClose(']')
+    )
+  }
+
+  private jsonPrettyAny(val: any): string {
+    if (Array.isArray(val)) {
+      return this.jsonPrettyArr(val)
+    } else if (typeof val === 'object' && val !== null) {
+      return this.jsonPrettyObj(val)
+    } else if (typeof val === 'string') {
+      return chalk.green(`"${val}"`)
     }
     }
+
+    // Number, boolean etc.
+    return chalk.cyan(val)
+  }
+
+  jsonPrettyPrint(json: string) {
+    try {
+      const parsed = JSON.parse(json)
+      console.log(this.jsonPrettyAny(parsed))
+    } catch (e) {
+      console.log(this.jsonPrettyAny(json))
+    }
+  }
+
+  async finally(err: any) {
+    // called after run and catch regardless of whether or not the command errored
+    // We'll force exit here, in case there is no error, to prevent console.log from hanging the process
+    if (!err) this.exit(ExitCodes.OK)
+    super.finally(err)
+  }
 }
 }

+ 94 - 79
cli/src/base/StateAwareCommandBase.ts

@@ -1,115 +1,130 @@
-import fs from 'fs';
-import path from 'path';
-import ExitCodes from '../ExitCodes';
-import { CLIError } from '@oclif/errors';
-import { DEFAULT_API_URI } from '../Api';
-import lockFile from 'proper-lockfile';
-import DefaultCommandBase from './DefaultCommandBase';
+import fs from 'fs'
+import path from 'path'
+import ExitCodes from '../ExitCodes'
+import { CLIError } from '@oclif/errors'
+import { DEFAULT_API_URI } from '../Api'
+import lockFile from 'proper-lockfile'
+import DefaultCommandBase from './DefaultCommandBase'
+import os from 'os'
 
 
 // Type for the state object (which is preserved as json in the state file)
 // Type for the state object (which is preserved as json in the state file)
 type StateObject = {
 type StateObject = {
-    selectedAccountFilename: string,
-    apiUri: string
-};
+  selectedAccountFilename: string
+  apiUri: string
+}
 
 
 // State object default values
 // State object default values
 const DEFAULT_STATE: StateObject = {
 const DEFAULT_STATE: StateObject = {
-    selectedAccountFilename: '',
-    apiUri: DEFAULT_API_URI
+  selectedAccountFilename: '',
+  apiUri: DEFAULT_API_URI,
 }
 }
 
 
-// State file path (relative to this.config.dataDir)
-const STATE_FILE = '/state.json';
+// State file path (relative to getAppDataPath())
+const STATE_FILE = '/state.json'
 
 
 // Possible data directory access errors
 // Possible data directory access errors
 enum DataDirErrorType {
 enum DataDirErrorType {
-    Init = 0,
-    Read = 1,
-    Write = 2,
+  Init = 0,
+  Read = 1,
+  Write = 2,
 }
 }
 
 
 /**
 /**
  * Abstract base class for commands that need to work with the preserved state.
  * Abstract base class for commands that need to work with the preserved state.
  *
  *
- * The preserved state is kept in a json file inside the data directory (this.config.dataDir, supplied by oclif).
+ * The preserved state is kept in a json file inside the data directory.
  * The state object contains all the information that needs to be preserved across sessions, ie. the default account
  * The state object contains all the information that needs to be preserved across sessions, ie. the default account
  * choosen by the user after executing account:choose command etc. (see "StateObject" type above).
  * choosen by the user after executing account:choose command etc. (see "StateObject" type above).
  */
  */
 export default abstract class StateAwareCommandBase extends DefaultCommandBase {
 export default abstract class StateAwareCommandBase extends DefaultCommandBase {
-    getStateFilePath(): string {
-        return path.join(this.config.dataDir, STATE_FILE);
+  getAppDataPath(): string {
+    const systemAppDataPath =
+      process.env.APPDATA ||
+      (process.platform === 'darwin'
+        ? path.join(os.homedir(), '/Library/Application Support')
+        : path.join(os.homedir(), '/.local/share'))
+    // eslint-disable-next-line @typescript-eslint/no-var-requires
+    const packageJson: { name?: string } = require('../../package.json')
+    if (!packageJson || !packageJson.name) {
+      throw new CLIError('Cannot get package name from package.json!')
     }
     }
+    return path.join(systemAppDataPath, packageJson.name)
+  }
 
 
-    private createDataDirFsError(errorType: DataDirErrorType, specificPath: string = '') {
-        const actionStrs: { [x in DataDirErrorType]: string } = {
-            [DataDirErrorType.Init]: 'initialize',
-            [DataDirErrorType.Read]: 'read from',
-            [DataDirErrorType.Write]: 'write into'
-        };
-
-        const errorMsg =
-            `Unexpected error while trying to ${ actionStrs[errorType] } the data directory.`+
-            `(${ path.join(this.config.dataDir, specificPath) })! Permissions issue?`;
+  getStateFilePath(): string {
+    return path.join(this.getAppDataPath(), STATE_FILE)
+  }
 
 
-        return new CLIError(errorMsg, { exit: ExitCodes.FsOperationFailed });
+  private createDataDirFsError(errorType: DataDirErrorType, specificPath = '') {
+    const actionStrs: { [x in DataDirErrorType]: string } = {
+      [DataDirErrorType.Init]: 'initialize',
+      [DataDirErrorType.Read]: 'read from',
+      [DataDirErrorType.Write]: 'write into',
     }
     }
 
 
-    createDataReadError(specificPath: string = ''): CLIError {
-        return this.createDataDirFsError(DataDirErrorType.Read, specificPath);
-    }
+    const errorMsg =
+      `Unexpected error while trying to ${actionStrs[errorType]} the data directory.` +
+      `(${path.join(this.getAppDataPath(), specificPath)})! Permissions issue?`
 
 
-    createDataWriteError(specificPath: string = ''): CLIError {
-        return this.createDataDirFsError(DataDirErrorType.Write, specificPath);
-    }
+    return new CLIError(errorMsg, { exit: ExitCodes.FsOperationFailed })
+  }
 
 
-    createDataDirInitError(specificPath: string = ''): CLIError {
-        return this.createDataDirFsError(DataDirErrorType.Init, specificPath);
-    }
+  createDataReadError(specificPath = ''): CLIError {
+    return this.createDataDirFsError(DataDirErrorType.Read, specificPath)
+  }
+
+  createDataWriteError(specificPath = ''): CLIError {
+    return this.createDataDirFsError(DataDirErrorType.Write, specificPath)
+  }
 
 
-    private initStateFs(): void {
-        if (!fs.existsSync(this.config.dataDir)) {
-            fs.mkdirSync(this.config.dataDir);
-        }
-        if (!fs.existsSync(this.getStateFilePath())) {
-            fs.writeFileSync(this.getStateFilePath(), JSON.stringify(DEFAULT_STATE));
-        }
+  createDataDirInitError(specificPath = ''): CLIError {
+    return this.createDataDirFsError(DataDirErrorType.Init, specificPath)
+  }
+
+  private initStateFs(): void {
+    if (!fs.existsSync(this.getAppDataPath())) {
+      fs.mkdirSync(this.getAppDataPath())
+    }
+    if (!fs.existsSync(this.getStateFilePath())) {
+      fs.writeFileSync(this.getStateFilePath(), JSON.stringify(DEFAULT_STATE))
     }
     }
+  }
 
 
-    getPreservedState(): StateObject {
-        let preservedState: StateObject;
-        try {
-            preservedState = <StateObject> require(this.getStateFilePath());
-        } catch(e) {
-            throw this.createDataReadError();
-        }
-        // The state preserved in a file may be missing some required values ie.
-        // if the user previously used the older version of the software.
-        // That's why we combine it with default state before returing.
-        return { ...DEFAULT_STATE, ...preservedState };
+  getPreservedState(): StateObject {
+    let preservedState: StateObject
+    try {
+      preservedState = require(this.getStateFilePath()) as StateObject
+    } catch (e) {
+      throw this.createDataReadError()
     }
     }
+    // The state preserved in a file may be missing some required values ie.
+    // if the user previously used the older version of the software.
+    // That's why we combine it with default state before returing.
+    return { ...DEFAULT_STATE, ...preservedState }
+  }
 
 
-    // Modifies preserved state. Uses file lock in order to avoid updating an older state.
-    // (which could potentialy change between read and write operation)
-    async setPreservedState(modifiedState: Partial<StateObject>): Promise<void> {
-        const stateFilePath = this.getStateFilePath();
-        const unlock = await lockFile.lock(stateFilePath);
-        let oldState: StateObject = this.getPreservedState();
-        let newState: StateObject = { ...oldState, ...modifiedState };
-        try {
-            fs.writeFileSync(stateFilePath, JSON.stringify(newState));
-        } catch(e) {
-            await unlock();
-            throw this.createDataWriteError();
-        }
-        await unlock();
+  // Modifies preserved state. Uses file lock in order to avoid updating an older state.
+  // (which could potentialy change between read and write operation)
+  async setPreservedState(modifiedState: Partial<StateObject>): Promise<void> {
+    const stateFilePath = this.getStateFilePath()
+    const unlock = await lockFile.lock(stateFilePath)
+    const oldState: StateObject = this.getPreservedState()
+    const newState: StateObject = { ...oldState, ...modifiedState }
+    try {
+      fs.writeFileSync(stateFilePath, JSON.stringify(newState))
+    } catch (e) {
+      await unlock()
+      throw this.createDataWriteError()
     }
     }
+    await unlock()
+  }
 
 
-    async init() {
-        await super.init();
-        try {
-            await this.initStateFs();
-        } catch (e) {
-            throw this.createDataDirInitError();
-        }
+  async init() {
+    await super.init()
+    try {
+      await this.initStateFs()
+    } catch (e) {
+      throw this.createDataDirInitError()
     }
     }
+  }
 }
 }

+ 271 - 0
cli/src/base/WorkingGroupsCommandBase.ts

@@ -0,0 +1,271 @@
+import ExitCodes from '../ExitCodes'
+import AccountsCommandBase from './AccountsCommandBase'
+import { flags } from '@oclif/command'
+import {
+  WorkingGroups,
+  AvailableGroups,
+  NamedKeyringPair,
+  GroupMember,
+  GroupOpening,
+  ApiMethodArg,
+  ApiMethodNamedArgs,
+  OpeningStatus,
+  GroupApplication,
+} from '../Types'
+import { apiModuleByGroup } from '../Api'
+import { CLIError } from '@oclif/errors'
+import fs from 'fs'
+import path from 'path'
+import _ from 'lodash'
+import { ApplicationStageKeys } from '@joystream/types/hiring'
+
+const DEFAULT_GROUP = WorkingGroups.StorageProviders
+const DRAFTS_FOLDER = 'opening-drafts'
+
+/**
+ * Abstract base class for commands related to working groups
+ */
+export default abstract class WorkingGroupsCommandBase extends AccountsCommandBase {
+  group: WorkingGroups = DEFAULT_GROUP
+
+  static flags = {
+    group: flags.string({
+      char: 'g',
+      description:
+        'The working group context in which the command should be executed\n' +
+        `Available values are: ${AvailableGroups.join(', ')}.`,
+      required: true,
+      default: DEFAULT_GROUP,
+    }),
+  }
+
+  // Use when lead access is required in given command
+  async getRequiredLead(): Promise<GroupMember> {
+    const selectedAccount: NamedKeyringPair = await this.getRequiredSelectedAccount()
+    const lead = await this.getApi().groupLead(this.group)
+
+    if (!lead || lead.roleAccount.toString() !== selectedAccount.address) {
+      this.error('Lead access required for this command!', { exit: ExitCodes.AccessDenied })
+    }
+
+    return lead
+  }
+
+  // Use when worker access is required in given command
+  async getRequiredWorker(): Promise<GroupMember> {
+    const selectedAccount: NamedKeyringPair = await this.getRequiredSelectedAccount()
+    const groupMembers = await this.getApi().groupMembers(this.group)
+    const groupMembersByAccount = groupMembers.filter((m) => m.roleAccount.toString() === selectedAccount.address)
+
+    if (!groupMembersByAccount.length) {
+      this.error('Worker access required for this command!', { exit: ExitCodes.AccessDenied })
+    } else if (groupMembersByAccount.length === 1) {
+      return groupMembersByAccount[0]
+    } else {
+      return await this.promptForWorker(groupMembersByAccount)
+    }
+  }
+
+  // Use when member controller access is required, but one of the associated roles is expected to be selected
+  async getRequiredWorkerByMemberController(): Promise<GroupMember> {
+    const selectedAccount: NamedKeyringPair = await this.getRequiredSelectedAccount()
+    const memberIds = await this.getApi().getMemberIdsByControllerAccount(selectedAccount.address)
+    const controlledWorkers = (await this.getApi().groupMembers(this.group)).filter((groupMember) =>
+      memberIds.some((memberId) => groupMember.memberId.eq(memberId))
+    )
+
+    if (!controlledWorkers.length) {
+      this.error(`Member controller account with some associated ${this.group} group roles needs to be selected!`, {
+        exit: ExitCodes.AccessDenied,
+      })
+    } else if (controlledWorkers.length === 1) {
+      return controlledWorkers[0]
+    } else {
+      return await this.promptForWorker(controlledWorkers)
+    }
+  }
+
+  async promptForWorker(groupMembers: GroupMember[]): Promise<GroupMember> {
+    const chosenWorkerIndex = await this.simplePrompt({
+      message: 'Choose the intended worker context:',
+      type: 'list',
+      choices: groupMembers.map((groupMember, index) => ({
+        name: `Worker ID ${groupMember.workerId.toString()}`,
+        value: index,
+      })),
+    })
+
+    return groupMembers[chosenWorkerIndex]
+  }
+
+  async promptForApplicationsToAccept(opening: GroupOpening): Promise<number[]> {
+    const acceptableApplications = opening.applications.filter((a) => a.stage === ApplicationStageKeys.Active)
+    const acceptedApplications = await this.simplePrompt({
+      message: 'Select succesful applicants',
+      type: 'checkbox',
+      choices: acceptableApplications.map((a) => ({
+        name: ` ${a.wgApplicationId}: ${a.member?.handle.toString()}`,
+        value: a.wgApplicationId,
+      })),
+    })
+
+    return acceptedApplications
+  }
+
+  async promptForNewOpeningDraftName() {
+    let draftName = '',
+      fileExists = false,
+      overrideConfirmed = false
+
+    do {
+      draftName = await this.simplePrompt({
+        type: 'input',
+        message: 'Provide the draft name',
+        validate: (val) => (typeof val === 'string' && val.length >= 1) || 'Draft name is required!',
+      })
+
+      fileExists = fs.existsSync(this.getOpeningDraftPath(draftName))
+      if (fileExists) {
+        overrideConfirmed = await this.simplePrompt({
+          type: 'confirm',
+          message: 'Such draft already exists. Do you wish to override it?',
+          default: false,
+        })
+      }
+    } while (fileExists && !overrideConfirmed)
+
+    return draftName
+  }
+
+  async promptForOpeningDraft() {
+    let draftFiles: string[] = []
+    try {
+      draftFiles = fs.readdirSync(this.getOpeingDraftsPath())
+    } catch (e) {
+      throw this.createDataReadError(DRAFTS_FOLDER)
+    }
+    if (!draftFiles.length) {
+      throw new CLIError('No drafts available!', { exit: ExitCodes.FileNotFound })
+    }
+    const draftNames = draftFiles.map((fileName) => _.startCase(fileName.replace('.json', '')))
+    const selectedDraftName = await this.simplePrompt({
+      message: 'Select a draft',
+      type: 'list',
+      choices: draftNames,
+    })
+
+    return selectedDraftName
+  }
+
+  async getOpeningForLeadAction(id: number, requiredStatus?: OpeningStatus): Promise<GroupOpening> {
+    const opening = await this.getApi().groupOpening(this.group, id)
+
+    if (!opening.type.isOfType('Worker')) {
+      this.error('A lead can only manage Worker openings!', { exit: ExitCodes.AccessDenied })
+    }
+
+    if (requiredStatus && opening.stage.status !== requiredStatus) {
+      this.error(
+        `The opening needs to be in "${_.startCase(requiredStatus)}" stage! ` +
+          `This one is: "${_.startCase(opening.stage.status)}"`,
+        { exit: ExitCodes.InvalidInput }
+      )
+    }
+
+    return opening
+  }
+
+  // An alias for better code readibility in case we don't need the actual return value
+  validateOpeningForLeadAction = this.getOpeningForLeadAction
+
+  async getApplicationForLeadAction(id: number, requiredStatus?: ApplicationStageKeys): Promise<GroupApplication> {
+    const application = await this.getApi().groupApplication(this.group, id)
+    const opening = await this.getApi().groupOpening(this.group, application.wgOpeningId)
+
+    if (!opening.type.isOfType('Worker')) {
+      this.error('A lead can only manage Worker opening applications!', { exit: ExitCodes.AccessDenied })
+    }
+
+    if (requiredStatus && application.stage !== requiredStatus) {
+      this.error(
+        `The application needs to have "${_.startCase(requiredStatus)}" status! ` +
+          `This one has: "${_.startCase(application.stage)}"`,
+        { exit: ExitCodes.InvalidInput }
+      )
+    }
+
+    return application
+  }
+
+  async getWorkerForLeadAction(id: number, requireStakeProfile = false) {
+    const groupMember = await this.getApi().groupMember(this.group, id)
+    const groupLead = await this.getApi().groupLead(this.group)
+
+    if (groupLead?.workerId.eq(groupMember.workerId)) {
+      this.error('A lead cannot manage his own role this way!', { exit: ExitCodes.AccessDenied })
+    }
+
+    if (requireStakeProfile && !groupMember.stake) {
+      this.error('This worker has no associated role stake profile!', { exit: ExitCodes.InvalidInput })
+    }
+
+    return groupMember
+  }
+
+  // Helper for better TS handling.
+  // We could also use some magic with conditional types instead, but those don't seem be very well supported yet.
+  async getWorkerWithStakeForLeadAction(id: number) {
+    return (await this.getWorkerForLeadAction(id, true)) as GroupMember & Required<Pick<GroupMember, 'stake'>>
+  }
+
+  loadOpeningDraftParams(draftName: string): ApiMethodNamedArgs {
+    const draftFilePath = this.getOpeningDraftPath(draftName)
+    const params = this.extrinsicArgsFromDraft(apiModuleByGroup[this.group], 'addOpening', draftFilePath)
+
+    return params
+  }
+
+  getOpeingDraftsPath() {
+    return path.join(this.getAppDataPath(), DRAFTS_FOLDER)
+  }
+
+  getOpeningDraftPath(draftName: string) {
+    return path.join(this.getOpeingDraftsPath(), _.snakeCase(draftName) + '.json')
+  }
+
+  saveOpeningDraft(draftName: string, params: ApiMethodArg[]) {
+    const paramsJson = JSON.stringify(
+      params.map((p) => p.toJSON()),
+      null,
+      2
+    )
+
+    try {
+      fs.writeFileSync(this.getOpeningDraftPath(draftName), paramsJson)
+    } catch (e) {
+      throw this.createDataWriteError(DRAFTS_FOLDER)
+    }
+  }
+
+  private initOpeningDraftsDir(): void {
+    if (!fs.existsSync(this.getOpeingDraftsPath())) {
+      fs.mkdirSync(this.getOpeingDraftsPath())
+    }
+  }
+
+  async init() {
+    await super.init()
+    try {
+      this.initOpeningDraftsDir()
+    } catch (e) {
+      throw this.createDataDirInitError()
+    }
+    const { flags } = this.parse(this.constructor as typeof WorkingGroupsCommandBase)
+    if (!AvailableGroups.includes(flags.group as any)) {
+      throw new CLIError(`Invalid group! Available values are: ${AvailableGroups.join(', ')}`, {
+        exit: ExitCodes.InvalidInput,
+      })
+    }
+    this.group = flags.group as WorkingGroups
+  }
+}

+ 24 - 16
cli/src/commands/account/choose.ts

@@ -1,25 +1,33 @@
-import AccountsCommandBase from '../../base/AccountsCommandBase';
-import chalk from 'chalk';
-import ExitCodes from '../../ExitCodes';
+import AccountsCommandBase from '../../base/AccountsCommandBase'
+import chalk from 'chalk'
+import ExitCodes from '../../ExitCodes'
 import { NamedKeyringPair } from '../../Types'
 import { NamedKeyringPair } from '../../Types'
+import { flags } from '@oclif/command'
 
 
 export default class AccountChoose extends AccountsCommandBase {
 export default class AccountChoose extends AccountsCommandBase {
-    static description = 'Choose default account to use in the CLI';
+  static description = 'Choose default account to use in the CLI'
+  static flags = {
+    showSpecial: flags.boolean({
+      description: 'Whether to show special (DEV chain) accounts',
+      required: false,
+    }),
+  }
 
 
-    async run() {
-        const accounts: NamedKeyringPair[] = this.fetchAccounts();
-        const selectedAccount: NamedKeyringPair | null = this.getSelectedAccount();
+  async run() {
+    const { showSpecial } = this.parse(AccountChoose).flags
+    const accounts: NamedKeyringPair[] = this.fetchAccounts(showSpecial)
+    const selectedAccount: NamedKeyringPair | null = this.getSelectedAccount()
 
 
-        this.log(chalk.white(`Found ${ accounts.length } existing accounts...\n`));
+    this.log(chalk.white(`Found ${accounts.length} existing accounts...\n`))
 
 
-        if (accounts.length === 0) {
-            this.warn('No account to choose from. Add accont using account:import or account:create.');
-            this.exit(ExitCodes.NoAccountFound);
-        }
+    if (accounts.length === 0) {
+      this.warn('No account to choose from. Add accont using account:import or account:create.')
+      this.exit(ExitCodes.NoAccountFound)
+    }
 
 
-        const choosenAccount: NamedKeyringPair = await this.promptForAccount(accounts, selectedAccount);
+    const choosenAccount: NamedKeyringPair = await this.promptForAccount(accounts, selectedAccount)
 
 
-        await this.setSelectedAccount(choosenAccount);
-        this.log(chalk.greenBright("\nAccount switched!"));
-    }
+    await this.setSelectedAccount(choosenAccount)
+    this.log(chalk.greenBright('\nAccount switched!'))
   }
   }
+}

+ 35 - 35
cli/src/commands/account/create.ts

@@ -1,47 +1,47 @@
-import chalk from 'chalk';
-import ExitCodes from '../../ExitCodes';
-import AccountsCommandBase from '../../base/AccountsCommandBase';
-import { Keyring } from '@polkadot/api';
+import chalk from 'chalk'
+import ExitCodes from '../../ExitCodes'
+import AccountsCommandBase from '../../base/AccountsCommandBase'
+import { Keyring } from '@polkadot/api'
 import { mnemonicGenerate } from '@polkadot/util-crypto'
 import { mnemonicGenerate } from '@polkadot/util-crypto'
-import { NamedKeyringPair } from '../../Types';
+import { NamedKeyringPair } from '../../Types'
 
 
 type AccountCreateArgs = {
 type AccountCreateArgs = {
-    name: string
-};
+  name: string
+}
 
 
 export default class AccountCreate extends AccountsCommandBase {
 export default class AccountCreate extends AccountsCommandBase {
-    static description = 'Create new account';
-
-    static args = [
-        {
-            name: 'name',
-            required: true,
-            description: 'Account name'
-        },
-    ];
-
-    validatePass(password: string, password2: string): void {
-        if (password !== password2) this.error('Passwords are not the same!', { exit: ExitCodes.InvalidInput });
-        if (!password) this.error('You didn\'t provide a password', { exit: ExitCodes.InvalidInput });
-    }
+  static description = 'Create new account'
+
+  static args = [
+    {
+      name: 'name',
+      required: true,
+      description: 'Account name',
+    },
+  ]
+
+  validatePass(password: string, password2: string): void {
+    if (password !== password2) this.error('Passwords are not the same!', { exit: ExitCodes.InvalidInput })
+    if (!password) this.error("You didn't provide a password", { exit: ExitCodes.InvalidInput })
+  }
 
 
-    async run() {
-        const args: AccountCreateArgs = <AccountCreateArgs> this.parse(AccountCreate).args;
-        const keyring: Keyring = new Keyring();
-        const mnemonic: string = mnemonicGenerate();
+  async run() {
+    const args: AccountCreateArgs = this.parse(AccountCreate).args as AccountCreateArgs
+    const keyring: Keyring = new Keyring()
+    const mnemonic: string = mnemonicGenerate()
 
 
-        keyring.addFromMnemonic(mnemonic, { name: args.name, whenCreated: Date.now() });
-        const keys: NamedKeyringPair = <NamedKeyringPair> keyring.pairs[0]; // We assigned the name above
+    keyring.addFromMnemonic(mnemonic, { name: args.name, whenCreated: Date.now() })
+    const keys: NamedKeyringPair = keyring.pairs[0] as NamedKeyringPair // We assigned the name above
 
 
-        const password = await this.promptForPassword('Set your account\'s password');
-        const password2 = await this.promptForPassword('Confirm your password');
+    const password = await this.promptForPassword("Set your account's password")
+    const password2 = await this.promptForPassword('Confirm your password')
 
 
-        this.validatePass(password, password2);
+    this.validatePass(password, password2)
 
 
-        this.saveAccount(keys, password);
+    this.saveAccount(keys, password)
 
 
-        this.log(chalk.greenBright(`\nAccount succesfully created!`));
-        this.log(chalk.white(`${chalk.bold('Name:    ') }${ args.name }`));
-        this.log(chalk.white(`${chalk.bold('Address: ') }${ keys.address }`));
-    }
+    this.log(chalk.greenBright(`\nAccount succesfully created!`))
+    this.log(chalk.white(`${chalk.bold('Name:    ')}${args.name}`))
+    this.log(chalk.white(`${chalk.bold('Address: ')}${keys.address}`))
   }
   }
+}

+ 34 - 34
cli/src/commands/account/current.ts

@@ -1,41 +1,41 @@
-import AccountsCommandBase from '../../base/AccountsCommandBase';
-import { AccountSummary, NameValueObj, NamedKeyringPair } from '../../Types';
-import { DerivedBalances } from '@polkadot/api-derive/types';
-import { displayHeader, displayNameValueTable } from '../../helpers/display';
-import { formatBalance } from '@polkadot/util';
-import moment from 'moment';
+import AccountsCommandBase from '../../base/AccountsCommandBase'
+import { AccountSummary, NameValueObj, NamedKeyringPair } from '../../Types'
+import { DerivedBalances } from '@polkadot/api-derive/types'
+import { displayHeader, displayNameValueTable } from '../../helpers/display'
+import { formatBalance } from '@polkadot/util'
+import moment from 'moment'
 
 
 export default class AccountCurrent extends AccountsCommandBase {
 export default class AccountCurrent extends AccountsCommandBase {
-    static description = 'Display information about currently choosen default account';
-    static aliases = ['account:info', 'account:default'];
+  static description = 'Display information about currently choosen default account'
+  static aliases = ['account:info', 'account:default']
 
 
-    async run() {
-        const currentAccount: NamedKeyringPair = await this.getRequiredSelectedAccount(false);
-        const summary: AccountSummary = await this.getApi().getAccountSummary(currentAccount.address);
+  async run() {
+    const currentAccount: NamedKeyringPair = await this.getRequiredSelectedAccount(false)
+    const summary: AccountSummary = await this.getApi().getAccountSummary(currentAccount.address)
 
 
-        displayHeader('Account information');
-        const creationDate: string = currentAccount.meta.whenCreated ?
-            moment(currentAccount.meta.whenCreated).format('YYYY-MM-DD HH:mm:ss')
-            : '?';
-        const accountRows: NameValueObj[] = [
-            { name: 'Account name:', value: currentAccount.meta.name },
-            { name: 'Address:', value: currentAccount.address },
-            { name: 'Created:', value: creationDate }
-        ];
-        displayNameValueTable(accountRows);
+    displayHeader('Account information')
+    const creationDate: string = currentAccount.meta.whenCreated
+      ? moment(currentAccount.meta.whenCreated).format('YYYY-MM-DD HH:mm:ss')
+      : '?'
+    const accountRows: NameValueObj[] = [
+      { name: 'Account name:', value: currentAccount.meta.name },
+      { name: 'Address:', value: currentAccount.address },
+      { name: 'Created:', value: creationDate },
+    ]
+    displayNameValueTable(accountRows)
 
 
-        displayHeader('Balances');
-        const balances: DerivedBalances = summary.balances;
-        let balancesRows: NameValueObj[] = [
-            { name: 'Total balance:', value: formatBalance(balances.votingBalance) },
-            { name: 'Transferable balance:', value: formatBalance(balances.availableBalance) }
-        ];
-        if (balances.lockedBalance.gtn(0)) {
-            balancesRows.push({ name: 'Locked balance:', value: formatBalance(balances.lockedBalance) });
-        }
-        if (balances.reservedBalance.gtn(0)) {
-            balancesRows.push({ name: 'Reserved balance:', value: formatBalance(balances.reservedBalance) });
-        }
-        displayNameValueTable(balancesRows);
+    displayHeader('Balances')
+    const balances: DerivedBalances = summary.balances
+    const balancesRows: NameValueObj[] = [
+      { name: 'Total balance:', value: formatBalance(balances.votingBalance) },
+      { name: 'Transferable balance:', value: formatBalance(balances.availableBalance) },
+    ]
+    if (balances.lockedBalance.gtn(0)) {
+      balancesRows.push({ name: 'Locked balance:', value: formatBalance(balances.lockedBalance) })
     }
     }
+    if (balances.reservedBalance.gtn(0)) {
+      balancesRows.push({ name: 'Reserved balance:', value: formatBalance(balances.reservedBalance) })
+    }
+    displayNameValueTable(balancesRows)
   }
   }
+}

+ 62 - 61
cli/src/commands/account/export.ts

@@ -1,73 +1,74 @@
-import fs from 'fs';
-import chalk from 'chalk';
-import path from 'path';
-import ExitCodes from '../../ExitCodes';
-import AccountsCommandBase from '../../base/AccountsCommandBase';
-import { flags } from '@oclif/command';
-import { NamedKeyringPair } from '../../Types';
+import fs from 'fs'
+import chalk from 'chalk'
+import path from 'path'
+import ExitCodes from '../../ExitCodes'
+import AccountsCommandBase from '../../base/AccountsCommandBase'
+import { flags } from '@oclif/command'
+import { NamedKeyringPair } from '../../Types'
 
 
-type AccountExportFlags = { all: boolean };
-type AccountExportArgs = { path: string };
+type AccountExportFlags = { all: boolean }
+type AccountExportArgs = { path: string }
 
 
 export default class AccountExport extends AccountsCommandBase {
 export default class AccountExport extends AccountsCommandBase {
-    static description = 'Export account(s) to given location';
-    static MULTI_EXPORT_FOLDER_NAME = 'exported_accounts';
+  static description = 'Export account(s) to given location'
+  static MULTI_EXPORT_FOLDER_NAME = 'exported_accounts'
 
 
-    static args = [
-        {
-            name: 'path',
-            required: true,
-            description: 'Path where the exported files should be placed'
-        }
-    ];
+  static args = [
+    {
+      name: 'path',
+      required: true,
+      description: 'Path where the exported files should be placed',
+    },
+  ]
 
 
-    static flags = {
-        all: flags.boolean({
-            char: 'a',
-            description: `If provided, exports all existing accounts into "${ AccountExport.MULTI_EXPORT_FOLDER_NAME }" folder inside given path`,
-        }),
-    };
-
-    exportAccount(account: NamedKeyringPair, destPath: string): string {
-        const sourceFilePath: string = this.getAccountFilePath(account);
-        const destFilePath: string = path.join(destPath, this.generateAccountFilename(account));
-        try {
-            fs.copyFileSync(sourceFilePath, destFilePath);
-        }
-        catch (e) {
-            this.error(
-                `Error while trying to copy into the export file: (${ destFilePath }). Permissions issue?`,
-                { exit: ExitCodes.FsOperationFailed }
-            );
-        }
+  static flags = {
+    all: flags.boolean({
+      char: 'a',
+      description: `If provided, exports all existing accounts into "${AccountExport.MULTI_EXPORT_FOLDER_NAME}" folder inside given path`,
+    }),
+  }
 
 
-        return destFilePath;
+  exportAccount(account: NamedKeyringPair, destPath: string): string {
+    const sourceFilePath: string = this.getAccountFilePath(account)
+    const destFilePath: string = path.join(destPath, this.generateAccountFilename(account))
+    try {
+      fs.copyFileSync(sourceFilePath, destFilePath)
+    } catch (e) {
+      this.error(`Error while trying to copy into the export file: (${destFilePath}). Permissions issue?`, {
+        exit: ExitCodes.FsOperationFailed,
+      })
     }
     }
 
 
-    async run() {
-        const args: AccountExportArgs = <AccountExportArgs> this.parse(AccountExport).args;
-        const flags: AccountExportFlags = <AccountExportFlags> this.parse(AccountExport).flags;
-        const accounts: NamedKeyringPair[] = this.fetchAccounts();
+    return destFilePath
+  }
 
 
-        if (!accounts.length) {
-            this.error('No accounts found!', { exit: ExitCodes.NoAccountFound });
-        }
+  async run() {
+    const args: AccountExportArgs = this.parse(AccountExport).args as AccountExportArgs
+    const flags: AccountExportFlags = this.parse(AccountExport).flags as AccountExportFlags
+    const accounts: NamedKeyringPair[] = this.fetchAccounts()
+
+    if (!accounts.length) {
+      this.error('No accounts found!', { exit: ExitCodes.NoAccountFound })
+    }
 
 
-        if (flags.all) {
-            const destPath: string = path.join(args.path, AccountExport.MULTI_EXPORT_FOLDER_NAME);
-            try {
-                if (!fs.existsSync(destPath)) fs.mkdirSync(destPath);
-            } catch(e) {
-                this.error(`Failed to create the export folder (${ destPath })`, { exit: ExitCodes.FsOperationFailed });
-            }
-            for (let account of accounts) this.exportAccount(account, destPath);
-            this.log(chalk.greenBright(`All accounts succesfully exported succesfully to: ${ chalk.white(destPath) }!`));
-        }
-        else {
-            const destPath: string = args.path;
-            const choosenAccount: NamedKeyringPair = await this.promptForAccount(accounts, null, 'Select an account to export');
-            const exportedFilePath: string = this.exportAccount(choosenAccount, destPath);
-            this.log(chalk.greenBright(`Account succesfully exported to: ${ chalk.white(exportedFilePath) }`));
-        }
+    if (flags.all) {
+      const destPath: string = path.join(args.path, AccountExport.MULTI_EXPORT_FOLDER_NAME)
+      try {
+        if (!fs.existsSync(destPath)) fs.mkdirSync(destPath)
+      } catch (e) {
+        this.error(`Failed to create the export folder (${destPath})`, { exit: ExitCodes.FsOperationFailed })
+      }
+      for (const account of accounts) this.exportAccount(account, destPath)
+      this.log(chalk.greenBright(`All accounts succesfully exported succesfully to: ${chalk.white(destPath)}!`))
+    } else {
+      const destPath: string = args.path
+      const choosenAccount: NamedKeyringPair = await this.promptForAccount(
+        accounts,
+        null,
+        'Select an account to export'
+      )
+      const exportedFilePath: string = this.exportAccount(choosenAccount, destPath)
+      this.log(chalk.greenBright(`Account succesfully exported to: ${chalk.white(exportedFilePath)}`))
     }
     }
   }
   }
+}

+ 23 - 21
cli/src/commands/account/forget.ts

@@ -1,29 +1,31 @@
-import fs from 'fs';
-import chalk from 'chalk';
-import ExitCodes from '../../ExitCodes';
-import AccountsCommandBase from '../../base/AccountsCommandBase';
-import { NamedKeyringPair } from '../../Types';
+import fs from 'fs'
+import chalk from 'chalk'
+import ExitCodes from '../../ExitCodes'
+import AccountsCommandBase from '../../base/AccountsCommandBase'
+import { NamedKeyringPair } from '../../Types'
 
 
 export default class AccountForget extends AccountsCommandBase {
 export default class AccountForget extends AccountsCommandBase {
-    static description = 'Forget (remove) account from the list of available accounts';
+  static description = 'Forget (remove) account from the list of available accounts'
 
 
-    async run() {
-        const accounts: NamedKeyringPair[] = this.fetchAccounts();
+  async run() {
+    const accounts: NamedKeyringPair[] = this.fetchAccounts()
 
 
-        if (!accounts.length) {
-            this.error('No accounts found!', { exit: ExitCodes.NoAccountFound });
-        }
-
-        const choosenAccount: NamedKeyringPair = await this.promptForAccount(accounts, null, 'Select an account to forget');
-        await this.requireConfirmation('Are you sure you want this account to be forgotten?');
+    if (!accounts.length) {
+      this.error('No accounts found!', { exit: ExitCodes.NoAccountFound })
+    }
 
 
-        const accountFilePath: string = this.getAccountFilePath(choosenAccount);
-        try {
-            fs.unlinkSync(accountFilePath);
-        } catch (e) {
-            this.error(`Could not remove account file (${ accountFilePath }). Permissions issue?`, { exit: ExitCodes.FsOperationFailed });
-        }
+    const choosenAccount: NamedKeyringPair = await this.promptForAccount(accounts, null, 'Select an account to forget')
+    await this.requireConfirmation('Are you sure you want this account to be forgotten?')
 
 
-        this.log(chalk.greenBright(`\nAccount has been forgotten!`))
+    const accountFilePath: string = this.getAccountFilePath(choosenAccount)
+    try {
+      fs.unlinkSync(accountFilePath)
+    } catch (e) {
+      this.error(`Could not remove account file (${accountFilePath}). Permissions issue?`, {
+        exit: ExitCodes.FsOperationFailed,
+      })
     }
     }
+
+    this.log(chalk.greenBright(`\nAccount has been forgotten!`))
   }
   }
+}

+ 34 - 36
cli/src/commands/account/import.ts

@@ -1,46 +1,44 @@
-import fs from 'fs';
-import chalk from 'chalk';
-import path from 'path';
-import ExitCodes from '../../ExitCodes';
-import AccountsCommandBase from '../../base/AccountsCommandBase';
-import { NamedKeyringPair } from '../../Types';
+import fs from 'fs'
+import chalk from 'chalk'
+import path from 'path'
+import ExitCodes from '../../ExitCodes'
+import AccountsCommandBase from '../../base/AccountsCommandBase'
+import { NamedKeyringPair } from '../../Types'
 
 
 type AccountImportArgs = {
 type AccountImportArgs = {
-    backupFilePath: string
-};
+  backupFilePath: string
+}
 
 
 export default class AccountImport extends AccountsCommandBase {
 export default class AccountImport extends AccountsCommandBase {
-    static description = 'Import account using JSON backup file';
+  static description = 'Import account using JSON backup file'
 
 
-    static args = [
-        {
-            name: 'backupFilePath',
-            required: true,
-            description: 'Path to account backup JSON file'
-        },
-    ];
+  static args = [
+    {
+      name: 'backupFilePath',
+      required: true,
+      description: 'Path to account backup JSON file',
+    },
+  ]
 
 
-    async run() {
-        const args: AccountImportArgs = <AccountImportArgs> this.parse(AccountImport).args;
-        const backupAcc: NamedKeyringPair = this.fetchAccountFromJsonFile(args.backupFilePath);
-        const accountName: string = backupAcc.meta.name;
-        const accountAddress: string = backupAcc.address;
+  async run() {
+    const args: AccountImportArgs = this.parse(AccountImport).args as AccountImportArgs
+    const backupAcc: NamedKeyringPair = this.fetchAccountFromJsonFile(args.backupFilePath)
+    const accountName: string = backupAcc.meta.name
+    const accountAddress: string = backupAcc.address
 
 
-        const sourcePath: string = args.backupFilePath;
-        const destPath: string = path.join(this.getAccountsDirPath(), this.generateAccountFilename(backupAcc));
+    const sourcePath: string = args.backupFilePath
+    const destPath: string = path.join(this.getAccountsDirPath(), this.generateAccountFilename(backupAcc))
 
 
-        try {
-            fs.copyFileSync(sourcePath, destPath);
-        }
-        catch (e) {
-            this.error(
-                'Unexpected error while trying to copy input file! Permissions issue?',
-                { exit: ExitCodes.FsOperationFailed }
-            );
-        }
-
-        this.log(chalk.bold.greenBright(`ACCOUNT IMPORTED SUCCESFULLY!`));
-        this.log(chalk.bold.white(`NAME:    `), accountName);
-        this.log(chalk.bold.white(`ADDRESS: `), accountAddress);
+    try {
+      fs.copyFileSync(sourcePath, destPath)
+    } catch (e) {
+      this.error('Unexpected error while trying to copy input file! Permissions issue?', {
+        exit: ExitCodes.FsOperationFailed,
+      })
     }
     }
+
+    this.log(chalk.bold.greenBright(`ACCOUNT IMPORTED SUCCESFULLY!`))
+    this.log(chalk.bold.white(`NAME:    `), accountName)
+    this.log(chalk.bold.white(`ADDRESS: `), accountAddress)
   }
   }
+}

+ 53 - 54
cli/src/commands/account/transferTokens.ts

@@ -1,68 +1,67 @@
-import BN from 'bn.js';
-import AccountsCommandBase from '../../base/AccountsCommandBase';
-import chalk from 'chalk';
-import ExitCodes from '../../ExitCodes';
-import { formatBalance } from '@polkadot/util';
-import { Hash } from '@polkadot/types/interfaces';
-import { NamedKeyringPair } from '../../Types';
-import { checkBalance, validateAddress } from '../../helpers/validation';
-import { DerivedBalances } from '@polkadot/api-derive/types';
+import BN from 'bn.js'
+import AccountsCommandBase from '../../base/AccountsCommandBase'
+import chalk from 'chalk'
+import ExitCodes from '../../ExitCodes'
+import { formatBalance } from '@polkadot/util'
+import { Hash } from '@polkadot/types/interfaces'
+import { NamedKeyringPair } from '../../Types'
+import { checkBalance, validateAddress } from '../../helpers/validation'
+import { DerivedBalances } from '@polkadot/api-derive/types'
 
 
 type AccountTransferArgs = {
 type AccountTransferArgs = {
-    recipient: string,
-    amount: string
-};
+  recipient: string
+  amount: string
+}
 
 
 export default class AccountTransferTokens extends AccountsCommandBase {
 export default class AccountTransferTokens extends AccountsCommandBase {
-    static description = 'Transfer tokens from currently choosen account';
+  static description = 'Transfer tokens from currently choosen account'
 
 
-    static args = [
-        {
-            name: 'recipient',
-            required: true,
-            description: 'Address of the transfer recipient'
-        },
-        {
-            name: 'amount',
-            required: true,
-            description: 'Amount of tokens to transfer'
-        },
-    ];
+  static args = [
+    {
+      name: 'recipient',
+      required: true,
+      description: 'Address of the transfer recipient',
+    },
+    {
+      name: 'amount',
+      required: true,
+      description: 'Amount of tokens to transfer',
+    },
+  ]
 
 
-    async run() {
-        const args: AccountTransferArgs = <AccountTransferArgs> this.parse(AccountTransferTokens).args;
-        const selectedAccount: NamedKeyringPair = await this.getRequiredSelectedAccount();
-        const amountBN: BN = new BN(args.amount);
+  async run() {
+    const args: AccountTransferArgs = this.parse(AccountTransferTokens).args as AccountTransferArgs
+    const selectedAccount: NamedKeyringPair = await this.getRequiredSelectedAccount()
+    const amountBN: BN = new BN(args.amount)
 
 
-        // Initial validation
-        validateAddress(args.recipient, 'Invalid recipient address');
-        const accBalances: DerivedBalances = (await this.getApi().getAccountsBalancesInfo([ selectedAccount.address ]))[0];
-        checkBalance(accBalances, amountBN);
+    // Initial validation
+    validateAddress(args.recipient, 'Invalid recipient address')
+    const accBalances: DerivedBalances = (await this.getApi().getAccountsBalancesInfo([selectedAccount.address]))[0]
+    checkBalance(accBalances, amountBN)
 
 
-        await this.requestAccountDecoding(selectedAccount);
+    await this.requestAccountDecoding(selectedAccount)
 
 
-        this.log(chalk.white('Estimating fee...'));
-        let estimatedFee: BN;
-        try {
-            estimatedFee = await this.getApi().estimateFee(selectedAccount, args.recipient, amountBN);
-        }
-        catch (e) {
-            this.error('Could not estimate the fee.', { exit: ExitCodes.UnexpectedException });
-        }
-        const totalAmount: BN = amountBN.add(estimatedFee);
-        this.log(chalk.white('Estimated fee:', formatBalance(estimatedFee)));
-        this.log(chalk.white('Total transfer amount:', formatBalance(totalAmount)));
+    this.log(chalk.white('Estimating fee...'))
+    let estimatedFee: BN
+    try {
+      estimatedFee = await this.getApi().estimateFee(selectedAccount, args.recipient, amountBN)
+    } catch (e) {
+      this.error('Could not estimate the fee.', { exit: ExitCodes.UnexpectedException })
+    }
+    const totalAmount: BN = amountBN.add(estimatedFee)
+    this.log(chalk.white('Estimated fee:', formatBalance(estimatedFee)))
+    this.log(chalk.white('Total transfer amount:', formatBalance(totalAmount)))
 
 
-        checkBalance(accBalances, totalAmount);
+    checkBalance(accBalances, totalAmount)
 
 
-        await this.requireConfirmation('Do you confirm the transfer?');
+    await this.requireConfirmation('Do you confirm the transfer?')
 
 
-        try {
-            const txHash: Hash = await this.getApi().transfer(selectedAccount, args.recipient, amountBN);
-            this.log(chalk.greenBright('Transaction succesfully sent!'));
-            this.log(chalk.white('Hash:', txHash.toString()));
-        } catch (e) {
-            this.error('Could not send the transaction.', { exit: ExitCodes.UnexpectedException });
-        }
+    try {
+      const txHash: Hash = await this.getApi().transfer(selectedAccount, args.recipient, amountBN)
+      this.log(chalk.greenBright('Transaction succesfully sent!'))
+      this.log(chalk.white('Hash:', txHash.toString()))
+    } catch (e) {
+      this.error('Could not send the transaction.', { exit: ExitCodes.UnexpectedException })
     }
     }
   }
   }
+}

+ 7 - 8
cli/src/commands/api/getUri.ts

@@ -1,12 +1,11 @@
-import StateAwareCommandBase from '../../base/StateAwareCommandBase';
-import chalk from 'chalk';
-
+import StateAwareCommandBase from '../../base/StateAwareCommandBase'
+import chalk from 'chalk'
 
 
 export default class ApiGetUri extends StateAwareCommandBase {
 export default class ApiGetUri extends StateAwareCommandBase {
-    static description = 'Get current api WS provider uri';
+  static description = 'Get current api WS provider uri'
 
 
-    async run() {
-        const currentUri:string = this.getPreservedState().apiUri;
-        this.log(chalk.green(currentUri));
-    }
+  async run() {
+    const currentUri: string = this.getPreservedState().apiUri
+    this.log(chalk.green(currentUri))
   }
   }
+}

+ 208 - 251
cli/src/commands/api/inspect.ts

@@ -1,277 +1,234 @@
-import { flags } from '@oclif/command';
-import { CLIError } from '@oclif/errors';
-import { displayNameValueTable } from '../../helpers/display';
-import { ApiPromise } from '@polkadot/api';
-import { getTypeDef } from '@polkadot/types';
-import { Codec, TypeDef, TypeDefInfo } from '@polkadot/types/types';
-import { ConstantCodec } from '@polkadot/api-metadata/consts/types';
-import ExitCodes from '../../ExitCodes';
-import chalk from 'chalk';
-import { NameValueObj } from '../../Types';
-import inquirer from 'inquirer';
-import ApiCommandBase from '../../base/ApiCommandBase';
+import { flags } from '@oclif/command'
+import { CLIError } from '@oclif/errors'
+import { displayNameValueTable } from '../../helpers/display'
+import { ApiPromise } from '@polkadot/api'
+import { Option } from '@polkadot/types'
+import { Codec } from '@polkadot/types/types'
+import { ConstantCodec } from '@polkadot/api-metadata/consts/types'
+import ExitCodes from '../../ExitCodes'
+import chalk from 'chalk'
+import { NameValueObj, ApiMethodArg } from '../../Types'
+import ApiCommandBase from '../../base/ApiCommandBase'
 
 
 // Command flags type
 // Command flags type
 type ApiInspectFlags = {
 type ApiInspectFlags = {
-    type: string,
-    module: string,
-    method: string,
-    exec: boolean,
-    callArgs: string
-};
+  type: string
+  module: string
+  method: string
+  exec: boolean
+  callArgs: string
+}
 
 
 // Currently "inspectable" api types
 // Currently "inspectable" api types
-const TYPES_AVAILABLE = [
-    'query',
-    'consts',
-] as const;
+const TYPES_AVAILABLE = ['query', 'consts'] as const
 
 
 // String literals type based on TYPES_AVAILABLE const.
 // String literals type based on TYPES_AVAILABLE const.
 // It works as if we specified: type ApiType = 'query' | 'consts'...;
 // It works as if we specified: type ApiType = 'query' | 'consts'...;
-type ApiType = typeof TYPES_AVAILABLE[number];
-
-// Format of the api input args (as they are specified in the CLI)
-type ApiMethodInputSimpleArg = string;
-// This recurring type allows the correct handling of nested types like:
-// ((Type1, Type2), Option<Type3>) etc.
-type ApiMethodInputArg = ApiMethodInputSimpleArg | ApiMethodInputArg[];
+type ApiType = typeof TYPES_AVAILABLE[number]
 
 
 export default class ApiInspect extends ApiCommandBase {
 export default class ApiInspect extends ApiCommandBase {
-    static description =
-        'Lists available node API modules/methods and/or their description(s), '+
-        'or calls one of the API methods (depending on provided arguments and flags)';
-
-    static examples = [
-        '$ api:inspect',
-        '$ api:inspect -t=query',
-        '$ api:inspect -t=query -M=members',
-        '$ api:inspect -t=query -M=members -m=memberProfile',
-        '$ api:inspect -t=query -M=members -m=memberProfile -e',
-        '$ api:inspect -t=query -M=members -m=memberProfile -e -a=1',
-    ];
-
-    static flags = {
-        type: flags.string({
-            char: 't',
-            description:
-                'Specifies the type/category of the inspected request (ie. "query", "consts" etc.).\n'+
-                'If no "--module" flag is provided then all available modules in that type will be listed.\n'+
-                'If this flag is not provided then all available types will be listed.',
-        }),
-        module: flags.string({
-            char: 'M',
-            description:
-                'Specifies the api module, ie. "system", "staking" etc.\n'+
-                'If no "--method" flag is provided then all methods in that module will be listed along with the descriptions.',
-            dependsOn: ['type'],
-        }),
-        method: flags.string({
-            char: 'm',
-            description: 'Specifies the api method to call/describe.',
-            dependsOn: ['module'],
-        }),
-        exec: flags.boolean({
-            char: 'e',
-            description: 'Provide this flag if you want to execute the actual call, instead of displaying the method description (which is default)',
-            dependsOn: ['method'],
-        }),
-        callArgs: flags.string({
-            char: 'a',
-            description:
-                'Specifies the arguments to use when calling a method. Multiple arguments can be separated with a comma, ie. "-a=arg1,arg2".\n'+
-                'You can omit this flag even if the method requires some aguments.\n'+
-                'In that case you will be promted to provide value for each required argument.\n' +
-                'Ommiting this flag is recommended when input parameters are of more complex types (and it\'s hard to specify them as just simple comma-separated strings)',
-            dependsOn: ['exec'],
-        })
-    };
-
-    getMethodMeta(apiType: ApiType, apiModule: string, apiMethod: string) {
-        if (apiType === 'query') {
-            return this.getOriginalApi().query[apiModule][apiMethod].creator.meta;
-        }
-        else {
-            // Currently the only other optoin is api.consts
-            const method:ConstantCodec = <ConstantCodec> this.getOriginalApi().consts[apiModule][apiMethod];
-            return method.meta;
-        }
+  static description =
+    'Lists available node API modules/methods and/or their description(s), ' +
+    'or calls one of the API methods (depending on provided arguments and flags)'
+
+  static examples = [
+    '$ api:inspect',
+    '$ api:inspect -t=query',
+    '$ api:inspect -t=query -M=members',
+    '$ api:inspect -t=query -M=members -m=memberProfile',
+    '$ api:inspect -t=query -M=members -m=memberProfile -e',
+    '$ api:inspect -t=query -M=members -m=memberProfile -e -a=1',
+  ]
+
+  static flags = {
+    type: flags.string({
+      char: 't',
+      description:
+        'Specifies the type/category of the inspected request (ie. "query", "consts" etc.).\n' +
+        'If no "--module" flag is provided then all available modules in that type will be listed.\n' +
+        'If this flag is not provided then all available types will be listed.',
+    }),
+    module: flags.string({
+      char: 'M',
+      description:
+        'Specifies the api module, ie. "system", "staking" etc.\n' +
+        'If no "--method" flag is provided then all methods in that module will be listed along with the descriptions.',
+      dependsOn: ['type'],
+    }),
+    method: flags.string({
+      char: 'm',
+      description: 'Specifies the api method to call/describe.',
+      dependsOn: ['module'],
+    }),
+    exec: flags.boolean({
+      char: 'e',
+      description:
+        'Provide this flag if you want to execute the actual call, instead of displaying the method description (which is default)',
+      dependsOn: ['method'],
+    }),
+    callArgs: flags.string({
+      char: 'a',
+      description:
+        'Specifies the arguments to use when calling a method. Multiple arguments can be separated with a comma, ie. "-a=arg1,arg2".\n' +
+        'You can omit this flag even if the method requires some aguments.\n' +
+        'In that case you will be promted to provide value for each required argument.\n' +
+        "Ommiting this flag is recommended when input parameters are of more complex types (and it's hard to specify them as just simple comma-separated strings)",
+      dependsOn: ['exec'],
+    }),
+  }
+
+  getMethodMeta(apiType: ApiType, apiModule: string, apiMethod: string) {
+    if (apiType === 'query') {
+      return this.getOriginalApi().query[apiModule][apiMethod].creator.meta
+    } else {
+      // Currently the only other optoin is api.consts
+      const method: ConstantCodec = this.getOriginalApi().consts[apiModule][apiMethod] as ConstantCodec
+      return method.meta
     }
     }
-
-    getMethodDescription(apiType: ApiType, apiModule: string, apiMethod: string): string {
-        let description:string = this.getMethodMeta(apiType, apiModule, apiMethod).documentation.join(' ');
-        return description || 'No description available.';
+  }
+
+  getMethodDescription(apiType: ApiType, apiModule: string, apiMethod: string): string {
+    const description: string = this.getMethodMeta(apiType, apiModule, apiMethod).documentation.join(' ')
+    return description || 'No description available.'
+  }
+
+  getQueryMethodParamsTypes(apiModule: string, apiMethod: string): string[] {
+    const method = this.getOriginalApi().query[apiModule][apiMethod]
+    const { type } = method.creator.meta
+    if (type.isDoubleMap) {
+      return [type.asDoubleMap.key1.toString(), type.asDoubleMap.key2.toString()]
     }
     }
-
-    getQueryMethodParamsTypes(apiModule: string, apiMethod: string): string[] {
-        const method = this.getOriginalApi().query[apiModule][apiMethod];
-        const { type } = method.creator.meta;
-        if (type.isDoubleMap) {
-            return [ type.asDoubleMap.key1.toString(), type.asDoubleMap.key2.toString() ];
-        }
-        if (type.isMap) {
-            return type.asMap.linked.isTrue ? [ `Option<${type.asMap.key.toString()}>` ] : [ type.asMap.key.toString() ];
-        }
-        return [];
+    if (type.isMap) {
+      return type.asMap.linked.isTrue ? [`Option<${type.asMap.key.toString()}>`] : [type.asMap.key.toString()]
     }
     }
-
-    getMethodReturnType(apiType: ApiType, apiModule: string, apiMethod: string): string {
-        if (apiType === 'query') {
-            const method = this.getOriginalApi().query[apiModule][apiMethod];
-            const { meta: { type, modifier } } = method.creator;
-            if (type.isDoubleMap) {
-                return type.asDoubleMap.value.toString();
-            }
-            if (modifier.isOptional) {
-                return `Option<${type.toString()}>`;
-            }
-        }
-        // Fallback for "query" and default for "consts"
-        return this.getMethodMeta(apiType, apiModule, apiMethod).type.toString();
+    return []
+  }
+
+  getMethodReturnType(apiType: ApiType, apiModule: string, apiMethod: string): string {
+    if (apiType === 'query') {
+      const method = this.getOriginalApi().query[apiModule][apiMethod]
+      const {
+        meta: { type, modifier },
+      } = method.creator
+      if (type.isDoubleMap) {
+        return type.asDoubleMap.value.toString()
+      }
+      if (modifier.isOptional) {
+        return `Option<${type.toString()}>`
+      }
     }
     }
-
-    // Validate the flags - throws an error if flags.type, flags.module or flags.method is invalid / does not exist in the api.
-    // Returns type, module and method which validity we can be sure about (notice they may still be "undefined" if weren't provided).
-    validateFlags(api: ApiPromise, flags: ApiInspectFlags): { apiType: ApiType | undefined, apiModule: string | undefined, apiMethod: string | undefined } {
-        let apiType: ApiType | undefined = undefined;
-        const { module: apiModule, method: apiMethod } = flags;
-
-        if (flags.type !== undefined) {
-            const availableTypes: readonly string[] = TYPES_AVAILABLE;
-            if (!availableTypes.includes(flags.type)) {
-                throw new CLIError('Such type is not available', { exit: ExitCodes.InvalidInput });
-            }
-            apiType = <ApiType> flags.type;
-            if (apiModule !== undefined) {
-                if (!api[apiType][apiModule]) {
-                    throw new CLIError('Such module was not found', { exit: ExitCodes.InvalidInput });
-                }
-                if (apiMethod !== undefined && !api[apiType][apiModule][apiMethod]) {
-                    throw new CLIError('Such method was not found', { exit: ExitCodes.InvalidInput });
-                }
-            }
+    // Fallback for "query" and default for "consts"
+    return this.getMethodMeta(apiType, apiModule, apiMethod).type.toString()
+  }
+
+  // Validate the flags - throws an error if flags.type, flags.module or flags.method is invalid / does not exist in the api.
+  // Returns type, module and method which validity we can be sure about (notice they may still be "undefined" if weren't provided).
+  validateFlags(
+    api: ApiPromise,
+    flags: ApiInspectFlags
+  ): { apiType: ApiType | undefined; apiModule: string | undefined; apiMethod: string | undefined } {
+    let apiType: ApiType | undefined = undefined
+    const { module: apiModule, method: apiMethod } = flags
+
+    if (flags.type !== undefined) {
+      const availableTypes: readonly string[] = TYPES_AVAILABLE
+      if (!availableTypes.includes(flags.type)) {
+        throw new CLIError('Such type is not available', { exit: ExitCodes.InvalidInput })
+      }
+      apiType = flags.type as ApiType
+      if (apiModule !== undefined) {
+        if (!api[apiType][apiModule]) {
+          throw new CLIError('Such module was not found', { exit: ExitCodes.InvalidInput })
         }
         }
-
-        return { apiType, apiModule, apiMethod };
-    }
-
-    // Prompt for simple value (string)
-    async promptForSimple(typeName: string): Promise<string> {
-        const userInput = await inquirer.prompt([{
-            name: 'providedValue',
-            message: `Provide value for ${ typeName }`,
-            type: 'input'
-        } ])
-        return <string> userInput.providedValue;
-    }
-
-    // Prompt for optional value (returns undefined if user refused to provide)
-    async promptForOption(typeDef: TypeDef): Promise<ApiMethodInputArg | undefined> {
-        const userInput = await inquirer.prompt([{
-            name: 'confirmed',
-            message: `Do you want to provide the optional ${ typeDef.type } parameter?`,
-            type: 'confirm'
-        } ]);
-
-        if (userInput.confirmed) {
-            const subtype = <TypeDef> typeDef.sub; // We assume that Opion always has a single subtype
-            let value = await this.promptForParam(subtype.type);
-            return value;
+        if (apiMethod !== undefined && !api[apiType][apiModule][apiMethod]) {
+          throw new CLIError('Such method was not found', { exit: ExitCodes.InvalidInput })
         }
         }
+      }
     }
     }
 
 
-    // Prompt for tuple - returns array of values
-    async promptForTuple(typeDef: TypeDef): Promise<(ApiMethodInputArg)[]> {
-        let result: ApiMethodInputArg[] = [];
-
-        if (!typeDef.sub) return [ await this.promptForSimple(typeDef.type) ];
-
-        const subtypes: TypeDef[] = Array.isArray(typeDef.sub) ? typeDef.sub : [ typeDef.sub ];
+    return { apiType, apiModule, apiMethod }
+  }
+
+  // Request values for params using array of param types (strings)
+  async requestParamsValues(paramTypes: string[]): Promise<ApiMethodArg[]> {
+    const result: ApiMethodArg[] = []
+    for (const [key, paramType] of Object.entries(paramTypes)) {
+      this.log(chalk.bold.white(`Parameter no. ${parseInt(key) + 1} (${paramType}):`))
+      const paramValue = await this.promptForParam(paramType)
+      if (paramValue instanceof Option && paramValue.isSome) {
+        result.push(paramValue.unwrap())
+      } else if (!(paramValue instanceof Option)) {
+        result.push(paramValue)
+      }
+      // In case of empty option we MUST NOT add anything to the array (otherwise it causes some error)
+    }
 
 
-        for (let subtype of subtypes) {
-            let inputParam = await this.promptForParam(subtype.type);
-            if (inputParam !== undefined) result.push(inputParam);
+    return result
+  }
+
+  async run() {
+    const api: ApiPromise = this.getOriginalApi()
+    const flags: ApiInspectFlags = this.parse(ApiInspect).flags as ApiInspectFlags
+    const availableTypes: readonly string[] = TYPES_AVAILABLE
+    const { apiType, apiModule, apiMethod } = this.validateFlags(api, flags)
+
+    // Executing a call
+    if (apiType && apiModule && apiMethod && flags.exec) {
+      let result: Codec
+
+      if (apiType === 'query') {
+        // Api query - call with (or without) arguments
+        let args: (string | ApiMethodArg)[] = flags.callArgs ? flags.callArgs.split(',') : []
+        const paramsTypes: string[] = this.getQueryMethodParamsTypes(apiModule, apiMethod)
+        if (args.length < paramsTypes.length) {
+          this.warn('Some parameters are missing! Please, provide the missing parameters:')
+          const missingParamsValues = await this.requestParamsValues(paramsTypes.slice(args.length))
+          args = args.concat(missingParamsValues)
         }
         }
+        result = await api.query[apiModule][apiMethod](...args)
+      } else {
+        // Api consts - just assign the value
+        result = api.consts[apiModule][apiMethod]
+      }
 
 
-        return result;
+      this.log(chalk.green(result.toString()))
     }
     }
-
-    // Prompt for param based on "paramType" string (ie. Option<MemeberId>)
-    async promptForParam(paramType: string): Promise<ApiMethodInputArg | undefined> {
-        const typeDef: TypeDef = getTypeDef(paramType);
-        if (typeDef.info === TypeDefInfo.Option) return await this.promptForOption(typeDef);
-        else if (typeDef.info === TypeDefInfo.Tuple) return await this.promptForTuple(typeDef);
-        else return await this.promptForSimple(typeDef.type);
+    // Describing a method
+    else if (apiType && apiModule && apiMethod) {
+      this.log(chalk.bold.white(`${apiType}.${apiModule}.${apiMethod}`))
+      const description: string = this.getMethodDescription(apiType, apiModule, apiMethod)
+      this.log(`\n${description}\n`)
+      const typesRows: NameValueObj[] = []
+      if (apiType === 'query') {
+        typesRows.push({
+          name: 'Params:',
+          value: this.getQueryMethodParamsTypes(apiModule, apiMethod).join(', ') || '-',
+        })
+      }
+      typesRows.push({ name: 'Returns:', value: this.getMethodReturnType(apiType, apiModule, apiMethod) })
+      displayNameValueTable(typesRows)
     }
     }
-
-    // Request values for params using array of param types (strings)
-    async requestParamsValues(paramTypes: string[]): Promise<ApiMethodInputArg[]> {
-        let result: ApiMethodInputArg[] = [];
-        for (let [key, paramType] of Object.entries(paramTypes)) {
-            this.log(chalk.bold.white(`Parameter no. ${ parseInt(key)+1 } (${ paramType }):`));
-            let paramValue = await this.promptForParam(paramType);
-            if (paramValue !== undefined) result.push(paramValue);
-        }
-
-        return result;
+    // Displaying all available methods
+    else if (apiType && apiModule) {
+      const module = api[apiType][apiModule]
+      const rows: NameValueObj[] = Object.keys(module).map((key: string) => {
+        return { name: key, value: this.getMethodDescription(apiType, apiModule, key) }
+      })
+      displayNameValueTable(rows)
     }
     }
-
-    async run() {
-        const api: ApiPromise = this.getOriginalApi();
-        const flags: ApiInspectFlags = <ApiInspectFlags> this.parse(ApiInspect).flags;
-        const availableTypes: readonly string[] = TYPES_AVAILABLE;
-        const { apiType, apiModule, apiMethod } = this.validateFlags(api, flags);
-
-        // Executing a call
-        if (apiType && apiModule && apiMethod && flags.exec) {
-            let result: Codec;
-
-            if (apiType === 'query') {
-                // Api query - call with (or without) arguments
-                let args: ApiMethodInputArg[] = flags.callArgs ? flags.callArgs.split(',') : [];
-                const paramsTypes: string[] = this.getQueryMethodParamsTypes(apiModule, apiMethod);
-                if (args.length < paramsTypes.length) {
-                    this.warn('Some parameters are missing! Please, provide the missing parameters:');
-                    let missingParamsValues = await this.requestParamsValues(paramsTypes.slice(args.length));
-                    args = args.concat(missingParamsValues);
-                }
-                result = await api.query[apiModule][apiMethod](...args);
-            }
-            else {
-                // Api consts - just assign the value
-                result = api.consts[apiModule][apiMethod];
-            }
-
-            this.log(chalk.green(result.toString()));
-        }
-        // Describing a method
-        else if (apiType && apiModule && apiMethod) {
-            this.log(chalk.bold.white(`${ apiType }.${ apiModule }.${ apiMethod }`));
-            const description: string = this.getMethodDescription(apiType, apiModule, apiMethod);
-            this.log(`\n${ description }\n`);
-            let typesRows: NameValueObj[] = [];
-            if (apiType === 'query') {
-                typesRows.push({ name: 'Params:', value: this.getQueryMethodParamsTypes(apiModule, apiMethod).join(', ') || '-' });
-            }
-            typesRows.push({ name: 'Returns:', value: this.getMethodReturnType(apiType, apiModule, apiMethod) });
-            displayNameValueTable(typesRows);
-        }
-        // Displaying all available methods
-        else if (apiType && apiModule) {
-            const module = api[apiType][apiModule];
-            const rows: NameValueObj[] = Object.keys(module).map((key: string) => {
-                return { name: key, value: this.getMethodDescription(apiType, apiModule, key) };
-            });
-            displayNameValueTable(rows);
-        }
-        // Displaying all available modules
-        else if (apiType) {
-            this.log(chalk.bold.white('Available modules:'));
-            this.log(Object.keys(api[apiType]).map(key => chalk.white(key)).join('\n'));
-        }
-        // Displaying all available types
-        else {
-            this.log(chalk.bold.white('Available types:'));
-            this.log(availableTypes.map(type => chalk.white(type)).join('\n'));
-        }
+    // Displaying all available modules
+    else if (apiType) {
+      this.log(chalk.bold.white('Available modules:'))
+      this.log(
+        Object.keys(api[apiType])
+          .map((key) => chalk.white(key))
+          .join('\n')
+      )
+    }
+    // Displaying all available types
+    else {
+      this.log(chalk.bold.white('Available types:'))
+      this.log(availableTypes.map((type) => chalk.white(type)).join('\n'))
     }
     }
+  }
 }
 }

+ 22 - 22
cli/src/commands/api/setUri.ts

@@ -1,28 +1,28 @@
-import StateAwareCommandBase from '../../base/StateAwareCommandBase';
-import chalk from 'chalk';
-import { WsProvider } from '@polkadot/api';
-import ExitCodes from '../../ExitCodes';
+import StateAwareCommandBase from '../../base/StateAwareCommandBase'
+import chalk from 'chalk'
+import { WsProvider } from '@polkadot/api'
+import ExitCodes from '../../ExitCodes'
 
 
-type ApiSetUriArgs = { uri: string };
+type ApiSetUriArgs = { uri: string }
 
 
 export default class ApiSetUri extends StateAwareCommandBase {
 export default class ApiSetUri extends StateAwareCommandBase {
-    static description = 'Set api WS provider uri';
-    static args = [
-        {
-            name: 'uri',
-            required: true,
-            description: 'Uri of the node api WS provider'
-        }
-    ];
+  static description = 'Set api WS provider uri'
+  static args = [
+    {
+      name: 'uri',
+      required: true,
+      description: 'Uri of the node api WS provider',
+    },
+  ]
 
 
-    async run() {
-        const args: ApiSetUriArgs = <ApiSetUriArgs> this.parse(ApiSetUri).args;
-        try {
-            new WsProvider(args.uri);
-        } catch(e) {
-            this.error('The WS provider uri seems to be incorrect', { exit: ExitCodes.InvalidInput });
-        }
-        await this.setPreservedState({ apiUri: args.uri });
-        this.log(chalk.greenBright('Api uri successfuly changed! New uri: ') + chalk.white(args.uri))
+  async run() {
+    const args: ApiSetUriArgs = this.parse(ApiSetUri).args as ApiSetUriArgs
+    try {
+      new WsProvider(args.uri)
+    } catch (e) {
+      this.error('The WS provider uri seems to be incorrect', { exit: ExitCodes.InvalidInput })
     }
     }
+    await this.setPreservedState({ apiUri: args.uri })
+    this.log(chalk.greenBright('Api uri successfuly changed! New uri: ') + chalk.white(args.uri))
   }
   }
+}

+ 48 - 49
cli/src/commands/council/info.ts

@@ -1,57 +1,56 @@
-import { ElectionStage } from '@joystream/types/';
-import { formatNumber, formatBalance } from '@polkadot/util';
-import { BlockNumber } from '@polkadot/types/interfaces';
-import { CouncilInfoObj, NameValueObj } from '../../Types';
-import { displayHeader, displayNameValueTable } from '../../helpers/display';
-import ApiCommandBase from '../../base/ApiCommandBase';
+import { ElectionStage } from '@joystream/types/council'
+import { formatNumber, formatBalance } from '@polkadot/util'
+import { BlockNumber } from '@polkadot/types/interfaces'
+import { CouncilInfoObj, NameValueObj } from '../../Types'
+import { displayHeader, displayNameValueTable } from '../../helpers/display'
+import ApiCommandBase from '../../base/ApiCommandBase'
 
 
 export default class CouncilInfo extends ApiCommandBase {
 export default class CouncilInfo extends ApiCommandBase {
-    static description = 'Get current council and council elections information';
+  static description = 'Get current council and council elections information'
 
 
-    displayInfo(infoObj: CouncilInfoObj) {
-        const { activeCouncil = [], round, stage } = infoObj;
+  displayInfo(infoObj: CouncilInfoObj) {
+    const { activeCouncil = [], round, stage } = infoObj
 
 
-        displayHeader('Council');
-        const councilRows: NameValueObj[] = [
-            { name: 'Elected:', value: activeCouncil.length ? 'YES' : 'NO' },
-            { name: 'Members:', value: activeCouncil.length.toString() },
-            { name: 'Term ends at block:', value: `#${formatNumber(infoObj.termEndsAt) }` },
-        ];
-        displayNameValueTable(councilRows);
+    displayHeader('Council')
+    const councilRows: NameValueObj[] = [
+      { name: 'Elected:', value: activeCouncil.length ? 'YES' : 'NO' },
+      { name: 'Members:', value: activeCouncil.length.toString() },
+      { name: 'Term ends at block:', value: `#${formatNumber(infoObj.termEndsAt)}` },
+    ]
+    displayNameValueTable(councilRows)
 
 
-
-        displayHeader('Election');
-        let electionTableRows: NameValueObj[] = [
-            { name: 'Running:', value: stage && stage.isSome ? 'YES' : 'NO' },
-            { name: 'Election round:', value: formatNumber(round) }
-        ];
-        if (stage && stage.isSome) {
-            const stageValue = <ElectionStage> stage.value;
-            const stageName: string = stageValue.type;
-            const stageEndsAt = <BlockNumber> stageValue.value;
-            electionTableRows.push({ name: 'Stage:', value: stageName });
-            electionTableRows.push({ name: 'Stage ends at block:', value: `#${stageEndsAt}` });
-        }
-        displayNameValueTable(electionTableRows);
-
-        displayHeader('Configuration');
-        const isAutoStart = (infoObj.autoStart || false).valueOf();
-        const configTableRows: NameValueObj[] = [
-            { name: 'Auto-start elections:', value: isAutoStart ? 'YES' : 'NO' },
-            { name: 'New term duration:', value: formatNumber(infoObj.newTermDuration) },
-            { name: 'Candidacy limit:', value: formatNumber(infoObj.candidacyLimit) },
-            { name: 'Council size:', value: formatNumber(infoObj.councilSize) },
-            { name: 'Min. council stake:', value: formatBalance(infoObj.minCouncilStake) },
-            { name: 'Min. voting stake:', value: formatBalance(infoObj.minVotingStake) },
-            { name: 'Announcing period:', value: `${ formatNumber(infoObj.announcingPeriod) } blocks` },
-            { name: 'Voting period:', value: `${ formatNumber(infoObj.votingPeriod) } blocks` },
-            { name: 'Revealing period:', value: `${ formatNumber(infoObj.revealingPeriod) } blocks` }
-        ];
-        displayNameValueTable(configTableRows);
+    displayHeader('Election')
+    const electionTableRows: NameValueObj[] = [
+      { name: 'Running:', value: stage && stage.isSome ? 'YES' : 'NO' },
+      { name: 'Election round:', value: formatNumber(round) },
+    ]
+    if (stage && stage.isSome) {
+      const stageValue = stage.value as ElectionStage
+      const stageName: string = stageValue.type
+      const stageEndsAt = stageValue.value as BlockNumber
+      electionTableRows.push({ name: 'Stage:', value: stageName })
+      electionTableRows.push({ name: 'Stage ends at block:', value: `#${stageEndsAt}` })
     }
     }
+    displayNameValueTable(electionTableRows)
 
 
-    async run() {
-        const infoObj = await this.getApi().getCouncilInfo();
-        this.displayInfo(infoObj);
-    }
+    displayHeader('Configuration')
+    const isAutoStart = (infoObj.autoStart || false).valueOf()
+    const configTableRows: NameValueObj[] = [
+      { name: 'Auto-start elections:', value: isAutoStart ? 'YES' : 'NO' },
+      { name: 'New term duration:', value: formatNumber(infoObj.newTermDuration) },
+      { name: 'Candidacy limit:', value: formatNumber(infoObj.candidacyLimit) },
+      { name: 'Council size:', value: formatNumber(infoObj.councilSize) },
+      { name: 'Min. council stake:', value: formatBalance(infoObj.minCouncilStake) },
+      { name: 'Min. voting stake:', value: formatBalance(infoObj.minVotingStake) },
+      { name: 'Announcing period:', value: `${formatNumber(infoObj.announcingPeriod)} blocks` },
+      { name: 'Voting period:', value: `${formatNumber(infoObj.votingPeriod)} blocks` },
+      { name: 'Revealing period:', value: `${formatNumber(infoObj.revealingPeriod)} blocks` },
+    ]
+    displayNameValueTable(configTableRows)
+  }
+
+  async run() {
+    const infoObj = await this.getApi().getCouncilInfo()
+    this.displayInfo(infoObj)
   }
   }
+}

+ 39 - 0
cli/src/commands/working-groups/application.ts

@@ -0,0 +1,39 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { displayCollapsedRow, displayHeader } from '../../helpers/display'
+import chalk from 'chalk'
+
+export default class WorkingGroupsApplication extends WorkingGroupsCommandBase {
+  static description = 'Shows an overview of given application by Working Group Application ID'
+  static args = [
+    {
+      name: 'wgApplicationId',
+      required: true,
+      description: 'Working Group Application ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsApplication)
+
+    const application = await this.getApi().groupApplication(this.group, parseInt(args.wgApplicationId))
+
+    displayHeader('Human readable text')
+    this.jsonPrettyPrint(application.humanReadableText)
+
+    displayHeader(`Details`)
+    const applicationRow = {
+      'WG application ID': application.wgApplicationId,
+      'Application ID': application.applicationId,
+      'Member handle': application.member?.handle.toString() || chalk.red('NONE'),
+      'Role account': application.roleAccout.toString(),
+      Stage: application.stage,
+      'Application stake': application.stakes.application,
+      'Role stake': application.stakes.role,
+      'Total stake': Object.values(application.stakes).reduce((a, b) => a + b),
+    }
+    displayCollapsedRow(applicationRow)
+  }
+}

+ 89 - 0
cli/src/commands/working-groups/createOpening.ts

@@ -0,0 +1,89 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { ApiMethodArg, ApiMethodNamedArgs } from '../../Types'
+import chalk from 'chalk'
+import { flags } from '@oclif/command'
+import { apiModuleByGroup } from '../../Api'
+import WorkerOpeningOptions from '../../promptOptions/addWorkerOpening'
+import { setDefaults } from '../../helpers/promptOptions'
+
+export default class WorkingGroupsCreateOpening extends WorkingGroupsCommandBase {
+  static description = 'Create working group opening (requires lead access)'
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+    useDraft: flags.boolean({
+      char: 'd',
+      description:
+        'Whether to create the opening from existing draft.\n' +
+        'If provided without --draftName - the list of choices will be displayed.',
+    }),
+    draftName: flags.string({
+      char: 'n',
+      description: 'Name of the draft to create the opening from.',
+      dependsOn: ['useDraft'],
+    }),
+    createDraftOnly: flags.boolean({
+      char: 'c',
+      description:
+        'If provided - the extrinsic will not be executed. Use this flag if you only want to create a draft.',
+    }),
+    skipPrompts: flags.boolean({
+      char: 's',
+      description: 'Whether to skip all prompts when adding from draft (will use all default values)',
+      dependsOn: ['useDraft'],
+      exclusive: ['createDraftOnly'],
+    }),
+  }
+
+  async run() {
+    const account = await this.getRequiredSelectedAccount()
+    // lead-only gate
+    await this.getRequiredLead()
+
+    const { flags } = this.parse(WorkingGroupsCreateOpening)
+
+    const promptOptions = new WorkerOpeningOptions()
+    let defaultValues: ApiMethodNamedArgs | undefined
+    if (flags.useDraft) {
+      const draftName = flags.draftName || (await this.promptForOpeningDraft())
+      defaultValues = await this.loadOpeningDraftParams(draftName)
+      setDefaults(promptOptions, defaultValues)
+    }
+
+    if (!flags.skipPrompts) {
+      const module = apiModuleByGroup[this.group]
+      const method = 'addOpening'
+
+      let saveDraft = false,
+        params: ApiMethodArg[]
+      if (flags.createDraftOnly) {
+        params = await this.promptForExtrinsicParams(module, method, promptOptions)
+        saveDraft = true
+      } else {
+        await this.requestAccountDecoding(account) // Prompt for password
+        params = await this.buildAndSendExtrinsic(account, module, method, promptOptions, true)
+
+        saveDraft = await this.simplePrompt({
+          message: 'Do you wish to save this opening as draft?',
+          type: 'confirm',
+        })
+      }
+
+      if (saveDraft) {
+        const draftName = await this.promptForNewOpeningDraftName()
+        this.saveOpeningDraft(draftName, params)
+
+        this.log(chalk.green(`Opening draft ${chalk.white(draftName)} succesfully saved!`))
+      }
+    } else {
+      await this.requestAccountDecoding(account) // Prompt for password
+      this.log(chalk.white('Sending the extrinsic...'))
+      await this.sendExtrinsic(
+        account,
+        apiModuleByGroup[this.group],
+        'addOpening',
+        defaultValues!.map((v) => v.value)
+      )
+      this.log(chalk.green('Opening succesfully created!'))
+    }
+  }
+}

+ 56 - 0
cli/src/commands/working-groups/decreaseWorkerStake.ts

@@ -0,0 +1,56 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { WorkerId } from '@joystream/types/working-group'
+import { Balance } from '@polkadot/types/interfaces'
+import { formatBalance } from '@polkadot/util'
+import { minMaxInt } from '../../validators/common'
+import chalk from 'chalk'
+import { createParamOptions } from '../../helpers/promptOptions'
+
+export default class WorkingGroupsDecreaseWorkerStake extends WorkingGroupsCommandBase {
+  static description =
+    'Decreases given worker stake by an amount that will be returned to the worker role account. ' +
+    'Requires lead access.'
+  static args = [
+    {
+      name: 'workerId',
+      required: true,
+      description: 'Worker ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsDecreaseWorkerStake)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Lead-only gate
+    await this.getRequiredLead()
+
+    const workerId = parseInt(args.workerId)
+    const groupMember = await this.getWorkerWithStakeForLeadAction(workerId)
+
+    this.log(chalk.white('Current worker stake: ', formatBalance(groupMember.stake)))
+    const balanceValidator = minMaxInt(1, groupMember.stake.toNumber())
+    const balance = (await this.promptForParam(
+      'Balance',
+      createParamOptions('amount', undefined, balanceValidator)
+    )) as Balance
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'decreaseStake', [
+      new WorkerId(workerId),
+      balance,
+    ])
+
+    this.log(
+      chalk.green(
+        `${chalk.white(formatBalance(balance))} from worker ${chalk.white(workerId)} stake ` +
+          `has been returned to worker's role account (${chalk.white(groupMember.roleAccount.toString())})!`
+      )
+    )
+  }
+}

+ 56 - 0
cli/src/commands/working-groups/evictWorker.ts

@@ -0,0 +1,56 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { WorkerId } from '@joystream/types/working-group'
+import { bool } from '@polkadot/types/primitive'
+import { formatBalance } from '@polkadot/util'
+import chalk from 'chalk'
+import { createParamOptions } from '../../helpers/promptOptions'
+
+export default class WorkingGroupsEvictWorker extends WorkingGroupsCommandBase {
+  static description = 'Evicts given worker. Requires lead access.'
+  static args = [
+    {
+      name: 'workerId',
+      required: true,
+      description: 'Worker ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsEvictWorker)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Lead-only gate
+    await this.getRequiredLead()
+
+    const workerId = parseInt(args.workerId)
+    // This will also make sure the worker is valid
+    const groupMember = await this.getWorkerForLeadAction(workerId)
+
+    // TODO: Terminate worker text limits? (minMaxStr)
+    const rationale = await this.promptForParam('Bytes', createParamOptions('rationale'))
+    const shouldSlash = groupMember.stake
+      ? await this.simplePrompt({
+          message: `Should the worker stake (${formatBalance(groupMember.stake)}) be slashed?`,
+          type: 'confirm',
+          default: false,
+        })
+      : false
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'terminateRole', [
+      new WorkerId(workerId),
+      rationale,
+      new bool(shouldSlash),
+    ])
+
+    this.log(chalk.green(`Worker ${chalk.white(workerId)} has been evicted!`))
+    if (shouldSlash) {
+      this.log(chalk.green(`Worker stake totalling ${chalk.white(formatBalance(groupMember.stake))} has been slashed!`))
+    }
+  }
+}

+ 52 - 0
cli/src/commands/working-groups/fillOpening.ts

@@ -0,0 +1,52 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { OpeningStatus } from '../../Types'
+import { apiModuleByGroup } from '../../Api'
+import { OpeningId } from '@joystream/types/hiring'
+import { ApplicationIdSet, RewardPolicy } from '@joystream/types/working-group'
+import chalk from 'chalk'
+import { createParamOptions } from '../../helpers/promptOptions'
+
+export default class WorkingGroupsFillOpening extends WorkingGroupsCommandBase {
+  static description = "Allows filling working group opening that's currently in review. Requires lead access."
+  static args = [
+    {
+      name: 'wgOpeningId',
+      required: true,
+      description: 'Working Group Opening ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsFillOpening)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Lead-only gate
+    await this.getRequiredLead()
+
+    const openingId = parseInt(args.wgOpeningId)
+    const opening = await this.getOpeningForLeadAction(openingId, OpeningStatus.InReview)
+
+    const applicationIds = await this.promptForApplicationsToAccept(opening)
+    const rewardPolicyOpt = await this.promptForParam(
+      `Option<${RewardPolicy.name}>`,
+      createParamOptions('RewardPolicy')
+    )
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'fillOpening', [
+      new OpeningId(openingId),
+      new ApplicationIdSet(applicationIds),
+      rewardPolicyOpt,
+    ])
+
+    this.log(chalk.green(`Opening ${chalk.white(openingId)} succesfully filled!`))
+    this.log(
+      chalk.green('Accepted working group application IDs: ') +
+        chalk.white(applicationIds.length ? applicationIds.join(chalk.green(', ')) : 'NONE')
+    )
+  }
+}

+ 46 - 0
cli/src/commands/working-groups/increaseStake.ts

@@ -0,0 +1,46 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { Balance } from '@polkadot/types/interfaces'
+import { formatBalance } from '@polkadot/util'
+import { positiveInt } from '../../validators/common'
+import chalk from 'chalk'
+import ExitCodes from '../../ExitCodes'
+import { createParamOptions } from '../../helpers/promptOptions'
+
+export default class WorkingGroupsIncreaseStake extends WorkingGroupsCommandBase {
+  static description = 'Increases current role (lead/worker) stake. Requires active role account to be selected.'
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const account = await this.getRequiredSelectedAccount()
+    // Worker-only gate
+    const worker = await this.getRequiredWorker()
+
+    if (!worker.stake) {
+      this.error('Cannot increase stake. No associated role stake profile found!', { exit: ExitCodes.InvalidInput })
+    }
+
+    this.log(chalk.white('Current stake: ', formatBalance(worker.stake)))
+    const balance = (await this.promptForParam(
+      'Balance',
+      createParamOptions('amount', undefined, positiveInt())
+    )) as Balance
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'increaseStake', [
+      worker.workerId,
+      balance,
+    ])
+
+    this.log(
+      chalk.green(
+        `Worker ${chalk.white(worker.workerId.toNumber())} stake has been increased by ${chalk.white(
+          formatBalance(balance)
+        )}`
+      )
+    )
+  }
+}

+ 28 - 0
cli/src/commands/working-groups/leaveRole.ts

@@ -0,0 +1,28 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { minMaxStr } from '../../validators/common'
+import chalk from 'chalk'
+import { createParamOptions } from '../../helpers/promptOptions'
+
+export default class WorkingGroupsLeaveRole extends WorkingGroupsCommandBase {
+  static description = 'Leave the worker or lead role associated with currently selected account.'
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const account = await this.getRequiredSelectedAccount()
+    // Worker-only gate
+    const worker = await this.getRequiredWorker()
+
+    const constraint = await this.getApi().workerExitRationaleConstraint(this.group)
+    const rationaleValidator = minMaxStr(constraint.min.toNumber(), constraint.max.toNumber())
+    const rationale = await this.promptForParam('Bytes', createParamOptions('rationale', undefined, rationaleValidator))
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'leaveRole', [worker.workerId, rationale])
+
+    this.log(chalk.green(`Succesfully left the role! (worker id: ${chalk.white(worker.workerId.toNumber())})`))
+  }
+}

+ 80 - 0
cli/src/commands/working-groups/opening.ts

@@ -0,0 +1,80 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { displayTable, displayCollapsedRow, displayHeader } from '../../helpers/display'
+import _ from 'lodash'
+import { OpeningStatus, GroupOpeningStage, GroupOpeningStakes } from '../../Types'
+import { StakingAmountLimitModeKeys, StakingPolicy } from '@joystream/types/hiring'
+import { formatBalance } from '@polkadot/util'
+import chalk from 'chalk'
+
+export default class WorkingGroupsOpening extends WorkingGroupsCommandBase {
+  static description = 'Shows an overview of given working group opening by Working Group Opening ID'
+  static args = [
+    {
+      name: 'wgOpeningId',
+      required: true,
+      description: 'Working Group Opening ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  stageColumns(stage: GroupOpeningStage) {
+    const { status, date, block } = stage
+    const statusTimeHeader = status === OpeningStatus.WaitingToBegin ? 'Starts at' : 'Last status change'
+    return {
+      Stage: _.startCase(status),
+      [statusTimeHeader]:
+        date && block
+          ? `~ ${date.toLocaleTimeString()} ${date.toLocaleDateString()} (#${block})`
+          : (block && `#${block}`) || '?',
+    }
+  }
+
+  formatStake(stake: StakingPolicy | undefined) {
+    if (!stake) return 'NONE'
+    const { amount, amount_mode: amountMode } = stake
+    return amountMode.type === StakingAmountLimitModeKeys.AtLeast
+      ? `>= ${formatBalance(amount)}`
+      : `== ${formatBalance(amount)}`
+  }
+
+  stakeColumns(stakes: GroupOpeningStakes) {
+    const { role, application } = stakes
+    return {
+      'Application stake': this.formatStake(application),
+      'Role stake': this.formatStake(role),
+    }
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsOpening)
+
+    const opening = await this.getApi().groupOpening(this.group, parseInt(args.wgOpeningId))
+
+    displayHeader('Human readable text')
+    this.jsonPrettyPrint(opening.opening.human_readable_text.toString())
+
+    displayHeader('Opening details')
+    const openingRow = {
+      'WG Opening ID': opening.wgOpeningId,
+      'Opening ID': opening.openingId,
+      Type: opening.type.type,
+      ...this.stageColumns(opening.stage),
+      ...this.stakeColumns(opening.stakes),
+    }
+    displayCollapsedRow(openingRow)
+
+    displayHeader(`Applications (${opening.applications.length})`)
+    const applicationsRows = opening.applications.map((a) => ({
+      'WG appl. ID': a.wgApplicationId,
+      'Appl. ID': a.applicationId,
+      Member: a.member?.handle.toString() || chalk.red('NONE'),
+      Stage: a.stage,
+      'Appl. stake': a.stakes.application,
+      'Role stake': a.stakes.role,
+      'Total stake': Object.values(a.stakes).reduce((a, b) => a + b),
+    }))
+    displayTable(applicationsRows, 5)
+  }
+}

+ 23 - 0
cli/src/commands/working-groups/openings.ts

@@ -0,0 +1,23 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { displayTable } from '../../helpers/display'
+import _ from 'lodash'
+
+export default class WorkingGroupsOpenings extends WorkingGroupsCommandBase {
+  static description = 'Shows an overview of given working group openings'
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const openings = await this.getApi().openingsByGroup(this.group)
+
+    const openingsRows = openings.map((o) => ({
+      'WG Opening ID': o.wgOpeningId,
+      'Opening ID': o.openingId,
+      Type: o.type.type,
+      Stage: `${_.startCase(o.stage.status)}${o.stage.block ? ` (#${o.stage.block})` : ''}`,
+      Applications: o.applications.length,
+    }))
+    displayTable(openingsRows, 5)
+  }
+}

+ 40 - 0
cli/src/commands/working-groups/overview.ts

@@ -0,0 +1,40 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { displayHeader, displayNameValueTable, displayTable, shortAddress } from '../../helpers/display'
+import { formatBalance } from '@polkadot/util'
+
+import chalk from 'chalk'
+
+export default class WorkingGroupsOverview extends WorkingGroupsCommandBase {
+  static description = 'Shows an overview of given working group (current lead and workers)'
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const lead = await this.getApi().groupLead(this.group)
+    const members = await this.getApi().groupMembers(this.group)
+
+    displayHeader('Group lead')
+    if (lead) {
+      displayNameValueTable([
+        { name: 'Member id:', value: lead.memberId.toString() },
+        { name: 'Member handle:', value: lead.profile.handle.toString() },
+        { name: 'Role account:', value: lead.roleAccount.toString() },
+      ])
+    } else {
+      this.log(chalk.yellow('No lead assigned!'))
+    }
+
+    displayHeader('Members')
+    const membersRows = members.map((m) => ({
+      '': lead?.workerId.eq(m.workerId) ? '\u{2B50}' : '', // A nice star for the lead
+      'Worker id': m.workerId.toString(),
+      'Member id': m.memberId.toString(),
+      'Member handle': m.profile.handle.toString(),
+      Stake: formatBalance(m.stake),
+      Earned: formatBalance(m.reward?.totalRecieved),
+      'Role account': shortAddress(m.roleAccount),
+    }))
+    displayTable(membersRows, 5)
+  }
+}

+ 55 - 0
cli/src/commands/working-groups/slashWorker.ts

@@ -0,0 +1,55 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { WorkerId } from '@joystream/types/working-group'
+import { Balance } from '@polkadot/types/interfaces'
+import { formatBalance } from '@polkadot/util'
+import { minMaxInt } from '../../validators/common'
+import chalk from 'chalk'
+import { createParamOptions } from '../../helpers/promptOptions'
+
+export default class WorkingGroupsSlashWorker extends WorkingGroupsCommandBase {
+  static description = 'Slashes given worker stake. Requires lead access.'
+  static args = [
+    {
+      name: 'workerId',
+      required: true,
+      description: 'Worker ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsSlashWorker)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Lead-only gate
+    await this.getRequiredLead()
+
+    const workerId = parseInt(args.workerId)
+    const groupMember = await this.getWorkerWithStakeForLeadAction(workerId)
+
+    this.log(chalk.white('Current worker stake: ', formatBalance(groupMember.stake)))
+    const balanceValidator = minMaxInt(1, groupMember.stake.toNumber())
+    const balance = (await this.promptForParam(
+      'Balance',
+      createParamOptions('amount', undefined, balanceValidator)
+    )) as Balance
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'slashStake', [
+      new WorkerId(workerId),
+      balance,
+    ])
+
+    this.log(
+      chalk.green(
+        `${chalk.white(formatBalance(balance))} from worker ${chalk.white(
+          workerId
+        )} stake has been succesfully slashed!`
+      )
+    )
+  }
+}

+ 40 - 0
cli/src/commands/working-groups/startAcceptingApplications.ts

@@ -0,0 +1,40 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { OpeningStatus } from '../../Types'
+import { apiModuleByGroup } from '../../Api'
+import { OpeningId } from '@joystream/types/hiring'
+import chalk from 'chalk'
+
+export default class WorkingGroupsStartAcceptingApplications extends WorkingGroupsCommandBase {
+  static description = 'Changes the status of pending opening to "Accepting applications". Requires lead access.'
+  static args = [
+    {
+      name: 'wgOpeningId',
+      required: true,
+      description: 'Working Group Opening ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsStartAcceptingApplications)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Lead-only gate
+    await this.getRequiredLead()
+
+    const openingId = parseInt(args.wgOpeningId)
+    await this.validateOpeningForLeadAction(openingId, OpeningStatus.WaitingToBegin)
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'acceptApplications', [
+      new OpeningId(openingId),
+    ])
+
+    this.log(
+      chalk.green(`Opening ${chalk.white(openingId)} status changed to: ${chalk.white('Accepting Applications')}`)
+    )
+  }
+}

+ 38 - 0
cli/src/commands/working-groups/startReviewPeriod.ts

@@ -0,0 +1,38 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { OpeningStatus } from '../../Types'
+import { apiModuleByGroup } from '../../Api'
+import { OpeningId } from '@joystream/types/hiring'
+import chalk from 'chalk'
+
+export default class WorkingGroupsStartReviewPeriod extends WorkingGroupsCommandBase {
+  static description = 'Changes the status of active opening to "In review". Requires lead access.'
+  static args = [
+    {
+      name: 'wgOpeningId',
+      required: true,
+      description: 'Working Group Opening ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsStartReviewPeriod)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Lead-only gate
+    await this.getRequiredLead()
+
+    const openingId = parseInt(args.wgOpeningId)
+    await this.validateOpeningForLeadAction(openingId, OpeningStatus.AcceptingApplications)
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'beginApplicantReview', [
+      new OpeningId(openingId),
+    ])
+
+    this.log(chalk.green(`Opening ${chalk.white(openingId)} status changed to: ${chalk.white('In Review')}`))
+  }
+}

+ 38 - 0
cli/src/commands/working-groups/terminateApplication.ts

@@ -0,0 +1,38 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { ApplicationStageKeys, ApplicationId } from '@joystream/types/hiring'
+import chalk from 'chalk'
+
+export default class WorkingGroupsTerminateApplication extends WorkingGroupsCommandBase {
+  static description = 'Terminates given working group application. Requires lead access.'
+  static args = [
+    {
+      name: 'wgApplicationId',
+      required: true,
+      description: 'Working Group Application ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsTerminateApplication)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Lead-only gate
+    await this.getRequiredLead()
+
+    const applicationId = parseInt(args.wgApplicationId)
+    // We don't really need the application itself here, so this one is just for validation purposes
+    await this.getApplicationForLeadAction(applicationId, ApplicationStageKeys.Active)
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'terminateApplication', [
+      new ApplicationId(applicationId),
+    ])
+
+    this.log(chalk.green(`Application ${chalk.white(applicationId)} has been succesfully terminated!`))
+  }
+}

+ 48 - 0
cli/src/commands/working-groups/updateRewardAccount.ts

@@ -0,0 +1,48 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { validateAddress } from '../../helpers/validation'
+import { GenericAccountId } from '@polkadot/types'
+import chalk from 'chalk'
+import ExitCodes from '../../ExitCodes'
+
+export default class WorkingGroupsUpdateRewardAccount extends WorkingGroupsCommandBase {
+  static description = 'Updates the worker/lead reward account (requires current role account to be selected)'
+  static args = [
+    {
+      name: 'accountAddress',
+      required: false,
+      description: 'New reward account address (if omitted, one of the existing CLI accounts can be selected)',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsUpdateRewardAccount)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Worker-only gate
+    const worker = await this.getRequiredWorker()
+
+    if (!worker.reward) {
+      this.error('There is no reward relationship associated with this role!', { exit: ExitCodes.InvalidInput })
+    }
+
+    let newRewardAccount: string = args.accountAddress
+    if (!newRewardAccount) {
+      const accounts = await this.fetchAccounts()
+      newRewardAccount = (await this.promptForAccount(accounts, undefined, 'Choose the new reward account')).address
+    }
+    validateAddress(newRewardAccount)
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'updateRewardAccount', [
+      worker.workerId,
+      new GenericAccountId(newRewardAccount),
+    ])
+
+    this.log(chalk.green(`Succesfully updated the reward account to: ${chalk.white(newRewardAccount)})`))
+  }
+}

+ 58 - 0
cli/src/commands/working-groups/updateRoleAccount.ts

@@ -0,0 +1,58 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { validateAddress } from '../../helpers/validation'
+import { GenericAccountId } from '@polkadot/types'
+import chalk from 'chalk'
+
+export default class WorkingGroupsUpdateRoleAccount extends WorkingGroupsCommandBase {
+  static description = 'Updates the worker/lead role account. Requires member controller account to be selected'
+  static args = [
+    {
+      name: 'accountAddress',
+      required: false,
+      description: 'New role account address (if omitted, one of the existing CLI accounts can be selected)',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsUpdateRoleAccount)
+
+    const account = await this.getRequiredSelectedAccount()
+    const worker = await this.getRequiredWorkerByMemberController()
+
+    const cliAccounts = await this.fetchAccounts()
+    let newRoleAccount: string = args.accountAddress
+    if (!newRoleAccount) {
+      newRoleAccount = (await this.promptForAccount(cliAccounts, undefined, 'Choose the new role account')).address
+    }
+    validateAddress(newRoleAccount)
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'updateRoleAccount', [
+      worker.workerId,
+      new GenericAccountId(newRoleAccount),
+    ])
+
+    this.log(chalk.green(`Succesfully updated the role account to: ${chalk.white(newRoleAccount)})`))
+
+    const matchingAccount = cliAccounts.find((account) => account.address === newRoleAccount)
+    if (matchingAccount) {
+      const switchAccount = await this.simplePrompt({
+        type: 'confirm',
+        message: 'Do you want to switch the currenly selected CLI account to the new role account?',
+        default: false,
+      })
+      if (switchAccount) {
+        await this.setSelectedAccount(matchingAccount)
+        this.log(
+          chalk.green('Account switched to: ') +
+            chalk.white(`${matchingAccount.meta.name} (${matchingAccount.address})`)
+        )
+      }
+    }
+  }
+}

+ 67 - 0
cli/src/commands/working-groups/updateWorkerReward.ts

@@ -0,0 +1,67 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase'
+import { apiModuleByGroup } from '../../Api'
+import { WorkerId } from '@joystream/types/working-group'
+import { formatBalance } from '@polkadot/util'
+import chalk from 'chalk'
+import { Reward } from '../../Types'
+import { positiveInt } from '../../validators/common'
+import { createParamOptions } from '../../helpers/promptOptions'
+import ExitCodes from '../../ExitCodes'
+
+export default class WorkingGroupsUpdateWorkerReward extends WorkingGroupsCommandBase {
+  static description = "Change given worker's reward (amount only). Requires lead access."
+  static args = [
+    {
+      name: 'workerId',
+      required: true,
+      description: 'Worker ID',
+    },
+  ]
+  static flags = {
+    ...WorkingGroupsCommandBase.flags,
+  }
+
+  formatReward(reward?: Reward) {
+    return reward
+      ? formatBalance(reward.value) +
+          (reward.interval && ` / ${reward.interval} block(s)`) +
+          (reward.nextPaymentBlock && ` (next payment: #${reward.nextPaymentBlock})`)
+      : 'NONE'
+  }
+
+  async run() {
+    const { args } = this.parse(WorkingGroupsUpdateWorkerReward)
+
+    const account = await this.getRequiredSelectedAccount()
+    // Lead-only gate
+    await this.getRequiredLead()
+
+    const workerId = parseInt(args.workerId)
+    // This will also make sure the worker is valid
+    const groupMember = await this.getWorkerForLeadAction(workerId)
+
+    const { reward } = groupMember
+
+    if (!reward) {
+      this.error('There is no reward relationship associated with this worker!', { exit: ExitCodes.InvalidInput })
+    }
+
+    console.log(chalk.white(`Current worker reward: ${this.formatReward(reward)}`))
+
+    const newRewardValue = await this.promptForParam(
+      'BalanceOfMint',
+      createParamOptions('new_amount', undefined, positiveInt())
+    )
+
+    await this.requestAccountDecoding(account)
+
+    await this.sendAndFollowExtrinsic(account, apiModuleByGroup[this.group], 'updateRewardAmount', [
+      new WorkerId(workerId),
+      newRewardValue,
+    ])
+
+    const updatedGroupMember = await this.getApi().groupMember(this.group, workerId)
+    this.log(chalk.green(`Worker ${chalk.white(workerId)} reward has been updated!`))
+    this.log(chalk.green(`New worker reward: ${chalk.white(this.formatReward(updatedGroupMember.reward))}`))
+  }
+}

+ 64 - 25
cli/src/helpers/display.ts

@@ -1,33 +1,72 @@
-import { cli } from 'cli-ux';
-import chalk from 'chalk';
-import { NameValueObj } from '../Types';
-
-export function displayHeader(caption: string, placeholderSign: string = '_', size: number = 50) {
-    let singsPerSide: number = Math.floor((size - (caption.length + 2)) / 2);
-    let finalStr: string = '';
-    for (let i = 0; i < singsPerSide; ++i) finalStr += placeholderSign;
-    finalStr += ` ${ caption} `;
-    while (finalStr.length < size) finalStr += placeholderSign;
-
-    process.stdout.write("\n" + chalk.bold.blueBright(finalStr) + "\n\n");
+import { cli, Table } from 'cli-ux'
+import chalk from 'chalk'
+import { NameValueObj } from '../Types'
+import { AccountId } from '@polkadot/types/interfaces'
+
+export function displayHeader(caption: string, placeholderSign = '_', size = 50) {
+  const singsPerSide: number = Math.floor((size - (caption.length + 2)) / 2)
+  let finalStr = ''
+  for (let i = 0; i < singsPerSide; ++i) finalStr += placeholderSign
+  finalStr += ` ${caption} `
+  while (finalStr.length < size) finalStr += placeholderSign
+
+  process.stdout.write('\n' + chalk.bold.blueBright(finalStr) + '\n\n')
 }
 }
 
 
 export function displayNameValueTable(rows: NameValueObj[]) {
 export function displayNameValueTable(rows: NameValueObj[]) {
-    cli.table(
-        rows,
-        {
-            name: { minWidth: 30, get: row => chalk.bold.white(row.name) },
-            value: { get: row => chalk.white(row.value) }
-        },
-        { 'no-header': true }
-    );
+  cli.table(
+    rows,
+    {
+      name: { minWidth: 30, get: (row) => chalk.bold.white(row.name) },
+      value: { get: (row) => chalk.white(row.value) },
+    },
+    { 'no-header': true }
+  )
+}
+
+export function displayCollapsedRow(row: { [k: string]: string | number }) {
+  const collapsedRow: NameValueObj[] = Object.keys(row).map((name) => ({
+    name,
+    value: typeof row[name] === 'string' ? (row[name] as string) : row[name].toString(),
+  }))
+
+  displayNameValueTable(collapsedRow)
+}
+
+export function displayCollapsedTable(rows: { [k: string]: string | number }[]) {
+  for (const row of rows) displayCollapsedRow(row)
+}
+
+export function displayTable(rows: { [k: string]: string | number }[], cellHorizontalPadding = 0) {
+  if (!rows.length) {
+    return
+  }
+  const maxLength = (columnName: string) =>
+    rows.reduce((maxLength, row) => {
+      const val = row[columnName]
+      const valLength = typeof val === 'string' ? val.length : val.toString().length
+      return Math.max(maxLength, valLength)
+    }, columnName.length)
+  const columnDef = (columnName: string) => ({
+    get: (row: typeof rows[number]) => chalk.white(`${row[columnName]}`),
+    minWidth: maxLength(columnName) + cellHorizontalPadding,
+  })
+  const columns: Table.table.Columns<{ [k: string]: string }> = {}
+  Object.keys(rows[0]).forEach((columnName) => (columns[columnName] = columnDef(columnName)))
+  cli.table(rows, columns)
 }
 }
 
 
 export function toFixedLength(text: string, length: number, spacesOnLeft = false): string {
 export function toFixedLength(text: string, length: number, spacesOnLeft = false): string {
-    if (text.length > length && length > 3) {
-        return text.slice(0, length-3) + '...';
-    }
-    while(text.length < length) { spacesOnLeft ? text = ' '+text : text += ' ' };
+  if (text.length > length && length > 3) {
+    return text.slice(0, length - 3) + '...'
+  }
+  while (text.length < length) {
+    spacesOnLeft ? (text = ' ' + text) : (text += ' ')
+  }
+
+  return text
+}
 
 
-    return text;
+export function shortAddress(address: AccountId | string): string {
+  return address.toString().substr(0, 6) + '...' + address.toString().substr(-6)
 }
 }

+ 30 - 0
cli/src/helpers/promptOptions.ts

@@ -0,0 +1,30 @@
+import { ApiParamsOptions, ApiMethodNamedArgs, ApiParamOptions, ApiMethodArg } from '../Types'
+import { Validator } from 'inquirer'
+
+export function setDefaults(promptOptions: ApiParamsOptions, defaultValues: ApiMethodNamedArgs) {
+  for (const defaultValue of defaultValues) {
+    const { name: paramName, value: paramValue } = defaultValue
+    const paramOptions = promptOptions[paramName]
+    if (paramOptions && paramOptions.value) {
+      paramOptions.value.default = paramValue
+    } else if (paramOptions) {
+      promptOptions[paramName].value = { default: paramValue }
+    } else {
+      promptOptions[paramName] = { value: { default: paramValue } }
+    }
+  }
+}
+
+// Temporary(?) helper for easier creation of common ApiParamOptions
+export function createParamOptions(
+  forcedName?: string,
+  defaultValue?: ApiMethodArg | undefined,
+  validator?: Validator
+): ApiParamOptions {
+  const paramOptions: ApiParamOptions = { forcedName, validator }
+  if (defaultValue) {
+    paramOptions.value = { default: defaultValue }
+  }
+
+  return paramOptions
+}

+ 14 - 14
cli/src/helpers/validation.ts

@@ -1,19 +1,19 @@
-import BN from 'bn.js';
-import ExitCodes from '../ExitCodes';
-import { decodeAddress } from '@polkadot/util-crypto';
-import { DerivedBalances } from '@polkadot/api-derive/types';
-import { CLIError } from '@oclif/errors';
+import BN from 'bn.js'
+import ExitCodes from '../ExitCodes'
+import { decodeAddress } from '@polkadot/util-crypto'
+import { DerivedBalances } from '@polkadot/api-derive/types'
+import { CLIError } from '@oclif/errors'
 
 
-export function validateAddress(address: string, errorMessage: string = 'Invalid address'): void {
-    try {
-        decodeAddress(address);
-    } catch (e) {
-        throw new CLIError(errorMessage, { exit: ExitCodes.InvalidInput });
-    }
+export function validateAddress(address: string, errorMessage = 'Invalid address'): void {
+  try {
+    decodeAddress(address)
+  } catch (e) {
+    throw new CLIError(errorMessage, { exit: ExitCodes.InvalidInput })
+  }
 }
 }
 
 
 export function checkBalance(accBalances: DerivedBalances, requiredBalance: BN): void {
 export function checkBalance(accBalances: DerivedBalances, requiredBalance: BN): void {
-    if (requiredBalance.gt(accBalances.availableBalance)) {
-        throw new CLIError('Not enough balance available', { exit: ExitCodes.InvalidInput });
-    }
+  if (requiredBalance.gt(accBalances.availableBalance)) {
+    throw new CLIError('Not enough balance available', { exit: ExitCodes.InvalidInput })
+  }
 }
 }

+ 1 - 1
cli/src/index.ts

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

+ 44 - 0
cli/src/promptOptions/addWorkerOpening.ts

@@ -0,0 +1,44 @@
+import { ApiParamsOptions, ApiParamOptions, HRTStruct } from '../Types'
+import {
+  OpeningType,
+  SlashingTerms,
+  UnslashableTerms,
+  OpeningType_Worker as OpeningTypeWorker,
+  WorkingGroupOpeningPolicyCommitment,
+} from '@joystream/types/working-group'
+import { Bytes } from '@polkadot/types'
+import { schemaValidator } from '@joystream/types/hiring'
+
+class OpeningPolicyCommitmentOptions implements ApiParamsOptions {
+  [paramName: string]: ApiParamOptions
+  public role_slashing_terms: ApiParamOptions<SlashingTerms> = {
+    value: {
+      default: SlashingTerms.create('Unslashable', new UnslashableTerms()),
+      locked: true,
+    },
+  }
+}
+
+class AddWrokerOpeningOptions implements ApiParamsOptions {
+  [paramName: string]: ApiParamOptions
+  // Lock value for opening_type
+  public opening_type: ApiParamOptions<OpeningType> = {
+    value: {
+      default: OpeningType.create('Worker', new OpeningTypeWorker()),
+      locked: true,
+    },
+  }
+  // Json schema for human_readable_text
+  public human_readable_text: ApiParamOptions<Bytes> = {
+    jsonSchema: {
+      schemaValidator,
+      struct: HRTStruct,
+    },
+  }
+  // Lock value for role_slashing_terms
+  public commitment: ApiParamOptions<WorkingGroupOpeningPolicyCommitment> = {
+    nestedOptions: new OpeningPolicyCommitmentOptions(),
+  }
+}
+
+export default AddWrokerOpeningOptions

+ 51 - 0
cli/src/validators/common.ts

@@ -0,0 +1,51 @@
+//
+// Validators for console input
+// (usable with inquirer package)
+//
+
+type Validator = (value: any) => boolean | string
+
+export const isInt = (message?: string) => (value: any) =>
+  (typeof value === 'number' && Math.floor(value) === value) ||
+  (typeof value === 'string' && parseInt(value).toString() === value)
+    ? true
+    : message || 'The value must be an integer!'
+
+export const gte = (min: number, message?: string) => (value: any) =>
+  parseFloat(value) >= min
+    ? true
+    : message?.replace('{min}', min.toString()) || `The value must be a number greater than or equal ${min}`
+
+export const lte = (max: number, message?: string) => (value: any) =>
+  parseFloat(value) <= max
+    ? true
+    : message?.replace('{max}', max.toString()) || `The value must be less than or equal ${max}`
+
+export const minLen = (min: number, message?: string) => (value: any) =>
+  typeof value === 'string' && value.length >= min
+    ? true
+    : message?.replace('{min}', min.toString()) || `The value should be at least ${min} character(s) long`
+
+export const maxLen = (max: number, message?: string) => (value: any) =>
+  typeof value === 'string' && value.length <= max
+    ? true
+    : message?.replace('{max}', max.toString()) || `The value cannot be more than ${max} character(s) long`
+
+export const combined = (validators: Validator[], message?: string) => (value: any) => {
+  for (const validator of validators) {
+    const result = validator(value)
+    if (result !== true) {
+      return message || result
+    }
+  }
+
+  return true
+}
+
+export const positiveInt = (message?: string) => combined([isInt(), gte(0)], message)
+
+export const minMaxInt = (min: number, max: number, message?: string) =>
+  combined([isInt(), gte(min), lte(max)], message?.replace('{min}', min.toString()).replace('{max}', max.toString()))
+
+export const minMaxStr = (min: number, max: number, message?: string) =>
+  combined([minLen(min), maxLen(max)], message?.replace('{min}', min.toString()).replace('{max}', max.toString()))

+ 7 - 7
cli/test/commands/council/info.test.ts

@@ -1,11 +1,11 @@
-import {expect, test} from '@oclif/test'
+import { expect, test } from '@oclif/test'
 
 
 describe('info', () => {
 describe('info', () => {
   test
   test
-  .stdout()
-  .command(['council:info'])
-  .exit(0)
-  .it('displays "Council" string', ctx => {
-    expect(ctx.stdout).to.contain('Council')
-  })
+    .stdout()
+    .command(['council:info'])
+    .exit(0)
+    .it('displays "Council" string', (ctx) => {
+      expect(ctx.stdout).to.contain('Council')
+    })
 })
 })

+ 1 - 3
cli/test/tsconfig.json

@@ -3,7 +3,5 @@
   "compilerOptions": {
   "compilerOptions": {
     "noEmit": true
     "noEmit": true
   },
   },
-  "references": [
-    {"path": ".."}
-  ]
+  "references": [{ "path": ".." }]
 }
 }

+ 3 - 1
cli/tsconfig.json

@@ -7,7 +7,9 @@
     "rootDir": "src",
     "rootDir": "src",
     "strict": true,
     "strict": true,
     "target": "es2017",
     "target": "es2017",
-    "esModuleInterop": true
+    "esModuleInterop": true,
+    "types" : [ "node" ],
+    "noUnusedLocals": true
   },
   },
   "include": [
   "include": [
     "src/**/*"
     "src/**/*"

+ 12 - 0
devops/ansible/build-and-run-tests-single-node-playbook.yml

@@ -0,0 +1,12 @@
+- name: install dependencies
+  import_playbook: install-dependencies-playbook.yml
+
+- hosts: 127.0.0.1
+  user: root
+  become: yes
+  become_method: sudo
+  tasks:
+    - name: build node
+      include: build-image-tasklist.yml
+- name: run tests
+  import_playbook: run-tests-single-node-playbook.yml

+ 4 - 0
devops/ansible/build-image-tasklist.yml

@@ -0,0 +1,4 @@
+- name: create testing node docker image
+  shell: ./scripts/build-joystream-testing-node-docker-image.sh
+  args:
+    chdir: ../../

+ 34 - 0
devops/ansible/docker-compose.yml

@@ -0,0 +1,34 @@
+version: "3"
+services:
+  node_alice:
+    image: joystream/node-testing
+    container_name: alice
+    entrypoint: ./node --chain=chainspec.json --alice --validator --ws-external --rpc-cors=all
+    ports:
+      - "30333:30333"
+      - "9933:9933"
+      - "9944:9944"
+    networks:
+      testing_net:
+        ipv4_address: 172.28.1.1
+
+  node_bob:
+    image: joystream/node-testing
+    container_name: bob
+    entrypoint: ./node --chain=chainspec.json --bob --ws-external --rpc-cors=all
+    ports:
+      - "30335:30333"
+      - "9935:9933"
+      - "9945:9944"
+    links:
+      - "node_alice:alice"
+    networks:
+      testing_net:
+        ipv4_address: 172.28.1.2
+
+networks:
+  testing_net:
+    ipam:
+      driver: default
+      config:
+        - subnet: 172.28.0.0/16

+ 2 - 0
devops/ansible/hosts

@@ -0,0 +1,2 @@
+[sites]
+127.0.0.1 ansible_connection=local

+ 15 - 0
devops/ansible/install-dependencies-playbook.yml

@@ -0,0 +1,15 @@
+- hosts: 127.0.0.1
+  user: root
+  become: yes
+  become_method: sudo
+  tasks:
+    - name: install pip
+      apt: name=python-pip state=present
+    - name: install docker
+      pip: name=docker
+    - name: Install yarn with npm
+      npm:
+        name: yarn
+        global: yes
+    - name: Install docker compose
+      pip: name=docker-compose

+ 24 - 0
devops/ansible/run-tests-single-node-playbook.yml

@@ -0,0 +1,24 @@
+- hosts: 127.0.0.1
+  user: root
+  become: yes
+  become_method: sudo
+  tasks:
+    - name: run network
+      block:
+        - name: run docker container
+          docker_container:
+            name: "joystream-node-testing"
+            image: "joystream/node-testing"
+            ports:
+              - "9944:9944"
+            entrypoint: ./node --chain=chainspec.json --alice --validator --ws-external --rpc-cors=all
+            state: started
+        - name: execute network tests
+          shell: yarn debug >> ../../.tmp/tests.log
+          args:
+            chdir: ../../tests/network-tests/
+      always:
+        - name: stop docker container
+          docker_container:
+            name: "joystream-node-testing"
+            state: absent

+ 24 - 0
devops/ansible/run-tests-two-nodes-playbook.yml

@@ -0,0 +1,24 @@
+- name: install dependencies
+  import_playbook: install-dependencies-playbook.yml
+
+- hosts: 127.0.0.1
+  user: root
+  become: yes
+  become_method: sudo
+
+  tasks:
+    - name: run network
+      block:
+        - name: run two nodes containerized network
+          docker_compose:
+            project_src: ./
+            state: present
+        - name: execute network tests
+          shell: yarn test >> ../../.tmp/tests.log
+          args:
+            chdir: ../../tests/network-tests/
+      always:
+        - name: stop containers
+          docker_compose:
+            project_src: ./
+            state: absent

+ 37 - 0
devops/dockerfiles/ansible-node/Dockerfile

@@ -0,0 +1,37 @@
+FROM joystream/rust-builder AS builder
+LABEL description="Compiles all workspace artifacts"
+WORKDIR /joystream
+COPY . /joystream
+
+# Build joystream-node and its dependencies - runtime
+RUN cargo build --release -p joystream-node
+RUN /joystream/scripts/create-test-chainspec.sh
+
+FROM debian:stretch
+LABEL description="Joystream node"
+WORKDIR /joystream
+COPY --from=builder /joystream/target/release/joystream-node /joystream/node
+COPY --from=builder /joystream/target/release/wbuild/joystream-node-runtime/joystream_node_runtime.compact.wasm /joystream/runtime.compact.wasm
+COPY --from=builder /joystream/.tmp/chainspec.json /joystream/chainspec.json
+
+# confirm it works
+RUN /joystream/node --version
+
+# https://manpages.debian.org/stretch/coreutils/b2sum.1.en.html
+# RUN apt-get install coreutils
+# print the blake2 256 hash of the wasm blob
+RUN b2sum -l 256 /joystream/runtime.compact.wasm
+# print the blake2 512 hash of the wasm blob
+RUN b2sum -l 512 /joystream/runtime.compact.wasm
+
+EXPOSE 30333 9933 9944
+
+# Use these volumes to persits chain state and keystore, eg.:
+# --base-path /data
+# optionally separate keystore (otherwise it will be stored in the base path)
+# --keystore-path /keystore
+# if base-path isn't specified, chain state is stored inside container in ~/.local/share/joystream-node/
+# which is not ideal
+VOLUME ["/data", "/keystore"]
+
+ENTRYPOINT ["/joystream/node"]

+ 4 - 0
devops/eslint-config/index.js

@@ -39,6 +39,10 @@ module.exports = {
     // drop these when using newer versions of eslint-plugin-react-hooks
     // drop these when using newer versions of eslint-plugin-react-hooks
     'react-hooks/rules-of-hooks': 'error',
     'react-hooks/rules-of-hooks': 'error',
     'react-hooks/exhaustive-deps': 'warn',
     'react-hooks/exhaustive-deps': 'warn',
+    // only cli projects should really have this rule, web apps
+    // should prefer using 'debug' package at least to allow control of
+    // output verbosity if logging to console.
+    'no-console': 'off',
   },
   },
   plugins: [
   plugins: [
     'standard',
     'standard',

+ 766 - 0
devops/vstore/classes.json

@@ -0,0 +1,766 @@
+[
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x4d65646961204f626a656374",
+			"0x436c61737320666f72207265736f6c76696e67206120636f6e74656e7420656e7469747920746f20616e2061637475616c206d656469612066696c65206f72206c696e6b2e",
+			{
+				"entity_permissions": { "update": [0, 1, 2], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0, 1, 2],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x4c616e6775616765",
+			"0x436c61737320666f722073657474696e67206c616e67756167652e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x436f6e74656e74204c6963656e7365",
+			"0x436c61737320666f722073706563696679696e6720746865206c6963656e736520756e64657220776869636820636f6e74656e74206973207075626c69736865642e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x5075626c69636174696f6e20537461747573",
+			"0x436c61737320666f722073657474696e6720746865207075626c69636174696f6e20737461747573206f66206120636f6e74656e7420656e746974792e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x4375726174696f6e20537461747573",
+			"0x436c61737320666f722063757261746f727320746f2073657420746865207075626c69636174696f6e20737461747573206f66206120636f6e74656e7420656e746974792e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x466561747572656420436f6e74656e74",
+			"0x436c61737320666f722073657474696e6720666561747572656420636f6e74656e74206f6e2074686520706c6174666f726d2e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x566964656f",
+			"0x436c61737320666f722067656e6572616c20766964656f73206e6f742061737369676e61626c6520746f2061206d6f726520737065636966696320766964656f20636f6e74656e7420747970652e",
+			{
+				"entity_permissions": { "update": [0, 1, 2], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0, 1, 2],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x566964656f2043617465676f7279",
+			"0x436c61737320666f722073657474696e67207468652063617465676f727920666f7220766964656f7320696e2074686520566964656f20636c6173732e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x4d7573696320416c62756d",
+			"0x416e20616c62756d206973206120636f6c6c656374696f6e206f6620747261636b73206f7220617564696f207265636f7264696e67732e20557375616c6c7920627920612073696e676c6520617274697374206f722067726f75702e",
+			{
+				"entity_permissions": { "update": [0, 1, 2], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0, 1, 2],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x4d757369632047656e7265",
+			"0x436c61737320666f722073657474696e67207468652067656e726520666f72206d757369632e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x4d75736963204d6f6f64",
+			"0x436c61737320666f722073657474696e6720746865206d6f6f647320666f72206d757369632e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x4d75736963205468656d65",
+			"0x436c61737320666f722073657474696e6720746865207468656d657320666f72206d757369632e",
+			{
+				"entity_permissions": { "update": [0], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "createClass",
+		"args": [
+			"0x4d7573696320547261636b",
+			"0x4120747261636b20697320616e20696e646976696475616c20736f6e67206f7220696e737472756d656e74616c207265636f7264696e672e",
+			{
+				"entity_permissions": { "update": [0, 1, 2], "maintainer_has_all_permissions": true },
+				"entities_can_be_created": true,
+				"add_schemas": [0],
+				"create_entities": [0, 1, 2],
+				"reference_constraint": { "NoConstraint": null },
+				"admins": [0],
+				"last_permissions_update": 0
+			}
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			1,
+			[],
+			[
+				{
+					"prop_type": { "Text": 48 },
+					"required": true,
+					"name": "Value",
+					"description": "ContentId of object in the data directory"
+				},
+				{
+					"prop_type": { "Uint64": null },
+					"required": false,
+					"name": "Channel Id",
+					"description": "Id of the channel this media object is published under."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			2,
+			[],
+			[
+				{
+					"prop_type": { "Text": 2 },
+					"required": true,
+					"name": "Value",
+					"description": "Language code following the ISO 639-1 two letter standard."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			3,
+			[],
+			[
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Value",
+					"description": "The license of which the content is originally published under."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			4,
+			[],
+			[
+				{
+					"prop_type": { "Text": 50 },
+					"required": true,
+					"name": "Value",
+					"description": "The publication status of the content in the content directory."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			5,
+			[],
+			[
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Value",
+					"description": "The curator publication status of the content in the content directory."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			6,
+			[],
+			[
+				{
+					"prop_type": { "Internal": 7 },
+					"required": false,
+					"name": "Top Video",
+					"description": "The video that has the most prominent position(s) on the platform."
+				},
+				{
+					"prop_type": { "InternalVec": [12, 7] },
+					"required": false,
+					"name": "Featured Videos",
+					"description": "Videos featured in the Video tab."
+				},
+				{
+					"prop_type": { "InternalVec": [12, 9] },
+					"required": false,
+					"name": "Featured Albums",
+					"description": "Music albums featured in the Music tab."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			7,
+			[],
+			[
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Title",
+					"description": "The title of the video"
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Thumbnail",
+					"description": "URL to video thumbnail: NOTE: Should be an https link to an image of ratio 16:9, ideally 1280 pixels wide by 720 pixels tall, with a minimum width of 640 pixels, in JPEG or PNG format."
+				},
+				{
+					"prop_type": { "Text": 4000 },
+					"required": true,
+					"name": "Description",
+					"description": "Information about the video."
+				},
+				{
+					"prop_type": { "Internal": 2 },
+					"required": true,
+					"name": "Language",
+					"description": "The main language used in the video."
+				},
+				{
+					"prop_type": { "Int64": null },
+					"required": true,
+					"name": "First Released",
+					"description": "When the video was first released"
+				},
+				{
+					"prop_type": { "Internal": 8 },
+					"required": false,
+					"name": "Category",
+					"description": "The category of the video."
+				},
+				{
+					"prop_type": { "TextVec": [5, 255] },
+					"required": false,
+					"name": "Links",
+					"description": "Links to the creators pages."
+				},
+				{
+					"prop_type": { "Internal": 1 },
+					"required": false,
+					"name": "Object",
+					"description": "The entityId of the object in the data directory."
+				},
+				{
+					"prop_type": { "Internal": 4 },
+					"required": true,
+					"name": "Publication Status",
+					"description": "The publication status of the video."
+				},
+				{
+					"prop_type": { "Internal": 5 },
+					"required": false,
+					"name": "Curation Status",
+					"description": "The publication status of the video set by the a content curator on the platform."
+				},
+				{
+					"prop_type": { "Bool": null },
+					"required": true,
+					"name": "Explicit",
+					"description": "Indicates whether the video contains explicit material."
+				},
+				{
+					"prop_type": { "Internal": 3 },
+					"required": true,
+					"name": "License",
+					"description": "The license of which the video is released under."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": false,
+					"name": "Attribution",
+					"description": "If the License requires attribution, add this here."
+				},
+				{
+					"prop_type": { "Uint64": null },
+					"required": false,
+					"name": "Channel Id",
+					"description": "Id of the channel this video is published under."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			8,
+			[],
+			[
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Value",
+					"description": "Categories for videos."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			9,
+			[],
+			[
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Title",
+					"description": "The title of the album"
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Artist",
+					"description": "The artist, composer, band or group that published the album."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Thumbnail",
+					"description": "URL to album cover art thumbnail: NOTE: Should be an https link to a square image, between 1400x1400 and 3000x3000 pixels, in JPEG or PNG format."
+				},
+				{
+					"prop_type": { "Text": 4000 },
+					"required": true,
+					"name": "Description",
+					"description": "Information about the album and artist."
+				},
+				{
+					"prop_type": { "Int64": null },
+					"required": true,
+					"name": "First Released",
+					"description": "When the album was first released"
+				},
+				{
+					"prop_type": { "InternalVec": [3, 10] },
+					"required": false,
+					"name": "Genre",
+					"description": "The genre(s) of the album."
+				},
+				{
+					"prop_type": { "InternalVec": [3, 11] },
+					"required": false,
+					"name": "Mood",
+					"description": "The mood(s) of the album."
+				},
+				{
+					"prop_type": { "InternalVec": [3, 12] },
+					"required": false,
+					"name": "Theme",
+					"description": "The theme(s) of the album."
+				},
+				{
+					"prop_type": { "InternalVec": [100, 13] },
+					"required": false,
+					"name": "Tracks",
+					"description": "The tracks of the album."
+				},
+				{
+					"prop_type": { "Internal": 2 },
+					"required": false,
+					"name": "Language",
+					"description": "The language of the song lyrics in the album."
+				},
+				{
+					"prop_type": { "TextVec": [5, 255] },
+					"required": false,
+					"name": "Links",
+					"description": "Links to the artist or album site, or social media pages."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": false,
+					"name": "Lyrics",
+					"description": "Link to the album tracks lyrics."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": false,
+					"name": "Composer or songwriter",
+					"description": "The composer(s) and/or songwriter(s) of the album."
+				},
+				{
+					"prop_type": { "TextVec": [5, 255] },
+					"required": false,
+					"name": "Reviews",
+					"description": "Links to reviews of the album."
+				},
+				{
+					"prop_type": { "Internal": 4 },
+					"required": true,
+					"name": "Publication Status",
+					"description": "The publication status of the album."
+				},
+				{
+					"prop_type": { "Internal": 5 },
+					"required": false,
+					"name": "Curation Status",
+					"description": "The publication status of the album set by the a content curator on the platform."
+				},
+				{
+					"prop_type": { "Bool": null },
+					"required": true,
+					"name": "Explicit",
+					"description": "Indicates whether the album contains explicit material."
+				},
+				{
+					"prop_type": { "Internal": 3 },
+					"required": true,
+					"name": "License",
+					"description": "The license of which the album is released under."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": false,
+					"name": "Attribution",
+					"description": "If the License requires attribution, add this here."
+				},
+				{
+					"prop_type": { "Uint64": null },
+					"required": false,
+					"name": "Channel Id",
+					"description": "Id of the channel this album is published under."
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			10,
+			[],
+			[{ "prop_type": { "Text": 100 }, "required": true, "name": "Value", "description": "Genres for music." }]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			11,
+			[],
+			[{ "prop_type": { "Text": 100 }, "required": true, "name": "Value", "description": "Moods for music." }]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			12,
+			[],
+			[{ "prop_type": { "Text": 100 }, "required": true, "name": "Value", "description": "Themes for music." }]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "addClassSchema",
+		"args": [
+			0,
+			13,
+			[],
+			[
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Title",
+					"description": "The title of the track"
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Artist",
+					"description": "The artist, composer, band or group that published the track."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": true,
+					"name": "Thumbnail",
+					"description": "URL to track cover art: NOTE: Should be an https link to a square image, between 1400x1400 and 3000x3000 pixels, in JPEG or PNG format."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": false,
+					"name": "Description",
+					"description": "Information about the track."
+				},
+				{
+					"prop_type": { "Internal": 2 },
+					"required": false,
+					"name": "Language",
+					"description": "The language of the lyrics in the track."
+				},
+				{
+					"prop_type": { "Int64": null },
+					"required": true,
+					"name": "First Released",
+					"description": "When the track was first released"
+				},
+				{
+					"prop_type": { "Internal": 10 },
+					"required": false,
+					"name": "Genre",
+					"description": "The genre of the track."
+				},
+				{
+					"prop_type": { "Internal": 11 },
+					"required": false,
+					"name": "Mood",
+					"description": "The mood of the track."
+				},
+				{
+					"prop_type": { "Internal": 12 },
+					"required": false,
+					"name": "Theme",
+					"description": "The theme of the track."
+				},
+				{
+					"prop_type": { "TextVec": [5, 255] },
+					"required": false,
+					"name": "Links",
+					"description": "Links to the artist site or social media pages."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": false,
+					"name": "Composer or songwriter",
+					"description": "The composer(s) and/or songwriter(s) of the track."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": false,
+					"name": "Lyrics",
+					"description": "Link to the track lyrics."
+				},
+				{
+					"prop_type": { "Internal": 1 },
+					"required": false,
+					"name": "Object",
+					"description": "The entityId of the object in the data directory."
+				},
+				{
+					"prop_type": { "Internal": 4 },
+					"required": true,
+					"name": "Publication Status",
+					"description": "The publication status of the track."
+				},
+				{
+					"prop_type": { "Internal": 5 },
+					"required": false,
+					"name": "Curation Status",
+					"description": "The publication status of the track set by the a content curator on the platform."
+				},
+				{
+					"prop_type": { "Bool": null },
+					"required": true,
+					"name": "Explicit",
+					"description": "Indicates whether the track contains explicit material."
+				},
+				{
+					"prop_type": { "Internal": 3 },
+					"required": true,
+					"name": "License",
+					"description": "The license of which the track is released under."
+				},
+				{
+					"prop_type": { "Text": 255 },
+					"required": false,
+					"name": "Attribution",
+					"description": "If the License requires attribution, add this here."
+				},
+				{
+					"prop_type": { "Uint64": null },
+					"required": false,
+					"name": "Channel Id",
+					"description": "Id of the channel this track is published under."
+				}
+			]
+		]
+	}
+]

+ 12694 - 0
devops/vstore/entities.json

@@ -0,0 +1,12694 @@
+[
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "transaction",
+		"args": [
+			[
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 2 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 4 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 4 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 5 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 5 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 5 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 5 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 3 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 3 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 3 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 3 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 0 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "aa" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 1 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ab" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 2 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ae" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 3 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "af" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 4 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ak" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 5 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "am" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 6 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "an" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 7 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ar" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 8 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "as" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 9 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "av" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 10 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ay" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 11 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "az" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 12 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ba" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 13 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "be" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 14 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "bg" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 15 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "bh" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 16 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "bi" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 17 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "bm" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 18 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "bn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 19 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "bo" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 20 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "br" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 21 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "bs" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 22 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ca" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 23 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ce" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 24 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ch" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 25 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "co" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 26 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "cr" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 27 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "cs" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 28 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "cu" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 29 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "cv" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 30 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "cy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 31 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "da" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 32 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "de" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 33 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "dv" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 34 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "dz" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 35 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ee" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 36 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "el" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 37 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "en" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 38 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "eo" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 39 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "es" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 40 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "et" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 41 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "eu" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 42 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "fa" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 43 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ff" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 44 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "fi" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 45 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "fj" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 46 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "fo" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 47 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "fr" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 48 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "fy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 49 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ga" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 50 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "gd" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 51 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "gl" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 52 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "gn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 53 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "gu" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 54 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "gv" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 55 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ha" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 56 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "he" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 57 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "hi" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 58 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ho" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 59 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "hr" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 60 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ht" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 61 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "hu" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 62 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "hy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 63 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "hz" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 64 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ia" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 65 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "id" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 66 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ie" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 67 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ig" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 68 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ii" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 69 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ik" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 70 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "io" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 71 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "is" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 72 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "it" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 73 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "iu" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 74 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ja" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 75 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "jv" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 76 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ka" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 77 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "kg" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 78 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ki" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 79 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "kj" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 80 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "kk" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 81 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "kl" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 82 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "km" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 83 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "kn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 84 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ko" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 85 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "kr" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 86 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ks" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 87 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ku" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 88 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "kv" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 89 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "kw" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 90 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ky" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 91 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "la" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 92 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "lb" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 93 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "lg" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 94 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "li" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 95 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ln" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 96 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "lo" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 97 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "lt" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 98 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "lu" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 99 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "lv" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 100 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "mg" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 101 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "mh" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 102 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "mi" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 103 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "mk" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 104 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ml" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 105 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "mn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 106 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "mr" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 107 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ms" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 108 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "mt" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 109 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "my" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 110 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "na" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 111 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "nb" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 112 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "nd" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 113 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ne" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 114 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ng" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 115 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "nl" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 116 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "nn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 117 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "no" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 118 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "nr" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 119 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "nv" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 120 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ny" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 121 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "oc" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 122 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "oj" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 123 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "om" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 124 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "or" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 125 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "os" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 126 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "pa" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 127 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "pi" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 128 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "pl" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 129 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ps" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 130 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "pt" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 131 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "qu" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 132 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "rm" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 133 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "rn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 134 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ro" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 135 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ru" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 136 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "rw" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 137 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sa" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 138 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sc" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 139 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sd" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 140 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "se" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 141 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sg" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 142 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "si" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 143 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sk" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 144 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sl" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 145 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sm" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 146 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 147 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "so" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 148 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sq" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 149 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sr" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 150 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ss" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 151 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "st" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 152 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "su" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 153 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sv" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 154 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "sw" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 155 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ta" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 156 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "te" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 157 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "tg" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 158 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "th" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 159 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ti" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 160 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "tk" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 161 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "tl" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 162 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "tn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 163 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "to" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 164 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "tr" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 165 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ts" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 166 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "tt" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 167 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "tw" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 168 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ty" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 169 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ug" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 170 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "uk" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 171 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ur" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 172 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "uz" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 173 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "ve" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 174 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "vi" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 175 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "vo" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 176 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "wa" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 177 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "wo" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 178 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "xh" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 179 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "yi" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 180 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "yo" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 181 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "za" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 182 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "zh" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 183 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "zu" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 184 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Public" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 185 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Unlisted" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 186 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Edited" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 187 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Updated schema" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 188 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Under review" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 189 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Removed" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 190 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Public Domain" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 191 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Original content" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 192 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Creative Commons (attribution required)" } }
+								}
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 193 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Fair Use  (attribution required)" } }
+								}
+							]
+						}
+					}
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "transaction",
+		"args": [
+			[
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 8 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 0 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Film & Animation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 1 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Autos & Vehicles" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 2 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Music" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 3 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Pets & Animals" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 4 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sports" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 5 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Travel & Events" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 6 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Gaming" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 7 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "People & Blogs" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 8 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Comedy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 9 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Entertainment" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 10 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "News & Politics" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 11 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Howto & Style" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 12 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Education" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 13 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Science & Technology" } }
+								}
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 14 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Nonprofits & Activism" } }
+								}
+							]
+						}
+					}
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "transaction",
+		"args": [
+			[
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 10 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 0 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Avant-Garde" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 1 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Blues" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 2 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Children's" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 3 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Classical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 4 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Comedy/Spoken" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 5 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Country" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 6 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Easy Listening" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 7 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Electronic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 8 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Folk" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 9 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Holiday" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 10 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "International" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 11 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Jazz" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 12 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Latin" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 13 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "New Age" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 14 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Pop/Rock" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 15 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "R&B" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 16 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rap" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 17 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Reggae" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 18 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Religious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 19 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Stage & Screen" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 20 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Vocal" } } }
+							]
+						}
+					}
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "transaction",
+		"args": [
+			[
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 11 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 0 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Acerbic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 1 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Aggressive" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 2 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Agreeable" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 3 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Airy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 4 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Ambitious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 5 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Amiable/Good-Natured" } }
+								}
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 6 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Angry" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 7 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Angst-Ridden" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 8 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Anguished/Distraught" } }
+								}
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 9 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Angular" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 10 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Animated" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 11 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Apocalyptic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 12 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Arid" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 13 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Athletic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 14 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Atmospheric" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 15 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Austere" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 16 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Autumnal" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 17 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Belligerent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 18 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Benevolent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 19 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Bitter" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 20 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Bittersweet" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 21 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Bleak" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 22 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Boisterous" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 23 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Bombastic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 24 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Brash" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 25 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Brassy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 26 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Bravado" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 27 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Bright" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 28 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Brittle" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 29 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Brooding" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 30 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Calm/Peaceful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 31 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Campy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 32 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Capricious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 33 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Carefree" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 34 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cartoonish" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 35 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cathartic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 36 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Celebratory" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 37 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cerebral" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 38 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cheerful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 39 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Child-like" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 40 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Circular" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 41 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Clinical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 42 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cold" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 43 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Comic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 44 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Complex" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 45 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Concise" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 46 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Confident" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 47 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Confrontational" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 48 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cosmopolitan" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 49 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Crunchy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 50 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cynical/Sarcastic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 51 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Dark" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 52 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Declamatory" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 53 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Defiant" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 54 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Delicate" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 55 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Demonic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 56 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Desperate" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 57 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Detached" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 58 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Devotional" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 59 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Difficult" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 60 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Dignified/Noble" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 61 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Dramatic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 62 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Dreamy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 63 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Driving" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 64 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Druggy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 65 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Earnest" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 66 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Earthy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 67 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Ebullient" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 68 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Eccentric" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 69 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Ecstatic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 70 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Eerie" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 71 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Effervescent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 72 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Elaborate" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 73 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Elegant" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 74 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Elegiac" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 75 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Energetic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 76 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Enigmatic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 77 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Epic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 78 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Erotic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 79 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Ethereal" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 80 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Euphoric" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 81 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Exciting" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 82 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Exotic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 83 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Explosive" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 84 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Extroverted" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 85 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Exuberant" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 86 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Fantastic/Fantasy-like" } }
+								}
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 87 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Feral" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 88 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Feverish" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 89 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Fierce" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 90 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Fiery" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 91 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Flashy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 92 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Flowing" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 93 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Fractured" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 94 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Freewheeling" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 95 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Fun" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 96 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Funereal" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 97 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Gentle" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 98 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Giddy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 99 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Gleeful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 100 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Gloomy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 101 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Graceful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 102 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Greasy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 103 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Grim" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 104 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Gritty" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 105 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Gutsy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 106 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Happy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 107 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Harsh" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 108 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Hedonistic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 109 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Heroic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 110 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Hostile" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 111 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Humorous" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 112 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Hungry" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 113 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Hymn-like" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 114 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Hyper" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 115 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Hypnotic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 116 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Improvisatory" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 117 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Indulgent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 118 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Innocent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 119 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Insular" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 120 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Intense" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 121 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Intimate" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 122 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Introspective" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 123 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Ironic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 124 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Irreverent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 125 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Jovial" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 126 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Joyous" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 127 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Kinetic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 128 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Knotty" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 129 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Laid-Back/Mellow" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 130 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Languid" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 131 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Lazy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 132 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Light" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 133 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Literate" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 134 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Lively" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 135 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Lonely" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 136 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Lush" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 137 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Lyrical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 138 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Macabre" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 139 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Magical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 140 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Majestic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 141 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Malevolent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 142 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Manic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 143 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Marching" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 144 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Martial" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 145 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Meandering" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 146 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Mechanical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 147 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Meditative" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 148 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Melancholy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 149 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Menacing" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 150 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Messy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 151 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Mighty" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 152 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Monastic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 153 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Monumental" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 154 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Motoric" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 155 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Mysterious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 156 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Mystical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 157 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Naive" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 158 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Narcotic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 159 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Narrative" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 160 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Negative" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 161 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Nervous/Jittery" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 162 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Nihilistic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 163 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Nocturnal" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 164 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Nostalgic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 165 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Ominous" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 166 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Optimistic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 167 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Opulent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 168 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Organic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 169 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Ornate" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 170 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Outraged" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 171 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Outrageous" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 172 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Paranoid" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 173 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Passionate" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 174 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Pastoral" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 175 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Patriotic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 176 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Perky" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 177 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Philosophical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 178 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Plain" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 179 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Plaintive" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 180 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Playful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 181 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Poignant" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 182 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Positive" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 183 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Powerful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 184 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Precious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 185 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Provocative" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 186 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Pulsing" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 187 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Pure" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 188 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Quirky" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 189 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rambunctious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 190 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Ramshackle" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 191 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Raucous" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 192 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Reassuring/Consoling" } }
+								}
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 193 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rebellious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 194 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Reckless" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 195 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Refined" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 196 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Reflective" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 197 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Regretful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 198 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Relaxed" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 199 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Reserved" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 200 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Resolute" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 201 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Restrained" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 202 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Reverent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 203 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rhapsodic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 204 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rollicking" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 205 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Romantic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 206 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rousing" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 207 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rowdy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 208 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rustic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 209 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sacred" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 210 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sad" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 211 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sarcastic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 212 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sardonic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 213 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Satirical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 214 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Savage" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 215 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Scary" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 216 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Scattered" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 217 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Searching" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 218 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Self-Conscious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 219 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sensual" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 220 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sentimental" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 221 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Serious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 222 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Severe" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 223 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sexual" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 224 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sexy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 225 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Shimmering" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 226 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Silly" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 227 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sleazy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 228 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Slick" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 229 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Smooth" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 230 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Snide" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 231 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Soft/Quiet" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 232 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Somber" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 233 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Soothing" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 234 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sophisticated" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 235 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Spacey" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 236 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sparkling" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 237 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sparse" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 238 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Spicy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 239 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Spiritual" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 240 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Spontaneous" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 241 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Spooky" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 242 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sprawling" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 243 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sprightly" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 244 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Springlike" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 245 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Stately" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 246 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Street-Smart" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 247 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Striding" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 248 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Strong" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 249 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Stylish" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 250 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Suffocating" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 251 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sugary" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 252 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Summery" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 253 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Suspenseful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 254 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Swaggering" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 255 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sweet" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 256 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Swinging" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 257 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Technical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 258 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Tender" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 259 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Tense/Anxious" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 260 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Theatrical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 261 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Thoughtful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 262 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Threatening" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 263 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Thrilling" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 264 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Thuggish" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 265 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Tragic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 266 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Transparent/Translucent" } }
+								}
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 267 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Trashy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 268 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Trippy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 269 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Triumphant" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 270 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Tuneful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 271 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Turbulent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 272 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Uncompromising" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 273 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Understated" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 274 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Unsettling" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 275 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Uplifting" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 276 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Urgent" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 277 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Virile" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 278 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Visceral" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 279 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Volatile" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 280 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Vulgar" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 281 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Warm" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 282 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Weary" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 283 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Whimsical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 284 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Wintry" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 285 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Wistful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 286 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Witty" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 287 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Wry" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 288 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Yearning" } } }
+							]
+						}
+					}
+				}
+			]
+		]
+	},
+
+	{
+		"sectionName": "versionedStorePermissions",
+		"methodName": "transaction",
+		"args": [
+			[
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": { "CreateEntity": { "class_id": 12 } }
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 0 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Adventure" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 1 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Affection/Fondness" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 2 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Affirmation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 3 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Anger/Hostility" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 4 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Animals" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 5 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Anniversary" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 6 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Argument" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 7 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "At the Beach" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 8 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "At the Office" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 9 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Autumn" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 10 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Award Winners" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 11 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Awareness" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 12 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Background Music" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 13 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Biographical" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 14 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Birth" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 15 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Birthday" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 16 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Breakup" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 17 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cars" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 18 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Celebration" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 19 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Celebrities" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 20 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Children" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 21 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Christmas" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 22 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Christmas Party" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 23 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "City Life" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 24 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Classy Gatherings" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 25 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Club" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 26 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Comfort" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 27 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Conflict" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 28 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Cool & Cocky" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 29 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Country Life" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 30 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Crime" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 31 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "D-I-V-O-R-C-E" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 32 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Dance Party" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 33 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Day Driving" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 34 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Daydreaming" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 35 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Death" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 36 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Despair" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 37 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Destiny" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 38 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Dinner Ambiance" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 39 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Disappointment" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 40 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Dreaming" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 41 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Drinking" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 42 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Drugs" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 43 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Early Morning" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 44 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Easter" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 45 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Empowering" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 46 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Everyday Life" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 47 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Exercise/Workout" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 48 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Family" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 49 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Family Gatherings" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 50 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Fantasy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 51 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Fear" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 52 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Feeling Blue" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 53 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Flying" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 54 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Food/Eating" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 55 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Forgiveness" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 56 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Fourth of July" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 57 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Freedom" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 58 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Friendship" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 59 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Funeral" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 60 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Girls Night Out" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 61 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Good Times" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 62 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Goodbyes" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 63 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Graduation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 64 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Guys Night Out" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 65 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Halloween" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 66 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Hanging Out" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 67 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Happiness" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 68 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Healing/Comfort" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 69 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Heartache" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 70 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Heartbreak" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 71 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "High School" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 72 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Historical Events" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 73 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Holidays" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 74 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Home" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 75 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Homecoming" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 76 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Hope" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 77 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Housework" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 78 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Illness" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 79 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "In Love" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 80 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Introspection" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 81 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Jealousy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 82 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Joy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 83 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Late Night" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 84 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Lifecycle" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 85 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Loneliness" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 86 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Long Walk" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 87 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Loss/Grief" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 88 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Lying" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 89 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Magic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 90 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Maverick" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 91 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Meditation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 92 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Memorial" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 93 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Military" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 94 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Mischievous" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 95 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Monday Morning" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 96 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Money" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 97 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Moon" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 98 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Morning" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 99 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Motivation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 100 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Music" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 101 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Myths & Legends" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 102 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Nature" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 103 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "New Love" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 104 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Night Driving" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 105 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Nighttime" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 106 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Open Road" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 107 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{
+									"in_class_index": 0,
+									"value": { "PropertyValue": { "Text": "Other Times & Places" } }
+								}
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 108 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Pain" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 109 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Parenthood" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 110 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Partying" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 111 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Passion" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 112 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Patriotism" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 113 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Peace" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 114 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Picnic" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 115 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Playful" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 116 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Poetry" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 117 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Politics/Society" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 118 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Pool Party" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 119 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Prom" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 120 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Promises" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 121 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Protest" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 122 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Rainy Day" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 123 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Reflection" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 124 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Regret" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 125 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Relationships" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 126 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Relaxation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 127 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Religion" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 128 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Reminiscing" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 129 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Reunion" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 130 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Revolutionary" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 131 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Road Trip" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 132 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Romance" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 133 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Romantic Evening" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 134 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Scary Music" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 135 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "School" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 136 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Science" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 137 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "SciFi" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 138 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Seduction" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 139 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Separation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 140 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sex" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 141 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Slow Dance" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 142 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Small Gathering" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 143 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Solitude" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 144 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sorrow" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 145 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sports" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 146 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Spring" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 147 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Starry Sky" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 148 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Starting Out" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 149 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Stay in Bed" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 150 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Storms" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 151 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Street Life" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 152 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Summer" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 153 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sun" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 154 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sunday Afternoon" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 155 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Sweet Dreams" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 156 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Teenagers" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 157 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Temptation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 158 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "TGIF" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 159 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Thanksgiving" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 160 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "The Creative Side" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 161 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "The Great Outdoors" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 162 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Value" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 163 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Tragedy" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 164 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Travel" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 165 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Truth" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 166 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Vacation" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 167 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Victory" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 168 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Violence" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 169 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Visions" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 170 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "War" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 171 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Water" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 172 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Weather" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 173 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Wedding" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 174 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Winter" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 175 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Wisdom" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 176 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Word Play" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 177 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Work" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 178 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "World View" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 179 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Yearning" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 180 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Youth" } } }
+							]
+						}
+					}
+				},
+				{
+					"with_credential": 0,
+					"as_entity_maintainer": true,
+					"operation_type": {
+						"AddSchemaSupportToEntity": {
+							"entity_id": { "InternalEntityJustAdded": 181 },
+							"schema_id": 0,
+							"parametrized_property_values": [
+								{ "in_class_index": 0, "value": { "PropertyValue": { "Text": "Zeitgeist" } } }
+							]
+						}
+					}
+				}
+			]
+		]
+	}
+]

+ 245 - 138
node/Cargo.toml

@@ -1,9 +1,9 @@
 [package]
 [package]
-authors = ['Joystream']
+authors = ['Joystream contributors']
 build = 'build.rs'
 build = 'build.rs'
 edition = '2018'
 edition = '2018'
 name = 'joystream-node'
 name = 'joystream-node'
-version = '2.3.0'
+version = '3.0.0'
 default-run = "joystream-node"
 default-run = "joystream-node"
 
 
 [[bin]]
 [[bin]]
@@ -13,144 +13,251 @@ path = 'bin/main.rs'
 [lib]
 [lib]
 crate-type = ["cdylib", "rlib"]
 crate-type = ["cdylib", "rlib"]
 
 
+#[dependencies]
+#derive_more = '0.14.0'
+#exit-future = '0.1.4'
+
+#hex = '0.4'
+
 [dependencies]
 [dependencies]
-hex-literal = '0.2.1'
-derive_more = '0.14.0'
-exit-future = '0.1.4'
-futures = '0.1.29'
-log = '0.4.8'
-parking_lot = '0.9.0'
-tokio = '0.1.22'
-jsonrpc-core = '13.2.0'
-rand = '0.7.2'
-structopt = '=0.3.5'
+# third-party dependencies
+codec = { package = "parity-scale-codec", version = "1.3.1" }
+serde = { version = "1.0.102", features = ["derive"] }
+futures = { version = "0.3.1", features = ["compat"] }
+hex-literal = "0.2.1"
+jsonrpc-core = "14.2.0"
+log = "0.4.8"
+rand = "0.7.2"
+structopt = { version = "0.3.8"}
+tracing = "0.1.10"
+parking_lot = "0.10.0"
+
 serde_json = '1.0'
 serde_json = '1.0'
-serde = '1.0'
-hex = '0.4'
-# https://users.rust-lang.org/t/failure-derive-compilation-error/39062
-# quote = '<=1.0.2'
-
-[dependencies.node-runtime]
-package = 'joystream-node-runtime'
-path = '../runtime'
-
-[dependencies.substrate-basic-authorship]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-basic-authorship'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.babe]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-consensus-babe'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.babe-primitives]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-consensus-babe-primitives'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.codec]
-package = 'parity-scale-codec'
-version = '1.0.0'
-
-[dependencies.ctrlc]
-features = ['termination']
-version = '3.0'
-
-[dependencies.inherents]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-inherents'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.network]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-network'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.primitives]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-primitives'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.sr-io]
-git = 'https://github.com/paritytech/substrate.git'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.substrate-cli]
-git = 'https://github.com/paritytech/substrate.git'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.substrate-client]
-git = 'https://github.com/paritytech/substrate.git'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.substrate-executor]
-git = 'https://github.com/paritytech/substrate.git'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.substrate-service]
-git = 'https://github.com/paritytech/substrate.git'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.transaction-pool]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-transaction-pool'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.substrate-telemetry]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-telemetry'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.grandpa]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-finality-grandpa'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.grandpa-primitives]
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-finality-grandpa-primitives'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.im-online]
-default_features = false
-git = 'https://github.com/paritytech/substrate.git'
-package = 'srml-im-online'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.substrate-rpc]
-default_features = false
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-rpc'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.authority-discovery]
-default_features = false
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-authority-discovery'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.client-db]
-default_features = false
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-client-db'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.runtime-primitives]
-default_features = false
-git = 'https://github.com/paritytech/substrate.git'
-package = 'sr-primitives'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.offchain]
-default_features = false
-git = 'https://github.com/paritytech/substrate.git'
-package = 'substrate-offchain'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dependencies.libp2p]
-version = '0.13.2'
-default-features = false
+tokio = '0.1.22'
+
+# primitives
+sp-authority-discovery = { package = 'sp-authority-discovery', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-consensus-babe = { package = 'sp-consensus-babe', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-finality-grandpa = { package = 'sp-finality-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-core = { package = 'sp-core', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-runtime = { package = 'sp-runtime', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-timestamp = { package = 'sp-timestamp', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-finality-tracker = { package = 'sp-finality-tracker', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-inherents = { package = 'sp-inherents', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-keyring = { package = 'sp-keyring', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-io = { package = 'sp-io', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-consensus = { package = 'sp-consensus', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-transaction-pool = { package = 'sp-transaction-pool', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-api = { package = 'sp-api', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-blockchain = { package = 'sp-blockchain', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+
+# client dependencies
+sc-client-api = { package = 'sc-client-api', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-chain-spec = { package = 'sc-chain-spec', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-consensus = { package = 'sc-consensus', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-transaction-pool = { package = 'sc-transaction-pool', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-network = { package = 'sc-network', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-consensus-babe = { package = 'sc-consensus-babe', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
+sc-finality-grandpa = { package = 'sc-finality-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-client-db = { package = 'sc-client-db', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-offchain = { package = 'sc-offchain', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-rpc = { package = 'sc-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-basic-authorship = { package = 'sc-basic-authorship', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-service = { package = 'sc-service', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-tracing = { package = 'sc-tracing', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-telemetry = { package = 'sc-telemetry', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-authority-discovery = { package = 'sc-authority-discovery', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-consensus-epochs = { package = 'sc-consensus-epochs', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-keystore = { package = 'sc-keystore', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-consensus-babe-rpc = { package = 'sc-consensus-babe-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-finality-grandpa-rpc = { package = 'sc-finality-grandpa-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-rpc-api = { package = 'sc-rpc-api', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-block-builder = { package = 'sp-block-builder', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-contracts-rpc = { package = 'pallet-contracts-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-transaction-payment-rpc = { package = 'pallet-transaction-payment-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+substrate-frame-rpc-system = { package = 'substrate-frame-rpc-system', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-executor = { package = 'sc-executor', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+frame-benchmarking = { package = 'frame-benchmarking', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+
+#sc-client-api = { version = "2.0.0-rc4", path = "../../../client/api" }
+#jsonrpc-core = "14.2.0"
+#node-primitives = { version = "2.0.0-rc4", path = "../primitives" }
+#node-runtime = { version = "2.0.0-rc4", path = "../runtime" }
+#sp-runtime = { version = "2.0.0-rc4", path = "../../../primitives/runtime" }
+#sp-api = { version = "2.0.0-rc4", path = "../../../primitives/api" }
+#pallet-contracts-rpc = { version = "0.8.0-rc4", path = "../../../frame/contracts/rpc/" }
+#pallet-transaction-payment-rpc = { version = "2.0.0-rc4", path = "../../../frame/transaction-payment/rpc/" }
+#substrate-frame-rpc-system = { version = "2.0.0-rc4", path = "../../../utils/frame/rpc/system" }
+#sp-transaction-pool = { version = "2.0.0-rc4", path = "../../../primitives/transaction-pool" }
+#sc-consensus-babe = { version = "0.8.0-rc4", path = "../../../client/consensus/babe" }
+#sc-consensus-babe-rpc = { version = "0.8.0-rc4", path = "../../../client/consensus/babe/rpc" }
+#sp-consensus-babe = { version = "0.8.0-rc4", path = "../../../primitives/consensus/babe" }
+#sc-keystore = { version = "2.0.0-rc4", path = "../../../client/keystore" }
+#sc-consensus-epochs = { version = "0.8.0-rc4", path = "../../../client/consensus/epochs" }
+#sp-consensus = { version = "0.8.0-rc4", path = "../../../primitives/consensus/common" }
+#sp-blockchain = { version = "2.0.0-rc4", path = "../../../primitives/blockchain" }
+#sc-finality-grandpa = { version = "0.8.0-rc4", path = "../../../client/finality-grandpa" }
+#sc-finality-grandpa-rpc = { version = "0.8.0-rc4", path = "../../../client/finality-grandpa/rpc" }
+#sc-rpc-api = { version = "0.8.0-rc4", path = "../../../client/rpc-api" }
+#sp-block-builder = { version = "2.0.0-rc4", path = "../../../primitives/block-builder" }
+
+# frame dependencies
+pallet-indices = { package = 'pallet-indices', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-timestamp = { package = 'pallet-timestamp', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-contracts = { package = 'pallet-contracts', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+frame-system = { package = 'frame-system', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-balances = { package = 'pallet-balances', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-transaction-payment = { package = 'pallet-transaction-payment', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+frame-support = { package = 'frame-support', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-im-online = { package = 'pallet-im-online', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-authority-discovery = { package = 'pallet-authority-discovery', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-staking = { package = 'pallet-staking', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-grandpa = { package = 'pallet-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+
+# node-specific dependencies
+node-runtime = { package= "joystream-node-runtime", path = "../runtime" }
+
+# CLI-specific dependencies
+sc-cli = { package = 'sc-cli', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+frame-benchmarking-cli = { package = 'frame-benchmarking-cli', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+node-inspect = { package = 'node-inspect', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+
+# WASM-specific dependencies
+wasm-bindgen = { version = "0.2.57", optional = true }
+wasm-bindgen-futures = { version = "0.4.7", optional = true }
+browser-utils = { package = 'substrate-browser-utils', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true}
+
+[dev-dependencies]
+#sc-keystore = { version = "2.0.0-rc4", path = "../../../client/keystore" }
+#sc-consensus = { version = "0.8.0-rc4", path = "../../../client/consensus/common" }
+sc-consensus-babe = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', features = ["test-helpers"]}
+#sc-consensus-epochs = { version = "0.8.0-rc4", path = "../../../client/consensus/epochs" }
+sc-service-test = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+#futures = "0.3.4"
+tempfile = "3.1.0"
+#assert_cmd = "1.0"
+#nix = "0.17"
+#serde_json = "1.0"
+#regex = "1"
+#platforms = "0.2.1"
+
+#[dependencies.substrate-basic-authorship]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-basic-authorship'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.babe]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-consensus-babe'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.babe-primitives]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-consensus-babe-primitives'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.codec]
+#package = 'parity-scale-codec'
+#version = '1.0.0'
+#
+#[dependencies.ctrlc]
+#features = ['termination']
+#version = '3.0'
+#
+#[dependencies.inherents]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-inherents'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.network]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-network'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.primitives]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-primitives'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.sr-io]
+#git = 'https://github.com/paritytech/substrate.git'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.substrate-cli]
+#git = 'https://github.com/paritytech/substrate.git'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.substrate-client]
+#git = 'https://github.com/paritytech/substrate.git'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.substrate-executor]
+#git = 'https://github.com/paritytech/substrate.git'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.substrate-service]
+#git = 'https://github.com/paritytech/substrate.git'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.transaction-pool]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-transaction-pool'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.substrate-telemetry]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-telemetry'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.grandpa]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-finality-grandpa'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.grandpa-primitives]
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-finality-grandpa-primitives'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.im-online]
+#default_features = false
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'srml-im-online'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.substrate-rpc]
+#default_features = false
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-rpc'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.authority-discovery]
+#default_features = false
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-authority-discovery'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.client-db]
+#default_features = false
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-client-db'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.runtime-primitives]
+#default_features = false
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'sr-primitives'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.offchain]
+#default_features = false
+#git = 'https://github.com/paritytech/substrate.git'
+#package = 'substrate-offchain'
+#rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+#
+#[dependencies.libp2p]
+#version = '0.13.2'
+#default-features = false
 
 
 [build-dependencies]
 [build-dependencies]
 vergen = '3'
 vergen = '3'

+ 3 - 20
node/bin/main.rs

@@ -14,27 +14,10 @@
 // You should have received a copy of the GNU General Public License
 // You should have received a copy of the GNU General Public License
 // along with Joystream node.  If not, see <http://www.gnu.org/licenses/>.
 // along with Joystream node.  If not, see <http://www.gnu.org/licenses/>.
 
 
-//! Substrate Node Template CLI library.
+//! Joystream Node.
 
 
 #![warn(missing_docs)]
 #![warn(missing_docs)]
-#![warn(unused_extern_crates)]
 
 
-use joystream_node::cli;
-pub use substrate_cli::{error, IntoExit, VersionInfo};
-
-fn main() {
-    let version = VersionInfo {
-        name: "Joystream Node",
-        commit: env!("VERGEN_SHA_SHORT"),
-        version: env!("CARGO_PKG_VERSION"),
-        executable_name: "joystream-node",
-        author: "Joystream",
-        description: "Joystream substrate node",
-        support_url: "https://www.joystream.org/",
-    };
-
-    if let Err(e) = cli::run(::std::env::args(), cli::Exit, version) {
-        eprintln!("Fatal error: {}\n\n{:?}", e, e);
-        std::process::exit(1)
-    }
+fn main() -> sc_cli::Result<()> {
+    joystream_node::command::run()
 }
 }

+ 196 - 71
node/src/chain_spec.rs

@@ -15,31 +15,37 @@
 // along with Joystream node.  If not, see <http://www.gnu.org/licenses/>.
 // along with Joystream node.  If not, see <http://www.gnu.org/licenses/>.
 
 
 // Clippy linter warning.
 // Clippy linter warning.
-#![allow(clippy::identity_op)] // disable it because we use such syntax for a code readability
-                               // Example:  voting_period: 1 * DAY
+// Disable it because we use such syntax for a code readability.
+// Example:  voting_period: 1 * DAY
+#![allow(clippy::identity_op)]
+
+use node_runtime::{AccountId, GenesisConfig};
+use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
+use serde_json as json;
+use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
+use sp_consensus_babe::AuthorityId as BabeId;
+use sp_core::{sr25519, Pair, Public};
+use sp_finality_grandpa::AuthorityId as GrandpaId;
+use sp_runtime::traits::{IdentifyAccount, Verify};
+use sp_runtime::Perbill;
 
 
 use node_runtime::{
 use node_runtime::{
-    versioned_store::InputValidationLengthConstraint as VsInputValidation, ActorsConfig,
+    versioned_store::InputValidationLengthConstraint as VsInputValidation,
     AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig, ContentWorkingGroupConfig,
     AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig, ContentWorkingGroupConfig,
-    CouncilConfig, CouncilElectionConfig, DataObjectStorageRegistryConfig,
+    ContractsConfig, CouncilConfig, CouncilElectionConfig, DataObjectStorageRegistryConfig,
     DataObjectTypeRegistryConfig, ElectionParameters, GrandpaConfig, ImOnlineConfig, IndicesConfig,
     DataObjectTypeRegistryConfig, ElectionParameters, GrandpaConfig, ImOnlineConfig, IndicesConfig,
-    MembersConfig, MigrationConfig, Perbill, ProposalsCodexConfig, SessionConfig, SessionKeys,
-    Signature, StakerStatus, StakingConfig, SudoConfig, SystemConfig, VersionedStoreConfig, DAYS,
-    WASM_BINARY,
+    MembersConfig, MigrationConfig, ProposalsCodexConfig, SessionConfig, SessionKeys, Signature,
+    StakerStatus, StakingConfig, StorageWorkingGroupConfig, SudoConfig, SystemConfig,
+    VersionedStoreConfig, DAYS, WASM_BINARY,
 };
 };
-pub use node_runtime::{AccountId, GenesisConfig};
-use primitives::{sr25519, Pair, Public};
-use runtime_primitives::traits::{IdentifyAccount, Verify};
-
-use babe_primitives::AuthorityId as BabeId;
-use grandpa_primitives::AuthorityId as GrandpaId;
-use im_online::sr25519::AuthorityId as ImOnlineId;
-use serde_json as json;
 
 
 type AccountPublic = <Signature as Verify>::Signer;
 type AccountPublic = <Signature as Verify>::Signer;
 
 
 /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
 /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
-pub type ChainSpec = substrate_service::ChainSpec<GenesisConfig>;
+pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;
+
+use node_runtime::common::constraints::InputValidationLengthConstraint;
+use sc_chain_spec::ChainType;
 
 
 /// The chain specification option. This is expected to come in from the CLI and
 /// The chain specification option. This is expected to come in from the CLI and
 /// is little more than one of a number of alternatives which can easily be converted
 /// is little more than one of a number of alternatives which can easily be converted
@@ -70,21 +76,35 @@ where
 /// Helper function to generate stash, controller and session key from seed
 /// Helper function to generate stash, controller and session key from seed
 pub fn get_authority_keys_from_seed(
 pub fn get_authority_keys_from_seed(
     seed: &str,
     seed: &str,
-) -> (AccountId, AccountId, GrandpaId, BabeId, ImOnlineId) {
+) -> (
+    AccountId,
+    AccountId,
+    GrandpaId,
+    BabeId,
+    ImOnlineId,
+    AuthorityDiscoveryId,
+) {
     (
     (
         get_account_id_from_seed::<sr25519::Public>(&format!("{}//stash", seed)),
         get_account_id_from_seed::<sr25519::Public>(&format!("{}//stash", seed)),
         get_account_id_from_seed::<sr25519::Public>(seed),
         get_account_id_from_seed::<sr25519::Public>(seed),
         get_from_seed::<GrandpaId>(seed),
         get_from_seed::<GrandpaId>(seed),
         get_from_seed::<BabeId>(seed),
         get_from_seed::<BabeId>(seed),
         get_from_seed::<ImOnlineId>(seed),
         get_from_seed::<ImOnlineId>(seed),
+        get_from_seed::<AuthorityDiscoveryId>(seed),
     )
     )
 }
 }
 
 
-fn session_keys(grandpa: GrandpaId, babe: BabeId, im_online: ImOnlineId) -> SessionKeys {
+fn session_keys(
+    grandpa: GrandpaId,
+    babe: BabeId,
+    im_online: ImOnlineId,
+    authority_discovery: AuthorityDiscoveryId,
+) -> SessionKeys {
     SessionKeys {
     SessionKeys {
         grandpa,
         grandpa,
         babe,
         babe,
         im_online,
         im_online,
+        authority_discovery,
     }
     }
 }
 }
 
 
@@ -95,6 +115,7 @@ impl Alternative {
             Alternative::Development => ChainSpec::from_genesis(
             Alternative::Development => ChainSpec::from_genesis(
                 "Development",
                 "Development",
                 "dev",
                 "dev",
+                ChainType::Development,
                 || {
                 || {
                     testnet_genesis(
                     testnet_genesis(
                         vec![get_authority_keys_from_seed("Alice")],
                         vec![get_authority_keys_from_seed("Alice")],
@@ -107,7 +128,7 @@ impl Alternative {
                         ],
                         ],
                     )
                     )
                 },
                 },
-                vec![],
+                Vec::new(),
                 None,
                 None,
                 None,
                 None,
                 Some(chain_spec_properties()),
                 Some(chain_spec_properties()),
@@ -116,6 +137,7 @@ impl Alternative {
             Alternative::LocalTestnet => ChainSpec::from_genesis(
             Alternative::LocalTestnet => ChainSpec::from_genesis(
                 "Local Testnet",
                 "Local Testnet",
                 "local_testnet",
                 "local_testnet",
+                ChainType::Local,
                 || {
                 || {
                     testnet_genesis(
                     testnet_genesis(
                         vec![
                         vec![
@@ -139,7 +161,7 @@ impl Alternative {
                         ],
                         ],
                     )
                     )
                 },
                 },
-                vec![],
+                Vec::new(),
                 None,
                 None,
                 None,
                 None,
                 Some(chain_spec_properties()),
                 Some(chain_spec_properties()),
@@ -147,14 +169,6 @@ impl Alternative {
             ),
             ),
         })
         })
     }
     }
-
-    pub(crate) fn from(s: &str) -> Option<Self> {
-        match s {
-            "dev" => Some(Alternative::Development),
-            "local" => Some(Alternative::LocalTestnet),
-            _ => None,
-        }
-    }
 }
 }
 
 
 fn new_vs_validation(min: u16, max_min_diff: u16) -> VsInputValidation {
 fn new_vs_validation(min: u16, max_min_diff: u16) -> VsInputValidation {
@@ -175,7 +189,14 @@ pub fn chain_spec_properties() -> json::map::Map<String, json::Value> {
 }
 }
 
 
 pub fn testnet_genesis(
 pub fn testnet_genesis(
-    initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId)>,
+    initial_authorities: Vec<(
+        AccountId,
+        AccountId,
+        GrandpaId,
+        BabeId,
+        ImOnlineId,
+        AuthorityDiscoveryId,
+    )>,
     root_key: AccountId,
     root_key: AccountId,
     endowed_accounts: Vec<AccountId>,
     endowed_accounts: Vec<AccountId>,
 ) -> GenesisConfig {
 ) -> GenesisConfig {
@@ -184,37 +205,26 @@ pub fn testnet_genesis(
     const STASH: Balance = 20 * DOLLARS;
     const STASH: Balance = 20 * DOLLARS;
     const ENDOWMENT: Balance = 100_000 * DOLLARS;
     const ENDOWMENT: Balance = 100_000 * DOLLARS;
 
 
+    let enable_println = false;
+
     // default codex proposals config parameters
     // default codex proposals config parameters
     let cpcp = node_runtime::ProposalsConfigParameters::default();
     let cpcp = node_runtime::ProposalsConfigParameters::default();
+    let default_text_constraint = node_runtime::working_group::default_text_constraint();
 
 
     GenesisConfig {
     GenesisConfig {
         system: Some(SystemConfig {
         system: Some(SystemConfig {
             code: WASM_BINARY.to_vec(),
             code: WASM_BINARY.to_vec(),
             changes_trie_config: Default::default(),
             changes_trie_config: Default::default(),
         }),
         }),
-        balances: Some(BalancesConfig {
+        pallet_balances: Some(BalancesConfig {
             balances: endowed_accounts
             balances: endowed_accounts
                 .iter()
                 .iter()
                 .cloned()
                 .cloned()
                 .map(|k| (k, ENDOWMENT))
                 .map(|k| (k, ENDOWMENT))
                 .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
                 .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
                 .collect(),
                 .collect(),
-            vesting: vec![],
-        }),
-        indices: Some(IndicesConfig { ids: vec![] }),
-        session: Some(SessionConfig {
-            keys: initial_authorities
-                .iter()
-                .map(|x| {
-                    (
-                        x.0.clone(),
-                        session_keys(x.2.clone(), x.3.clone(), x.4.clone()),
-                    )
-                })
-                .collect::<Vec<_>>(),
         }),
         }),
-        staking: Some(StakingConfig {
-            current_era: 0,
+        pallet_staking: Some(StakingConfig {
             validator_count: 20,
             validator_count: 20,
             minimum_validator_count: 1,
             minimum_validator_count: 1,
             stakers: initial_authorities
             stakers: initial_authorities
@@ -225,15 +235,34 @@ pub fn testnet_genesis(
             slash_reward_fraction: Perbill::from_percent(10),
             slash_reward_fraction: Perbill::from_percent(10),
             ..Default::default()
             ..Default::default()
         }),
         }),
-        sudo: Some(SudoConfig { key: root_key }),
-        babe: Some(BabeConfig {
+        pallet_sudo: Some(SudoConfig { key: root_key }),
+        pallet_babe: Some(BabeConfig {
             authorities: vec![],
             authorities: vec![],
         }),
         }),
-        im_online: Some(ImOnlineConfig { keys: vec![] }),
-        authority_discovery: Some(AuthorityDiscoveryConfig { keys: vec![] }),
-        grandpa: Some(GrandpaConfig {
+        pallet_im_online: Some(ImOnlineConfig { keys: vec![] }),
+        pallet_authority_discovery: Some(AuthorityDiscoveryConfig { keys: vec![] }),
+        pallet_grandpa: Some(GrandpaConfig {
             authorities: vec![],
             authorities: vec![],
         }),
         }),
+        pallet_indices: Some(IndicesConfig { indices: vec![] }),
+        pallet_session: Some(SessionConfig {
+            keys: initial_authorities
+                .iter()
+                .map(|x| {
+                    (
+                        x.0.clone(),
+                        x.0.clone(),
+                        session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()),
+                    )
+                })
+                .collect::<Vec<_>>(),
+        }),
+        pallet_contracts: Some(ContractsConfig {
+            current_schedule: pallet_contracts::Schedule {
+                enable_println, // this should only be enabled on development chains
+                ..Default::default()
+            },
+        }),
         council: Some(CouncilConfig {
         council: Some(CouncilConfig {
             active_council: vec![],
             active_council: vec![],
             term_ends_at: 1,
             term_ends_at: 1,
@@ -251,9 +280,9 @@ pub fn testnet_genesis(
                 min_voting_stake: 1 * DOLLARS,
                 min_voting_stake: 1 * DOLLARS,
             },
             },
         }),
         }),
-        members: Some(MembersConfig {
+        membership: Some(MembersConfig {
             default_paid_membership_fee: 100u128,
             default_paid_membership_fee: 100u128,
-            members: crate::members_config::initial_members(),
+            members: vec![],
         }),
         }),
         forum: Some(crate::forum_config::from_serialized::create(
         forum: Some(crate::forum_config::from_serialized::create(
             endowed_accounts[0].clone(),
             endowed_accounts[0].clone(),
@@ -264,9 +293,12 @@ pub fn testnet_genesis(
         data_object_storage_registry: Some(DataObjectStorageRegistryConfig {
         data_object_storage_registry: Some(DataObjectStorageRegistryConfig {
             first_relationship_id: 1,
             first_relationship_id: 1,
         }),
         }),
-        actors: Some(ActorsConfig {
-            enable_storage_role: true,
-            request_life_time: 300,
+        working_group_Instance2: Some(StorageWorkingGroupConfig {
+            phantom: Default::default(),
+            storage_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,
         }),
         }),
         versioned_store: Some(VersionedStoreConfig {
         versioned_store: Some(VersionedStoreConfig {
             class_by_id: vec![],
             class_by_id: vec![],
@@ -293,14 +325,14 @@ pub fn testnet_genesis(
             next_principal_id: 0,
             next_principal_id: 0,
             channel_creation_enabled: true, // there is no extrinsic to change it so enabling at genesis
             channel_creation_enabled: true, // there is no extrinsic to change it so enabling at genesis
             unstaker_by_stake_id: vec![],
             unstaker_by_stake_id: vec![],
-            channel_handle_constraint: crate::forum_config::new_validation(5, 20),
-            channel_description_constraint: crate::forum_config::new_validation(1, 1024),
-            opening_human_readable_text: crate::forum_config::new_validation(1, 2048),
-            curator_application_human_readable_text: crate::forum_config::new_validation(1, 2048),
-            curator_exit_rationale_text: crate::forum_config::new_validation(1, 2048),
-            channel_avatar_constraint: crate::forum_config::new_validation(5, 1024),
-            channel_banner_constraint: crate::forum_config::new_validation(5, 1024),
-            channel_title_constraint: crate::forum_config::new_validation(5, 1024),
+            channel_handle_constraint: InputValidationLengthConstraint::new(5, 20),
+            channel_description_constraint: InputValidationLengthConstraint::new(1, 1024),
+            opening_human_readable_text: InputValidationLengthConstraint::new(1, 2048),
+            curator_application_human_readable_text: InputValidationLengthConstraint::new(1, 2048),
+            curator_exit_rationale_text: InputValidationLengthConstraint::new(1, 2048),
+            channel_avatar_constraint: InputValidationLengthConstraint::new(5, 1024),
+            channel_banner_constraint: InputValidationLengthConstraint::new(5, 1024),
+            channel_title_constraint: InputValidationLengthConstraint::new(5, 1024),
         }),
         }),
         migration: Some(MigrationConfig {}),
         migration: Some(MigrationConfig {}),
         proposals_codex: Some(ProposalsCodexConfig {
         proposals_codex: Some(ProposalsCodexConfig {
@@ -324,14 +356,107 @@ pub fn testnet_genesis(
             set_lead_proposal_grace_period: cpcp.set_lead_proposal_voting_period,
             set_lead_proposal_grace_period: cpcp.set_lead_proposal_voting_period,
             spending_proposal_voting_period: cpcp.spending_proposal_voting_period,
             spending_proposal_voting_period: cpcp.spending_proposal_voting_period,
             spending_proposal_grace_period: cpcp.spending_proposal_grace_period,
             spending_proposal_grace_period: cpcp.spending_proposal_grace_period,
-            evict_storage_provider_proposal_voting_period: cpcp
-                .evict_storage_provider_proposal_voting_period,
-            evict_storage_provider_proposal_grace_period: cpcp
-                .evict_storage_provider_proposal_grace_period,
-            set_storage_role_parameters_proposal_voting_period: cpcp
-                .set_storage_role_parameters_proposal_voting_period,
-            set_storage_role_parameters_proposal_grace_period: cpcp
-                .set_storage_role_parameters_proposal_grace_period,
+            add_working_group_opening_proposal_voting_period: cpcp
+                .add_working_group_opening_proposal_voting_period,
+            add_working_group_opening_proposal_grace_period: cpcp
+                .add_working_group_opening_proposal_grace_period,
+            begin_review_working_group_leader_applications_proposal_voting_period: cpcp
+                .begin_review_working_group_leader_applications_proposal_voting_period,
+            begin_review_working_group_leader_applications_proposal_grace_period: cpcp
+                .begin_review_working_group_leader_applications_proposal_grace_period,
+            fill_working_group_leader_opening_proposal_voting_period: cpcp
+                .fill_working_group_leader_opening_proposal_voting_period,
+            fill_working_group_leader_opening_proposal_grace_period: cpcp
+                .fill_working_group_leader_opening_proposal_grace_period,
+            set_working_group_mint_capacity_proposal_voting_period: cpcp
+                .set_content_working_group_mint_capacity_proposal_voting_period,
+            set_working_group_mint_capacity_proposal_grace_period: cpcp
+                .set_content_working_group_mint_capacity_proposal_grace_period,
+            decrease_working_group_leader_stake_proposal_voting_period: cpcp
+                .decrease_working_group_leader_stake_proposal_voting_period,
+            decrease_working_group_leader_stake_proposal_grace_period: cpcp
+                .decrease_working_group_leader_stake_proposal_grace_period,
+            slash_working_group_leader_stake_proposal_voting_period: cpcp
+                .slash_working_group_leader_stake_proposal_voting_period,
+            slash_working_group_leader_stake_proposal_grace_period: cpcp
+                .slash_working_group_leader_stake_proposal_grace_period,
+            set_working_group_leader_reward_proposal_voting_period: cpcp
+                .set_working_group_leader_reward_proposal_voting_period,
+            set_working_group_leader_reward_proposal_grace_period: cpcp
+                .set_working_group_leader_reward_proposal_grace_period,
+            terminate_working_group_leader_role_proposal_voting_period: cpcp
+                .terminate_working_group_leader_role_proposal_voting_period,
+            terminate_working_group_leader_role_proposal_grace_period: cpcp
+                .terminate_working_group_leader_role_proposal_grace_period,
         }),
         }),
     }
     }
 }
 }
+
+#[cfg(test)]
+pub(crate) mod tests {
+    use super::*;
+    use crate::service::{new_full, new_light};
+    use sc_service_test;
+
+    fn local_testnet_genesis_instant_single() -> GenesisConfig {
+        testnet_genesis(
+            vec![get_authority_keys_from_seed("Alice")],
+            get_account_id_from_seed::<sr25519::Public>("Alice"),
+            vec![get_authority_keys_from_seed("Alice").0],
+        )
+    }
+
+    /// Local testnet config (single validator - Alice)
+    pub fn integration_test_config_with_single_authority() -> ChainSpec {
+        ChainSpec::from_genesis(
+            "Integration Test",
+            "test",
+            ChainType::Development,
+            local_testnet_genesis_instant_single,
+            vec![],
+            None,
+            None,
+            None,
+            Default::default(),
+        )
+    }
+
+    fn local_testnet_genesis() -> GenesisConfig {
+        testnet_genesis(
+            vec![
+                get_authority_keys_from_seed("Alice"),
+                get_authority_keys_from_seed("Bob"),
+            ],
+            get_account_id_from_seed::<sr25519::Public>("Alice"),
+            vec![
+                get_authority_keys_from_seed("Alice").0,
+                get_authority_keys_from_seed("Bob").0,
+            ],
+        )
+    }
+
+    /// Local testnet config (multivalidator Alice + Bob)
+    pub fn integration_test_config_with_two_authorities() -> ChainSpec {
+        ChainSpec::from_genesis(
+            "Integration Test",
+            "test",
+            ChainType::Development,
+            local_testnet_genesis,
+            vec![],
+            None,
+            None,
+            None,
+            Default::default(),
+        )
+    }
+
+    #[test]
+    #[ignore]
+    fn test_connectivity() {
+        sc_service_test::connectivity(
+            integration_test_config_with_two_authorities(),
+            |config| new_full(config),
+            |config| new_light(config),
+        );
+    }
+}

+ 45 - 125
node/src/cli.rs

@@ -1,128 +1,48 @@
-use crate::chain_spec;
-use crate::new_full_start;
-use crate::service;
-use futures::{future, sync::oneshot, Future};
-use log::info;
-use std::cell::RefCell;
-pub use substrate_cli::{error, IntoExit, VersionInfo};
-use substrate_cli::{informant, parse_and_prepare, NoCustom, ParseAndPrepare};
-use substrate_service::{AbstractService, Configuration, Roles as ServiceRoles};
-use tokio::runtime::Runtime;
-
-/// Parse command line arguments into service configuration.
-pub fn run<I, T, E>(args: I, exit: E, version: VersionInfo) -> error::Result<()>
-where
-    I: IntoIterator<Item = T>,
-    T: Into<std::ffi::OsString> + Clone,
-    E: IntoExit,
-{
-    type Config<T> = Configuration<(), T>;
-    match parse_and_prepare::<NoCustom, NoCustom, _>(&version, "joystream-node", args) {
-        ParseAndPrepare::Run(cmd) => cmd.run(
-            load_spec,
-            exit,
-            |exit, _cli_args, _custom_args, config: Config<_>| {
-                info!("{}", version.name);
-                info!("  version {}", config.full_version());
-                info!("  by {}, 2019", version.author);
-                info!("Chain specification: {}", config.chain_spec.name());
-                info!("Node name: {}", config.name);
-                info!("Roles: {:?}", config.roles);
-                let runtime = Runtime::new().map_err(|e| format!("{:?}", e))?;
-                match config.roles {
-                    ServiceRoles::LIGHT => run_until_exit(
-                        runtime,
-                        service::new_light(config).map_err(|e| format!("{:?}", e))?,
-                        exit,
-                    ),
-                    _ => run_until_exit(
-                        runtime,
-                        service::new_full(config).map_err(|e| format!("{:?}", e))?,
-                        exit,
-                    ),
-                }
-                .map_err(|e| format!("{:?}", e))
-            },
-        ),
-        ParseAndPrepare::BuildSpec(cmd) => cmd.run::<NoCustom, _, _, _>(load_spec),
-        ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(
-            |config: Config<_>| Ok(new_full_start!(config).0),
-            load_spec,
-            exit,
-        ),
-        ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(
-            |config: Config<_>| Ok(new_full_start!(config).0),
-            load_spec,
-            exit,
-        ),
-        ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec),
-        ParseAndPrepare::RevertChain(cmd) => {
-            cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec)
-        }
-        ParseAndPrepare::CustomCommand(_) => Ok(()),
-    }?;
-
-    Ok(())
-}
-
-fn load_spec(id: &str) -> Result<Option<chain_spec::ChainSpec>, String> {
-    Ok(match chain_spec::Alternative::from(id) {
-        Some(spec) => Some(spec.load()?),
-        None => None,
-    })
-}
-
-fn run_until_exit<T, E>(mut runtime: Runtime, service: T, e: E) -> error::Result<()>
-where
-    T: AbstractService,
-    E: IntoExit,
-{
-    let (exit_send, exit) = exit_future::signal();
-
-    let informant = informant::build(&service);
-    runtime.executor().spawn(exit.until(informant).map(|_| ()));
-
-    // we eagerly drop the service so that the internal exit future is fired,
-    // but we need to keep holding a reference to the global telemetry guard
-    let _telemetry = service.telemetry();
-
-    let service_res = {
-        let exit = e
-            .into_exit()
-            .map_err(|_| error::Error::Other("Exit future failed.".into()));
-        let service = service.map_err(error::Error::Service);
-        let select = service.select(exit).map(|_| ()).map_err(|(err, _)| err);
-        runtime.block_on(select)
-    };
-
-    exit_send.fire();
-
-    // TODO [andre]: timeout this future #1318
-    let _ = runtime.shutdown_on_idle().wait();
-
-    service_res
+// Copyright 2019 Joystream Contributors
+// This file is part of Joystream node.
+
+// Joystream node is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Joystream node is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Joystream node.  If not, see <http://www.gnu.org/licenses/>.
+
+use sc_cli::RunCmd;
+use structopt::StructOpt;
+
+/// An overarching CLI command definition.
+#[derive(Debug, StructOpt)]
+pub struct Cli {
+    /// Possible subcommand with parameters.
+    #[structopt(subcommand)]
+    pub subcommand: Option<Subcommand>,
+    #[allow(missing_docs)]
+    #[structopt(flatten)]
+    pub run: RunCmd,
 }
 }
 
 
-// handles ctrl-c
-pub struct Exit;
-impl IntoExit for Exit {
-    type Exit = future::MapErr<oneshot::Receiver<()>, fn(oneshot::Canceled) -> ()>;
-    fn into_exit(self) -> Self::Exit {
-        // can't use signal directly here because CtrlC takes only `Fn`.
-        let (exit_send, exit) = oneshot::channel();
-
-        let exit_send_cell = RefCell::new(Some(exit_send));
-        ctrlc::set_handler(move || {
-            let exit_send = exit_send_cell
-                .try_borrow_mut()
-                .expect("signal handler not reentrant; qed")
-                .take();
-            if let Some(exit_send) = exit_send {
-                exit_send.send(()).expect("Error sending exit notification");
-            }
-        })
-        .expect("Error setting Ctrl-C handler");
-
-        exit.map_err(drop)
-    }
+/// Possible subcommands of the main binary.
+#[derive(Debug, StructOpt)]
+pub enum Subcommand {
+    /// A set of base subcommands handled by `sc_cli`.
+    #[structopt(flatten)]
+    Base(sc_cli::Subcommand),
+
+    /// The custom inspect subcommmand for decoding blocks and extrinsics.
+    #[structopt(
+        name = "inspect",
+        about = "Decode given block or extrinsic using current native runtime."
+    )]
+    Inspect(node_inspect::cli::InspectCmd),
+
+    /// The custom benchmark subcommmand benchmarking runtime pallets.
+    #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
+    Benchmark(frame_benchmarking_cli::BenchmarkCmd),
 }
 }

+ 100 - 0
node/src/command.rs

@@ -0,0 +1,100 @@
+// Copyright 2019 Joystream Contributors
+// This file is part of Joystream node.
+
+// Joystream node is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Joystream node is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Joystream node.  If not, see <http://www.gnu.org/licenses/>.
+
+use crate::cli::{Cli, Subcommand};
+use crate::node_executor;
+use crate::node_rpc;
+use crate::{chain_spec, service};
+
+use node_executor::Executor;
+use node_runtime::{opaque::Block, RuntimeApi};
+use sc_cli::{Result, SubstrateCli};
+use sc_finality_grandpa::{self as grandpa};
+
+impl SubstrateCli for Cli {
+    fn impl_name() -> &'static str {
+        "Joystream Node"
+    }
+
+    fn impl_version() -> &'static str {
+        "3.0.0"
+    }
+
+    fn description() -> &'static str {
+        "Joystream substrate node"
+    }
+
+    fn author() -> &'static str {
+        "Joystream contributors"
+    }
+
+    fn support_url() -> &'static str {
+        "https://www.joystream.org/"
+    }
+
+    fn copyright_start_year() -> i32 {
+        2019
+    }
+
+    fn executable_name() -> &'static str {
+        "joystream-node"
+    }
+
+    fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
+        Ok(match id {
+            "dev" => Box::new(chain_spec::Alternative::Development.load().unwrap()), //TODO
+            "local" => Box::new(chain_spec::Alternative::LocalTestnet.load().unwrap()),
+            path => Box::new(chain_spec::ChainSpec::from_json_file(
+                std::path::PathBuf::from(path),
+            )?),
+        })
+    }
+}
+
+/// Parse command line arguments into service configuration.
+pub fn run() -> Result<()> {
+    let cli = Cli::from_args();
+
+    match &cli.subcommand {
+        None => {
+            let runner = cli.create_runner(&cli.run)?;
+            runner.run_node(service::new_light, service::new_full, node_runtime::VERSION)
+        }
+        Some(Subcommand::Inspect(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+
+            runner.sync_run(|config| cmd.run::<Block, RuntimeApi, Executor>(config))
+        }
+        Some(Subcommand::Benchmark(cmd)) => {
+            if cfg!(feature = "runtime-benchmarks") {
+                let runner = cli.create_runner(cmd)?;
+
+                runner.sync_run(|config| cmd.run::<Block, Executor>(config))
+            } else {
+                println!(
+                    "Benchmarking wasn't enabled when building the node. \
+				You can enable it with `--features runtime-benchmarks`."
+                );
+                Ok(())
+            }
+        }
+        Some(Subcommand::Base(subcommand)) => {
+            let runner = cli.create_runner(subcommand)?;
+
+            runner.run_subcommand(subcommand, |config| Ok(new_full_start!(config).0))
+        }
+    }
+}

+ 2 - 2
node/src/forum_config/from_serialized.rs

@@ -19,7 +19,7 @@ struct ForumData {
 }
 }
 
 
 fn parse_forum_json() -> Result<ForumData> {
 fn parse_forum_json() -> Result<ForumData> {
-    let data = include_str!("../../res/forum_data_acropolis_serialized.json");
+    let data = include_str!("../../res/forum_data_empty.json");
     serde_json::from_str(data)
     serde_json::from_str(data)
 }
 }
 
 
@@ -40,12 +40,12 @@ pub fn create(forum_sudo: AccountId) -> ForumConfig {
         next_category_id,
         next_category_id,
         next_thread_id,
         next_thread_id,
         next_post_id,
         next_post_id,
-        forum_sudo,
         category_title_constraint: new_validation(10, 90),
         category_title_constraint: new_validation(10, 90),
         category_description_constraint: new_validation(10, 490),
         category_description_constraint: new_validation(10, 490),
         thread_title_constraint: new_validation(10, 90),
         thread_title_constraint: new_validation(10, 90),
         post_text_constraint: new_validation(10, 990),
         post_text_constraint: new_validation(10, 990),
         thread_moderation_rationale_constraint: new_validation(10, 290),
         thread_moderation_rationale_constraint: new_validation(10, 290),
         post_moderation_rationale_constraint: new_validation(10, 290),
         post_moderation_rationale_constraint: new_validation(10, 290),
+        forum_sudo,
     }
     }
 }
 }

+ 1 - 1
node/src/forum_config/mod.rs

@@ -3,7 +3,7 @@ pub mod from_serialized;
 // Not exported - only here as sample code
 // Not exported - only here as sample code
 // mod from_encoded;
 // mod from_encoded;
 
 
-use node_runtime::forum::InputValidationLengthConstraint;
+use node_runtime::common::constraints::InputValidationLengthConstraint;
 
 
 pub fn new_validation(min: u16, max_min_diff: u16) -> InputValidationLengthConstraint {
 pub fn new_validation(min: u16, max_min_diff: u16) -> InputValidationLengthConstraint {
     InputValidationLengthConstraint { min, max_min_diff }
     InputValidationLengthConstraint { min, max_min_diff }

+ 4 - 0
node/src/lib.rs

@@ -2,4 +2,8 @@ pub mod chain_spec;
 pub mod cli;
 pub mod cli;
 pub mod forum_config;
 pub mod forum_config;
 pub mod members_config;
 pub mod members_config;
+#[macro_use]
 pub mod service;
 pub mod service;
+pub mod command;
+pub mod node_executor;
+pub mod node_rpc;

+ 1 - 13
node/src/members_config.rs

@@ -1,7 +1,7 @@
 use serde::Deserialize;
 use serde::Deserialize;
 use serde_json::Result;
 use serde_json::Result;
 
 
-use primitives::crypto::{AccountId32, Ss58Codec};
+use sp_core::crypto::{AccountId32, Ss58Codec};
 
 
 #[derive(Deserialize)]
 #[derive(Deserialize)]
 struct Member {
 struct Member {
@@ -12,18 +12,6 @@ struct Member {
     about: String,
     about: String,
 }
 }
 
 
-// fn test_load_members() -> Result<Vec<Member>> {
-//     let data = r#"
-//         [{
-//             "address": "5Gn9n7SDJ7VgHqHQWYzkSA4vX6DCmS5TFWdHxikTXp9b4L32",
-//             "handle": "mokhtar",
-//             "avatar_uri": "http://mokhtar.net/avatar.png",
-//             "about": "Mokhtar"
-//         }]"#;
-
-//     serde_json::from_str(data)
-// }
-
 fn parse_members_json() -> Result<Vec<Member>> {
 fn parse_members_json() -> Result<Vec<Member>> {
     let data = include_str!("../res/acropolis_members.json");
     let data = include_str!("../res/acropolis_members.json");
     serde_json::from_str(data)
     serde_json::from_str(data)

+ 10 - 0
node/src/node_executor.rs

@@ -0,0 +1,10 @@
+use sc_executor::native_executor_instance;
+
+// Declare an instance of the native executor named `Executor`. Include the wasm binary as the
+// equivalent wasm code.
+native_executor_instance!(
+    pub Executor,
+    node_runtime::api::dispatch,
+    node_runtime::native_version,
+    frame_benchmarking::benchmarking::HostFunctions,
+);

+ 191 - 0
node/src/node_rpc.rs

@@ -0,0 +1,191 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! A collection of node-specific RPC methods.
+//!
+//! Since `substrate` core functionality makes no assumptions
+//! about the modules used inside the runtime, so do
+//! RPC methods defined in `sc-rpc` crate.
+//! It means that `client/rpc` can't have any methods that
+//! need some strong assumptions about the particular runtime.
+//!
+//! The RPCs available in this crate however can make some assumptions
+//! about how the runtime is constructed and what FRAME pallets
+//! are part of it. Therefore all node-runtime-specific RPCs can
+//! be placed here or imported from corresponding FRAME RPC definitions.
+
+#![warn(missing_docs)]
+
+use std::sync::Arc;
+
+use node_runtime::UncheckedExtrinsic;
+use node_runtime::{opaque::Block, AccountId, Balance, BlockNumber, Hash, Index};
+use sc_consensus_babe::{Config, Epoch};
+use sc_consensus_babe_rpc::BabeRpcHandler;
+use sc_consensus_epochs::SharedEpochChanges;
+use sc_finality_grandpa::{SharedAuthoritySet, SharedVoterState};
+use sc_finality_grandpa_rpc::GrandpaRpcHandler;
+use sc_keystore::KeyStorePtr;
+use sc_rpc_api::DenyUnsafe;
+use sp_api::ProvideRuntimeApi;
+use sp_block_builder::BlockBuilder;
+use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
+use sp_consensus::SelectChain;
+use sp_consensus_babe::BabeApi;
+use sp_transaction_pool::TransactionPool;
+
+/// Light client extra dependencies.
+pub struct LightDeps<C, F, P> {
+    /// The client instance to use.
+    pub client: Arc<C>,
+    /// Transaction pool instance.
+    pub pool: Arc<P>,
+    /// Remote access to the blockchain (async).
+    pub remote_blockchain: Arc<dyn sc_client_api::light::RemoteBlockchain<Block>>,
+    /// Fetcher instance.
+    pub fetcher: Arc<F>,
+}
+
+/// Extra dependencies for BABE.
+pub struct BabeDeps {
+    /// BABE protocol config.
+    pub babe_config: Config,
+    /// BABE pending epoch changes.
+    pub shared_epoch_changes: SharedEpochChanges<Block, Epoch>,
+    /// The keystore that manages the keys of the node.
+    pub keystore: KeyStorePtr,
+}
+
+/// Extra dependencies for GRANDPA
+pub struct GrandpaDeps {
+    /// Voting round info.
+    pub shared_voter_state: SharedVoterState,
+    /// Authority set info.
+    pub shared_authority_set: SharedAuthoritySet<Hash, BlockNumber>,
+}
+
+/// Full client dependencies.
+pub struct FullDeps<C, P, SC> {
+    /// The client instance to use.
+    pub client: Arc<C>,
+    /// Transaction pool instance.
+    pub pool: Arc<P>,
+    /// The SelectChain Strategy
+    pub select_chain: SC,
+    /// Whether to deny unsafe calls
+    pub deny_unsafe: DenyUnsafe,
+    /// BABE specific dependencies.
+    pub babe: BabeDeps,
+    /// GRANDPA specific dependencies.
+    pub grandpa: GrandpaDeps,
+}
+
+/// Instantiate all Full RPC extensions.
+pub fn create_full<C, P, M, SC>(deps: FullDeps<C, P, SC>) -> jsonrpc_core::IoHandler<M>
+where
+    C: ProvideRuntimeApi<Block>,
+    C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,
+    C: Send + Sync + 'static,
+    C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>,
+    C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber>,
+    C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<
+        Block,
+        Balance,
+        UncheckedExtrinsic,
+    >,
+    C::Api: BabeApi<Block>,
+    C::Api: BlockBuilder<Block>,
+    P: TransactionPool + 'static,
+    M: jsonrpc_core::Metadata + Default,
+    SC: SelectChain<Block> + 'static,
+{
+    use pallet_contracts_rpc::{Contracts, ContractsApi};
+    use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
+    use substrate_frame_rpc_system::{FullSystem, SystemApi};
+
+    let mut io = jsonrpc_core::IoHandler::default();
+    let FullDeps {
+        client,
+        pool,
+        select_chain,
+        deny_unsafe,
+        babe,
+        grandpa,
+    } = deps;
+    let BabeDeps {
+        keystore,
+        babe_config,
+        shared_epoch_changes,
+    } = babe;
+    let GrandpaDeps {
+        shared_voter_state,
+        shared_authority_set,
+    } = grandpa;
+
+    io.extend_with(SystemApi::to_delegate(FullSystem::new(
+        client.clone(),
+        pool,
+        deny_unsafe,
+    )));
+    // Making synchronous calls in light client freezes the browser currently,
+    // more context: https://github.com/paritytech/substrate/pull/3480
+    // These RPCs should use an asynchronous caller instead.
+    io.extend_with(ContractsApi::to_delegate(Contracts::new(client.clone())));
+    io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(
+        client.clone(),
+    )));
+    io.extend_with(sc_consensus_babe_rpc::BabeApi::to_delegate(
+        BabeRpcHandler::new(
+            client,
+            shared_epoch_changes,
+            keystore,
+            babe_config,
+            select_chain,
+            deny_unsafe,
+        ),
+    ));
+    io.extend_with(sc_finality_grandpa_rpc::GrandpaApi::to_delegate(
+        GrandpaRpcHandler::new(shared_authority_set, shared_voter_state),
+    ));
+
+    io
+}
+
+/// Instantiate all Light RPC extensions.
+pub fn create_light<C, P, M, F>(deps: LightDeps<C, F, P>) -> jsonrpc_core::IoHandler<M>
+where
+    C: sp_blockchain::HeaderBackend<Block>,
+    C: Send + Sync + 'static,
+    F: sc_client_api::light::Fetcher<Block> + 'static,
+    P: TransactionPool + 'static,
+    M: jsonrpc_core::Metadata + Default,
+{
+    use substrate_frame_rpc_system::{LightSystem, SystemApi};
+
+    let LightDeps {
+        client,
+        pool,
+        remote_blockchain,
+        fetcher,
+    } = deps;
+    let mut io = jsonrpc_core::IoHandler::default();
+    io.extend_with(SystemApi::<Hash, AccountId, Index>::to_delegate(
+        LightSystem::new(client, remote_blockchain, fetcher, pool),
+    ));
+
+    io
+}

+ 529 - 225
node/src/service.rs

@@ -16,107 +16,141 @@
 
 
 #![warn(unused_extern_crates)]
 #![warn(unused_extern_crates)]
 
 
-// Clippy linter warning.
-#![allow(clippy::type_complexity)] // disable it because this is foreign code and can be changed any time
-
-// Clippy linter warning.
-#![allow(clippy::redundant_closure_call)] // disable it because of the substrate lib design
-
-//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.
-
-use client_db::Backend;
-use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
-use inherents::InherentDataProviders;
-use network::{construct_simple_protocol, NetworkService};
-use node_runtime::{self, opaque::Block, GenesisConfig, RuntimeApi};
-use offchain::OffchainWorkers;
-use primitives::Blake2Hasher;
-use runtime_primitives::traits::Block as BlockT;
-use std::sync::Arc;
-use substrate_client::{Client, LocalCallExecutor, LongestChain};
-pub use substrate_executor::{native_executor_instance, NativeExecutor};
-use substrate_service::{
-    error::Error as ServiceError, AbstractService, Configuration, NetworkStatus, Service,
-    ServiceBuilder,
-};
-use transaction_pool::{self, txpool::Pool as TransactionPool};
+// Substrate implementation issue.
+#![allow(clippy::redundant_closure_call)]
 
 
-construct_simple_protocol! {
-    /// Demo protocol attachment for substrate.
-    pub struct NodeProtocol where Block = Block { }
-}
+//! Service implementation. Specialized wrapper over substrate service.
+
+use node_runtime::opaque::Block;
+use node_runtime::RuntimeApi;
+use sc_consensus::LongestChain;
+use sc_finality_grandpa::{
+    self as grandpa, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider,
+};
+use sc_service::{
+    config::Configuration, error::Error as ServiceError, AbstractService, ServiceBuilder,
+};
+use sp_inherents::InherentDataProviders;
+use std::sync::Arc;
 
 
-// Declare an instance of the native executor named `Executor`. Include the wasm binary as the
-// equivalent wasm code.
-native_executor_instance!(
-    pub Executor,
-    node_runtime::api::dispatch,
-    node_runtime::native_version
-);
+use crate::node_executor;
+use crate::node_rpc;
 
 
 /// Starts a `ServiceBuilder` for a full service.
 /// Starts a `ServiceBuilder` for a full service.
 ///
 ///
 /// Use this macro if you don't actually need the full service, but just the builder in order to
 /// Use this macro if you don't actually need the full service, but just the builder in order to
 /// be able to perform chain operations.
 /// be able to perform chain operations.
-#[macro_export]
 macro_rules! new_full_start {
 macro_rules! new_full_start {
     ($config:expr) => {{
     ($config:expr) => {{
-        // type RpcExtension = jsonrpc_core::IoHandler<substrate_rpc::Metadata>;
+        use std::sync::Arc;
+
         let mut import_setup = None;
         let mut import_setup = None;
-        let inherent_data_providers = inherents::InherentDataProviders::new();
+        let mut rpc_setup = None;
+        let inherent_data_providers = sp_inherents::InherentDataProviders::new();
 
 
-        let builder = substrate_service::ServiceBuilder::new_full::<
-            node_runtime::opaque::Block,
-            node_runtime::RuntimeApi,
-            crate::service::Executor,
+        let builder = sc_service::ServiceBuilder::new_full::<
+            Block,
+            RuntimeApi,
+            node_executor::Executor,
         >($config)?
         >($config)?
-        .with_select_chain(|_config, backend| {
-            Ok(substrate_client::LongestChain::new(backend.clone()))
-        })?
-        .with_transaction_pool(|config, client| {
-            Ok(transaction_pool::txpool::Pool::new(
-                config,
-                transaction_pool::FullChainApi::new(client),
+        .with_select_chain(|_config, backend| Ok(sc_consensus::LongestChain::new(backend.clone())))?
+        .with_transaction_pool(|builder| {
+            let pool_api = sc_transaction_pool::FullChainApi::new(builder.client().clone());
+            let config = builder.config();
+
+            Ok(sc_transaction_pool::BasicPool::new(
+                config.transaction_pool.clone(),
+                std::sync::Arc::new(pool_api),
+                builder.prometheus_registry(),
             ))
             ))
         })?
         })?
-        .with_import_queue(|_config, client, mut select_chain, _transaction_pool| {
-            let select_chain = select_chain
-                .take()
-                .ok_or_else(|| substrate_service::Error::SelectChainRequired)?;
-            let (grandpa_block_import, grandpa_link) =
-                grandpa::block_import::<_, _, _, node_runtime::RuntimeApi, _>(
+        .with_import_queue(
+            |_config,
+             client,
+             mut select_chain,
+             _transaction_pool,
+             spawn_task_handle,
+             prometheus_registry| {
+                let select_chain = select_chain
+                    .take()
+                    .ok_or_else(|| sc_service::Error::SelectChainRequired)?;
+                let (grandpa_block_import, grandpa_link) = grandpa::block_import(
                     client.clone(),
                     client.clone(),
-                    &*client,
+                    &(client.clone() as Arc<_>),
                     select_chain,
                     select_chain,
                 )?;
                 )?;
-            let justification_import = grandpa_block_import.clone();
-
-            let (block_import, babe_link) = babe::block_import(
-                babe::Config::get_or_compute(&*client)?,
-                grandpa_block_import,
-                client.clone(),
-                client.clone(),
-            )?;
-
-            let import_queue = babe::import_queue(
-                babe_link.clone(),
-                block_import.clone(),
-                Some(Box::new(justification_import)),
-                None,
-                client.clone(),
-                client,
-                inherent_data_providers.clone(),
-            )?;
-
-            import_setup = Some((block_import, grandpa_link, babe_link));
-            Ok(import_queue)
+                let justification_import = grandpa_block_import.clone();
+
+                let (block_import, babe_link) = sc_consensus_babe::block_import(
+                    sc_consensus_babe::Config::get_or_compute(&*client)?,
+                    grandpa_block_import,
+                    client.clone(),
+                )?;
+
+                let import_queue = sc_consensus_babe::import_queue(
+                    babe_link.clone(),
+                    block_import.clone(),
+                    Some(Box::new(justification_import)),
+                    None,
+                    client,
+                    inherent_data_providers.clone(),
+                    spawn_task_handle,
+                    prometheus_registry,
+                )?;
+
+                import_setup = Some((block_import, grandpa_link, babe_link));
+                Ok(import_queue)
+            },
+        )?
+        .with_rpc_extensions_builder(|builder| {
+            let grandpa_link = import_setup
+                .as_ref()
+                .map(|s| &s.1)
+                .expect("GRANDPA LinkHalf is present for full services or set up failed; qed.");
+
+            let shared_authority_set = grandpa_link.shared_authority_set().clone();
+            let shared_voter_state = grandpa::SharedVoterState::empty();
+
+            rpc_setup = Some((shared_voter_state.clone()));
+
+            let babe_link = import_setup
+                .as_ref()
+                .map(|s| &s.2)
+                .expect("BabeLink is present for full services or set up failed; qed.");
+
+            let babe_config = babe_link.config().clone();
+            let shared_epoch_changes = babe_link.epoch_changes().clone();
+
+            let client = builder.client().clone();
+            let pool = builder.pool().clone();
+            let select_chain = builder
+                .select_chain()
+                .cloned()
+                .expect("SelectChain is present for full services or set up failed; qed.");
+            let keystore = builder.keystore().clone();
+
+            Ok(move |deny_unsafe| {
+                let deps = node_rpc::FullDeps {
+                    client: client.clone(),
+                    pool: pool.clone(),
+                    select_chain: select_chain.clone(),
+                    deny_unsafe,
+                    babe: node_rpc::BabeDeps {
+                        babe_config: babe_config.clone(),
+                        shared_epoch_changes: shared_epoch_changes.clone(),
+                        keystore: keystore.clone(),
+                    },
+                    grandpa: node_rpc::GrandpaDeps {
+                        shared_voter_state: shared_voter_state.clone(),
+                        shared_authority_set: shared_authority_set.clone(),
+                    },
+                };
+
+                node_rpc::create_full(deps)
+            })
         })?;
         })?;
-        // We don't have any custom rpc commands...
-        // .with_rpc_extensions(|client, pool| -> RpcExtension {
-        // 	node_rpc::create(client, pool)
-        // })?;
 
 
-        (builder, import_setup, inherent_data_providers)
+        (builder, import_setup, inherent_data_providers, rpc_setup)
     }};
     }};
 }
 }
 
 
@@ -126,58 +160,57 @@ macro_rules! new_full_start {
 /// concrete types instead.
 /// concrete types instead.
 macro_rules! new_full {
 macro_rules! new_full {
 	($config:expr, $with_startup_data: expr) => {{
 	($config:expr, $with_startup_data: expr) => {{
-		use futures::sync::mpsc;
-		use network::DhtEvent;
+		use futures::prelude::*;
+		use sc_network::Event;
+		use sc_client_api::ExecutorProvider;
+		use sp_core::traits::BareCryptoStorePtr;
 
 
 		let (
 		let (
-			is_authority,
+			role,
 			force_authoring,
 			force_authoring,
 			name,
 			name,
-			disable_grandpa
+			disable_grandpa,
 		) = (
 		) = (
-			$config.roles.is_authority(),
+			$config.role.clone(),
 			$config.force_authoring,
 			$config.force_authoring,
-			$config.name.clone(),
-			$config.disable_grandpa
+			$config.network.node_name.clone(),
+			$config.disable_grandpa,
 		);
 		);
 
 
-        // sentry nodes announce themselves as authorities to the network
-		// and should run the same protocols authorities do, but it should
-		// never actively participate in any consensus process.
-        let participates_in_consensus = is_authority && !$config.sentry_mode;
+		let (builder, mut import_setup, inherent_data_providers, mut rpc_setup) =
+			new_full_start!($config);
 
 
-		let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config);
-
-		// Dht event channel from the network to the authority discovery module. Use bounded channel to ensure
-		// back-pressure. Authority discovery is triggering one event per authority within the current authority set.
-		// This estimates the authority set size to be somewhere below 10 000 thereby setting the channel buffer size to
-		// 10 000.
-		let (dht_event_tx, _dht_event_rx) =
-			mpsc::channel::<DhtEvent>(10_000);
-
-		let service = builder.with_network_protocol(|_| Ok(crate::service::NodeProtocol::new()))?
-			.with_finality_proof_provider(|client, backend|
-				Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, client)) as _)
-			)?
-			.with_dht_event_tx(dht_event_tx)?
-			.build()?;
+		let service = builder
+			.with_finality_proof_provider(|client, backend| {
+				// GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
+				let provider = client as Arc<dyn grandpa::StorageAndProofProvider<_, _>>;
+				Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, provider)) as _)
+			})?
+			.build_full()?;
 
 
 		let (block_import, grandpa_link, babe_link) = import_setup.take()
 		let (block_import, grandpa_link, babe_link) = import_setup.take()
-				.expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
+			.expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
+
+		let shared_voter_state = rpc_setup.take()
+			.expect("The SharedVoterState is present for Full Services or setup failed before. qed");
 
 
 		($with_startup_data)(&block_import, &babe_link);
 		($with_startup_data)(&block_import, &babe_link);
 
 
-		if participates_in_consensus {
-			let proposer = substrate_basic_authorship::ProposerFactory {
-				client: service.client(),
-				transaction_pool: service.transaction_pool(),
-			};
+		if let sc_service::config::Role::Authority { .. } = &role {
+			let proposer = sc_basic_authorship::ProposerFactory::new(
+				service.client(),
+				service.transaction_pool(),
+				service.prometheus_registry().as_ref(),
+			);
 
 
 			let client = service.client();
 			let client = service.client();
 			let select_chain = service.select_chain()
 			let select_chain = service.select_chain()
-				.ok_or(substrate_service::Error::SelectChainRequired)?;
+				.ok_or(sc_service::Error::SelectChainRequired)?;
+
+			let can_author_with =
+				sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
 
 
-			let babe_config = babe::BabeParams {
+			let babe_config = sc_consensus_babe::BabeParams {
 				keystore: service.keystore(),
 				keystore: service.keystore(),
 				client,
 				client,
 				select_chain,
 				select_chain,
@@ -187,62 +220,95 @@ macro_rules! new_full {
 				inherent_data_providers: inherent_data_providers.clone(),
 				inherent_data_providers: inherent_data_providers.clone(),
 				force_authoring,
 				force_authoring,
 				babe_link,
 				babe_link,
+				can_author_with,
 			};
 			};
 
 
-			let babe = babe::start_babe(babe_config)?;
-			service.spawn_essential_task(babe);
-        }
+			let babe = sc_consensus_babe::start_babe(babe_config)?;
+			service.spawn_essential_task_handle().spawn_blocking("babe-proposer", babe);
+		}
+
+		// Spawn authority discovery module.
+		if matches!(role, sc_service::config::Role::Authority{..} | sc_service::config::Role::Sentry {..}) {
+			let (sentries, authority_discovery_role) = match role {
+				sc_service::config::Role::Authority { ref sentry_nodes } => (
+					sentry_nodes.clone(),
+					sc_authority_discovery::Role::Authority (
+						service.keystore(),
+					),
+				),
+				sc_service::config::Role::Sentry {..} => (
+					vec![],
+					sc_authority_discovery::Role::Sentry,
+				),
+				_ => unreachable!("Due to outer matches! constraint; qed.")
+			};
+
+			let network = service.network();
+			let dht_event_stream = network.event_stream("authority-discovery").filter_map(|e| async move { match e {
+				Event::Dht(e) => Some(e),
+				_ => None,
+			}}).boxed();
+			let authority_discovery = sc_authority_discovery::AuthorityDiscovery::new(
+				service.client(),
+				network,
+				sentries,
+				dht_event_stream,
+				authority_discovery_role,
+				service.prometheus_registry(),
+			);
+
+			service.spawn_task_handle().spawn("authority-discovery", authority_discovery);
+		}
 
 
-        // if the node isn't actively participating in consensus then it doesn't
+		// if the node isn't actively participating in consensus then it doesn't
 		// need a keystore, regardless of which protocol we use below.
 		// need a keystore, regardless of which protocol we use below.
-		let keystore = if participates_in_consensus {
-			Some(service.keystore())
+		let keystore = if role.is_authority() {
+			Some(service.keystore() as BareCryptoStorePtr)
 		} else {
 		} else {
 			None
 			None
-        };
-
-        let config = grandpa::Config {
-            // FIXME #1578 make this available through chainspec
-            gossip_duration: std::time::Duration::from_millis(333),
-            justification_period: 512,
-            name: Some(name),
-            observer_enabled: true,
-            keystore,
-            is_authority,
-        };
-
-		match (is_authority, disable_grandpa) {
-			(false, false) => {
-				// start the lightweight GRANDPA observer
-				service.spawn_task(Box::new(grandpa::run_grandpa_observer(
-					config,
-					grandpa_link,
-					service.network(),
-					service.on_exit(),
-				)?));
-			},
-			(true, false) => {
-				// start the full GRANDPA voter
-				let grandpa_config = grandpa::GrandpaParams {
-					config,
-					link: grandpa_link,
-					network: service.network(),
-					inherent_data_providers: inherent_data_providers.clone(),
-					on_exit: service.on_exit(),
-					telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
-					voting_rule: grandpa::VotingRulesBuilder::default().build(),
-                };
-                // the GRANDPA voter task is considered infallible, i.e.
-				// if it fails we take down the service with it.
-				service.spawn_essential_task(grandpa::run_grandpa_voter(grandpa_config)?);
-			},
-			(_, true) => {
-				grandpa::setup_disabled_grandpa(
-					service.client(),
-					&inherent_data_providers,
-					service.network(),
-				)?;
-			},
+		};
+
+		let config = grandpa::Config {
+			// FIXME #1578 make this available through chainspec
+			gossip_duration: std::time::Duration::from_millis(333),
+			justification_period: 512,
+			name: Some(name),
+			observer_enabled: false,
+			keystore,
+			is_authority: role.is_network_authority(),
+		};
+
+		let enable_grandpa = !disable_grandpa;
+		if enable_grandpa {
+			// start the full GRANDPA voter
+			// NOTE: non-authorities could run the GRANDPA observer protocol, but at
+			// this point the full voter should provide better guarantees of block
+			// and vote data availability than the observer. The observer has not
+			// been tested extensively yet and having most nodes in a network run it
+			// could lead to finality stalls.
+			let grandpa_config = grandpa::GrandpaParams {
+				config,
+				link: grandpa_link,
+				network: service.network(),
+				inherent_data_providers: inherent_data_providers.clone(),
+				telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
+				voting_rule: grandpa::VotingRulesBuilder::default().build(),
+				prometheus_registry: service.prometheus_registry(),
+				shared_voter_state,
+			};
+
+			// the GRANDPA voter task is considered infallible, i.e.
+			// if it fails we take down the service with it.
+			service.spawn_essential_task_handle().spawn_blocking(
+				"grandpa-voter",
+				grandpa::run_grandpa_voter(grandpa_config)?
+			);
+		} else {
+			grandpa::setup_disabled_grandpa(
+				service.client(),
+				&inherent_data_providers,
+				service.network(),
+			)?;
 		}
 		}
 
 
 		Ok((service, inherent_data_providers))
 		Ok((service, inherent_data_providers))
@@ -252,70 +318,49 @@ macro_rules! new_full {
 	}}
 	}}
 }
 }
 
 
-#[allow(dead_code)]
-type ConcreteBlock = node_runtime::opaque::Block;
-#[allow(dead_code)]
-type ConcreteClient = Client<
-    Backend<ConcreteBlock>,
-    LocalCallExecutor<Backend<ConcreteBlock>, NativeExecutor<Executor>>,
-    ConcreteBlock,
-    node_runtime::RuntimeApi,
->;
-#[allow(dead_code)]
-type ConcreteBackend = Backend<ConcreteBlock>;
-
-/// A specialized configuration object for setting up the node..
-pub type NodeConfiguration<C> =
-    Configuration<C, GenesisConfig /*, crate::chain_spec::Extensions*/>;
-
 /// Builds a new service for a full client.
 /// Builds a new service for a full client.
-pub fn new_full<C: Send + Default + 'static>(config: NodeConfiguration<C>)
--> Result<
-	Service<
-		ConcreteBlock,
-		ConcreteClient,
-		LongestChain<ConcreteBackend, ConcreteBlock>,
-		NetworkStatus<ConcreteBlock>,
-		NetworkService<ConcreteBlock, crate::service::NodeProtocol, <ConcreteBlock as BlockT>::Hash>,
-		TransactionPool<transaction_pool::FullChainApi<ConcreteClient, ConcreteBlock>>,
-		OffchainWorkers<
-			ConcreteClient,
-			<ConcreteBackend as substrate_client::backend::Backend<Block, Blake2Hasher>>::OffchainStorage,
-			ConcreteBlock,
-		>
-	>,
-	ServiceError,
->
-{
+pub fn new_full(config: Configuration) -> Result<impl AbstractService, ServiceError> {
     new_full!(config).map(|(service, _)| service)
     new_full!(config).map(|(service, _)| service)
 }
 }
 
 
 /// Builds a new service for a light client.
 /// Builds a new service for a light client.
-pub fn new_light<C: Send + Default + 'static>(
-    config: NodeConfiguration<C>,
-) -> Result<impl AbstractService, ServiceError> {
-    // type RpcExtension = jsonrpc_core::IoHandler<substrate_rpc::Metadata>;
+pub fn new_light(config: Configuration) -> Result<impl AbstractService, ServiceError> {
     let inherent_data_providers = InherentDataProviders::new();
     let inherent_data_providers = InherentDataProviders::new();
 
 
-    let service = ServiceBuilder::new_light::<Block, RuntimeApi, Executor>(config)?
+    let service = ServiceBuilder::new_light::<Block, RuntimeApi, node_executor::Executor>(config)?
         .with_select_chain(|_config, backend| Ok(LongestChain::new(backend.clone())))?
         .with_select_chain(|_config, backend| Ok(LongestChain::new(backend.clone())))?
-        .with_transaction_pool(|config, client| {
-            Ok(TransactionPool::new(
-                config,
-                transaction_pool::FullChainApi::new(client),
-            ))
+        .with_transaction_pool(|builder| {
+            let fetcher = builder
+                .fetcher()
+                .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
+            let pool_api =
+                sc_transaction_pool::LightChainApi::new(builder.client().clone(), fetcher);
+            let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
+                builder.config().transaction_pool.clone(),
+                Arc::new(pool_api),
+                builder.prometheus_registry(),
+                sc_transaction_pool::RevalidationType::Light,
+            );
+            Ok(pool)
         })?
         })?
         .with_import_queue_and_fprb(
         .with_import_queue_and_fprb(
-            |_config, client, backend, fetcher, _select_chain, _tx_pool| {
+            |_config,
+             client,
+             backend,
+             fetcher,
+             _select_chain,
+             _tx_pool,
+             spawn_task_handle,
+             registry| {
                 let fetch_checker = fetcher
                 let fetch_checker = fetcher
                     .map(|fetcher| fetcher.checker().clone())
                     .map(|fetcher| fetcher.checker().clone())
                     .ok_or_else(|| {
                     .ok_or_else(|| {
                         "Trying to start light import queue without active fetch checker"
                         "Trying to start light import queue without active fetch checker"
                     })?;
                     })?;
-                let grandpa_block_import = grandpa::light_block_import::<_, _, _, RuntimeApi>(
+                let grandpa_block_import = grandpa::light_block_import(
                     client.clone(),
                     client.clone(),
                     backend,
                     backend,
-                    &*client,
+                    &(client.clone() as Arc<_>),
                     Arc::new(fetch_checker),
                     Arc::new(fetch_checker),
                 )?;
                 )?;
 
 
@@ -323,35 +368,294 @@ pub fn new_light<C: Send + Default + 'static>(
                 let finality_proof_request_builder =
                 let finality_proof_request_builder =
                     finality_proof_import.create_finality_proof_request_builder();
                     finality_proof_import.create_finality_proof_request_builder();
 
 
-                let (babe_block_import, babe_link) = babe::block_import(
-                    babe::Config::get_or_compute(&*client)?,
+                let (babe_block_import, babe_link) = sc_consensus_babe::block_import(
+                    sc_consensus_babe::Config::get_or_compute(&*client)?,
                     grandpa_block_import,
                     grandpa_block_import,
                     client.clone(),
                     client.clone(),
-                    client.clone(),
                 )?;
                 )?;
 
 
-                let import_queue = babe::import_queue(
+                let import_queue = sc_consensus_babe::import_queue(
                     babe_link,
                     babe_link,
                     babe_block_import,
                     babe_block_import,
                     None,
                     None,
                     Some(Box::new(finality_proof_import)),
                     Some(Box::new(finality_proof_import)),
-                    client.clone(),
                     client,
                     client,
                     inherent_data_providers.clone(),
                     inherent_data_providers.clone(),
+                    spawn_task_handle,
+                    registry,
                 )?;
                 )?;
 
 
                 Ok((import_queue, finality_proof_request_builder))
                 Ok((import_queue, finality_proof_request_builder))
             },
             },
         )?
         )?
-        .with_network_protocol(|_| Ok(NodeProtocol::new()))?
         .with_finality_proof_provider(|client, backend| {
         .with_finality_proof_provider(|client, backend| {
-            Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _)
+            // GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
+            let provider = client as Arc<dyn StorageAndProofProvider<_, _>>;
+            Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
+        })?
+        .with_rpc_extensions(|builder| {
+            let fetcher = builder
+                .fetcher()
+                .ok_or_else(|| "Trying to start node RPC without active fetcher")?;
+            let remote_blockchain = builder
+                .remote_backend()
+                .ok_or_else(|| "Trying to start node RPC without active remote blockchain")?;
+
+            let light_deps = node_rpc::LightDeps {
+                remote_blockchain,
+                fetcher,
+                client: builder.client().clone(),
+                pool: builder.pool(),
+            };
+
+            Ok(node_rpc::create_light(light_deps))
         })?
         })?
-        // We don't have any custom rpc extensions
-        // .with_rpc_extensions(|client, pool| -> RpcExtension {
-        // 	node_rpc::create(client, pool)
-        // })?
-        .build()?;
+        .build_light()?;
 
 
     Ok(service)
     Ok(service)
 }
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::node_executor;
+    use crate::node_rpc;
+    use crate::service::{new_full, new_light};
+    use codec::{Decode, Encode};
+    use node_runtime::RuntimeApi;
+    use node_runtime::{currency::CENTS, SLOT_DURATION};
+    use node_runtime::{opaque::Block, DigestItem, Signature};
+    use node_runtime::{Address, BalancesCall, Call, UncheckedExtrinsic};
+    use sc_consensus_babe::{BabeIntermediate, CompatibleDigestItem, INTERMEDIATE_KEY};
+    use sc_consensus_epochs::descendent_query;
+    use sc_finality_grandpa::{self as grandpa};
+    use sc_service::AbstractService;
+    use sp_consensus::{
+        BlockImport, BlockImportParams, BlockOrigin, Environment, ForkChoiceStrategy, Proposer,
+        RecordProof,
+    };
+    use sp_core::{crypto::Pair as CryptoPair, H256};
+    use sp_finality_tracker;
+    use sp_keyring::AccountKeyring;
+    use sp_runtime::traits::IdentifyAccount;
+    use sp_runtime::{
+        generic::{BlockId, Digest, Era, SignedPayload},
+        traits::Verify,
+        traits::{Block as BlockT, Header as HeaderT},
+        OpaqueExtrinsic,
+    };
+    use sp_timestamp;
+    use sp_transaction_pool::{ChainEvent, MaintainedTransactionPool};
+    use std::{any::Any, borrow::Cow, sync::Arc};
+
+    type AccountPublic = <Signature as Verify>::Signer;
+
+    // Long running test. Run it locally only after the node changes.
+    #[test]
+    // It is "ignored", but the node-cli ignored tests are running on the CI.
+    // This can be run locally with `cargo test --release -p node-cli test_sync -- --ignored`.
+    #[ignore]
+    fn test_sync() {
+        let keystore_path = tempfile::tempdir().expect("Creates keystore path");
+        let keystore =
+            sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore");
+        let alice = keystore
+            .write()
+            .insert_ephemeral_from_seed::<sc_consensus_babe::AuthorityPair>("//Alice")
+            .expect("Creates authority pair");
+
+        let chain_spec = crate::chain_spec::tests::integration_test_config_with_single_authority();
+
+        // For the block factory
+        let mut slot_num = 1u64;
+
+        // For the extrinsics factory
+        let bob = Arc::new(AccountKeyring::Bob.pair());
+        let charlie = Arc::new(AccountKeyring::Charlie.pair());
+        let mut index = 0;
+
+        sc_service_test::sync(
+            chain_spec,
+            |config| {
+                let mut setup_handles = None;
+                new_full!(
+                    config,
+                    |block_import: &sc_consensus_babe::BabeBlockImport<Block, _, _>,
+                     babe_link: &sc_consensus_babe::BabeLink<Block>| {
+                        setup_handles = Some((block_import.clone(), babe_link.clone()));
+                    }
+                )
+                .map(move |(node, x)| (node, (x, setup_handles.unwrap())))
+            },
+            |config| new_light(config),
+            |service, &mut (ref inherent_data_providers, (ref mut block_import, ref babe_link))| {
+                let mut inherent_data = inherent_data_providers
+                    .create_inherent_data()
+                    .expect("Creates inherent data.");
+                inherent_data.replace_data(sp_finality_tracker::INHERENT_IDENTIFIER, &1u64);
+
+                let parent_id = BlockId::number(service.client().chain_info().best_number);
+                let parent_header = service.client().header(&parent_id).unwrap().unwrap();
+                let parent_hash = parent_header.hash();
+                let parent_number = *parent_header.number();
+
+                futures::executor::block_on(service.transaction_pool().maintain(
+                    ChainEvent::NewBlock {
+                        is_new_best: true,
+                        hash: parent_header.hash(),
+                        tree_route: None,
+                        header: parent_header.clone(),
+                    },
+                ));
+
+                let mut proposer_factory = sc_basic_authorship::ProposerFactory::new(
+                    service.client(),
+                    service.transaction_pool(),
+                    None,
+                );
+
+                let epoch_descriptor = babe_link
+                    .epoch_changes()
+                    .lock()
+                    .epoch_descriptor_for_child_of(
+                        descendent_query(&*service.client()),
+                        &parent_hash,
+                        parent_number,
+                        slot_num,
+                    )
+                    .unwrap()
+                    .unwrap();
+
+                let mut digest = Digest::<H256>::default();
+
+                // even though there's only one authority some slots might be empty,
+                // so we must keep trying the next slots until we can claim one.
+                let babe_pre_digest = loop {
+                    inherent_data.replace_data(
+                        sp_timestamp::INHERENT_IDENTIFIER,
+                        &(slot_num * SLOT_DURATION),
+                    );
+                    if let Some(babe_pre_digest) = sc_consensus_babe::test_helpers::claim_slot(
+                        slot_num,
+                        &parent_header,
+                        &*service.client(),
+                        &keystore,
+                        &babe_link,
+                    ) {
+                        break babe_pre_digest;
+                    }
+
+                    slot_num += 1;
+                };
+
+                digest.push(<DigestItem as CompatibleDigestItem>::babe_pre_digest(
+                    babe_pre_digest,
+                ));
+
+                let new_block = futures::executor::block_on(async move {
+                    let proposer = proposer_factory.init(&parent_header).await;
+                    proposer
+                        .unwrap()
+                        .propose(
+                            inherent_data,
+                            digest,
+                            std::time::Duration::from_secs(1),
+                            RecordProof::Yes,
+                        )
+                        .await
+                })
+                .expect("Error making test block")
+                .block;
+
+                let (new_header, new_body) = new_block.deconstruct();
+                let pre_hash = new_header.hash();
+                // sign the pre-sealed hash of the block and then
+                // add it to a digest item.
+                let to_sign = pre_hash.encode();
+                let signature = alice.sign(&to_sign[..]);
+                let item = <DigestItem as CompatibleDigestItem>::babe_seal(signature.into());
+                slot_num += 1;
+
+                let mut params = BlockImportParams::new(BlockOrigin::File, new_header);
+                params.post_digests.push(item);
+                params.body = Some(new_body);
+                params.intermediates.insert(
+                    Cow::from(INTERMEDIATE_KEY),
+                    Box::new(BabeIntermediate::<Block> { epoch_descriptor }) as Box<dyn Any>,
+                );
+                params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
+
+                block_import
+                    .import_block(params, Default::default())
+                    .expect("error importing test block");
+            },
+            |service, _| {
+                let amount = 5 * CENTS;
+                let to: Address = AccountPublic::from(bob.public()).into_account().into();
+                let from: Address = AccountPublic::from(charlie.public()).into_account().into();
+                let genesis_hash = service.client().block_hash(0).unwrap().unwrap();
+                let best_block_id = BlockId::number(service.client().chain_info().best_number);
+                let (spec_version, transaction_version) = {
+                    let version = service.client().runtime_version_at(&best_block_id).unwrap();
+                    (version.spec_version, version.transaction_version)
+                };
+                let signer = charlie.clone();
+
+                let function = Call::Balances(BalancesCall::transfer(to.into(), amount));
+
+                let check_spec_version = frame_system::CheckSpecVersion::new();
+                let check_tx_version = frame_system::CheckTxVersion::new();
+                let check_genesis = frame_system::CheckGenesis::new();
+                let check_era = frame_system::CheckEra::from(Era::Immortal);
+                let check_nonce = frame_system::CheckNonce::from(index);
+                let check_weight = frame_system::CheckWeight::new();
+                let payment = pallet_transaction_payment::ChargeTransactionPayment::from(0);
+                let validate_grandpa_equivocation =
+                    pallet_grandpa::ValidateEquivocationReport::new();
+                let extra = (
+                    check_spec_version,
+                    check_tx_version,
+                    check_genesis,
+                    check_era,
+                    check_nonce,
+                    check_weight,
+                    payment,
+                    validate_grandpa_equivocation,
+                );
+                let raw_payload = SignedPayload::from_raw(
+                    function,
+                    extra,
+                    (
+                        spec_version,
+                        transaction_version,
+                        genesis_hash,
+                        genesis_hash,
+                        (),
+                        (),
+                        (),
+                        (),
+                    ),
+                );
+                let signature = raw_payload.using_encoded(|payload| signer.sign(payload));
+                let (function, extra, _) = raw_payload.deconstruct();
+                let xt =
+                    UncheckedExtrinsic::new_signed(function, from.into(), signature.into(), extra)
+                        .encode();
+                let v: Vec<u8> = Decode::decode(&mut xt.as_slice()).unwrap();
+
+                index += 1;
+                OpaqueExtrinsic(v)
+            },
+        );
+    }
+
+    #[test]
+    #[ignore]
+    fn test_consensus() {
+        sc_service_test::consensus(
+            crate::chain_spec::tests::integration_test_config_with_two_authorities(),
+            |config| new_full(config),
+            |config| new_light(config),
+            vec!["//Alice".into(), "//Bob".into()],
+        )
+    }
+}

+ 4 - 1
package.json

@@ -1,11 +1,12 @@
 {
 {
   "private": true,
   "private": true,
   "name": "joystream",
   "name": "joystream",
+  "version": "1.0.0",
   "license": "GPL-3.0-only",
   "license": "GPL-3.0-only",
   "scripts": {
   "scripts": {
     "test": "yarn && yarn workspaces run test",
     "test": "yarn && yarn workspaces run test",
     "test-migration": "yarn && yarn workspaces run test-migration",
     "test-migration": "yarn && yarn workspaces run test-migration",
-    "postinstall": "yarn workspace @joystream/types build",
+    "postinstall": "yarn workspace @joystream/types build && yarn workspace storage-node run build",
     "cargo-checks": "devops/git-hooks/pre-commit && devops/git-hooks/pre-push",
     "cargo-checks": "devops/git-hooks/pre-commit && devops/git-hooks/pre-push",
     "cargo-build": "scripts/cargo-build.sh",
     "cargo-build": "scripts/cargo-build.sh",
     "lint": "yarn workspaces run lint"
     "lint": "yarn workspaces run lint"
@@ -16,6 +17,8 @@
     "types",
     "types",
     "pioneer",
     "pioneer",
     "pioneer/packages/*",
     "pioneer/packages/*",
+    "storage-node",
+    "storage-node/packages/*",
     "devops/eslint-config",
     "devops/eslint-config",
     "devops/prettier-config"
     "devops/prettier-config"
   ],
   ],

+ 1 - 0
pioneer/.eslintrc.js

@@ -17,6 +17,7 @@ module.exports = {
     'react/prop-types': 'off',
     'react/prop-types': 'off',
     'new-cap': 'off',
     'new-cap': 'off',
     '@typescript-eslint/interface-name-prefix': 'off',
     '@typescript-eslint/interface-name-prefix': 'off',
+    '@typescript-eslint/ban-ts-comment': 'error',
     // why only required in VSCode!?!? is eslint plugin not working like eslint commandline?
     // why only required in VSCode!?!? is eslint plugin not working like eslint commandline?
     // Or are we having to add this because of new versions of eslint-config-* ?
     // Or are we having to add this because of new versions of eslint-config-* ?
     'no-console': 'off',
     'no-console': 'off',

+ 1 - 1
pioneer/package.json

@@ -82,6 +82,6 @@
     "node-sass": "^4.13.0",
     "node-sass": "^4.13.0",
     "sass-loader": "^8.0.0",
     "sass-loader": "^8.0.0",
     "style-loader": "^1.0.0",
     "style-loader": "^1.0.0",
-    "@joystream/types": "^0.10.0"
+    "@joystream/types": "./types"
   }
   }
 }
 }

+ 0 - 2
pioneer/packages/apps-routing/src/index.ts

@@ -13,7 +13,6 @@ import media from './joy-media';
 import members from './joy-members';
 import members from './joy-members';
 import proposals from './joy-proposals';
 import proposals from './joy-proposals';
 import roles from './joy-roles';
 import roles from './joy-roles';
-import storageRoles from './joy-storage';
 import pages from './joy-pages';
 import pages from './joy-pages';
 
 
 // import template from './123code';
 // import template from './123code';
@@ -46,7 +45,6 @@ routes = routes.concat(
   proposals,
   proposals,
   election,
   election,
   forum,
   forum,
-  storageRoles,
   members,
   members,
   staking,
   staking,
   null,
   null,

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

@@ -7,7 +7,8 @@ export default ([
     Component: Roles,
     Component: Roles,
     display: {
     display: {
       needsApi: [
       needsApi: [
-        'query.actors.actorAccountIds'
+        'query.contentWorkingGroup.mint',
+        'query.storageWorkingGroup.mint'
       ]
       ]
     },
     },
     i18n: {
     i18n: {

+ 0 - 17
pioneer/packages/apps-routing/src/joy-storage.ts

@@ -1,17 +0,0 @@
-import { Routes } from './types';
-
-import Storage from '@polkadot/joy-storage/index';
-
-export default [
-  {
-    Component: Storage,
-    display: {
-      needsApi: ['query.actors.actorAccountIds']
-    },
-    i18n: {
-      defaultValue: 'Storage'
-    },
-    icon: 'database',
-    name: 'storage'
-  }
-] as Routes;

+ 1 - 1
pioneer/packages/apps/src/SideBar/Item.tsx

@@ -20,7 +20,7 @@ import { Option } from '@polkadot/types';
 import translate from '../translate';
 import translate from '../translate';
 
 
 import { queryToProp } from '@polkadot/joy-utils/index';
 import { queryToProp } from '@polkadot/joy-utils/index';
-import { ElectionStage } from '@joystream/types/';
+import { ElectionStage } from '@joystream/types/council';
 import { councilSidebarName } from '@polkadot/apps-routing/joy-election';
 import { councilSidebarName } from '@polkadot/apps-routing/joy-election';
 
 
 interface Props extends I18nProps {
 interface Props extends I18nProps {

+ 1 - 1
pioneer/packages/joy-election/src/Applicant.tsx

@@ -11,7 +11,7 @@ import CandidatePreview from './CandidatePreview';
 
 
 import translate from './translate';
 import translate from './translate';
 import { calcTotalStake } from '@polkadot/joy-utils/index';
 import { calcTotalStake } from '@polkadot/joy-utils/index';
-import { Stake } from '@joystream/types/';
+import { Stake } from '@joystream/types/council';
 
 
 type Props = ApiProps & I18nProps & {
 type Props = ApiProps & I18nProps & {
   index: number;
   index: number;

+ 1 - 1
pioneer/packages/joy-election/src/ApplyForm.tsx

@@ -10,7 +10,7 @@ import { Balance } from '@polkadot/types/interfaces';
 import translate from './translate';
 import translate from './translate';
 import TxButton from '@polkadot/joy-utils/TxButton';
 import TxButton from '@polkadot/joy-utils/TxButton';
 import InputStake from '@polkadot/joy-utils/InputStake';
 import InputStake from '@polkadot/joy-utils/InputStake';
-import { Stake } from '@joystream/types/';
+import { Stake } from '@joystream/types/council';
 import { calcTotalStake, ZERO } from '@polkadot/joy-utils/index';
 import { calcTotalStake, ZERO } from '@polkadot/joy-utils/index';
 import { MyAddressProps, withOnlyMembers } from '@polkadot/joy-utils/MyAccount';
 import { MyAddressProps, withOnlyMembers } from '@polkadot/joy-utils/MyAccount';
 
 

+ 1 - 1
pioneer/packages/joy-election/src/Council.tsx

@@ -8,7 +8,7 @@ import { formatBalance } from '@polkadot/util';
 import CouncilCandidate from './CandidatePreview';
 import CouncilCandidate from './CandidatePreview';
 
 
 import { calcBackersStake } from '@polkadot/joy-utils/index';
 import { calcBackersStake } from '@polkadot/joy-utils/index';
-import { Seat } from '@joystream/types/';
+import { Seat } from '@joystream/types/council';
 import translate from './translate';
 import translate from './translate';
 import Section from '@polkadot/joy-utils/Section';
 import Section from '@polkadot/joy-utils/Section';
 
 

+ 1 - 1
pioneer/packages/joy-election/src/Dashboard.tsx

@@ -11,7 +11,7 @@ import { formatNumber, formatBalance } from '@polkadot/util';
 
 
 import Section from '@polkadot/joy-utils/Section';
 import Section from '@polkadot/joy-utils/Section';
 import { queryToProp } from '@polkadot/joy-utils/index';
 import { queryToProp } from '@polkadot/joy-utils/index';
-import { ElectionStage, Seat } from '@joystream/types/';
+import { ElectionStage, Seat } from '@joystream/types/council';
 import translate from './translate';
 import translate from './translate';
 
 
 type Props = ApiProps & I18nProps & {
 type Props = ApiProps & I18nProps & {

+ 1 - 1
pioneer/packages/joy-election/src/SealedVote.tsx

@@ -10,7 +10,7 @@ import { formatBalance } from '@polkadot/util';
 
 
 import translate from './translate';
 import translate from './translate';
 import { calcTotalStake } from '@polkadot/joy-utils/index';
 import { calcTotalStake } from '@polkadot/joy-utils/index';
-import { SealedVote } from '@joystream/types/';
+import { SealedVote } from '@joystream/types/council';
 import AddressMini from '@polkadot/react-components/AddressMiniJoy';
 import AddressMini from '@polkadot/react-components/AddressMiniJoy';
 import CandidatePreview from './CandidatePreview';
 import CandidatePreview from './CandidatePreview';
 import { findVoteByHash } from './myVotesStore';
 import { findVoteByHash } from './myVotesStore';

+ 1 - 1
pioneer/packages/joy-election/src/index.tsx

@@ -18,7 +18,7 @@ import Applicants from './Applicants';
 import Votes from './Votes';
 import Votes from './Votes';
 import Reveals from './Reveals';
 import Reveals from './Reveals';
 import { queryToProp } from '@polkadot/joy-utils/index';
 import { queryToProp } from '@polkadot/joy-utils/index';
-import { Seat } from '@joystream/types/';
+import { Seat } from '@joystream/types/council';
 
 
 // define out internal types
 // define out internal types
 type Props = AppProps & ApiProps & I18nProps & {
 type Props = AppProps & ApiProps & I18nProps & {

+ 2 - 1
pioneer/packages/joy-forum/src/CategoryList.tsx

@@ -7,7 +7,8 @@ import orderBy from 'lodash/orderBy';
 import BN from 'bn.js';
 import BN from 'bn.js';
 
 
 import { Option, bool } from '@polkadot/types';
 import { Option, bool } from '@polkadot/types';
-import { CategoryId, Category, ThreadId, Thread } from '@joystream/types/forum';
+import { ThreadId } from '@joystream/types/common';
+import { CategoryId, Category, Thread } from '@joystream/types/forum';
 import { ViewThread } from './ViewThread';
 import { ViewThread } from './ViewThread';
 import { MutedSpan } from '@polkadot/joy-utils/MutedText';
 import { MutedSpan } from '@polkadot/joy-utils/MutedText';
 import { UrlHasIdProps, CategoryCrumbs, Pagination, ThreadsPerPage, usePagination } from './utils';
 import { UrlHasIdProps, CategoryCrumbs, Pagination, ThreadsPerPage, usePagination } from './utils';

+ 4 - 3
pioneer/packages/joy-forum/src/Context.tsx

@@ -2,7 +2,8 @@
 // NOTE: The purpose of this context is to immitate a Substrate storage for the forum until it's implemented as a substrate runtime module.
 // NOTE: The purpose of this context is to immitate a Substrate storage for the forum until it's implemented as a substrate runtime module.
 
 
 import React, { useReducer, createContext, useContext } from 'react';
 import React, { useReducer, createContext, useContext } from 'react';
-import { Category, Thread, Reply, ModerationAction, BlockchainTimestamp } from '@joystream/types/forum';
+import { Category, Thread, Reply, ModerationAction } from '@joystream/types/forum';
+import { BlockAndTime } from '@joystream/types/common';
 import { Option, Text, GenericAccountId } from '@polkadot/types';
 import { Option, Text, GenericAccountId } from '@polkadot/types';
 
 
 type CategoryId = number;
 type CategoryId = number;
@@ -220,7 +221,7 @@ function reducer (state: ForumState, action: ForumAction): ForumState {
 
 
       const thread = threadById.get(id) as Thread;
       const thread = threadById.get(id) as Thread;
       const moderation = new ModerationAction({
       const moderation = new ModerationAction({
-        moderated_at: BlockchainTimestamp.newEmpty(),
+        moderated_at: BlockAndTime.newEmpty(),
         moderator_id: new GenericAccountId(moderator),
         moderator_id: new GenericAccountId(moderator),
         rationale: new Text(rationale)
         rationale: new Text(rationale)
       });
       });
@@ -285,7 +286,7 @@ function reducer (state: ForumState, action: ForumAction): ForumState {
 
 
       const reply = replyById.get(id) as Reply;
       const reply = replyById.get(id) as Reply;
       const moderation = new ModerationAction({
       const moderation = new ModerationAction({
-        moderated_at: BlockchainTimestamp.newEmpty(),
+        moderated_at: BlockAndTime.newEmpty(),
         moderator_id: new GenericAccountId(moderator),
         moderator_id: new GenericAccountId(moderator),
         rationale: new Text(rationale)
         rationale: new Text(rationale)
       });
       });

+ 2 - 1
pioneer/packages/joy-forum/src/EditReply.tsx

@@ -10,7 +10,8 @@ import { withMulti } from '@polkadot/react-api/with';
 
 
 import * as JoyForms from '@polkadot/joy-utils/forms';
 import * as JoyForms from '@polkadot/joy-utils/forms';
 import { Text } from '@polkadot/types';
 import { Text } from '@polkadot/types';
-import { PostId, Post, ThreadId } from '@joystream/types/forum';
+import { PostId, ThreadId } from '@joystream/types/common';
+import { Post } from '@joystream/types/forum';
 import { withOnlyMembers } from '@polkadot/joy-utils/MyAccount';
 import { withOnlyMembers } from '@polkadot/joy-utils/MyAccount';
 import Section from '@polkadot/joy-utils/Section';
 import Section from '@polkadot/joy-utils/Section';
 import { useMyAccount } from '@polkadot/joy-utils/MyAccountContext';
 import { useMyAccount } from '@polkadot/joy-utils/MyAccountContext';

+ 2 - 1
pioneer/packages/joy-forum/src/EditThread.tsx

@@ -12,7 +12,8 @@ import { withMulti } from '@polkadot/react-api/with';
 
 
 import * as JoyForms from '@polkadot/joy-utils/forms';
 import * as JoyForms from '@polkadot/joy-utils/forms';
 import { Text } from '@polkadot/types';
 import { Text } from '@polkadot/types';
-import { ThreadId, Thread, CategoryId } from '@joystream/types/forum';
+import { ThreadId } from '@joystream/types/common';
+import { Thread, CategoryId } from '@joystream/types/forum';
 import { withOnlyMembers } from '@polkadot/joy-utils/MyAccount';
 import { withOnlyMembers } from '@polkadot/joy-utils/MyAccount';
 import Section from '@polkadot/joy-utils/Section';
 import Section from '@polkadot/joy-utils/Section';
 import { useMyAccount } from '@polkadot/joy-utils/MyAccountContext';
 import { useMyAccount } from '@polkadot/joy-utils/MyAccountContext';

+ 2 - 1
pioneer/packages/joy-forum/src/ForumRoot.tsx

@@ -6,7 +6,8 @@ import BN from 'bn.js';
 
 
 import Section from '@polkadot/joy-utils/Section';
 import Section from '@polkadot/joy-utils/Section';
 import { withMulti, withApi } from '@polkadot/react-api';
 import { withMulti, withApi } from '@polkadot/react-api';
-import { PostId, Post, Thread } from '@joystream/types/forum';
+import { PostId } from '@joystream/types/common';
+import { Post, Thread } from '@joystream/types/forum';
 import { bnToStr } from '@polkadot/joy-utils/';
 import { bnToStr } from '@polkadot/joy-utils/';
 import { ApiProps } from '@polkadot/react-api/types';
 import { ApiProps } from '@polkadot/react-api/types';
 import { MemberPreview } from '@polkadot/joy-members/MemberPreview';
 import { MemberPreview } from '@polkadot/joy-members/MemberPreview';

+ 2 - 1
pioneer/packages/joy-forum/src/Moderate.tsx

@@ -9,7 +9,8 @@ import { withMulti } from '@polkadot/react-api/with';
 
 
 import * as JoyForms from '@polkadot/joy-utils/forms';
 import * as JoyForms from '@polkadot/joy-utils/forms';
 import { Text } from '@polkadot/types';
 import { Text } from '@polkadot/types';
-import { ReplyId, ThreadId } from '@joystream/types/forum';
+import { ThreadId } from '@joystream/types/common';
+import { ReplyId } from '@joystream/types/forum';
 import Section from '@polkadot/joy-utils/Section';
 import Section from '@polkadot/joy-utils/Section';
 import { withOnlyForumSudo } from './ForumSudo';
 import { withOnlyForumSudo } from './ForumSudo';
 import { ValidationProps, withPostModerationValidation } from './validation';
 import { ValidationProps, withPostModerationValidation } from './validation';

+ 2 - 1
pioneer/packages/joy-forum/src/ViewThread.tsx

@@ -5,7 +5,8 @@ import styled from 'styled-components';
 import { Table, Button, Label, Icon } from 'semantic-ui-react';
 import { Table, Button, Label, Icon } from 'semantic-ui-react';
 import BN from 'bn.js';
 import BN from 'bn.js';
 
 
-import { Category, Thread, ThreadId, Post, PostId } from '@joystream/types/forum';
+import { ThreadId, PostId } from '@joystream/types/common';
+import { Category, Thread, Post } from '@joystream/types/forum';
 import { Pagination, RepliesPerPage, CategoryCrumbs, TimeAgoDate, usePagination, useQueryParam, ReplyIdxQueryParam, ReplyEditIdQueryParam } from './utils';
 import { Pagination, RepliesPerPage, CategoryCrumbs, TimeAgoDate, usePagination, useQueryParam, ReplyIdxQueryParam, ReplyEditIdQueryParam } from './utils';
 import { ViewReply } from './ViewReply';
 import { ViewReply } from './ViewReply';
 import { Moderate } from './Moderate';
 import { Moderate } from './Moderate';

+ 2 - 1
pioneer/packages/joy-forum/src/utils.tsx

@@ -6,7 +6,8 @@ import styled from 'styled-components';
 import moment from 'moment';
 import moment from 'moment';
 import Tooltip from 'react-tooltip';
 import Tooltip from 'react-tooltip';
 
 
-import { Category, CategoryId, Thread, ThreadId } from '@joystream/types/forum';
+import { ThreadId } from '@joystream/types/common';
+import { Category, CategoryId, Thread } from '@joystream/types/forum';
 import { withForumCalls } from './calls';
 import { withForumCalls } from './calls';
 import { withMulti } from '@polkadot/react-api';
 import { withMulti } from '@polkadot/react-api';
 
 

+ 1 - 1
pioneer/packages/joy-forum/src/validation.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import React from 'react';
 import { withMulti } from '@polkadot/react-api/with';
 import { withMulti } from '@polkadot/react-api/with';
-import { InputValidationLengthConstraint } from '@joystream/types/forum';
+import { InputValidationLengthConstraint } from '@joystream/types/common';
 import { withForumCalls } from './calls';
 import { withForumCalls } from './calls';
 import { componentName } from '@polkadot/joy-utils/react/helpers';
 import { componentName } from '@polkadot/joy-utils/react/helpers';
 
 

+ 5 - 5
pioneer/packages/joy-media/src/DiscoveryProvider.tsx

@@ -2,7 +2,7 @@ import React, { useState, useEffect, useContext, createContext } from 'react';
 import { Message } from 'semantic-ui-react';
 import { Message } from 'semantic-ui-react';
 import axios, { CancelToken } from 'axios';
 import axios, { CancelToken } from 'axios';
 
 
-import { AccountId } from '@polkadot/types/interfaces';
+import { StorageProviderId } from '@joystream/types/working-group';
 import { Vec } from '@polkadot/types';
 import { Vec } from '@polkadot/types';
 import { Url } from '@joystream/types/discovery';
 import { Url } from '@joystream/types/discovery';
 import ApiContext from '@polkadot/react-api/ApiContext';
 import ApiContext from '@polkadot/react-api/ApiContext';
@@ -15,8 +15,8 @@ export type BootstrapNodes = {
 };
 };
 
 
 export type DiscoveryProvider = {
 export type DiscoveryProvider = {
-  resolveAssetEndpoint: (provider: AccountId, contentId?: string, cancelToken?: CancelToken) => Promise<string>;
-  reportUnreachable: (provider: AccountId) => void;
+  resolveAssetEndpoint: (provider: StorageProviderId, contentId?: string, cancelToken?: CancelToken) => Promise<string>;
+  reportUnreachable: (provider: StorageProviderId) => void;
 };
 };
 
 
 export type DiscoveryProviderProps = {
 export type DiscoveryProviderProps = {
@@ -41,7 +41,7 @@ type ProviderStats = {
 function newDiscoveryProvider ({ bootstrapNodes }: BootstrapNodes): DiscoveryProvider {
 function newDiscoveryProvider ({ bootstrapNodes }: BootstrapNodes): DiscoveryProvider {
   const stats: Map<string, ProviderStats> = new Map();
   const stats: Map<string, ProviderStats> = new Map();
 
 
-  const resolveAssetEndpoint = async (storageProvider: AccountId, contentId?: string, cancelToken?: CancelToken) => {
+  const resolveAssetEndpoint = async (storageProvider: StorageProviderId, contentId?: string, cancelToken?: CancelToken) => {
     const providerKey = storageProvider.toString();
     const providerKey = storageProvider.toString();
 
 
     let stat = stats.get(providerKey);
     let stat = stats.get(providerKey);
@@ -98,7 +98,7 @@ function newDiscoveryProvider ({ bootstrapNodes }: BootstrapNodes): DiscoveryPro
     throw new Error('Resolving failed.');
     throw new Error('Resolving failed.');
   };
   };
 
 
-  const reportUnreachable = (provider: AccountId) => {
+  const reportUnreachable = (provider: StorageProviderId) => {
     const key = provider.toString();
     const key = provider.toString();
     const stat = stats.get(key);
     const stat = stats.get(key);
     if (stat) {
     if (stat) {

+ 11 - 11
pioneer/packages/joy-media/src/Upload.tsx

@@ -11,12 +11,11 @@ import { SubmittableResult } from '@polkadot/api';
 import { Option } from '@polkadot/types/codec';
 import { Option } from '@polkadot/types/codec';
 import { withMulti, withApi } from '@polkadot/react-api';
 import { withMulti, withApi } from '@polkadot/react-api';
 import { formatNumber } from '@polkadot/util';
 import { formatNumber } from '@polkadot/util';
-import { AccountId } from '@polkadot/types/interfaces';
 
 
 import translate from './translate';
 import translate from './translate';
 import { fileNameWoExt } from './utils';
 import { fileNameWoExt } from './utils';
 import { ContentId, DataObject } from '@joystream/types/media';
 import { ContentId, DataObject } from '@joystream/types/media';
-import { withMembershipRequired } from '@polkadot/joy-utils/MyAccount';
+import { withOnlyMembers, MyAccountProps } from '@polkadot/joy-utils/MyAccount';
 import { DiscoveryProviderProps, withDiscoveryProvider } from './DiscoveryProvider';
 import { DiscoveryProviderProps, withDiscoveryProvider } from './DiscoveryProvider';
 import TxButton from '@polkadot/joy-utils/TxButton';
 import TxButton from '@polkadot/joy-utils/TxButton';
 import IpfsHash from 'ipfs-only-hash';
 import IpfsHash from 'ipfs-only-hash';
@@ -24,11 +23,12 @@ import { ChannelId } from '@joystream/types/content-working-group';
 import { EditVideoView } from './upload/EditVideo.view';
 import { EditVideoView } from './upload/EditVideo.view';
 import { JoyInfo } from '@polkadot/joy-utils/JoyStatus';
 import { JoyInfo } from '@polkadot/joy-utils/JoyStatus';
 import { IterableFile } from './IterableFile';
 import { IterableFile } from './IterableFile';
+import { StorageProviderId } from '@joystream/types/working-group';
 
 
 const MAX_FILE_SIZE_MB = 500;
 const MAX_FILE_SIZE_MB = 500;
 const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
 const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
 
 
-type Props = ApiProps & I18nProps & DiscoveryProviderProps & {
+type Props = ApiProps & I18nProps & DiscoveryProviderProps & MyAccountProps & {
   channelId: ChannelId;
   channelId: ChannelId;
   history?: History;
   history?: History;
   match: {
   match: {
@@ -62,7 +62,7 @@ const defaultState = (): State => ({
   cancelSource: axios.CancelToken.source()
   cancelSource: axios.CancelToken.source()
 });
 });
 
 
-class Component extends React.PureComponent<Props, State> {
+class Upload extends React.PureComponent<Props, State> {
   state = defaultState();
   state = defaultState();
 
 
   componentWillUnmount () {
   componentWillUnmount () {
@@ -107,8 +107,8 @@ class Component extends React.PureComponent<Props, State> {
   private resetForm = () => {
   private resetForm = () => {
     const { cancelSource } = this.state;
     const { cancelSource } = this.state;
     this.setState({
     this.setState({
-      cancelSource,
-      ...defaultState()
+      ...defaultState(),
+      cancelSource
     });
     });
   }
   }
 
 
@@ -248,8 +248,8 @@ class Component extends React.PureComponent<Props, State> {
 
 
     // TODO get corresponding data type id based on file content
     // TODO get corresponding data type id based on file content
     const dataObjectTypeId = new BN(1);
     const dataObjectTypeId = new BN(1);
-
-    return [newContentId, dataObjectTypeId, new BN(file.size), ipfs_cid];
+    const { myMemberId } = this.props;
+    return [myMemberId, newContentId, dataObjectTypeId, new BN(file.size), ipfs_cid];
   }
   }
 
 
   private onDataObjectCreated = async (_txResult: SubmittableResult) => {
   private onDataObjectCreated = async (_txResult: SubmittableResult) => {
@@ -285,7 +285,7 @@ class Component extends React.PureComponent<Props, State> {
     }
     }
   }
   }
 
 
-  private uploadFileTo = async (storageProvider: AccountId) => {
+  private uploadFileTo = async (storageProvider: StorageProviderId) => {
     const { file, newContentId, cancelSource } = this.state;
     const { file, newContentId, cancelSource } = this.state;
     if (!file || !file.size) {
     if (!file || !file.size) {
       this.setState({
       this.setState({
@@ -349,9 +349,9 @@ class Component extends React.PureComponent<Props, State> {
 }
 }
 
 
 export const UploadWithRouter = withMulti(
 export const UploadWithRouter = withMulti(
-  Component,
+  Upload,
   translate,
   translate,
   withApi,
   withApi,
-  withMembershipRequired,
+  withOnlyMembers,
   withDiscoveryProvider
   withDiscoveryProvider
 );
 );

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