Browse Source

Merge branch 'olympia' into council_olympia

ondratra 4 years ago
parent
commit
4af4d7224c
100 changed files with 1907 additions and 11326 deletions
  1. 9 16
      .env
  2. 1 1
      .github/workflows/content-directory-schemas.yml
  3. 1 1
      .github/workflows/joystream-node-docker.yml
  4. 4 4
      .github/workflows/run-network-tests.yml
  5. 113 295
      Cargo.lock
  6. 2 6
      Cargo.toml
  7. 0 8698
      _Cargo.lock
  8. 3 3
      build.sh
  9. 225 63
      cli/README.md
  10. 1 1
      cli/package.json
  11. 0 3
      cli/src/@types/@ffmpeg-installer/ffmpeg/index.d.ts
  12. 3 0
      cli/src/@types/@ffprobe-installer/ffprobe/index.d.ts
  13. 5 2
      cli/src/base/AccountsCommandBase.ts
  14. 33 13
      cli/src/base/ContentDirectoryCommandBase.ts
  15. 10 5
      cli/src/base/MediaCommandBase.ts
  16. 19 4
      cli/src/commands/account/choose.ts
  17. 3 3
      cli/src/commands/content-directory/addClassSchema.ts
  18. 3 3
      cli/src/commands/content-directory/createClass.ts
  19. 2 2
      cli/src/commands/content-directory/entity.ts
  20. 15 8
      cli/src/commands/content-directory/initialize.ts
  21. 2 2
      cli/src/commands/content-directory/updateClassPermissions.ts
  22. 12 7
      cli/src/commands/media/createChannel.ts
  23. 3 3
      cli/src/commands/media/curateContent.ts
  24. 36 0
      cli/src/commands/media/featuredVideos.ts
  25. 2 2
      cli/src/commands/media/myChannels.ts
  26. 1 1
      cli/src/commands/media/myVideos.ts
  27. 3 3
      cli/src/commands/media/removeChannel.ts
  28. 1 1
      cli/src/commands/media/removeVideo.ts
  29. 79 0
      cli/src/commands/media/setFeaturedVideos.ts
  30. 7 6
      cli/src/commands/media/updateChannel.ts
  31. 4 4
      cli/src/commands/media/updateVideo.ts
  32. 2 2
      cli/src/commands/media/updateVideoLicense.ts
  33. 131 73
      cli/src/commands/media/uploadVideo.ts
  34. 11 7
      cli/src/helpers/InputOutput.ts
  35. 40 35
      cli/src/helpers/JsonSchemaPrompt.ts
  36. 1 1
      cli/src/helpers/display.ts
  37. 20 20
      content-directory-schemas/README.md
  38. 5 5
      content-directory-schemas/examples/createChannel.ts
  39. 6 6
      content-directory-schemas/examples/createChannelWithoutTransaction.ts
  40. 6 6
      content-directory-schemas/examples/createVideo.ts
  41. 5 5
      content-directory-schemas/examples/updateChannelTitle.ts
  42. 6 6
      content-directory-schemas/examples/updateChannelTitleWithoutTransaction.ts
  43. 6 0
      content-directory-schemas/inputs/classes/FeaturedVideoClass.json
  44. 18 0
      content-directory-schemas/inputs/classes/index.js
  45. 0 13
      content-directory-schemas/inputs/entityBatches/ChannelBatch.json
  46. 48 6
      content-directory-schemas/inputs/entityBatches/KnownLicenseBatch.json
  47. 0 63
      content-directory-schemas/inputs/entityBatches/VideoBatch.json
  48. 5 6
      content-directory-schemas/inputs/schemas/ChannelSchema.json
  49. 12 0
      content-directory-schemas/inputs/schemas/FeaturedVideoSchema.json
  50. 9 0
      content-directory-schemas/inputs/schemas/KnownLicenseSchema.json
  51. 6 0
      content-directory-schemas/inputs/schemas/LicenseSchema.json
  52. 2 3
      content-directory-schemas/inputs/schemas/VideoSchema.json
  53. 3 3
      content-directory-schemas/package.json
  54. 2 7
      content-directory-schemas/scripts/initializeContentDir.ts
  55. 1 1
      content-directory-schemas/scripts/inputSchemasToEntitySchemas.ts
  56. 4 8
      content-directory-schemas/src/helpers/InputParser.ts
  57. 25 5
      content-directory-schemas/src/helpers/inputs.ts
  58. 1 1
      content-directory-schemas/src/index.ts
  59. 25 15
      docker-compose.yml
  60. 0 391
      node/src/chain_spec/content_config.rs
  61. 2 1
      node/src/chain_spec/forum_config.rs
  62. 5 58
      node/src/chain_spec/mod.rs
  63. 2 2
      package.json
  64. 0 62
      query-node/.env
  65. 5 1
      query-node/README.md
  66. 19 1
      query-node/build.sh
  67. 13 0
      query-node/db-migrate.sh
  68. 64 57
      query-node/mappings/content-directory/content-dir-consts.ts
  69. 29 13
      query-node/mappings/content-directory/decode.ts
  70. 105 46
      query-node/mappings/content-directory/entity/create.ts
  71. 29 3
      query-node/mappings/content-directory/entity/index.ts
  72. 69 46
      query-node/mappings/content-directory/entity/remove.ts
  73. 105 33
      query-node/mappings/content-directory/entity/update.ts
  74. 69 40
      query-node/mappings/content-directory/get-or-create.ts
  75. 1 1
      query-node/mappings/content-directory/mapping.ts
  76. 45 21
      query-node/mappings/content-directory/transaction.ts
  77. 19 9
      query-node/mappings/types.ts
  78. 6 7
      query-node/package.json
  79. 15 0
      query-node/processor-start.sh
  80. 21 10
      query-node/run-tests.sh
  81. 80 32
      query-node/schema.graphql
  82. 0 974
      query-node/typedefs.json
  83. 2 1
      runtime-modules/constitution/Cargo.toml
  84. 55 0
      runtime-modules/constitution/src/benchmarking.rs
  85. 22 2
      runtime-modules/constitution/src/lib.rs
  86. 7 0
      runtime-modules/constitution/src/tests/mocks.rs
  87. 1 1
      runtime-modules/constitution/src/tests/mod.rs
  88. 102 45
      runtime-modules/content-directory/src/lib.rs
  89. 2 1
      runtime-modules/content-directory/src/mock.rs
  90. 1 1
      runtime-modules/content-directory/src/tests.rs
  91. 1 1
      runtime-modules/content-directory/src/tests/add_class_schema.rs
  92. 1 1
      runtime-modules/content-directory/src/tests/add_curator_group.rs
  93. 1 1
      runtime-modules/content-directory/src/tests/add_curator_to_group.rs
  94. 1 1
      runtime-modules/content-directory/src/tests/add_maintainer_to_class.rs
  95. 1 1
      runtime-modules/content-directory/src/tests/clear_entity_property_vector.rs
  96. 1 1
      runtime-modules/content-directory/src/tests/create_class.rs
  97. 1 1
      runtime-modules/content-directory/src/tests/create_entity.rs
  98. 1 1
      runtime-modules/content-directory/src/tests/insert_at_entity_property_vector.rs
  99. 1 1
      runtime-modules/content-directory/src/tests/remove_at_entity_property_vector.rs
  100. 1 1
      runtime-modules/content-directory/src/tests/remove_curator_from_group.rs

+ 9 - 16
.env

@@ -1,17 +1,14 @@
 COMPOSE_PROJECT_NAME=joystream
 COMPOSE_PROJECT_NAME=joystream
+PROJECT_NAME=query_node
 
 
-###########################
-#     Common settings     #
-###########################
-
-# The env variables below are by default used by all services and should be
-# overriden in local env files (e.g. ./generated/indexer) if needed
-# DB config
-DB_NAME=query_node
+# We will use a single postgres service with multiple databases
+INDEXER_DB_NAME=query_node_indexer
+PROCESSOR_DB_NAME=query_node_processor
 DB_USER=postgres
 DB_USER=postgres
 DB_PASS=postgres
 DB_PASS=postgres
 DB_HOST=localhost
 DB_HOST=localhost
 DB_PORT=5432
 DB_PORT=5432
+
 DEBUG=index-builder:*
 DEBUG=index-builder:*
 TYPEORM_LOGGING=error
 TYPEORM_LOGGING=error
 
 
@@ -20,16 +17,12 @@ TYPEORM_LOGGING=error
 ###########################
 ###########################
 
 
 # Substrate endpoint to source events from
 # Substrate endpoint to source events from
-WS_PROVIDER_ENDPOINT_URI=ws://joystream-node:9944/
+WS_PROVIDER_ENDPOINT_URI=ws://localhost:9944/
+
 # Block height to start indexing from.
 # Block height to start indexing from.
 # Note, that if there are already some indexed events, this setting is ignored
 # Note, that if there are already some indexed events, this setting is ignored
 BLOCK_HEIGHT=0
 BLOCK_HEIGHT=0
 
 
-# Custom types to register for Substrate API
-# TYPE_REGISTER_PACKAGE_NAME=
-# TYPE_REGISTER_PACKAGE_VERSION=
-# TYPE_REGISTER_FUNCTION=
-
 # Redis cache server
 # Redis cache server
 REDIS_URI=redis://localhost:6379/0
 REDIS_URI=redis://localhost:6379/0
 
 
@@ -38,10 +31,10 @@ REDIS_URI=redis://localhost:6379/0
 ###########################
 ###########################
 
 
 # Where the mapping scripts are located, relative to ./generated/indexer
 # Where the mapping scripts are located, relative to ./generated/indexer
-TYPES_JSON=../../typedefs.json
+TYPES_JSON=../../../types/augment/all/defs.json
 
 
 # Indexer GraphQL API endpoint to fetch indexed events
 # Indexer GraphQL API endpoint to fetch indexed events
-INDEXER_ENDPOINT_URL=http://localhost:4100/graphql
+INDEXER_ENDPOINT_URL=http://localhost:4000/graphql
 
 
 # Block height from which the processor starts. Note that if
 # Block height from which the processor starts. Note that if
 # there are already processed events in the database, this setting is ignored
 # there are already processed events in the database, this setting is ignored

+ 1 - 1
.github/workflows/content-directory-schemas.yml

@@ -17,4 +17,4 @@ jobs:
     - name: validate
     - name: validate
       run: |
       run: |
         yarn install --frozen-lockfile
         yarn install --frozen-lockfile
-        yarn workspace cd-schemas checks --quiet
+        yarn workspace @joystream/cd-schemas checks --quiet

+ 1 - 1
.github/workflows/joystream-node-docker.yml

@@ -55,7 +55,7 @@ jobs:
             docker save --output joystream-node-docker-image.tar joystream/node
             docker save --output joystream-node-docker-image.tar joystream/node
             gzip joystream-node-docker-image.tar
             gzip joystream-node-docker-image.tar
             cp joystream-node-docker-image.tar.gz ~/docker-images/
             cp joystream-node-docker-image.tar.gz ~/docker-images/
-            echo "::set-env name=NEW_BUILD::true"
+            echo "NEW_BUILD=true" >> $GITHUB_ENV
           fi
           fi
 
 
       - name: Save joystream/node image to Artifacts
       - name: Save joystream/node image to Artifacts

+ 4 - 4
.github/workflows/run-network-tests.yml

@@ -77,7 +77,7 @@ jobs:
         with:
         with:
           name: ${{ steps.compute_shasum.outputs.shasum }}-joystream-node-docker-image.tar.gz
           name: ${{ steps.compute_shasum.outputs.shasum }}-joystream-node-docker-image.tar.gz
           path: joystream-node-docker-image.tar.gz
           path: joystream-node-docker-image.tar.gz
-  
+
   basic_runtime_with_upgrade:
   basic_runtime_with_upgrade:
     name: Integration Tests (Runtime Upgrade)
     name: Integration Tests (Runtime Upgrade)
     needs: build_images
     needs: build_images
@@ -146,11 +146,11 @@ jobs:
       - name: Install packages and dependencies
       - name: Install packages and dependencies
         run: yarn install --frozen-lockfile
         run: yarn install --frozen-lockfile
       - name: Ensure tests are runnable
       - name: Ensure tests are runnable
-        run: yarn workspace cd-schemas checks --quiet
+        run: yarn workspace @joystream/cd-schemas checks --quiet
       - name: Start chain
       - name: Start chain
         run: docker-compose up -d joystream-node
         run: docker-compose up -d joystream-node
       - name: Initialize the content directory
       - name: Initialize the content directory
-        run: yarn workspace cd-schemas initialize:dev
+        run: yarn workspace @joystream/cd-schemas initialize:dev
 
 
   query_node:
   query_node:
     name: Query Node Integration Tests
     name: Query Node Integration Tests
@@ -179,7 +179,7 @@ jobs:
       # integration tests
       # integration tests
       - name: Execute Tests
       - name: Execute Tests
         run: query-node/run-tests.sh
         run: query-node/run-tests.sh
-  
+
   storage_node:
   storage_node:
     name: Storage Node Tests
     name: Storage Node Tests
     needs: build_images
     needs: build_images

File diff suppressed because it is too large
+ 113 - 295
Cargo.lock


+ 2 - 6
Cargo.toml

@@ -5,28 +5,24 @@ members = [
 	"runtime-modules/proposals/codex",
 	"runtime-modules/proposals/codex",
 	"runtime-modules/proposals/discussion",
 	"runtime-modules/proposals/discussion",
 	"runtime-modules/common",
 	"runtime-modules/common",
-	"runtime-modules/content-working-group",
 	"runtime-modules/council",
 	"runtime-modules/council",
 	"runtime-modules/forum",
 	"runtime-modules/forum",
 	"runtime-modules/governance",
 	"runtime-modules/governance",
-	"runtime-modules/hiring",
 	"runtime-modules/membership",
 	"runtime-modules/membership",
 	"runtime-modules/memo",
 	"runtime-modules/memo",
 	"runtime-modules/recurring-reward",
 	"runtime-modules/recurring-reward",
 	"runtime-modules/referendum",
 	"runtime-modules/referendum",
 	"runtime-modules/service-discovery",
 	"runtime-modules/service-discovery",
-	"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-permissions",
 	"runtime-modules/working-group",
 	"runtime-modules/working-group",
 	"runtime-modules/content-directory",
 	"runtime-modules/content-directory",
 	"runtime-modules/constitution",
 	"runtime-modules/constitution",
+	"runtime-modules/staking-handler",
 	"node",
 	"node",
 	"utils/chain-spec-builder/"
 	"utils/chain-spec-builder/"
 ]
 ]
 
 
 [profile.release]
 [profile.release]
 # Substrate runtime requires unwinding.
 # Substrate runtime requires unwinding.
-panic = "unwind"
+panic = "unwind"

+ 0 - 8698
_Cargo.lock

@@ -1,8698 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-[[package]]
-name = "Inflector"
-version = "0.11.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
-dependencies = [
- "lazy_static",
- "regex",
-]
-
-[[package]]
-name = "addr2line"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
-dependencies = [
- "gimli",
-]
-
-[[package]]
-name = "adler"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
-
-[[package]]
-name = "aead"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331"
-dependencies = [
- "generic-array 0.14.4",
-]
-
-[[package]]
-name = "aes"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd2bc6d3f370b5666245ff421e231cba4353df936e26986d2918e61a8fd6aef6"
-dependencies = [
- "aes-soft",
- "aesni",
- "block-cipher",
-]
-
-[[package]]
-name = "aes-gcm"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0301c9e9c443494d970a07885e8cf3e587bae8356a1d5abd0999068413f7205f"
-dependencies = [
- "aead",
- "aes",
- "block-cipher",
- "ghash",
- "subtle 2.3.0",
-]
-
-[[package]]
-name = "aes-soft"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63dd91889c49327ad7ef3b500fd1109dbd3c509a03db0d4a9ce413b79f575cb6"
-dependencies = [
- "block-cipher",
- "byteorder 1.3.4",
- "opaque-debug 0.3.0",
-]
-
-[[package]]
-name = "aesni"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a6fe808308bb07d393e2ea47780043ec47683fcf19cf5efc8ca51c50cc8c68a"
-dependencies = [
- "block-cipher",
- "opaque-debug 0.3.0",
-]
-
-[[package]]
-name = "ahash"
-version = "0.2.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29661b60bec623f0586702976ff4d0c9942dcb6723161c2df0eea78455cfedfb"
-dependencies = [
- "const-random",
-]
-
-[[package]]
-name = "ahash"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
-
-[[package]]
-name = "ahash"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6789e291be47ace86a60303502173d84af8327e3627ecf334356ee0f87a164c"
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "alga"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2"
-dependencies = [
- "approx",
- "num-complex",
- "num-traits",
-]
-
-[[package]]
-name = "ansi_term"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-dependencies = [
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.34"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
-
-[[package]]
-name = "approx"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "arc-swap"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
-
-[[package]]
-name = "arrayref"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
-
-[[package]]
-name = "arrayvec"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
-dependencies = [
- "nodrop",
-]
-
-[[package]]
-name = "arrayvec"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
-
-[[package]]
-name = "asn1_der"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fce6b6a0ffdafebd82c87e79e3f40e8d2c523e5fea5566ff6b90509bf98d638"
-dependencies = [
- "asn1_der_derive",
-]
-
-[[package]]
-name = "asn1_der_derive"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502"
-dependencies = [
- "quote",
- "syn",
-]
-
-[[package]]
-name = "async-channel"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9"
-dependencies = [
- "concurrent-queue",
- "event-listener",
- "futures-core",
-]
-
-[[package]]
-name = "async-executor"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146"
-dependencies = [
- "async-task",
- "concurrent-queue",
- "fastrand",
- "futures-lite",
- "once_cell 1.4.1",
- "vec-arena",
-]
-
-[[package]]
-name = "async-global-executor"
-version = "1.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73079b49cd26b8fd5a15f68fc7707fc78698dc2a3d61430f2a7a9430230dfa04"
-dependencies = [
- "async-executor",
- "async-io",
- "futures-lite",
- "num_cpus",
- "once_cell 1.4.1",
-]
-
-[[package]]
-name = "async-io"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40a0b2bb8ae20fede194e779150fe283f65a4a08461b496de546ec366b174ad9"
-dependencies = [
- "concurrent-queue",
- "fastrand",
- "futures-lite",
- "libc",
- "log",
- "nb-connect",
- "once_cell 1.4.1",
- "parking",
- "polling",
- "vec-arena",
- "waker-fn",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "async-mutex"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
-dependencies = [
- "event-listener",
-]
-
-[[package]]
-name = "async-std"
-version = "1.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7e82538bc65a25dbdff70e4c5439d52f068048ab97cdea0acd73f131594caa1"
-dependencies = [
- "async-global-executor",
- "async-io",
- "async-mutex",
- "blocking",
- "crossbeam-utils 0.8.0",
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-lite",
- "gloo-timers",
- "kv-log-macro",
- "log",
- "memchr",
- "num_cpus",
- "once_cell 1.4.1",
- "pin-project-lite",
- "pin-utils",
- "slab",
- "wasm-bindgen-futures",
-]
-
-[[package]]
-name = "async-task"
-version = "4.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
-
-[[package]]
-name = "async-tls"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df097e3f506bec0e1a24f06bb3c962c228f36671de841ff579cb99f371772634"
-dependencies = [
- "futures 0.3.8",
- "rustls",
- "webpki",
- "webpki-roots 0.19.0",
-]
-
-[[package]]
-name = "async-trait"
-version = "0.1.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "atomic"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64f46ca51dca4837f1520754d1c8c36636356b81553d928dc9c177025369a06e"
-
-[[package]]
-name = "atomic-waker"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "autocfg"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
-
-[[package]]
-name = "autocfg"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
-
-[[package]]
-name = "backtrace"
-version = "0.3.54"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28"
-dependencies = [
- "addr2line",
- "cfg-if 1.0.0",
- "libc",
- "miniz_oxide",
- "object",
- "rustc-demangle",
-]
-
-[[package]]
-name = "base58"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83"
-
-[[package]]
-name = "base64"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
-
-[[package]]
-name = "base64"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
-
-[[package]]
-name = "bindgen"
-version = "0.54.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66c0bb6167449588ff70803f4127f0684f9063097eca5016f37eb52b92c2cf36"
-dependencies = [
- "bitflags",
- "cexpr",
- "cfg-if 0.1.10",
- "clang-sys",
- "clap",
- "env_logger",
- "lazy_static",
- "lazycell",
- "log",
- "peeking_take_while",
- "proc-macro2",
- "quote",
- "regex",
- "rustc-hash",
- "shlex",
- "which",
-]
-
-[[package]]
-name = "bip39"
-version = "0.6.0-beta.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7059804e226b3ac116519a252d7f5fb985a5ccc0e93255e036a5f7e7283323f4"
-dependencies = [
- "failure",
- "hashbrown 0.1.8",
- "hmac",
- "once_cell 0.1.8",
- "pbkdf2",
- "rand 0.6.5",
- "sha2 0.8.2",
-]
-
-[[package]]
-name = "bitflags"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
-
-[[package]]
-name = "bitmask"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5da9b3d9f6f585199287a473f4f8dfab6566cf827d15c00c219f53c645687ead"
-
-[[package]]
-name = "bitvec"
-version = "0.17.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c"
-dependencies = [
- "either",
- "radium",
-]
-
-[[package]]
-name = "blake2"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a5720225ef5daecf08657f23791354e1685a8c91a4c60c7f3d3b2892f978f4"
-dependencies = [
- "crypto-mac 0.8.0",
- "digest 0.9.0",
- "opaque-debug 0.3.0",
-]
-
-[[package]]
-name = "blake2-rfc"
-version = "0.2.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
-dependencies = [
- "arrayvec 0.4.12",
- "constant_time_eq",
-]
-
-[[package]]
-name = "blake2b_simd"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
-dependencies = [
- "arrayref",
- "arrayvec 0.5.2",
- "constant_time_eq",
-]
-
-[[package]]
-name = "blake2s_simd"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e461a7034e85b211a4acb57ee2e6730b32912b06c08cc242243c39fc21ae6a2"
-dependencies = [
- "arrayref",
- "arrayvec 0.5.2",
- "constant_time_eq",
-]
-
-[[package]]
-name = "block-buffer"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
-dependencies = [
- "block-padding 0.1.5",
- "byte-tools",
- "byteorder 1.3.4",
- "generic-array 0.12.3",
-]
-
-[[package]]
-name = "block-buffer"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
-dependencies = [
- "block-padding 0.2.1",
- "generic-array 0.14.4",
-]
-
-[[package]]
-name = "block-cipher"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f337a3e6da609650eb74e02bc9fac7b735049f7623ab12f2e4c719316fcc7e80"
-dependencies = [
- "generic-array 0.14.4",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
-dependencies = [
- "byte-tools",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
-
-[[package]]
-name = "blocking"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9"
-dependencies = [
- "async-channel",
- "async-task",
- "atomic-waker",
- "fastrand",
- "futures-lite",
- "once_cell 1.4.1",
-]
-
-[[package]]
-name = "bs58"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb"
-
-[[package]]
-name = "bs58"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
-
-[[package]]
-name = "bstr"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
-
-[[package]]
-name = "byte-slice-cast"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3"
-
-[[package]]
-name = "byte-tools"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
-
-[[package]]
-name = "byteorder"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
-
-[[package]]
-name = "byteorder"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
-
-[[package]]
-name = "bytes"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
-dependencies = [
- "byteorder 1.3.4",
- "either",
- "iovec",
-]
-
-[[package]]
-name = "bytes"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
-
-[[package]]
-name = "c_linked_list"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b"
-
-[[package]]
-name = "cache-padded"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
-
-[[package]]
-name = "cc"
-version = "1.0.62"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40"
-dependencies = [
- "jobserver",
-]
-
-[[package]]
-name = "cexpr"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "chacha20"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "244fbce0d47e97e8ef2f63b81d5e05882cb518c68531eb33194990d7b7e85845"
-dependencies = [
- "stream-cipher",
- "zeroize",
-]
-
-[[package]]
-name = "chacha20poly1305"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bf18d374d66df0c05cdddd528a7db98f78c28e2519b120855c4f84c5027b1f5"
-dependencies = [
- "aead",
- "chacha20",
- "poly1305",
- "stream-cipher",
- "zeroize",
-]
-
-[[package]]
-name = "chain-spec-builder"
-version = "3.1.1"
-dependencies = [
- "ansi_term 0.12.1",
- "enum-utils",
- "joystream-node",
- "rand 0.7.3",
- "sc-chain-spec",
- "sc-keystore",
- "sc-telemetry",
- "sp-core",
- "structopt",
-]
-
-[[package]]
-name = "chrono"
-version = "0.4.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
-dependencies = [
- "js-sys",
- "libc",
- "num-integer",
- "num-traits",
- "time",
- "wasm-bindgen",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "clang-sys"
-version = "0.29.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a"
-dependencies = [
- "glob",
- "libc",
- "libloading",
-]
-
-[[package]]
-name = "clap"
-version = "2.33.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
-dependencies = [
- "ansi_term 0.11.0",
- "atty",
- "bitflags",
- "strsim",
- "textwrap",
- "unicode-width",
- "vec_map",
-]
-
-[[package]]
-name = "cloudabi"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "cloudabi"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "concurrent-queue"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
-dependencies = [
- "cache-padded",
-]
-
-[[package]]
-name = "console_error_panic_hook"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211"
-dependencies = [
- "cfg-if 0.1.10",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "console_log"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e7871d2947441b0fdd8e2bd1ce2a2f75304f896582c0d572162d48290683c48"
-dependencies = [
- "log",
- "web-sys",
-]
-
-[[package]]
-name = "const-random"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02dc82c12dc2ee6e1ded861cf7d582b46f66f796d1b6c93fa28b911ead95da02"
-dependencies = [
- "const-random-macro",
- "proc-macro-hack",
-]
-
-[[package]]
-name = "const-random-macro"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc757bbb9544aa296c2ae00c679e81f886b37e28e59097defe0cf524306f6685"
-dependencies = [
- "getrandom 0.2.0",
- "proc-macro-hack",
-]
-
-[[package]]
-name = "const_fn"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab"
-
-[[package]]
-name = "constant_time_eq"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
-
-[[package]]
-name = "core-foundation"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
-
-[[package]]
-name = "cpuid-bool"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
-
-[[package]]
-name = "crc32fast"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
-dependencies = [
- "cfg-if 1.0.0",
-]
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
-dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-utils 0.8.0",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
-dependencies = [
- "crossbeam-epoch 0.8.2",
- "crossbeam-utils 0.7.2",
- "maybe-uninit",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
-dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-epoch 0.9.0",
- "crossbeam-utils 0.8.0",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
-dependencies = [
- "autocfg 1.0.1",
- "cfg-if 0.1.10",
- "crossbeam-utils 0.7.2",
- "lazy_static",
- "maybe-uninit",
- "memoffset",
- "scopeguard 1.1.0",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f"
-dependencies = [
- "cfg-if 1.0.0",
- "const_fn",
- "crossbeam-utils 0.8.0",
- "lazy_static",
- "memoffset",
- "scopeguard 1.1.0",
-]
-
-[[package]]
-name = "crossbeam-queue"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
-dependencies = [
- "cfg-if 0.1.10",
- "crossbeam-utils 0.7.2",
- "maybe-uninit",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
-dependencies = [
- "autocfg 1.0.1",
- "cfg-if 0.1.10",
- "lazy_static",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5"
-dependencies = [
- "autocfg 1.0.1",
- "cfg-if 1.0.0",
- "const_fn",
- "lazy_static",
-]
-
-[[package]]
-name = "crunchy"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
-
-[[package]]
-name = "crypto-mac"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
-dependencies = [
- "generic-array 0.12.3",
- "subtle 1.0.0",
-]
-
-[[package]]
-name = "crypto-mac"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
-dependencies = [
- "generic-array 0.14.4",
- "subtle 2.3.0",
-]
-
-[[package]]
-name = "ct-logs"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c8e13110a84b6315df212c045be706af261fd364791cad863285439ebba672e"
-dependencies = [
- "sct",
-]
-
-[[package]]
-name = "cuckoofilter"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f"
-dependencies = [
- "byteorder 0.5.3",
- "rand 0.3.23",
-]
-
-[[package]]
-name = "curve25519-dalek"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5"
-dependencies = [
- "byteorder 1.3.4",
- "digest 0.8.1",
- "rand_core 0.5.1",
- "subtle 2.3.0",
- "zeroize",
-]
-
-[[package]]
-name = "curve25519-dalek"
-version = "3.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8492de420e9e60bc9a1d66e2dbb91825390b738a388606600663fc529b4b307"
-dependencies = [
- "byteorder 1.3.4",
- "digest 0.9.0",
- "rand_core 0.5.1",
- "subtle 2.3.0",
- "zeroize",
-]
-
-[[package]]
-name = "data-encoding"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "993a608597367c6377b258c25d7120740f00ed23a2252b729b1932dd7866f908"
-
-[[package]]
-name = "derive_more"
-version = "0.99.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "difference"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
-
-[[package]]
-name = "digest"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
-dependencies = [
- "generic-array 0.12.3",
-]
-
-[[package]]
-name = "digest"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
-dependencies = [
- "generic-array 0.14.4",
-]
-
-[[package]]
-name = "directories"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c"
-dependencies = [
- "cfg-if 0.1.10",
- "dirs-sys",
-]
-
-[[package]]
-name = "dirs-sys"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
-dependencies = [
- "libc",
- "redox_users",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "dns-parser"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea"
-dependencies = [
- "byteorder 1.3.4",
- "quick-error",
-]
-
-[[package]]
-name = "downcast"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d"
-
-[[package]]
-name = "dyn-clonable"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4"
-dependencies = [
- "dyn-clonable-impl",
- "dyn-clone",
-]
-
-[[package]]
-name = "dyn-clonable-impl"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "dyn-clone"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d55796afa1b20c2945ca8eabfc421839f2b766619209f1ede813cf2484f31804"
-
-[[package]]
-name = "ed25519"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37c66a534cbb46ab4ea03477eae19d5c22c01da8258030280b7bd9d8433fb6ef"
-dependencies = [
- "signature",
-]
-
-[[package]]
-name = "ed25519-dalek"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
-dependencies = [
- "curve25519-dalek 3.0.0",
- "ed25519",
- "rand 0.7.3",
- "serde",
- "sha2 0.9.2",
- "zeroize",
-]
-
-[[package]]
-name = "either"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
-
-[[package]]
-name = "enum-utils"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed327f716d0d351d86c9fd3398d20ee39ad8f681873cc081da2ca1c10fed398a"
-dependencies = [
- "enum-utils-from-str",
- "failure",
- "proc-macro2",
- "quote",
- "serde_derive_internals",
- "syn",
-]
-
-[[package]]
-name = "enum-utils-from-str"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d49be08bad6e4ca87b2b8e74146987d4e5cb3b7512efa50ef505b51a22227ee1"
-dependencies = [
- "proc-macro2",
- "quote",
-]
-
-[[package]]
-name = "env_logger"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
-dependencies = [
- "atty",
- "humantime",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "environmental"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6576a1755ddffd988788025e75bce9e74b018f7cc226198fe931d077911c6d7e"
-
-[[package]]
-name = "erased-serde"
-version = "0.3.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ca8b296792113e1500fd935ae487be6e00ce318952a6880555554824d6ebf38"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "event-listener"
-version = "2.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
-
-[[package]]
-name = "exit-future"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5"
-dependencies = [
- "futures 0.3.8",
-]
-
-[[package]]
-name = "failure"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
-dependencies = [
- "backtrace",
- "failure_derive",
-]
-
-[[package]]
-name = "failure_derive"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "fake-simd"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
-
-[[package]]
-name = "fastrand"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3"
-dependencies = [
- "instant",
-]
-
-[[package]]
-name = "fdlimit"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c4c9e43643f5a3be4ca5b67d26b98031ff9db6806c3440ae32e02e3ceac3f1b"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "finality-grandpa"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8feb87a63249689640ac9c011742c33139204e3c134293d3054022276869133b"
-dependencies = [
- "either",
- "futures 0.3.8",
- "futures-timer 2.0.2",
- "log",
- "num-traits",
- "parity-scale-codec",
- "parking_lot 0.9.0",
-]
-
-[[package]]
-name = "fixed-hash"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c"
-dependencies = [
- "byteorder 1.3.4",
- "rand 0.7.3",
- "rustc-hex",
- "static_assertions",
-]
-
-[[package]]
-name = "fixedbitset"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
-
-[[package]]
-name = "flate2"
-version = "1.0.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
-dependencies = [
- "cfg-if 1.0.0",
- "crc32fast",
- "libc",
- "libz-sys",
- "miniz_oxide",
-]
-
-[[package]]
-name = "float-cmp"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "fork-tree"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
-]
-
-[[package]]
-name = "form_urlencoded"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
-dependencies = [
- "matches",
- "percent-encoding 2.1.0",
-]
-
-[[package]]
-name = "fragile"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69a039c3498dc930fe810151a34ba0c1c70b02b8625035592e74432f678591f2"
-
-[[package]]
-name = "frame-benchmarking"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "linregress",
- "parity-scale-codec",
- "paste",
- "sp-api",
- "sp-io",
- "sp-runtime",
- "sp-runtime-interface",
- "sp-std",
- "sp-storage",
-]
-
-[[package]]
-name = "frame-benchmarking-cli"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "parity-scale-codec",
- "sc-cli",
- "sc-client-db",
- "sc-executor",
- "sc-service",
- "sp-core",
- "sp-externalities",
- "sp-runtime",
- "sp-state-machine",
- "structopt",
-]
-
-[[package]]
-name = "frame-executive"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
- "sp-tracing",
-]
-
-[[package]]
-name = "frame-metadata"
-version = "12.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-std",
-]
-
-[[package]]
-name = "frame-support"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "bitmask",
- "frame-metadata",
- "frame-support-procedural",
- "impl-trait-for-tuples",
- "log",
- "once_cell 1.4.1",
- "parity-scale-codec",
- "paste",
- "serde",
- "smallvec 1.4.2",
- "sp-arithmetic",
- "sp-core",
- "sp-inherents",
- "sp-io",
- "sp-runtime",
- "sp-state-machine",
- "sp-std",
- "sp-tracing",
-]
-
-[[package]]
-name = "frame-support-procedural"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support-procedural-tools",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "frame-support-procedural-tools"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support-procedural-tools-derive",
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "frame-support-procedural-tools-derive"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "frame-system"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "impl-trait-for-tuples",
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
- "sp-version",
-]
-
-[[package]]
-name = "frame-system-benchmarking"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "sp-core",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "frame-system-rpc-runtime-api"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-api",
-]
-
-[[package]]
-name = "fs-swap"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "921d332c89b3b61a826de38c61ee5b6e02c56806cade1b0e5d81bd71f57a71bb"
-dependencies = [
- "lazy_static",
- "libc",
- "libloading",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-
-[[package]]
-name = "fuchsia-zircon"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
-dependencies = [
- "bitflags",
- "fuchsia-zircon-sys",
-]
-
-[[package]]
-name = "fuchsia-zircon-sys"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
-
-[[package]]
-name = "futures"
-version = "0.1.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed"
-
-[[package]]
-name = "futures"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-channel-preview"
-version = "0.3.0-alpha.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a"
-dependencies = [
- "futures-core-preview",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748"
-
-[[package]]
-name = "futures-core-preview"
-version = "0.3.0-alpha.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a"
-
-[[package]]
-name = "futures-cpupool"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
-dependencies = [
- "futures 0.1.30",
- "num_cpus",
-]
-
-[[package]]
-name = "futures-diagnose"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdcef58a173af8148b182684c9f2d5250875adbcaff7b5794073894f9d8634a9"
-dependencies = [
- "futures 0.1.30",
- "futures 0.3.8",
- "lazy_static",
- "log",
- "parking_lot 0.9.0",
- "pin-project 0.4.27",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "futures-executor"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
- "num_cpus",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb"
-
-[[package]]
-name = "futures-lite"
-version = "1.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e6c079abfac3ab269e2927ec048dabc89d009ebfdda6b8ee86624f30c689658"
-dependencies = [
- "fastrand",
- "futures-core",
- "futures-io",
- "memchr",
- "parking",
- "pin-project-lite",
- "waker-fn",
-]
-
-[[package]]
-name = "futures-macro"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556"
-dependencies = [
- "proc-macro-hack",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d"
-
-[[package]]
-name = "futures-task"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d"
-dependencies = [
- "once_cell 1.4.1",
-]
-
-[[package]]
-name = "futures-timer"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6"
-
-[[package]]
-name = "futures-timer"
-version = "3.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
-dependencies = [
- "gloo-timers",
- "send_wrapper 0.4.0",
-]
-
-[[package]]
-name = "futures-util"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2"
-dependencies = [
- "futures 0.1.30",
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project 1.0.1",
- "pin-utils",
- "proc-macro-hack",
- "proc-macro-nested",
- "slab",
-]
-
-[[package]]
-name = "futures-util-preview"
-version = "0.3.0-alpha.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d"
-dependencies = [
- "futures-channel-preview",
- "futures-core-preview",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "futures_codec"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b"
-dependencies = [
- "bytes 0.5.6",
- "futures 0.3.8",
- "memchr",
- "pin-project 0.4.27",
-]
-
-[[package]]
-name = "gcc"
-version = "0.3.55"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
-
-[[package]]
-name = "generator"
-version = "0.6.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cdc09201b2e8ca1b19290cf7e65de2246b8e91fb6874279722189c4de7b94dc"
-dependencies = [
- "cc",
- "libc",
- "log",
- "rustc_version",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "generic-array"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
-dependencies = [
- "typenum",
-]
-
-[[package]]
-name = "generic-array"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
-dependencies = [
- "typenum",
- "version_check",
-]
-
-[[package]]
-name = "get_if_addrs"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7"
-dependencies = [
- "c_linked_list",
- "get_if_addrs-sys",
- "libc",
- "winapi 0.2.8",
-]
-
-[[package]]
-name = "get_if_addrs-sys"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48"
-dependencies = [
- "gcc",
- "libc",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.1.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
-]
-
-[[package]]
-name = "ghash"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6e27f0689a6e15944bdce7e45425efb87eaa8ab0c6e87f11d0987a9133e2531"
-dependencies = [
- "polyval",
-]
-
-[[package]]
-name = "gimli"
-version = "0.23.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
-
-[[package]]
-name = "glob"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
-
-[[package]]
-name = "globset"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
-dependencies = [
- "aho-corasick",
- "bstr",
- "fnv",
- "log",
- "regex",
-]
-
-[[package]]
-name = "gloo-timers"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
-dependencies = [
- "futures-channel",
- "futures-core",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "h2"
-version = "0.1.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
-dependencies = [
- "byteorder 1.3.4",
- "bytes 0.4.12",
- "fnv",
- "futures 0.1.30",
- "http 0.1.21",
- "indexmap",
- "log",
- "slab",
- "string",
- "tokio-io",
-]
-
-[[package]]
-name = "h2"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535"
-dependencies = [
- "bytes 0.5.6",
- "fnv",
- "futures-core",
- "futures-sink",
- "futures-util",
- "http 0.2.1",
- "indexmap",
- "slab",
- "tokio 0.2.22",
- "tokio-util",
- "tracing",
- "tracing-futures",
-]
-
-[[package]]
-name = "hash-db"
-version = "0.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a"
-
-[[package]]
-name = "hash256-std-hasher"
-version = "0.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2"
-dependencies = [
- "crunchy",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da"
-dependencies = [
- "byteorder 1.3.4",
- "scopeguard 0.3.3",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead"
-dependencies = [
- "ahash 0.2.19",
- "autocfg 0.1.7",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25"
-dependencies = [
- "ahash 0.3.8",
- "autocfg 1.0.1",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
-dependencies = [
- "ahash 0.4.6",
-]
-
-[[package]]
-name = "heck"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "hex"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
-
-[[package]]
-name = "hex-literal"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "hex-literal"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8"
-
-[[package]]
-name = "hex_fmt"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f"
-
-[[package]]
-name = "hmac"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
-dependencies = [
- "crypto-mac 0.7.0",
- "digest 0.8.1",
-]
-
-[[package]]
-name = "hmac-drbg"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b"
-dependencies = [
- "digest 0.8.1",
- "generic-array 0.12.3",
- "hmac",
-]
-
-[[package]]
-name = "http"
-version = "0.1.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0"
-dependencies = [
- "bytes 0.4.12",
- "fnv",
- "itoa",
-]
-
-[[package]]
-name = "http"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
-dependencies = [
- "bytes 0.5.6",
- "fnv",
- "itoa",
-]
-
-[[package]]
-name = "http-body"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "http 0.1.21",
- "tokio-buf",
-]
-
-[[package]]
-name = "http-body"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
-dependencies = [
- "bytes 0.5.6",
- "http 0.2.1",
-]
-
-[[package]]
-name = "httparse"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
-
-[[package]]
-name = "httpdate"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
-
-[[package]]
-name = "humantime"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-dependencies = [
- "quick-error",
-]
-
-[[package]]
-name = "hyper"
-version = "0.12.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "futures-cpupool",
- "h2 0.1.26",
- "http 0.1.21",
- "http-body 0.1.0",
- "httparse",
- "iovec",
- "itoa",
- "log",
- "net2",
- "rustc_version",
- "time",
- "tokio 0.1.22",
- "tokio-buf",
- "tokio-executor 0.1.10",
- "tokio-io",
- "tokio-reactor",
- "tokio-tcp",
- "tokio-threadpool",
- "tokio-timer",
- "want 0.2.0",
-]
-
-[[package]]
-name = "hyper"
-version = "0.13.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6ad767baac13b44d4529fcf58ba2cd0995e36e7b435bc5b039de6f47e880dbf"
-dependencies = [
- "bytes 0.5.6",
- "futures-channel",
- "futures-core",
- "futures-util",
- "h2 0.2.7",
- "http 0.2.1",
- "http-body 0.3.1",
- "httparse",
- "httpdate",
- "itoa",
- "pin-project 1.0.1",
- "socket2",
- "tokio 0.2.22",
- "tower-service",
- "tracing",
- "want 0.3.0",
-]
-
-[[package]]
-name = "hyper-rustls"
-version = "0.21.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6"
-dependencies = [
- "bytes 0.5.6",
- "ct-logs",
- "futures-util",
- "hyper 0.13.9",
- "log",
- "rustls",
- "rustls-native-certs",
- "tokio 0.2.22",
- "tokio-rustls",
- "webpki",
-]
-
-[[package]]
-name = "idna"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
-dependencies = [
- "matches",
- "unicode-bidi",
- "unicode-normalization",
-]
-
-[[package]]
-name = "idna"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
-dependencies = [
- "matches",
- "unicode-bidi",
- "unicode-normalization",
-]
-
-[[package]]
-name = "impl-codec"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53"
-dependencies = [
- "parity-scale-codec",
-]
-
-[[package]]
-name = "impl-serde"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b47ca4d2b6931707a55fce5cf66aff80e2178c8b63bbb4ecb5695cbc870ddf6f"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "impl-trait-for-tuples"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "indexmap"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
-dependencies = [
- "autocfg 1.0.1",
- "hashbrown 0.9.1",
-]
-
-[[package]]
-name = "instant"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613"
-dependencies = [
- "cfg-if 1.0.0",
-]
-
-[[package]]
-name = "integer-sqrt"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "intervalier"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64fa110ec7b8f493f416eed552740d10e7030ad5f63b2308f82c9608ec2df275"
-dependencies = [
- "futures 0.3.8",
- "futures-timer 2.0.2",
-]
-
-[[package]]
-name = "iovec"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "ip_network"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ee15951c035f79eddbef745611ec962f63f4558f1dadf98ab723cc603487c6f"
-
-[[package]]
-name = "ipnet"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
-
-[[package]]
-name = "itertools"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itoa"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
-
-[[package]]
-name = "jobserver"
-version = "0.1.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "joystream-node"
-version = "4.0.0"
-dependencies = [
- "frame-benchmarking",
- "frame-benchmarking-cli",
- "frame-system",
- "futures 0.3.8",
- "hex",
- "joystream-node-runtime",
- "jsonrpc-core",
- "node-inspect",
- "pallet-grandpa",
- "pallet-im-online",
- "pallet-transaction-payment",
- "pallet-transaction-payment-rpc",
- "parity-scale-codec",
- "sc-authority-discovery",
- "sc-basic-authorship",
- "sc-chain-spec",
- "sc-cli",
- "sc-client-api",
- "sc-consensus",
- "sc-consensus-babe",
- "sc-consensus-babe-rpc",
- "sc-consensus-epochs",
- "sc-executor",
- "sc-finality-grandpa",
- "sc-finality-grandpa-rpc",
- "sc-keystore",
- "sc-network",
- "sc-rpc",
- "sc-rpc-api",
- "sc-service",
- "sc-service-test",
- "sc-transaction-pool",
- "serde",
- "serde_json",
- "sp-api",
- "sp-authority-discovery",
- "sp-block-builder",
- "sp-blockchain",
- "sp-consensus",
- "sp-consensus-babe",
- "sp-core",
- "sp-finality-grandpa",
- "sp-finality-tracker",
- "sp-inherents",
- "sp-keyring",
- "sp-runtime",
- "sp-timestamp",
- "sp-transaction-pool",
- "structopt",
- "substrate-browser-utils",
- "substrate-build-script-utils",
- "substrate-frame-rpc-system",
- "tempfile",
- "wasm-bindgen",
- "wasm-bindgen-futures",
-]
-
-[[package]]
-name = "joystream-node-runtime"
-version = "7.8.0"
-dependencies = [
- "frame-benchmarking",
- "frame-executive",
- "frame-support",
- "frame-system",
- "frame-system-benchmarking",
- "frame-system-rpc-runtime-api",
- "hex-literal 0.3.1",
- "lazy_static",
- "lite-json",
- "pallet-authority-discovery",
- "pallet-authorship",
- "pallet-babe",
- "pallet-balances",
- "pallet-common",
- "pallet-constitution",
- "pallet-content-directory",
- "pallet-content-working-group",
- "pallet-finality-tracker",
- "pallet-forum",
- "pallet-governance",
- "pallet-grandpa",
- "pallet-hiring",
- "pallet-im-online",
- "pallet-membership",
- "pallet-memo",
- "pallet-offences",
- "pallet-offences-benchmarking",
- "pallet-proposals-codex",
- "pallet-proposals-discussion",
- "pallet-proposals-engine",
- "pallet-randomness-collective-flip",
- "pallet-recurring-reward",
- "pallet-service-discovery",
- "pallet-session",
- "pallet-session-benchmarking",
- "pallet-stake",
- "pallet-staking",
- "pallet-staking-reward-curve",
- "pallet-storage",
- "pallet-sudo",
- "pallet-timestamp",
- "pallet-token-mint",
- "pallet-transaction-payment",
- "pallet-transaction-payment-rpc-runtime-api",
- "pallet-utility",
- "pallet-versioned-store",
- "pallet-versioned-store-permissions",
- "pallet-working-group",
- "parity-scale-codec",
- "serde",
- "sp-api",
- "sp-application-crypto",
- "sp-arithmetic",
- "sp-authority-discovery",
- "sp-block-builder",
- "sp-consensus-babe",
- "sp-core",
- "sp-io",
- "sp-offchain",
- "sp-runtime",
- "sp-session",
- "sp-staking",
- "sp-std",
- "sp-transaction-pool",
- "sp-version",
- "strum 0.19.5",
- "substrate-wasm-builder-runner",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "jsonrpc-client-transports"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "489b9c612e60c766f751ab40fcb43cbb55a1e10bb44a9b4307ed510ca598cbd7"
-dependencies = [
- "failure",
- "futures 0.1.30",
- "jsonrpc-core",
- "jsonrpc-pubsub",
- "log",
- "serde",
- "serde_json",
- "url 1.7.2",
-]
-
-[[package]]
-name = "jsonrpc-core"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0745a6379e3edc893c84ec203589790774e4247420033e71a76d3ab4687991fa"
-dependencies = [
- "futures 0.1.30",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
-]
-
-[[package]]
-name = "jsonrpc-core-client"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f764902d7b891344a0acb65625f32f6f7c6db006952143bd650209fbe7d94db"
-dependencies = [
- "jsonrpc-client-transports",
-]
-
-[[package]]
-name = "jsonrpc-derive"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99a847f9ec7bb52149b2786a17c9cb260d6effc6b8eeb8c16b343a487a7563a3"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "jsonrpc-http-server"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb5c4513b7b542f42da107942b7b759f27120b5cc894729f88254b28dff44b7"
-dependencies = [
- "hyper 0.12.35",
- "jsonrpc-core",
- "jsonrpc-server-utils",
- "log",
- "net2",
- "parking_lot 0.10.2",
- "unicase",
-]
-
-[[package]]
-name = "jsonrpc-ipc-server"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf50e53e4eea8f421a7316c5f63e395f7bc7c4e786a6dc54d76fab6ff7aa7ce7"
-dependencies = [
- "jsonrpc-core",
- "jsonrpc-server-utils",
- "log",
- "parity-tokio-ipc",
- "parking_lot 0.10.2",
- "tokio-service",
-]
-
-[[package]]
-name = "jsonrpc-pubsub"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "639558e0604013be9787ae52f798506ae42bf4220fe587bdc5625871cc8b9c77"
-dependencies = [
- "jsonrpc-core",
- "log",
- "parking_lot 0.10.2",
- "rand 0.7.3",
- "serde",
-]
-
-[[package]]
-name = "jsonrpc-server-utils"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72f1f3990650c033bd8f6bd46deac76d990f9bbfb5f8dc8c4767bf0a00392176"
-dependencies = [
- "bytes 0.4.12",
- "globset",
- "jsonrpc-core",
- "lazy_static",
- "log",
- "tokio 0.1.22",
- "tokio-codec",
- "unicase",
-]
-
-[[package]]
-name = "jsonrpc-ws-server"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6596fe75209b73a2a75ebe1dce4e60e03b88a2b25e8807b667597f6315150d22"
-dependencies = [
- "jsonrpc-core",
- "jsonrpc-server-utils",
- "log",
- "parity-ws",
- "parking_lot 0.10.2",
- "slab",
-]
-
-[[package]]
-name = "keccak"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
-
-[[package]]
-name = "kernel32-sys"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-dependencies = [
- "winapi 0.2.8",
- "winapi-build",
-]
-
-[[package]]
-name = "kv-log-macro"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
-dependencies = [
- "log",
-]
-
-[[package]]
-name = "kvdb"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0315ef2f688e33844400b31f11c263f2b3dc21d8b9355c6891c5f185fae43f9a"
-dependencies = [
- "parity-util-mem",
- "smallvec 1.4.2",
-]
-
-[[package]]
-name = "kvdb-memorydb"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73de822b260a3bdfb889dbbb65bb2d473eee2253973d6fa4a5d149a2a4a7c66e"
-dependencies = [
- "kvdb",
- "parity-util-mem",
- "parking_lot 0.10.2",
-]
-
-[[package]]
-name = "kvdb-rocksdb"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44947dd392f09475af614d740fe0320b66d01cb5b977f664bbbb5e45a70ea4c1"
-dependencies = [
- "fs-swap",
- "kvdb",
- "log",
- "num_cpus",
- "owning_ref",
- "parity-util-mem",
- "parking_lot 0.10.2",
- "regex",
- "rocksdb",
- "smallvec 1.4.2",
-]
-
-[[package]]
-name = "kvdb-web"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2701a1369d6ea4f1b9f606db46e5e2a4a8e47f22530a07823d653f85ab1f6c34"
-dependencies = [
- "futures 0.3.8",
- "js-sys",
- "kvdb",
- "kvdb-memorydb",
- "log",
- "parity-util-mem",
- "send_wrapper 0.3.0",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-dependencies = [
- "spin",
-]
-
-[[package]]
-name = "lazycell"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
-
-[[package]]
-name = "libc"
-version = "0.2.80"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
-
-[[package]]
-name = "libloading"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
-dependencies = [
- "cc",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "libm"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
-
-[[package]]
-name = "libp2p"
-version = "0.28.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "571f5a4604c1a40d75651da141dfde29ad15329f537a779528803297d2220274"
-dependencies = [
- "atomic",
- "bytes 0.5.6",
- "futures 0.3.8",
- "lazy_static",
- "libp2p-core",
- "libp2p-core-derive",
- "libp2p-deflate",
- "libp2p-dns",
- "libp2p-floodsub",
- "libp2p-gossipsub",
- "libp2p-identify",
- "libp2p-kad",
- "libp2p-mdns",
- "libp2p-mplex",
- "libp2p-noise",
- "libp2p-ping",
- "libp2p-plaintext",
- "libp2p-pnet",
- "libp2p-request-response",
- "libp2p-swarm",
- "libp2p-tcp",
- "libp2p-uds",
- "libp2p-wasm-ext",
- "libp2p-websocket",
- "libp2p-yamux",
- "multihash",
- "parity-multiaddr",
- "parking_lot 0.10.2",
- "pin-project 0.4.27",
- "smallvec 1.4.2",
- "wasm-timer",
-]
-
-[[package]]
-name = "libp2p-core"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52f13ba8c7df0768af2eb391696d562c7de88cc3a35122531aaa6a7d77754d25"
-dependencies = [
- "asn1_der",
- "bs58 0.3.1",
- "ed25519-dalek",
- "either",
- "fnv",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "lazy_static",
- "libsecp256k1",
- "log",
- "multihash",
- "multistream-select",
- "parity-multiaddr",
- "parking_lot 0.10.2",
- "pin-project 0.4.27",
- "prost",
- "prost-build",
- "rand 0.7.3",
- "ring",
- "rw-stream-sink",
- "sha2 0.8.2",
- "smallvec 1.4.2",
- "thiserror",
- "unsigned-varint 0.4.0",
- "void",
- "zeroize",
-]
-
-[[package]]
-name = "libp2p-core-derive"
-version = "0.20.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f753d9324cd3ec14bf04b8a8cd0d269c87f294153d6bf2a84497a63a5ad22213"
-dependencies = [
- "quote",
- "syn",
-]
-
-[[package]]
-name = "libp2p-deflate"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74029ae187f35f4b8ddf26b9779a68b340045d708528a103917cdca49a296db5"
-dependencies = [
- "flate2",
- "futures 0.3.8",
- "libp2p-core",
-]
-
-[[package]]
-name = "libp2p-dns"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cf319822e08dd65c8e060d2354e9f952895bbc433f5706c75ed010c152aee5e"
-dependencies = [
- "futures 0.3.8",
- "libp2p-core",
- "log",
-]
-
-[[package]]
-name = "libp2p-floodsub"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8a9acb43a3e4a4e413e0c4abe0fa49308df7c6335c88534757b647199cb8a51"
-dependencies = [
- "cuckoofilter",
- "fnv",
- "futures 0.3.8",
- "libp2p-core",
- "libp2p-swarm",
- "prost",
- "prost-build",
- "rand 0.7.3",
- "smallvec 1.4.2",
-]
-
-[[package]]
-name = "libp2p-gossipsub"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab20fcb60edebe3173bbb708c6ac3444afdf1e3152dc2866b10c4f5497f17467"
-dependencies = [
- "base64 0.11.0",
- "byteorder 1.3.4",
- "bytes 0.5.6",
- "fnv",
- "futures 0.3.8",
- "futures_codec",
- "hex_fmt",
- "libp2p-core",
- "libp2p-swarm",
- "log",
- "lru_time_cache",
- "prost",
- "prost-build",
- "rand 0.7.3",
- "sha2 0.8.2",
- "smallvec 1.4.2",
- "unsigned-varint 0.4.0",
- "wasm-timer",
-]
-
-[[package]]
-name = "libp2p-identify"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56396ee63aa9164eacf40c2c5d2bda8c4133c2f57e1b0425d51d3a4e362583b1"
-dependencies = [
- "futures 0.3.8",
- "libp2p-core",
- "libp2p-swarm",
- "log",
- "prost",
- "prost-build",
- "smallvec 1.4.2",
- "wasm-timer",
-]
-
-[[package]]
-name = "libp2p-kad"
-version = "0.23.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc7fa9047f8b8f544278a35c2d9d45d3b2c1785f2d86d4e1629d6edf97be3955"
-dependencies = [
- "arrayvec 0.5.2",
- "bytes 0.5.6",
- "either",
- "fnv",
- "futures 0.3.8",
- "futures_codec",
- "libp2p-core",
- "libp2p-swarm",
- "log",
- "multihash",
- "prost",
- "prost-build",
- "rand 0.7.3",
- "sha2 0.8.2",
- "smallvec 1.4.2",
- "uint",
- "unsigned-varint 0.4.0",
- "void",
- "wasm-timer",
-]
-
-[[package]]
-name = "libp2p-mdns"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3173b5a6b2f690c29ae07798d85b9441a131ac76ddae9015ef22905b623d0c69"
-dependencies = [
- "async-std",
- "data-encoding",
- "dns-parser",
- "either",
- "futures 0.3.8",
- "lazy_static",
- "libp2p-core",
- "libp2p-swarm",
- "log",
- "net2",
- "rand 0.7.3",
- "smallvec 1.4.2",
- "void",
- "wasm-timer",
-]
-
-[[package]]
-name = "libp2p-mplex"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a73a799cc8410b36e40b8f4c4b6babbcb9efd3727111bf517876e4acfa612d3"
-dependencies = [
- "bytes 0.5.6",
- "fnv",
- "futures 0.3.8",
- "futures_codec",
- "libp2p-core",
- "log",
- "parking_lot 0.10.2",
- "unsigned-varint 0.4.0",
-]
-
-[[package]]
-name = "libp2p-noise"
-version = "0.24.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ef6c490042f549fb1025f2892dfe6083d97a77558f450c1feebe748ca9eb15a"
-dependencies = [
- "bytes 0.5.6",
- "curve25519-dalek 2.1.0",
- "futures 0.3.8",
- "lazy_static",
- "libp2p-core",
- "log",
- "prost",
- "prost-build",
- "rand 0.7.3",
- "sha2 0.8.2",
- "snow",
- "static_assertions",
- "x25519-dalek 0.6.0",
- "zeroize",
-]
-
-[[package]]
-name = "libp2p-ping"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad063c21dfcea4518ac9e8bd4119d33a5b26c41e674f602f41f05617a368a5c8"
-dependencies = [
- "futures 0.3.8",
- "libp2p-core",
- "libp2p-swarm",
- "log",
- "rand 0.7.3",
- "void",
- "wasm-timer",
-]
-
-[[package]]
-name = "libp2p-plaintext"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "903a12e99c72dbebefea258de887982adeacc7025baa1ceb10b7fa9928f54791"
-dependencies = [
- "bytes 0.5.6",
- "futures 0.3.8",
- "futures_codec",
- "libp2p-core",
- "log",
- "prost",
- "prost-build",
- "rw-stream-sink",
- "unsigned-varint 0.4.0",
- "void",
-]
-
-[[package]]
-name = "libp2p-pnet"
-version = "0.19.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96b3c2d5d26a9500e959a0e19743897239a6c4be78dadf99b70414301a70c006"
-dependencies = [
- "futures 0.3.8",
- "log",
- "pin-project 0.4.27",
- "rand 0.7.3",
- "salsa20",
- "sha3",
-]
-
-[[package]]
-name = "libp2p-request-response"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c0c9e8a4cd69d97e9646c54313d007512f411aba8c5226cfcda16df6a6e84a3"
-dependencies = [
- "async-trait",
- "bytes 0.5.6",
- "futures 0.3.8",
- "libp2p-core",
- "libp2p-swarm",
- "log",
- "lru 0.6.1",
- "minicbor",
- "rand 0.7.3",
- "smallvec 1.4.2",
- "unsigned-varint 0.5.1",
- "wasm-timer",
-]
-
-[[package]]
-name = "libp2p-swarm"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7193e444210132237b81b755ec7fe53f1c4bd2f53cf719729b94c0c72eb6eaa1"
-dependencies = [
- "either",
- "futures 0.3.8",
- "libp2p-core",
- "log",
- "rand 0.7.3",
- "smallvec 1.4.2",
- "void",
- "wasm-timer",
-]
-
-[[package]]
-name = "libp2p-tcp"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44f42ec130d7a37a7e47bf4398026b7ad9185c08ed26972e2720f8b94112796f"
-dependencies = [
- "async-std",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "get_if_addrs",
- "ipnet",
- "libp2p-core",
- "log",
- "socket2",
-]
-
-[[package]]
-name = "libp2p-uds"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dea7acb0a034f70d7db94c300eba3f65c0f6298820105624088a9609c9974d77"
-dependencies = [
- "async-std",
- "futures 0.3.8",
- "libp2p-core",
- "log",
-]
-
-[[package]]
-name = "libp2p-wasm-ext"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34c1faac6f92c21fbe155417957863ea822fba9e9fd5eb24c0912336a100e63f"
-dependencies = [
- "futures 0.3.8",
- "js-sys",
- "libp2p-core",
- "parity-send-wrapper",
- "wasm-bindgen",
- "wasm-bindgen-futures",
-]
-
-[[package]]
-name = "libp2p-websocket"
-version = "0.23.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d650534ebd99f48f6fa292ed5db10d30df2444943afde4407ceeddab8e513fca"
-dependencies = [
- "async-tls",
- "either",
- "futures 0.3.8",
- "libp2p-core",
- "log",
- "quicksink",
- "rustls",
- "rw-stream-sink",
- "soketto",
- "url 2.2.0",
- "webpki",
- "webpki-roots 0.18.0",
-]
-
-[[package]]
-name = "libp2p-yamux"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "781d9b9f043dcdabc40640807125368596b849fd4d96cdca2dcf052fdf6f33fd"
-dependencies = [
- "futures 0.3.8",
- "libp2p-core",
- "parking_lot 0.11.0",
- "thiserror",
- "yamux",
-]
-
-[[package]]
-name = "librocksdb-sys"
-version = "6.11.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb5b56f651c204634b936be2f92dbb42c36867e00ff7fe2405591f3b9fa66f09"
-dependencies = [
- "bindgen",
- "cc",
- "glob",
- "libc",
-]
-
-[[package]]
-name = "libsecp256k1"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962"
-dependencies = [
- "arrayref",
- "crunchy",
- "digest 0.8.1",
- "hmac-drbg",
- "rand 0.7.3",
- "sha2 0.8.2",
- "subtle 2.3.0",
- "typenum",
-]
-
-[[package]]
-name = "libz-sys"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
-dependencies = [
- "cc",
- "pkg-config",
- "vcpkg",
-]
-
-[[package]]
-name = "linked-hash-map"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
-
-[[package]]
-name = "linked_hash_set"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588"
-dependencies = [
- "linked-hash-map",
-]
-
-[[package]]
-name = "linregress"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9290cf6f928576eeb9c096c6fad9d8d452a0a1a70a2bbffa6e36064eedc0aac9"
-dependencies = [
- "failure",
- "nalgebra",
- "statrs",
-]
-
-[[package]]
-name = "lite-json"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0460d985423a026b4d9b828a7c6eed1bcf606f476322f3f9b507529686a61715"
-dependencies = [
- "lite-parser",
-]
-
-[[package]]
-name = "lite-parser"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c50092e40e0ccd1bf2015a10333fde0502ff95b832b0895dc1ca0d7ac6c52f6"
-dependencies = [
- "paste",
-]
-
-[[package]]
-name = "lock_api"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
-dependencies = [
- "scopeguard 0.3.3",
-]
-
-[[package]]
-name = "lock_api"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
-dependencies = [
- "scopeguard 1.1.0",
-]
-
-[[package]]
-name = "lock_api"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
-dependencies = [
- "scopeguard 1.1.0",
-]
-
-[[package]]
-name = "log"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
-dependencies = [
- "cfg-if 0.1.10",
-]
-
-[[package]]
-name = "loom"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed"
-dependencies = [
- "cfg-if 0.1.10",
- "generator",
- "scoped-tls",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "lru"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0609345ddee5badacf857d4f547e0e5a2e987db77085c24cd887f73573a04237"
-dependencies = [
- "hashbrown 0.6.3",
-]
-
-[[package]]
-name = "lru"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be716eb6878ca2263eb5d00a781aa13264a794f519fe6af4fbb2668b2d5441c0"
-dependencies = [
- "hashbrown 0.9.1",
-]
-
-[[package]]
-name = "lru_time_cache"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb241df5c4caeb888755363fc95f8a896618dc0d435e9e775f7930cb099beab"
-
-[[package]]
-name = "matchers"
-version = "0.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
-dependencies = [
- "regex-automata",
-]
-
-[[package]]
-name = "matches"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
-
-[[package]]
-name = "matrixmultiply"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f"
-dependencies = [
- "rawpointer",
-]
-
-[[package]]
-name = "maybe-uninit"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
-
-[[package]]
-name = "memchr"
-version = "2.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
-
-[[package]]
-name = "memmap"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
-dependencies = [
- "libc",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "memoffset"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
-dependencies = [
- "autocfg 1.0.1",
-]
-
-[[package]]
-name = "memory-db"
-version = "0.24.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36f36ddb0b2cdc25d38babba472108798e3477f02be5165f038c5e393e50c57a"
-dependencies = [
- "hash-db",
- "hashbrown 0.8.2",
- "parity-util-mem",
-]
-
-[[package]]
-name = "memory_units"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
-
-[[package]]
-name = "merlin"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6feca46f4fa3443a01769d768727f10c10a20fdb65e52dc16a81f0c8269bb78"
-dependencies = [
- "byteorder 1.3.4",
- "keccak",
- "rand_core 0.5.1",
- "zeroize",
-]
-
-[[package]]
-name = "minicbor"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fc03ad6f8f548db7194a5ff5a6f96342ecae4e3ef67d2bf18bacc0e245cd041"
-dependencies = [
- "minicbor-derive",
-]
-
-[[package]]
-name = "minicbor-derive"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c214bf3d90099b52f3e4b328ae0fe34837fd0fab683ad1e10fceb4629106df48"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
-dependencies = [
- "adler",
- "autocfg 1.0.1",
-]
-
-[[package]]
-name = "mio"
-version = "0.6.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
-dependencies = [
- "cfg-if 0.1.10",
- "fuchsia-zircon",
- "fuchsia-zircon-sys",
- "iovec",
- "kernel32-sys",
- "libc",
- "log",
- "miow 0.2.1",
- "net2",
- "slab",
- "winapi 0.2.8",
-]
-
-[[package]]
-name = "mio-extras"
-version = "2.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
-dependencies = [
- "lazycell",
- "log",
- "mio",
- "slab",
-]
-
-[[package]]
-name = "mio-named-pipes"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
-dependencies = [
- "log",
- "mio",
- "miow 0.3.5",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "mio-uds"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
-dependencies = [
- "iovec",
- "libc",
- "mio",
-]
-
-[[package]]
-name = "miow"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
-dependencies = [
- "kernel32-sys",
- "net2",
- "winapi 0.2.8",
- "ws2_32-sys",
-]
-
-[[package]]
-name = "miow"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e"
-dependencies = [
- "socket2",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "mockall"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01458f8a19b10cb28195290942e3149161c75acf67ebc8fbf714ab67a2b943bc"
-dependencies = [
- "cfg-if 0.1.10",
- "downcast",
- "fragile",
- "lazy_static",
- "mockall_derive",
- "predicates",
- "predicates-tree",
-]
-
-[[package]]
-name = "mockall_derive"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a673cb441f78cd9af4f5919c28576a3cc325fb6b54e42f7047dacce3c718c17b"
-dependencies = [
- "cfg-if 0.1.10",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "multihash"
-version = "0.11.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567122ab6492f49b59def14ecc36e13e64dca4188196dd0cd41f9f3f979f3df6"
-dependencies = [
- "blake2b_simd",
- "blake2s_simd",
- "digest 0.9.0",
- "sha-1 0.9.2",
- "sha2 0.9.2",
- "sha3",
- "unsigned-varint 0.5.1",
-]
-
-[[package]]
-name = "multimap"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1255076139a83bb467426e7f8d0134968a8118844faa755985e077cf31850333"
-
-[[package]]
-name = "multistream-select"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93faf2e41f9ee62fb01680ed48f3cc26652352327aa2e59869070358f6b7dd75"
-dependencies = [
- "bytes 0.5.6",
- "futures 0.3.8",
- "log",
- "pin-project 1.0.1",
- "smallvec 1.4.2",
- "unsigned-varint 0.5.1",
-]
-
-[[package]]
-name = "nalgebra"
-version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaa9fddbc34c8c35dd2108515587b8ce0cab396f17977b8c738568e4edb521a2"
-dependencies = [
- "alga",
- "approx",
- "generic-array 0.12.3",
- "matrixmultiply",
- "num-complex",
- "num-rational",
- "num-traits",
- "rand 0.6.5",
- "typenum",
-]
-
-[[package]]
-name = "names"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da"
-dependencies = [
- "rand 0.3.23",
-]
-
-[[package]]
-name = "nb-connect"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998"
-dependencies = [
- "libc",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "net2"
-version = "0.2.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "nix"
-version = "0.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
-dependencies = [
- "bitflags",
- "cc",
- "cfg-if 0.1.10",
- "libc",
- "void",
-]
-
-[[package]]
-name = "node-inspect"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "log",
- "parity-scale-codec",
- "sc-cli",
- "sc-client-api",
- "sc-service",
- "sp-blockchain",
- "sp-core",
- "sp-runtime",
- "structopt",
-]
-
-[[package]]
-name = "nodrop"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
-
-[[package]]
-name = "nohash-hasher"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
-
-[[package]]
-name = "nom"
-version = "5.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
-dependencies = [
- "memchr",
- "version_check",
-]
-
-[[package]]
-name = "normalize-line-endings"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
-
-[[package]]
-name = "num-bigint"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
-dependencies = [
- "autocfg 1.0.1",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-complex"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
-dependencies = [
- "autocfg 1.0.1",
- "num-traits",
-]
-
-[[package]]
-name = "num-integer"
-version = "0.1.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
-dependencies = [
- "autocfg 1.0.1",
- "num-traits",
-]
-
-[[package]]
-name = "num-rational"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
-dependencies = [
- "autocfg 1.0.1",
- "num-bigint",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
-dependencies = [
- "autocfg 1.0.1",
- "libm",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "object"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
-
-[[package]]
-name = "once_cell"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37"
-dependencies = [
- "parking_lot 0.7.1",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
-dependencies = [
- "parking_lot 0.11.0",
-]
-
-[[package]]
-name = "opaque-debug"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
-
-[[package]]
-name = "opaque-debug"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
-
-[[package]]
-name = "openssl-probe"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
-
-[[package]]
-name = "owning_ref"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"
-dependencies = [
- "stable_deref_trait",
-]
-
-[[package]]
-name = "pallet-authority-discovery"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-session",
- "parity-scale-codec",
- "serde",
- "sp-application-crypto",
- "sp-authority-discovery",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-authorship"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "impl-trait-for-tuples",
- "parity-scale-codec",
- "sp-authorship",
- "sp-inherents",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-babe"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-authorship",
- "pallet-session",
- "pallet-timestamp",
- "parity-scale-codec",
- "serde",
- "sp-application-crypto",
- "sp-consensus-babe",
- "sp-consensus-vrf",
- "sp-inherents",
- "sp-io",
- "sp-runtime",
- "sp-session",
- "sp-staking",
- "sp-std",
- "sp-timestamp",
-]
-
-[[package]]
-name = "pallet-balances"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "serde",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-common"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-timestamp",
- "parity-scale-codec",
- "serde",
- "sp-runtime",
- "strum 0.19.5",
- "strum_macros 0.19.4",
-]
-
-[[package]]
-name = "pallet-constitution"
-version = "1.0.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-content-directory"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-content-working-group"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-hiring",
- "pallet-membership",
- "pallet-recurring-reward",
- "pallet-stake",
- "pallet-timestamp",
- "pallet-token-mint",
- "pallet-versioned-store",
- "pallet-versioned-store-permissions",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-finality-tracker"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "impl-trait-for-tuples",
- "parity-scale-codec",
- "serde",
- "sp-finality-tracker",
- "sp-inherents",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-forum"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-common",
- "pallet-timestamp",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-governance"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-membership",
- "pallet-recurring-reward",
- "pallet-timestamp",
- "pallet-token-mint",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-grandpa"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-authorship",
- "pallet-finality-tracker",
- "pallet-session",
- "parity-scale-codec",
- "serde",
- "sp-application-crypto",
- "sp-core",
- "sp-finality-grandpa",
- "sp-runtime",
- "sp-session",
- "sp-staking",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-hiring"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "mockall",
- "pallet-balances",
- "pallet-stake",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-im-online"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-authorship",
- "pallet-session",
- "parity-scale-codec",
- "serde",
- "sp-application-crypto",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-staking",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-membership"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-timestamp",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-memo"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-common",
- "parity-scale-codec",
- "sp-arithmetic",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-offences"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "parity-scale-codec",
- "serde",
- "sp-runtime",
- "sp-staking",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-offences-benchmarking"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-babe",
- "pallet-balances",
- "pallet-grandpa",
- "pallet-im-online",
- "pallet-offences",
- "pallet-session",
- "pallet-staking",
- "parity-scale-codec",
- "sp-runtime",
- "sp-staking",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-proposals-codex"
-version = "4.0.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-constitution",
- "pallet-governance",
- "pallet-hiring",
- "pallet-membership",
- "pallet-proposals-discussion",
- "pallet-proposals-engine",
- "pallet-recurring-reward",
- "pallet-stake",
- "pallet-staking",
- "pallet-staking-reward-curve",
- "pallet-timestamp",
- "pallet-token-mint",
- "pallet-working-group",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-staking",
- "sp-std",
- "strum 0.19.5",
-]
-
-[[package]]
-name = "pallet-proposals-discussion"
-version = "4.0.0"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-membership",
- "pallet-timestamp",
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-proposals-engine"
-version = "4.0.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-membership",
- "pallet-timestamp",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-randomness-collective-flip"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "safe-mix",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-recurring-reward"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-token-mint",
- "parity-scale-codec",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
-]
-
-[[package]]
-name = "pallet-service-discovery"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-hiring",
- "pallet-membership",
- "pallet-recurring-reward",
- "pallet-stake",
- "pallet-timestamp",
- "pallet-token-mint",
- "pallet-working-group",
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-session"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "impl-trait-for-tuples",
- "pallet-timestamp",
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-session",
- "sp-staking",
- "sp-std",
- "sp-trie",
-]
-
-[[package]]
-name = "pallet-session-benchmarking"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-session",
- "pallet-staking",
- "rand 0.7.3",
- "sp-runtime",
- "sp-session",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-stake"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-timestamp",
- "parity-scale-codec",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-staking"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-authorship",
- "pallet-session",
- "parity-scale-codec",
- "rand_chacha 0.2.2",
- "serde",
- "sp-application-crypto",
- "sp-io",
- "sp-npos-elections",
- "sp-runtime",
- "sp-staking",
- "sp-std",
- "static_assertions",
-]
-
-[[package]]
-name = "pallet-staking-reward-curve"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "pallet-storage"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-hiring",
- "pallet-membership",
- "pallet-recurring-reward",
- "pallet-stake",
- "pallet-timestamp",
- "pallet-token-mint",
- "pallet-working-group",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-sudo"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "serde",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-timestamp"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "impl-trait-for-tuples",
- "parity-scale-codec",
- "serde",
- "sp-inherents",
- "sp-io",
- "sp-runtime",
- "sp-std",
- "sp-timestamp",
-]
-
-[[package]]
-name = "pallet-token-mint"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "parity-scale-codec",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
-]
-
-[[package]]
-name = "pallet-transaction-payment"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-transaction-payment-rpc-runtime-api",
- "parity-scale-codec",
- "serde",
- "smallvec 1.4.2",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-transaction-payment-rpc"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "jsonrpc-core",
- "jsonrpc-core-client",
- "jsonrpc-derive",
- "pallet-transaction-payment-rpc-runtime-api",
- "parity-scale-codec",
- "serde",
- "sp-api",
- "sp-blockchain",
- "sp-core",
- "sp-rpc",
- "sp-runtime",
-]
-
-[[package]]
-name = "pallet-transaction-payment-rpc-runtime-api"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-support",
- "parity-scale-codec",
- "serde",
- "sp-api",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-utility"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-versioned-store"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-common",
- "pallet-timestamp",
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-versioned-store-permissions"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-common",
- "pallet-timestamp",
- "pallet-versioned-store",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-working-group"
-version = "3.1.0"
-dependencies = [
- "frame-support",
- "frame-system",
- "pallet-balances",
- "pallet-common",
- "pallet-hiring",
- "pallet-membership",
- "pallet-recurring-reward",
- "pallet-stake",
- "pallet-timestamp",
- "pallet-token-mint",
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "parity-db"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00d595e372d119261593297debbe4193811a4dc811d2a1ccbb8caaa6666ad7ab"
-dependencies = [
- "blake2-rfc",
- "crc32fast",
- "libc",
- "log",
- "memmap",
- "parking_lot 0.10.2",
-]
-
-[[package]]
-name = "parity-multiaddr"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22fe99b938abd57507e37f8d4ef30cd74b33c71face2809b37b8beb71bab15ab"
-dependencies = [
- "arrayref",
- "bs58 0.4.0",
- "byteorder 1.3.4",
- "data-encoding",
- "multihash",
- "percent-encoding 2.1.0",
- "serde",
- "static_assertions",
- "unsigned-varint 0.5.1",
- "url 2.2.0",
-]
-
-[[package]]
-name = "parity-scale-codec"
-version = "1.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c740e5fbcb6847058b40ac7e5574766c6388f585e184d769910fe0d3a2ca861"
-dependencies = [
- "arrayvec 0.5.2",
- "bitvec",
- "byte-slice-cast",
- "parity-scale-codec-derive",
- "serde",
-]
-
-[[package]]
-name = "parity-scale-codec-derive"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "198db82bb1c18fc00176004462dd809b2a6d851669550aa17af6dacd21ae0c14"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "parity-send-wrapper"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f"
-
-[[package]]
-name = "parity-tokio-ipc"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e57fea504fea33f9fbb5f49f378359030e7e026a6ab849bb9e8f0787376f1bf"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "libc",
- "log",
- "mio-named-pipes",
- "miow 0.3.5",
- "rand 0.7.3",
- "tokio 0.1.22",
- "tokio-named-pipes",
- "tokio-uds",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "parity-util-mem"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "297ff91fa36aec49ce183484b102f6b75b46776822bd81525bfc4cc9b0dd0f5c"
-dependencies = [
- "cfg-if 0.1.10",
- "hashbrown 0.8.2",
- "impl-trait-for-tuples",
- "parity-util-mem-derive",
- "parking_lot 0.10.2",
- "primitive-types",
- "smallvec 1.4.2",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "parity-util-mem-derive"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2"
-dependencies = [
- "proc-macro2",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "parity-wasm"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865"
-
-[[package]]
-name = "parity-ws"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e02a625dd75084c2a7024f07c575b61b782f729d18702dabb3cdbf31911dc61"
-dependencies = [
- "byteorder 1.3.4",
- "bytes 0.4.12",
- "httparse",
- "log",
- "mio",
- "mio-extras",
- "rand 0.7.3",
- "sha-1 0.8.2",
- "slab",
- "url 2.2.0",
-]
-
-[[package]]
-name = "parking"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
-
-[[package]]
-name = "parking_lot"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
-dependencies = [
- "lock_api 0.1.5",
- "parking_lot_core 0.4.0",
-]
-
-[[package]]
-name = "parking_lot"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
-dependencies = [
- "lock_api 0.3.4",
- "parking_lot_core 0.6.2",
- "rustc_version",
-]
-
-[[package]]
-name = "parking_lot"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
-dependencies = [
- "lock_api 0.3.4",
- "parking_lot_core 0.7.2",
-]
-
-[[package]]
-name = "parking_lot"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
-dependencies = [
- "instant",
- "lock_api 0.4.1",
- "parking_lot_core 0.8.0",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
-dependencies = [
- "libc",
- "rand 0.6.5",
- "rustc_version",
- "smallvec 0.6.13",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
-dependencies = [
- "cfg-if 0.1.10",
- "cloudabi 0.0.3",
- "libc",
- "redox_syscall",
- "rustc_version",
- "smallvec 0.6.13",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
-dependencies = [
- "cfg-if 0.1.10",
- "cloudabi 0.0.3",
- "libc",
- "redox_syscall",
- "smallvec 1.4.2",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
-dependencies = [
- "cfg-if 0.1.10",
- "cloudabi 0.1.0",
- "instant",
- "libc",
- "redox_syscall",
- "smallvec 1.4.2",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "paste"
-version = "0.1.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
-dependencies = [
- "paste-impl",
- "proc-macro-hack",
-]
-
-[[package]]
-name = "paste-impl"
-version = "0.1.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
-dependencies = [
- "proc-macro-hack",
-]
-
-[[package]]
-name = "pbkdf2"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9"
-dependencies = [
- "byteorder 1.3.4",
- "crypto-mac 0.7.0",
- "rayon",
-]
-
-[[package]]
-name = "pdqselect"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27"
-
-[[package]]
-name = "peeking_take_while"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
-
-[[package]]
-name = "percent-encoding"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
-
-[[package]]
-name = "percent-encoding"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
-
-[[package]]
-name = "petgraph"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
-dependencies = [
- "fixedbitset",
- "indexmap",
-]
-
-[[package]]
-name = "pin-project"
-version = "0.4.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15"
-dependencies = [
- "pin-project-internal 0.4.27",
-]
-
-[[package]]
-name = "pin-project"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841"
-dependencies = [
- "pin-project-internal 1.0.1",
-]
-
-[[package]]
-name = "pin-project-internal"
-version = "0.4.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "pin-project-internal"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "pin-project-lite"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "pkg-config"
-version = "0.3.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
-
-[[package]]
-name = "platforms"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "feb3b2b1033b8a60b4da6ee470325f887758c95d5320f52f9ce0df055a55940e"
-
-[[package]]
-name = "polling"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "log",
- "wepoll-sys",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "poly1305"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22ce46de8e53ee414ca4d02bfefac75d8c12fba948b76622a40b4be34dfce980"
-dependencies = [
- "universal-hash",
-]
-
-[[package]]
-name = "polyval"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5884790f1ce3553ad55fec37b5aaac5882e0e845a2612df744d6c85c9bf046c"
-dependencies = [
- "cfg-if 0.1.10",
- "universal-hash",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
-
-[[package]]
-name = "predicates"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96bfead12e90dccead362d62bb2c90a5f6fc4584963645bc7f71a735e0b0735a"
-dependencies = [
- "difference",
- "float-cmp",
- "normalize-line-endings",
- "predicates-core",
- "regex",
-]
-
-[[package]]
-name = "predicates-core"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178"
-
-[[package]]
-name = "predicates-tree"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124"
-dependencies = [
- "predicates-core",
- "treeline",
-]
-
-[[package]]
-name = "primitive-types"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8"
-dependencies = [
- "fixed-hash",
- "impl-codec",
- "impl-serde",
- "uint",
-]
-
-[[package]]
-name = "proc-macro-crate"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
-dependencies = [
- "toml",
-]
-
-[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
-dependencies = [
- "proc-macro2",
- "quote",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-hack"
-version = "0.5.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
-
-[[package]]
-name = "proc-macro-nested"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "prometheus"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30d70cf4412832bcac9cffe27906f4a66e450d323525e977168c70d1b36120ae"
-dependencies = [
- "cfg-if 0.1.10",
- "fnv",
- "lazy_static",
- "parking_lot 0.11.0",
- "regex",
- "thiserror",
-]
-
-[[package]]
-name = "prost"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212"
-dependencies = [
- "bytes 0.5.6",
- "prost-derive",
-]
-
-[[package]]
-name = "prost-build"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b10678c913ecbd69350e8535c3aef91a8676c0773fc1d7b95cdd196d7f2f26"
-dependencies = [
- "bytes 0.5.6",
- "heck",
- "itertools",
- "log",
- "multimap",
- "petgraph",
- "prost",
- "prost-types",
- "tempfile",
- "which",
-]
-
-[[package]]
-name = "prost-derive"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72"
-dependencies = [
- "anyhow",
- "itertools",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "prost-types"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1834f67c0697c001304b75be76f67add9c89742eda3a085ad8ee0bb38c3417aa"
-dependencies = [
- "bytes 0.5.6",
- "prost",
-]
-
-[[package]]
-name = "quick-error"
-version = "1.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
-
-[[package]]
-name = "quicksink"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858"
-dependencies = [
- "futures-core",
- "futures-sink",
- "pin-project-lite",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "radium"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac"
-
-[[package]]
-name = "rand"
-version = "0.3.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
-dependencies = [
- "libc",
- "rand 0.4.6",
-]
-
-[[package]]
-name = "rand"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
-dependencies = [
- "fuchsia-cprng",
- "libc",
- "rand_core 0.3.1",
- "rdrand",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "rand"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
-dependencies = [
- "cloudabi 0.0.3",
- "fuchsia-cprng",
- "libc",
- "rand_core 0.3.1",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "rand"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
-dependencies = [
- "autocfg 0.1.7",
- "libc",
- "rand_chacha 0.1.1",
- "rand_core 0.4.2",
- "rand_hc 0.1.0",
- "rand_isaac",
- "rand_jitter",
- "rand_os",
- "rand_pcg 0.1.2",
- "rand_xorshift",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom 0.1.15",
- "libc",
- "rand_chacha 0.2.2",
- "rand_core 0.5.1",
- "rand_hc 0.2.0",
- "rand_pcg 0.2.1",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
-dependencies = [
- "autocfg 0.1.7",
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core 0.5.1",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
-
-[[package]]
-name = "rand_core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
-dependencies = [
- "getrandom 0.1.15",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
-dependencies = [
- "rand_core 0.5.1",
-]
-
-[[package]]
-name = "rand_isaac"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_jitter"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
-dependencies = [
- "libc",
- "rand_core 0.4.2",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "rand_os"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
-dependencies = [
- "cloudabi 0.0.3",
- "fuchsia-cprng",
- "libc",
- "rand_core 0.4.2",
- "rdrand",
- "wasm-bindgen",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "rand_pcg"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
-dependencies = [
- "autocfg 0.1.7",
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_pcg"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
-dependencies = [
- "rand_core 0.5.1",
-]
-
-[[package]]
-name = "rand_xorshift"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rawpointer"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
-
-[[package]]
-name = "rayon"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
-dependencies = [
- "autocfg 1.0.1",
- "crossbeam-deque 0.8.0",
- "either",
- "rayon-core",
-]
-
-[[package]]
-name = "rayon-core"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
-dependencies = [
- "crossbeam-channel",
- "crossbeam-deque 0.8.0",
- "crossbeam-utils 0.8.0",
- "lazy_static",
- "num_cpus",
-]
-
-[[package]]
-name = "rdrand"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.1.57"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
-
-[[package]]
-name = "redox_users"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
-dependencies = [
- "getrandom 0.1.15",
- "redox_syscall",
- "rust-argon2",
-]
-
-[[package]]
-name = "ref-cast"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17626b2f4bcf35b84bf379072a66e28cfe5c3c6ae58b38e4914bb8891dabece"
-dependencies = [
- "ref-cast-impl",
-]
-
-[[package]]
-name = "ref-cast-impl"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c523ccaed8ac4b0288948849a350b37d3035827413c458b6a40ddb614bb4f72"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "regex"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
- "thread_local",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
-dependencies = [
- "byteorder 1.3.4",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "retain_mut"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e005d658ad26eacc2b6c506dfde519f4e277e328d0eb3379ca61647d70a8f531"
-
-[[package]]
-name = "ring"
-version = "0.16.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4"
-dependencies = [
- "cc",
- "libc",
- "once_cell 1.4.1",
- "spin",
- "untrusted",
- "web-sys",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "rocksdb"
-version = "0.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23d83c02c429044d58474eaf5ae31e062d0de894e21125b47437ec0edc1397e6"
-dependencies = [
- "libc",
- "librocksdb-sys",
-]
-
-[[package]]
-name = "rpassword"
-version = "4.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f"
-dependencies = [
- "libc",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "rust-argon2"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19"
-dependencies = [
- "base64 0.12.3",
- "blake2b_simd",
- "constant_time_eq",
- "crossbeam-utils 0.7.2",
-]
-
-[[package]]
-name = "rustc-demangle"
-version = "0.1.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
-
-[[package]]
-name = "rustc-hash"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "rustc-hex"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
-
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "rustls"
-version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81"
-dependencies = [
- "base64 0.12.3",
- "log",
- "ring",
- "sct",
- "webpki",
-]
-
-[[package]]
-name = "rustls-native-certs"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "629d439a7672da82dd955498445e496ee2096fe2117b9f796558a43fdb9e59b8"
-dependencies = [
- "openssl-probe",
- "rustls",
- "schannel",
- "security-framework",
-]
-
-[[package]]
-name = "rw-stream-sink"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020"
-dependencies = [
- "futures 0.3.8",
- "pin-project 0.4.27",
- "static_assertions",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
-
-[[package]]
-name = "safe-mix"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d3d055a2582e6b00ed7a31c1524040aa391092bf636328350813f3a0605215c"
-dependencies = [
- "rustc_version",
-]
-
-[[package]]
-name = "salsa20"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7f47b10fa80f6969bbbd9c8e7cc998f082979d402a9e10579e2303a87955395"
-dependencies = [
- "stream-cipher",
-]
-
-[[package]]
-name = "sc-authority-discovery"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "bytes 0.5.6",
- "derive_more",
- "either",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "libp2p",
- "log",
- "parity-scale-codec",
- "prost",
- "prost-build",
- "rand 0.7.3",
- "sc-client-api",
- "sc-keystore",
- "sc-network",
- "serde_json",
- "sp-api",
- "sp-authority-discovery",
- "sp-blockchain",
- "sp-core",
- "sp-runtime",
- "substrate-prometheus-endpoint",
-]
-
-[[package]]
-name = "sc-basic-authorship"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "log",
- "parity-scale-codec",
- "sc-block-builder",
- "sc-client-api",
- "sc-proposer-metrics",
- "sc-telemetry",
- "sp-api",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-inherents",
- "sp-runtime",
- "sp-transaction-pool",
- "substrate-prometheus-endpoint",
- "tokio-executor 0.2.0-alpha.6",
-]
-
-[[package]]
-name = "sc-block-builder"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sc-client-api",
- "sp-api",
- "sp-block-builder",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-inherents",
- "sp-runtime",
- "sp-state-machine",
-]
-
-[[package]]
-name = "sc-chain-spec"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "impl-trait-for-tuples",
- "parity-scale-codec",
- "sc-chain-spec-derive",
- "sc-network",
- "sc-telemetry",
- "serde",
- "serde_json",
- "sp-chain-spec",
- "sp-core",
- "sp-runtime",
-]
-
-[[package]]
-name = "sc-chain-spec-derive"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "sc-cli"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "ansi_term 0.12.1",
- "atty",
- "bip39",
- "chrono",
- "derive_more",
- "fdlimit",
- "futures 0.3.8",
- "hex",
- "lazy_static",
- "libp2p",
- "log",
- "names",
- "nix",
- "parity-scale-codec",
- "parity-util-mem",
- "rand 0.7.3",
- "regex",
- "rpassword",
- "sc-client-api",
- "sc-informant",
- "sc-keystore",
- "sc-network",
- "sc-service",
- "sc-telemetry",
- "sc-tracing",
- "serde",
- "serde_json",
- "sp-blockchain",
- "sp-core",
- "sp-keyring",
- "sp-panic-handler",
- "sp-runtime",
- "sp-state-machine",
- "sp-utils",
- "sp-version",
- "structopt",
- "substrate-prometheus-endpoint",
- "time",
- "tokio 0.2.22",
- "tracing",
- "tracing-log",
- "tracing-subscriber",
-]
-
-[[package]]
-name = "sc-client-api"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "fnv",
- "futures 0.3.8",
- "hash-db",
- "hex-literal 0.2.1",
- "kvdb",
- "lazy_static",
- "log",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sc-executor",
- "sc-telemetry",
- "sp-api",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-database",
- "sp-externalities",
- "sp-inherents",
- "sp-keyring",
- "sp-runtime",
- "sp-state-machine",
- "sp-std",
- "sp-storage",
- "sp-transaction-pool",
- "sp-trie",
- "sp-utils",
- "sp-version",
- "substrate-prometheus-endpoint",
-]
-
-[[package]]
-name = "sc-client-db"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "blake2-rfc",
- "hash-db",
- "kvdb",
- "kvdb-memorydb",
- "kvdb-rocksdb",
- "linked-hash-map",
- "log",
- "parity-db",
- "parity-scale-codec",
- "parity-util-mem",
- "parking_lot 0.10.2",
- "sc-client-api",
- "sc-executor",
- "sc-state-db",
- "sp-arithmetic",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-database",
- "sp-runtime",
- "sp-state-machine",
- "sp-trie",
- "substrate-prometheus-endpoint",
-]
-
-[[package]]
-name = "sc-consensus"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "sc-client-api",
- "sp-blockchain",
- "sp-consensus",
- "sp-runtime",
-]
-
-[[package]]
-name = "sc-consensus-babe"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "fork-tree",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "log",
- "merlin",
- "num-bigint",
- "num-rational",
- "num-traits",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "pdqselect",
- "rand 0.7.3",
- "retain_mut",
- "sc-client-api",
- "sc-consensus-epochs",
- "sc-consensus-slots",
- "sc-consensus-uncles",
- "sc-keystore",
- "sc-telemetry",
- "schnorrkel",
- "serde",
- "sp-api",
- "sp-application-crypto",
- "sp-block-builder",
- "sp-blockchain",
- "sp-consensus",
- "sp-consensus-babe",
- "sp-consensus-vrf",
- "sp-core",
- "sp-inherents",
- "sp-io",
- "sp-runtime",
- "sp-timestamp",
- "sp-utils",
- "sp-version",
- "substrate-prometheus-endpoint",
-]
-
-[[package]]
-name = "sc-consensus-babe-rpc"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "futures 0.3.8",
- "jsonrpc-core",
- "jsonrpc-core-client",
- "jsonrpc-derive",
- "sc-consensus-babe",
- "sc-consensus-epochs",
- "sc-keystore",
- "sc-rpc-api",
- "serde",
- "sp-api",
- "sp-application-crypto",
- "sp-blockchain",
- "sp-consensus",
- "sp-consensus-babe",
- "sp-core",
- "sp-runtime",
-]
-
-[[package]]
-name = "sc-consensus-epochs"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "fork-tree",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sc-client-api",
- "sp-blockchain",
- "sp-runtime",
-]
-
-[[package]]
-name = "sc-consensus-slots"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "log",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sc-client-api",
- "sc-telemetry",
- "sp-api",
- "sp-application-crypto",
- "sp-blockchain",
- "sp-consensus",
- "sp-consensus-slots",
- "sp-core",
- "sp-inherents",
- "sp-runtime",
- "sp-state-machine",
-]
-
-[[package]]
-name = "sc-consensus-uncles"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "log",
- "sc-client-api",
- "sp-authorship",
- "sp-consensus",
- "sp-core",
- "sp-inherents",
- "sp-runtime",
-]
-
-[[package]]
-name = "sc-executor"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "lazy_static",
- "libsecp256k1",
- "log",
- "parity-scale-codec",
- "parity-wasm",
- "parking_lot 0.10.2",
- "sc-executor-common",
- "sc-executor-wasmi",
- "sp-api",
- "sp-core",
- "sp-externalities",
- "sp-io",
- "sp-panic-handler",
- "sp-runtime-interface",
- "sp-serializer",
- "sp-trie",
- "sp-version",
- "sp-wasm-interface",
- "wasmi",
-]
-
-[[package]]
-name = "sc-executor-common"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "log",
- "parity-scale-codec",
- "parity-wasm",
- "sp-allocator",
- "sp-core",
- "sp-runtime-interface",
- "sp-serializer",
- "sp-wasm-interface",
- "wasmi",
-]
-
-[[package]]
-name = "sc-executor-wasmi"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "log",
- "parity-scale-codec",
- "sc-executor-common",
- "sp-allocator",
- "sp-core",
- "sp-runtime-interface",
- "sp-wasm-interface",
- "wasmi",
-]
-
-[[package]]
-name = "sc-finality-grandpa"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "finality-grandpa",
- "fork-tree",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "log",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "pin-project 0.4.27",
- "rand 0.7.3",
- "sc-block-builder",
- "sc-client-api",
- "sc-consensus",
- "sc-keystore",
- "sc-network",
- "sc-network-gossip",
- "sc-telemetry",
- "serde_json",
- "sp-api",
- "sp-application-crypto",
- "sp-arithmetic",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-finality-grandpa",
- "sp-finality-tracker",
- "sp-inherents",
- "sp-runtime",
- "sp-utils",
- "substrate-prometheus-endpoint",
-]
-
-[[package]]
-name = "sc-finality-grandpa-rpc"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "finality-grandpa",
- "futures 0.3.8",
- "jsonrpc-core",
- "jsonrpc-core-client",
- "jsonrpc-derive",
- "jsonrpc-pubsub",
- "log",
- "parity-scale-codec",
- "sc-client-api",
- "sc-finality-grandpa",
- "sc-rpc",
- "serde",
- "serde_json",
- "sp-blockchain",
- "sp-core",
- "sp-runtime",
-]
-
-[[package]]
-name = "sc-informant"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "ansi_term 0.12.1",
- "futures 0.3.8",
- "log",
- "parity-util-mem",
- "sc-client-api",
- "sc-network",
- "sp-blockchain",
- "sp-runtime",
- "sp-transaction-pool",
- "sp-utils",
- "wasm-timer",
-]
-
-[[package]]
-name = "sc-keystore"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "hex",
- "merlin",
- "parking_lot 0.10.2",
- "rand 0.7.3",
- "serde_json",
- "sp-application-crypto",
- "sp-core",
- "subtle 2.3.0",
-]
-
-[[package]]
-name = "sc-light"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "hash-db",
- "lazy_static",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sc-client-api",
- "sc-executor",
- "sp-api",
- "sp-blockchain",
- "sp-core",
- "sp-externalities",
- "sp-runtime",
- "sp-state-machine",
-]
-
-[[package]]
-name = "sc-network"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "async-std",
- "async-trait",
- "bitflags",
- "bs58 0.3.1",
- "bytes 0.5.6",
- "derive_more",
- "either",
- "erased-serde",
- "fnv",
- "fork-tree",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "futures_codec",
- "hex",
- "ip_network",
- "libp2p",
- "linked-hash-map",
- "linked_hash_set",
- "log",
- "lru 0.4.3",
- "nohash-hasher",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "pin-project 0.4.27",
- "prost",
- "prost-build",
- "rand 0.7.3",
- "sc-block-builder",
- "sc-client-api",
- "sc-peerset",
- "serde",
- "serde_json",
- "slog",
- "slog_derive",
- "smallvec 0.6.13",
- "sp-arithmetic",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-runtime",
- "sp-utils",
- "substrate-prometheus-endpoint",
- "thiserror",
- "unsigned-varint 0.4.0",
- "void",
- "wasm-timer",
- "zeroize",
-]
-
-[[package]]
-name = "sc-network-gossip"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "libp2p",
- "log",
- "lru 0.4.3",
- "sc-network",
- "sp-runtime",
- "wasm-timer",
-]
-
-[[package]]
-name = "sc-offchain"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "bytes 0.5.6",
- "fnv",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "hyper 0.13.9",
- "hyper-rustls",
- "log",
- "num_cpus",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "rand 0.7.3",
- "sc-client-api",
- "sc-keystore",
- "sc-network",
- "sp-api",
- "sp-core",
- "sp-offchain",
- "sp-runtime",
- "sp-utils",
- "threadpool",
-]
-
-[[package]]
-name = "sc-peerset"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "libp2p",
- "log",
- "serde_json",
- "sp-utils",
- "wasm-timer",
-]
-
-[[package]]
-name = "sc-proposer-metrics"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "log",
- "substrate-prometheus-endpoint",
-]
-
-[[package]]
-name = "sc-rpc"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "hash-db",
- "jsonrpc-core",
- "jsonrpc-pubsub",
- "log",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sc-block-builder",
- "sc-client-api",
- "sc-executor",
- "sc-keystore",
- "sc-rpc-api",
- "serde_json",
- "sp-api",
- "sp-blockchain",
- "sp-chain-spec",
- "sp-core",
- "sp-offchain",
- "sp-rpc",
- "sp-runtime",
- "sp-session",
- "sp-state-machine",
- "sp-transaction-pool",
- "sp-utils",
- "sp-version",
-]
-
-[[package]]
-name = "sc-rpc-api"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "futures 0.3.8",
- "jsonrpc-core",
- "jsonrpc-core-client",
- "jsonrpc-derive",
- "jsonrpc-pubsub",
- "log",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "serde",
- "serde_json",
- "sp-chain-spec",
- "sp-core",
- "sp-rpc",
- "sp-runtime",
- "sp-transaction-pool",
- "sp-version",
-]
-
-[[package]]
-name = "sc-rpc-server"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.1.30",
- "jsonrpc-core",
- "jsonrpc-http-server",
- "jsonrpc-ipc-server",
- "jsonrpc-pubsub",
- "jsonrpc-ws-server",
- "log",
- "serde",
- "serde_json",
- "sp-runtime",
- "substrate-prometheus-endpoint",
-]
-
-[[package]]
-name = "sc-service"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "directories",
- "exit-future",
- "futures 0.1.30",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "hash-db",
- "jsonrpc-core",
- "jsonrpc-pubsub",
- "lazy_static",
- "log",
- "parity-scale-codec",
- "parity-util-mem",
- "parking_lot 0.10.2",
- "pin-project 0.4.27",
- "rand 0.7.3",
- "sc-block-builder",
- "sc-chain-spec",
- "sc-client-api",
- "sc-client-db",
- "sc-executor",
- "sc-informant",
- "sc-keystore",
- "sc-light",
- "sc-network",
- "sc-offchain",
- "sc-rpc",
- "sc-rpc-server",
- "sc-telemetry",
- "sc-tracing",
- "sc-transaction-pool",
- "serde",
- "serde_json",
- "slog",
- "sp-api",
- "sp-application-crypto",
- "sp-block-builder",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-externalities",
- "sp-inherents",
- "sp-io",
- "sp-runtime",
- "sp-session",
- "sp-state-machine",
- "sp-tracing",
- "sp-transaction-pool",
- "sp-trie",
- "sp-utils",
- "sp-version",
- "substrate-prometheus-endpoint",
- "tempfile",
- "tracing",
- "wasm-timer",
-]
-
-[[package]]
-name = "sc-service-test"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "fdlimit",
- "futures 0.1.30",
- "futures 0.3.8",
- "hex-literal 0.2.1",
- "log",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sc-block-builder",
- "sc-client-api",
- "sc-client-db",
- "sc-executor",
- "sc-light",
- "sc-network",
- "sc-service",
- "sp-api",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-externalities",
- "sp-panic-handler",
- "sp-runtime",
- "sp-state-machine",
- "sp-storage",
- "sp-tracing",
- "sp-transaction-pool",
- "sp-trie",
- "substrate-test-runtime",
- "substrate-test-runtime-client",
- "tempfile",
- "tokio 0.1.22",
-]
-
-[[package]]
-name = "sc-state-db"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "log",
- "parity-scale-codec",
- "parity-util-mem",
- "parity-util-mem-derive",
- "parking_lot 0.10.2",
- "sc-client-api",
- "sp-core",
-]
-
-[[package]]
-name = "sc-telemetry"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "libp2p",
- "log",
- "parking_lot 0.10.2",
- "pin-project 0.4.27",
- "rand 0.7.3",
- "serde",
- "slog",
- "slog-json",
- "slog-scope",
- "take_mut",
- "void",
- "wasm-timer",
-]
-
-[[package]]
-name = "sc-tracing"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "erased-serde",
- "log",
- "parking_lot 0.10.2",
- "rustc-hash",
- "sc-telemetry",
- "serde",
- "serde_json",
- "slog",
- "sp-tracing",
- "tracing",
- "tracing-core",
- "tracing-subscriber",
-]
-
-[[package]]
-name = "sc-transaction-graph"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "futures 0.3.8",
- "linked-hash-map",
- "log",
- "parity-util-mem",
- "parking_lot 0.10.2",
- "retain_mut",
- "serde",
- "sp-blockchain",
- "sp-core",
- "sp-runtime",
- "sp-transaction-pool",
- "sp-utils",
- "wasm-timer",
-]
-
-[[package]]
-name = "sc-transaction-pool"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "futures 0.3.8",
- "futures-diagnose",
- "intervalier",
- "log",
- "parity-scale-codec",
- "parity-util-mem",
- "parking_lot 0.10.2",
- "sc-client-api",
- "sc-transaction-graph",
- "sp-api",
- "sp-blockchain",
- "sp-core",
- "sp-runtime",
- "sp-tracing",
- "sp-transaction-pool",
- "sp-utils",
- "substrate-prometheus-endpoint",
- "wasm-timer",
-]
-
-[[package]]
-name = "schannel"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
-dependencies = [
- "lazy_static",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "schnorrkel"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862"
-dependencies = [
- "arrayref",
- "arrayvec 0.5.2",
- "curve25519-dalek 2.1.0",
- "getrandom 0.1.15",
- "merlin",
- "rand 0.7.3",
- "rand_core 0.5.1",
- "sha2 0.8.2",
- "subtle 2.3.0",
- "zeroize",
-]
-
-[[package]]
-name = "scoped-tls"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
-
-[[package]]
-name = "scopeguard"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[package]]
-name = "sct"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
-dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
-name = "secrecy"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9182278ed645df3477a9c27bfee0621c621aa16f6972635f7f795dae3d81070f"
-dependencies = [
- "zeroize",
-]
-
-[[package]]
-name = "security-framework"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad502866817f0575705bd7be36e2b2535cc33262d493aa733a2ec862baa2bc2b"
-dependencies = [
- "bitflags",
- "core-foundation",
- "core-foundation-sys",
- "libc",
- "security-framework-sys",
-]
-
-[[package]]
-name = "security-framework-sys"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51ceb04988b17b6d1dcd555390fa822ca5637b4a14e1f5099f13d351bed4d6c7"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
-[[package]]
-name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-
-[[package]]
-name = "send_wrapper"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "686ef91cf020ad8d4aca9a7047641fd6add626b7b89e14546c2b6a76781cf822"
-
-[[package]]
-name = "send_wrapper"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0"
-
-[[package]]
-name = "serde"
-version = "1.0.117"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.117"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_derive_internals"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.59"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
-dependencies = [
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "sha-1"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
-dependencies = [
- "block-buffer 0.7.3",
- "digest 0.8.1",
- "fake-simd",
- "opaque-debug 0.2.3",
-]
-
-[[package]]
-name = "sha-1"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c"
-dependencies = [
- "block-buffer 0.9.0",
- "cfg-if 1.0.0",
- "cpuid-bool",
- "digest 0.9.0",
- "opaque-debug 0.3.0",
-]
-
-[[package]]
-name = "sha2"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
-dependencies = [
- "block-buffer 0.7.3",
- "digest 0.8.1",
- "fake-simd",
- "opaque-debug 0.2.3",
-]
-
-[[package]]
-name = "sha2"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8"
-dependencies = [
- "block-buffer 0.9.0",
- "cfg-if 1.0.0",
- "cpuid-bool",
- "digest 0.9.0",
- "opaque-debug 0.3.0",
-]
-
-[[package]]
-name = "sha3"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809"
-dependencies = [
- "block-buffer 0.9.0",
- "digest 0.9.0",
- "keccak",
- "opaque-debug 0.3.0",
-]
-
-[[package]]
-name = "sharded-slab"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4921be914e16899a80adefb821f8ddb7974e3f1250223575a44ed994882127"
-dependencies = [
- "lazy_static",
- "loom",
-]
-
-[[package]]
-name = "shlex"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
-
-[[package]]
-name = "signal-hook-registry"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "signature"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210"
-
-[[package]]
-name = "slab"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
-
-[[package]]
-name = "slog"
-version = "2.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cc9c640a4adbfbcc11ffb95efe5aa7af7309e002adab54b185507dbf2377b99"
-dependencies = [
- "erased-serde",
-]
-
-[[package]]
-name = "slog-json"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a"
-dependencies = [
- "chrono",
- "erased-serde",
- "serde",
- "serde_json",
- "slog",
-]
-
-[[package]]
-name = "slog-scope"
-version = "4.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6"
-dependencies = [
- "arc-swap",
- "lazy_static",
- "slog",
-]
-
-[[package]]
-name = "slog_derive"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a945ec7f7ce853e89ffa36be1e27dce9a43e82ff9093bf3461c30d5da74ed11b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "smallvec"
-version = "0.6.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
-dependencies = [
- "maybe-uninit",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
-
-[[package]]
-name = "snow"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "795dd7aeeee24468e5a32661f6d27f7b5cbed802031b2d7640c7b10f8fb2dd50"
-dependencies = [
- "aes-gcm",
- "blake2",
- "chacha20poly1305",
- "rand 0.7.3",
- "rand_core 0.5.1",
- "ring",
- "rustc_version",
- "sha2 0.9.2",
- "subtle 2.3.0",
- "x25519-dalek 1.1.0",
-]
-
-[[package]]
-name = "socket2"
-version = "0.3.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fd8b795c389288baa5f355489c65e71fd48a02104600d15c4cfbc561e9e429d"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "redox_syscall",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "soketto"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5c71ed3d54db0a699f4948e1bb3e45b450fa31fe602621dee6680361d569c88"
-dependencies = [
- "base64 0.12.3",
- "bytes 0.5.6",
- "flate2",
- "futures 0.3.8",
- "httparse",
- "log",
- "rand 0.7.3",
- "sha-1 0.9.2",
-]
-
-[[package]]
-name = "sp-allocator"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "log",
- "sp-core",
- "sp-std",
- "sp-wasm-interface",
-]
-
-[[package]]
-name = "sp-api"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "hash-db",
- "parity-scale-codec",
- "sp-api-proc-macro",
- "sp-core",
- "sp-runtime",
- "sp-state-machine",
- "sp-std",
- "sp-version",
-]
-
-[[package]]
-name = "sp-api-proc-macro"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "blake2-rfc",
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "sp-application-crypto"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "serde",
- "sp-core",
- "sp-io",
- "sp-std",
-]
-
-[[package]]
-name = "sp-arithmetic"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "integer-sqrt",
- "num-traits",
- "parity-scale-codec",
- "serde",
- "sp-debug-derive",
- "sp-std",
-]
-
-[[package]]
-name = "sp-authority-discovery"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-api",
- "sp-application-crypto",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "sp-authorship"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-inherents",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "sp-block-builder"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-api",
- "sp-inherents",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "sp-blockchain"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "log",
- "lru 0.4.3",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sp-block-builder",
- "sp-consensus",
- "sp-database",
- "sp-runtime",
- "sp-state-machine",
-]
-
-[[package]]
-name = "sp-chain-spec"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "sp-consensus"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "libp2p",
- "log",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "serde",
- "sp-api",
- "sp-core",
- "sp-inherents",
- "sp-runtime",
- "sp-state-machine",
- "sp-std",
- "sp-trie",
- "sp-utils",
- "sp-version",
- "substrate-prometheus-endpoint",
- "wasm-timer",
-]
-
-[[package]]
-name = "sp-consensus-aura"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-api",
- "sp-application-crypto",
- "sp-inherents",
- "sp-runtime",
- "sp-std",
- "sp-timestamp",
-]
-
-[[package]]
-name = "sp-consensus-babe"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "merlin",
- "parity-scale-codec",
- "sp-api",
- "sp-application-crypto",
- "sp-consensus",
- "sp-consensus-slots",
- "sp-consensus-vrf",
- "sp-core",
- "sp-inherents",
- "sp-runtime",
- "sp-std",
- "sp-timestamp",
-]
-
-[[package]]
-name = "sp-consensus-slots"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-runtime",
-]
-
-[[package]]
-name = "sp-consensus-vrf"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "schnorrkel",
- "sp-core",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "sp-core"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "base58",
- "blake2-rfc",
- "byteorder 1.3.4",
- "derive_more",
- "dyn-clonable",
- "ed25519-dalek",
- "futures 0.3.8",
- "hash-db",
- "hash256-std-hasher",
- "hex",
- "impl-serde",
- "lazy_static",
- "libsecp256k1",
- "log",
- "merlin",
- "num-traits",
- "parity-scale-codec",
- "parity-util-mem",
- "parking_lot 0.10.2",
- "primitive-types",
- "rand 0.7.3",
- "regex",
- "schnorrkel",
- "secrecy",
- "serde",
- "sha2 0.8.2",
- "sp-debug-derive",
- "sp-externalities",
- "sp-runtime-interface",
- "sp-std",
- "sp-storage",
- "substrate-bip39",
- "tiny-bip39",
- "tiny-keccak",
- "twox-hash",
- "wasmi",
- "zeroize",
-]
-
-[[package]]
-name = "sp-database"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "kvdb",
- "parking_lot 0.10.2",
-]
-
-[[package]]
-name = "sp-debug-derive"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "sp-externalities"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "environmental",
- "parity-scale-codec",
- "sp-std",
- "sp-storage",
-]
-
-[[package]]
-name = "sp-finality-grandpa"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "finality-grandpa",
- "log",
- "parity-scale-codec",
- "serde",
- "sp-api",
- "sp-application-crypto",
- "sp-core",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "sp-finality-tracker"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-inherents",
- "sp-std",
-]
-
-[[package]]
-name = "sp-inherents"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sp-core",
- "sp-std",
-]
-
-[[package]]
-name = "sp-io"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "hash-db",
- "libsecp256k1",
- "log",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "sp-core",
- "sp-externalities",
- "sp-runtime-interface",
- "sp-state-machine",
- "sp-std",
- "sp-tracing",
- "sp-trie",
- "sp-wasm-interface",
- "tracing",
- "tracing-core",
-]
-
-[[package]]
-name = "sp-keyring"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "lazy_static",
- "sp-core",
- "sp-runtime",
- "strum 0.16.0",
-]
-
-[[package]]
-name = "sp-npos-elections"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "serde",
- "sp-arithmetic",
- "sp-npos-elections-compact",
- "sp-std",
-]
-
-[[package]]
-name = "sp-npos-elections-compact"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "sp-offchain"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "sp-api",
- "sp-core",
- "sp-runtime",
-]
-
-[[package]]
-name = "sp-panic-handler"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "backtrace",
- "log",
-]
-
-[[package]]
-name = "sp-rpc"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "serde",
- "sp-core",
-]
-
-[[package]]
-name = "sp-runtime"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "either",
- "hash256-std-hasher",
- "impl-trait-for-tuples",
- "log",
- "parity-scale-codec",
- "parity-util-mem",
- "paste",
- "rand 0.7.3",
- "serde",
- "sp-application-crypto",
- "sp-arithmetic",
- "sp-core",
- "sp-inherents",
- "sp-io",
- "sp-std",
-]
-
-[[package]]
-name = "sp-runtime-interface"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "primitive-types",
- "sp-externalities",
- "sp-runtime-interface-proc-macro",
- "sp-std",
- "sp-storage",
- "sp-tracing",
- "sp-wasm-interface",
- "static_assertions",
-]
-
-[[package]]
-name = "sp-runtime-interface-proc-macro"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "Inflector",
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "sp-serializer"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "sp-session"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-api",
- "sp-core",
- "sp-runtime",
- "sp-staking",
- "sp-std",
-]
-
-[[package]]
-name = "sp-staking"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "parity-scale-codec",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "sp-state-machine"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "hash-db",
- "log",
- "num-traits",
- "parity-scale-codec",
- "parking_lot 0.10.2",
- "rand 0.7.3",
- "smallvec 1.4.2",
- "sp-core",
- "sp-externalities",
- "sp-panic-handler",
- "sp-std",
- "sp-trie",
- "trie-db",
- "trie-root",
-]
-
-[[package]]
-name = "sp-std"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-
-[[package]]
-name = "sp-storage"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "impl-serde",
- "parity-scale-codec",
- "ref-cast",
- "serde",
- "sp-debug-derive",
- "sp-std",
-]
-
-[[package]]
-name = "sp-timestamp"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "impl-trait-for-tuples",
- "parity-scale-codec",
- "sp-api",
- "sp-inherents",
- "sp-runtime",
- "sp-std",
- "wasm-timer",
-]
-
-[[package]]
-name = "sp-tracing"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "log",
- "parity-scale-codec",
- "sp-std",
- "tracing",
- "tracing-core",
- "tracing-subscriber",
-]
-
-[[package]]
-name = "sp-transaction-pool"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "derive_more",
- "futures 0.3.8",
- "log",
- "parity-scale-codec",
- "serde",
- "sp-api",
- "sp-blockchain",
- "sp-runtime",
-]
-
-[[package]]
-name = "sp-trie"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "hash-db",
- "memory-db",
- "parity-scale-codec",
- "sp-core",
- "sp-std",
- "trie-db",
- "trie-root",
-]
-
-[[package]]
-name = "sp-utils"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "futures-core",
- "futures-timer 3.0.2",
- "lazy_static",
- "prometheus",
-]
-
-[[package]]
-name = "sp-version"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "impl-serde",
- "parity-scale-codec",
- "serde",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "sp-wasm-interface"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "impl-trait-for-tuples",
- "parity-scale-codec",
- "sp-std",
- "wasmi",
-]
-
-[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
-
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "statrs"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10102ac8d55e35db2b3fafc26f81ba8647da2e15879ab686a67e6d19af2685e8"
-dependencies = [
- "rand 0.5.6",
-]
-
-[[package]]
-name = "stream-cipher"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c80e15f898d8d8f25db24c253ea615cc14acf418ff307822995814e7d42cfa89"
-dependencies = [
- "block-cipher",
- "generic-array 0.14.4",
-]
-
-[[package]]
-name = "string"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
-dependencies = [
- "bytes 0.4.12",
-]
-
-[[package]]
-name = "strsim"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
-
-[[package]]
-name = "structopt"
-version = "0.3.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8"
-dependencies = [
- "clap",
- "lazy_static",
- "structopt-derive",
-]
-
-[[package]]
-name = "structopt-derive"
-version = "0.4.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "strum"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6138f8f88a16d90134763314e3fc76fa3ed6a7db4725d6acf9a3ef95a3188d22"
-dependencies = [
- "strum_macros 0.16.0",
-]
-
-[[package]]
-name = "strum"
-version = "0.19.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b89a286a7e3b5720b9a477b23253bc50debac207c8d21505f8e70b36792f11b5"
-
-[[package]]
-name = "strum_macros"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0054a7df764039a6cd8592b9de84be4bec368ff081d203a7d5371cbfa8e65c81"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "strum_macros"
-version = "0.19.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e61bb0be289045cb80bfce000512e32d09f8337e54c186725da381377ad1f8d5"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "substrate-bip39"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bed6646a0159b9935b5d045611560eeef842b78d7adc3ba36f5ca325a13a0236"
-dependencies = [
- "hmac",
- "pbkdf2",
- "schnorrkel",
- "sha2 0.8.2",
- "zeroize",
-]
-
-[[package]]
-name = "substrate-browser-utils"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "chrono",
- "console_error_panic_hook",
- "console_log",
- "futures 0.1.30",
- "futures 0.3.8",
- "futures-timer 3.0.2",
- "js-sys",
- "kvdb-web",
- "libp2p-wasm-ext",
- "log",
- "rand 0.6.5",
- "rand 0.7.3",
- "sc-chain-spec",
- "sc-informant",
- "sc-network",
- "sc-service",
- "sp-database",
- "wasm-bindgen",
- "wasm-bindgen-futures",
-]
-
-[[package]]
-name = "substrate-build-script-utils"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "platforms",
-]
-
-[[package]]
-name = "substrate-frame-rpc-system"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "frame-system-rpc-runtime-api",
- "futures 0.3.8",
- "jsonrpc-core",
- "jsonrpc-core-client",
- "jsonrpc-derive",
- "log",
- "parity-scale-codec",
- "sc-client-api",
- "sc-rpc-api",
- "serde",
- "sp-api",
- "sp-block-builder",
- "sp-blockchain",
- "sp-core",
- "sp-runtime",
- "sp-transaction-pool",
-]
-
-[[package]]
-name = "substrate-prometheus-endpoint"
-version = "0.8.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "async-std",
- "derive_more",
- "futures-util",
- "hyper 0.13.9",
- "log",
- "prometheus",
- "tokio 0.2.22",
-]
-
-[[package]]
-name = "substrate-test-client"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.1.30",
- "futures 0.3.8",
- "hash-db",
- "hex",
- "parity-scale-codec",
- "sc-client-api",
- "sc-client-db",
- "sc-consensus",
- "sc-executor",
- "sc-light",
- "sc-service",
- "serde",
- "serde_json",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-keyring",
- "sp-runtime",
- "sp-state-machine",
-]
-
-[[package]]
-name = "substrate-test-runtime"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "cfg-if 0.1.10",
- "frame-executive",
- "frame-support",
- "frame-system",
- "frame-system-rpc-runtime-api",
- "log",
- "memory-db",
- "pallet-babe",
- "pallet-timestamp",
- "parity-scale-codec",
- "parity-util-mem",
- "sc-service",
- "serde",
- "sp-api",
- "sp-application-crypto",
- "sp-block-builder",
- "sp-consensus-aura",
- "sp-consensus-babe",
- "sp-core",
- "sp-externalities",
- "sp-finality-grandpa",
- "sp-inherents",
- "sp-io",
- "sp-keyring",
- "sp-offchain",
- "sp-runtime",
- "sp-runtime-interface",
- "sp-session",
- "sp-state-machine",
- "sp-std",
- "sp-transaction-pool",
- "sp-trie",
- "sp-version",
- "substrate-wasm-builder-runner",
- "trie-db",
-]
-
-[[package]]
-name = "substrate-test-runtime-client"
-version = "2.0.0"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-dependencies = [
- "futures 0.3.8",
- "parity-scale-codec",
- "sc-block-builder",
- "sc-client-api",
- "sc-consensus",
- "sc-light",
- "sc-service",
- "sp-api",
- "sp-blockchain",
- "sp-consensus",
- "sp-core",
- "sp-runtime",
- "substrate-test-client",
- "substrate-test-runtime",
-]
-
-[[package]]
-name = "substrate-wasm-builder-runner"
-version = "1.0.6"
-source = "git+https://github.com/paritytech/substrate.git?rev=a200cdb93c6af5763b9c7bf313fa708764ac88ca#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
-
-[[package]]
-name = "subtle"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
-
-[[package]]
-name = "subtle"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd"
-
-[[package]]
-name = "syn"
-version = "1.0.48"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.12.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "unicode-xid",
-]
-
-[[package]]
-name = "take_mut"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
-
-[[package]]
-name = "tempfile"
-version = "3.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "rand 0.7.3",
- "redox_syscall",
- "remove_dir_all",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "thread_local"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "threadpool"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
-dependencies = [
- "num_cpus",
-]
-
-[[package]]
-name = "time"
-version = "0.1.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
-dependencies = [
- "libc",
- "wasi 0.10.0+wasi-snapshot-preview1",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "tiny-bip39"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0165e045cc2ae1660270ca65e1676dbaab60feb0f91b10f7d0665e9b47e31f2"
-dependencies = [
- "failure",
- "hmac",
- "once_cell 1.4.1",
- "pbkdf2",
- "rand 0.7.3",
- "rustc-hash",
- "sha2 0.8.2",
- "unicode-normalization",
-]
-
-[[package]]
-name = "tiny-keccak"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
-dependencies = [
- "crunchy",
-]
-
-[[package]]
-name = "tinyvec"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
-
-[[package]]
-name = "tokio"
-version = "0.1.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "mio",
- "num_cpus",
- "tokio-codec",
- "tokio-current-thread",
- "tokio-executor 0.1.10",
- "tokio-fs",
- "tokio-io",
- "tokio-reactor",
- "tokio-sync 0.1.8",
- "tokio-tcp",
- "tokio-threadpool",
- "tokio-timer",
- "tokio-udp",
- "tokio-uds",
-]
-
-[[package]]
-name = "tokio"
-version = "0.2.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd"
-dependencies = [
- "bytes 0.5.6",
- "fnv",
- "futures-core",
- "iovec",
- "lazy_static",
- "libc",
- "memchr",
- "mio",
- "mio-uds",
- "num_cpus",
- "pin-project-lite",
- "signal-hook-registry",
- "slab",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "tokio-buf"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46"
-dependencies = [
- "bytes 0.4.12",
- "either",
- "futures 0.1.30",
-]
-
-[[package]]
-name = "tokio-codec"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "tokio-io",
-]
-
-[[package]]
-name = "tokio-current-thread"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e"
-dependencies = [
- "futures 0.1.30",
- "tokio-executor 0.1.10",
-]
-
-[[package]]
-name = "tokio-executor"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
-dependencies = [
- "crossbeam-utils 0.7.2",
- "futures 0.1.30",
-]
-
-[[package]]
-name = "tokio-executor"
-version = "0.2.0-alpha.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ee9ceecf69145923834ea73f32ba40c790fd877b74a7817dd0b089f1eb9c7c8"
-dependencies = [
- "futures-util-preview",
- "lazy_static",
- "tokio-sync 0.2.0-alpha.6",
-]
-
-[[package]]
-name = "tokio-fs"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4"
-dependencies = [
- "futures 0.1.30",
- "tokio-io",
- "tokio-threadpool",
-]
-
-[[package]]
-name = "tokio-io"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "log",
-]
-
-[[package]]
-name = "tokio-named-pipes"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d282d483052288b2308ba5ee795f5673b159c9bdf63c385a05609da782a5eae"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "mio",
- "mio-named-pipes",
- "tokio 0.1.22",
-]
-
-[[package]]
-name = "tokio-reactor"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
-dependencies = [
- "crossbeam-utils 0.7.2",
- "futures 0.1.30",
- "lazy_static",
- "log",
- "mio",
- "num_cpus",
- "parking_lot 0.9.0",
- "slab",
- "tokio-executor 0.1.10",
- "tokio-io",
- "tokio-sync 0.1.8",
-]
-
-[[package]]
-name = "tokio-rustls"
-version = "0.14.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a"
-dependencies = [
- "futures-core",
- "rustls",
- "tokio 0.2.22",
- "webpki",
-]
-
-[[package]]
-name = "tokio-service"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
-dependencies = [
- "futures 0.1.30",
-]
-
-[[package]]
-name = "tokio-sync"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee"
-dependencies = [
- "fnv",
- "futures 0.1.30",
-]
-
-[[package]]
-name = "tokio-sync"
-version = "0.2.0-alpha.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f1aaeb685540f7407ea0e27f1c9757d258c7c6bf4e3eb19da6fc59b747239d2"
-dependencies = [
- "fnv",
- "futures-core-preview",
- "futures-util-preview",
-]
-
-[[package]]
-name = "tokio-tcp"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "iovec",
- "mio",
- "tokio-io",
- "tokio-reactor",
-]
-
-[[package]]
-name = "tokio-threadpool"
-version = "0.1.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89"
-dependencies = [
- "crossbeam-deque 0.7.3",
- "crossbeam-queue",
- "crossbeam-utils 0.7.2",
- "futures 0.1.30",
- "lazy_static",
- "log",
- "num_cpus",
- "slab",
- "tokio-executor 0.1.10",
-]
-
-[[package]]
-name = "tokio-timer"
-version = "0.2.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296"
-dependencies = [
- "crossbeam-utils 0.7.2",
- "futures 0.1.30",
- "slab",
- "tokio-executor 0.1.10",
-]
-
-[[package]]
-name = "tokio-udp"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "log",
- "mio",
- "tokio-codec",
- "tokio-io",
- "tokio-reactor",
-]
-
-[[package]]
-name = "tokio-uds"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0"
-dependencies = [
- "bytes 0.4.12",
- "futures 0.1.30",
- "iovec",
- "libc",
- "log",
- "mio",
- "mio-uds",
- "tokio-codec",
- "tokio-io",
- "tokio-reactor",
-]
-
-[[package]]
-name = "tokio-util"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
-dependencies = [
- "bytes 0.5.6",
- "futures-core",
- "futures-sink",
- "log",
- "pin-project-lite",
- "tokio 0.2.22",
-]
-
-[[package]]
-name = "toml"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "tower-service"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
-
-[[package]]
-name = "tracing"
-version = "0.1.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27"
-dependencies = [
- "cfg-if 0.1.10",
- "log",
- "pin-project-lite",
- "tracing-attributes",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-attributes"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tracing-core"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "tracing-futures"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
-dependencies = [
- "pin-project 0.4.27",
- "tracing",
-]
-
-[[package]]
-name = "tracing-log"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e0f8c7178e13481ff6765bd169b33e8d554c5d2bbede5e32c356194be02b9b9"
-dependencies = [
- "lazy_static",
- "log",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-serde"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
-dependencies = [
- "serde",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-subscriber"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1fa8f0c8f4c594e4fc9debc1990deab13238077271ba84dd853d54902ee3401"
-dependencies = [
- "ansi_term 0.12.1",
- "chrono",
- "lazy_static",
- "matchers",
- "regex",
- "serde",
- "serde_json",
- "sharded-slab",
- "smallvec 1.4.2",
- "thread_local",
- "tracing",
- "tracing-core",
- "tracing-log",
- "tracing-serde",
-]
-
-[[package]]
-name = "treeline"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
-
-[[package]]
-name = "trie-db"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e55f7ace33d6237e14137e386f4e1672e2a5c6bbc97fef9f438581a143971f0"
-dependencies = [
- "hash-db",
- "hashbrown 0.8.2",
- "log",
- "rustc-hex",
- "smallvec 1.4.2",
-]
-
-[[package]]
-name = "trie-root"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "652931506d2c1244d7217a70b99f56718a7b4161b37f04e7cd868072a99f68cd"
-dependencies = [
- "hash-db",
-]
-
-[[package]]
-name = "try-lock"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
-
-[[package]]
-name = "twox-hash"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59"
-dependencies = [
- "cfg-if 0.1.10",
- "rand 0.7.3",
- "static_assertions",
-]
-
-[[package]]
-name = "typenum"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
-
-[[package]]
-name = "uint"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177"
-dependencies = [
- "byteorder 1.3.4",
- "crunchy",
- "rustc-hex",
- "static_assertions",
-]
-
-[[package]]
-name = "unicase"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
-dependencies = [
- "version_check",
-]
-
-[[package]]
-name = "unicode-bidi"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
-dependencies = [
- "matches",
-]
-
-[[package]]
-name = "unicode-normalization"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
-dependencies = [
- "tinyvec",
-]
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
-
-[[package]]
-name = "universal-hash"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
-dependencies = [
- "generic-array 0.14.4",
- "subtle 2.3.0",
-]
-
-[[package]]
-name = "unsigned-varint"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "669d776983b692a906c881fcd0cfb34271a48e197e4d6cb8df32b05bfc3d3fa5"
-dependencies = [
- "bytes 0.5.6",
- "futures-io",
- "futures-util",
- "futures_codec",
-]
-
-[[package]]
-name = "unsigned-varint"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7fdeedbf205afadfe39ae559b75c3240f24e257d0ca27e85f85cb82aa19ac35"
-dependencies = [
- "futures-io",
- "futures-util",
-]
-
-[[package]]
-name = "untrusted"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
-
-[[package]]
-name = "url"
-version = "1.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
-dependencies = [
- "idna 0.1.5",
- "matches",
- "percent-encoding 1.0.1",
-]
-
-[[package]]
-name = "url"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
-dependencies = [
- "form_urlencoded",
- "idna 0.2.0",
- "matches",
- "percent-encoding 2.1.0",
-]
-
-[[package]]
-name = "vcpkg"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
-
-[[package]]
-name = "vec-arena"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d"
-
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
-[[package]]
-name = "version_check"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
-
-[[package]]
-name = "void"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
-
-[[package]]
-name = "waker-fn"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
-
-[[package]]
-name = "want"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230"
-dependencies = [
- "futures 0.1.30",
- "log",
- "try-lock",
-]
-
-[[package]]
-name = "want"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
-dependencies = [
- "log",
- "try-lock",
-]
-
-[[package]]
-name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
-[[package]]
-name = "wasi"
-version = "0.10.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.68"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
-dependencies = [
- "cfg-if 0.1.10",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.68"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-futures"
-version = "0.4.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da"
-dependencies = [
- "cfg-if 0.1.10",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.68"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.68"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.68"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
-
-[[package]]
-name = "wasm-timer"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
-dependencies = [
- "futures 0.3.8",
- "js-sys",
- "parking_lot 0.11.0",
- "pin-utils",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
-]
-
-[[package]]
-name = "wasmi"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf617d864d25af3587aa745529f7aaa541066c876d57e050c0d0c85c61c92aff"
-dependencies = [
- "libc",
- "memory_units",
- "num-rational",
- "num-traits",
- "parity-wasm",
- "wasmi-validation",
-]
-
-[[package]]
-name = "wasmi-validation"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea78c597064ba73596099281e2f4cfc019075122a65cdda3205af94f0b264d93"
-dependencies = [
- "parity-wasm",
-]
-
-[[package]]
-name = "web-sys"
-version = "0.3.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "webpki"
-version = "0.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae"
-dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
-name = "webpki-roots"
-version = "0.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4"
-dependencies = [
- "webpki",
-]
-
-[[package]]
-name = "webpki-roots"
-version = "0.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739"
-dependencies = [
- "webpki",
-]
-
-[[package]]
-name = "wepoll-sys"
-version = "3.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "which"
-version = "3.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "winapi"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-build"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "ws2_32-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
-dependencies = [
- "winapi 0.2.8",
- "winapi-build",
-]
-
-[[package]]
-name = "x25519-dalek"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "637ff90c9540fa3073bb577e65033069e4bae7c79d49d74aa3ffdf5342a53217"
-dependencies = [
- "curve25519-dalek 2.1.0",
- "rand_core 0.5.1",
- "zeroize",
-]
-
-[[package]]
-name = "x25519-dalek"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc614d95359fd7afc321b66d2107ede58b246b844cf5d8a0adcca413e439f088"
-dependencies = [
- "curve25519-dalek 3.0.0",
- "rand_core 0.5.1",
- "zeroize",
-]
-
-[[package]]
-name = "yamux"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aeb8c4043cac71c3c299dff107171c220d179492350ea198e109a414981b83c"
-dependencies = [
- "futures 0.3.8",
- "log",
- "nohash-hasher",
- "parking_lot 0.11.0",
- "rand 0.7.3",
- "static_assertions",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f33972566adbd2d3588b0491eb94b98b43695c4ef897903470ede4f3f5a28a"
-dependencies = [
- "zeroize_derive",
-]
-
-[[package]]
-name = "zeroize_derive"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]

+ 3 - 3
build.sh

@@ -4,8 +4,8 @@ set -e
 
 
 yarn
 yarn
 yarn workspace @joystream/types build
 yarn workspace @joystream/types build
-yarn workspace cd-schemas generate:all
-yarn workspace cd-schemas build
+yarn workspace @joystream/cd-schemas generate:all
+yarn workspace @joystream/cd-schemas build
 yarn workspace @joystream/cli build
 yarn workspace @joystream/cli build
 yarn workspace query-node-root build
 yarn workspace query-node-root build
 yarn workspace storage-node build
 yarn workspace storage-node build
@@ -52,4 +52,4 @@ do
 
 
    * )     break;;
    * )     break;;
   esac
   esac
-done
+done

+ 225 - 63
cli/README.md

@@ -87,17 +87,26 @@ When using the CLI for the first time there are a few common steps you might wan
 * [`joystream-cli content-directory:curatorGroups`](#joystream-cli-content-directorycuratorgroups)
 * [`joystream-cli content-directory:curatorGroups`](#joystream-cli-content-directorycuratorgroups)
 * [`joystream-cli content-directory:entities CLASSNAME [PROPERTIES]`](#joystream-cli-content-directoryentities-classname-properties)
 * [`joystream-cli content-directory:entities CLASSNAME [PROPERTIES]`](#joystream-cli-content-directoryentities-classname-properties)
 * [`joystream-cli content-directory:entity ID`](#joystream-cli-content-directoryentity-id)
 * [`joystream-cli content-directory:entity ID`](#joystream-cli-content-directoryentity-id)
+* [`joystream-cli content-directory:initialize`](#joystream-cli-content-directoryinitialize)
+* [`joystream-cli content-directory:removeCuratorFromGroup [GROUPID] [CURATORID]`](#joystream-cli-content-directoryremovecuratorfromgroup-groupid-curatorid)
 * [`joystream-cli content-directory:removeCuratorGroup [ID]`](#joystream-cli-content-directoryremovecuratorgroup-id)
 * [`joystream-cli content-directory:removeCuratorGroup [ID]`](#joystream-cli-content-directoryremovecuratorgroup-id)
+* [`joystream-cli content-directory:removeEntity ID`](#joystream-cli-content-directoryremoveentity-id)
 * [`joystream-cli content-directory:removeMaintainerFromClass [CLASSNAME] [GROUPID]`](#joystream-cli-content-directoryremovemaintainerfromclass-classname-groupid)
 * [`joystream-cli content-directory:removeMaintainerFromClass [CLASSNAME] [GROUPID]`](#joystream-cli-content-directoryremovemaintainerfromclass-classname-groupid)
 * [`joystream-cli content-directory:setCuratorGroupStatus [ID] [STATUS]`](#joystream-cli-content-directorysetcuratorgroupstatus-id-status)
 * [`joystream-cli content-directory:setCuratorGroupStatus [ID] [STATUS]`](#joystream-cli-content-directorysetcuratorgroupstatus-id-status)
 * [`joystream-cli content-directory:updateClassPermissions [CLASSNAME]`](#joystream-cli-content-directoryupdateclasspermissions-classname)
 * [`joystream-cli content-directory:updateClassPermissions [CLASSNAME]`](#joystream-cli-content-directoryupdateclasspermissions-classname)
 * [`joystream-cli council:info`](#joystream-cli-councilinfo)
 * [`joystream-cli council:info`](#joystream-cli-councilinfo)
 * [`joystream-cli help [COMMAND]`](#joystream-cli-help-command)
 * [`joystream-cli help [COMMAND]`](#joystream-cli-help-command)
 * [`joystream-cli media:createChannel`](#joystream-cli-mediacreatechannel)
 * [`joystream-cli media:createChannel`](#joystream-cli-mediacreatechannel)
+* [`joystream-cli media:curateContent`](#joystream-cli-mediacuratecontent)
+* [`joystream-cli media:featuredVideos`](#joystream-cli-mediafeaturedvideos)
 * [`joystream-cli media:myChannels`](#joystream-cli-mediamychannels)
 * [`joystream-cli media:myChannels`](#joystream-cli-mediamychannels)
 * [`joystream-cli media:myVideos`](#joystream-cli-mediamyvideos)
 * [`joystream-cli media:myVideos`](#joystream-cli-mediamyvideos)
+* [`joystream-cli media:removeChannel [ID]`](#joystream-cli-mediaremovechannel-id)
+* [`joystream-cli media:removeVideo [ID]`](#joystream-cli-mediaremovevideo-id)
+* [`joystream-cli media:setFeaturedVideos VIDEOIDS`](#joystream-cli-mediasetfeaturedvideos-videoids)
 * [`joystream-cli media:updateChannel [ID]`](#joystream-cli-mediaupdatechannel-id)
 * [`joystream-cli media:updateChannel [ID]`](#joystream-cli-mediaupdatechannel-id)
 * [`joystream-cli media:updateVideo [ID]`](#joystream-cli-mediaupdatevideo-id)
 * [`joystream-cli media:updateVideo [ID]`](#joystream-cli-mediaupdatevideo-id)
+* [`joystream-cli media:updateVideoLicense [ID]`](#joystream-cli-mediaupdatevideolicense-id)
 * [`joystream-cli media:uploadVideo FILEPATH`](#joystream-cli-mediauploadvideo-filepath)
 * [`joystream-cli media:uploadVideo FILEPATH`](#joystream-cli-mediauploadvideo-filepath)
 * [`joystream-cli working-groups:application WGAPPLICATIONID`](#joystream-cli-working-groupsapplication-wgapplicationid)
 * [`joystream-cli working-groups:application WGAPPLICATIONID`](#joystream-cli-working-groupsapplication-wgapplicationid)
 * [`joystream-cli working-groups:createOpening`](#joystream-cli-working-groupscreateopening)
 * [`joystream-cli working-groups:createOpening`](#joystream-cli-working-groupscreateopening)
@@ -109,6 +118,7 @@ When using the CLI for the first time there are a few common steps you might wan
 * [`joystream-cli working-groups:opening WGOPENINGID`](#joystream-cli-working-groupsopening-wgopeningid)
 * [`joystream-cli working-groups:opening WGOPENINGID`](#joystream-cli-working-groupsopening-wgopeningid)
 * [`joystream-cli working-groups:openings`](#joystream-cli-working-groupsopenings)
 * [`joystream-cli working-groups:openings`](#joystream-cli-working-groupsopenings)
 * [`joystream-cli working-groups:overview`](#joystream-cli-working-groupsoverview)
 * [`joystream-cli working-groups:overview`](#joystream-cli-working-groupsoverview)
+* [`joystream-cli working-groups:setDefaultGroup`](#joystream-cli-working-groupssetdefaultgroup)
 * [`joystream-cli working-groups:slashWorker WORKERID`](#joystream-cli-working-groupsslashworker-workerid)
 * [`joystream-cli working-groups:slashWorker WORKERID`](#joystream-cli-working-groupsslashworker-workerid)
 * [`joystream-cli working-groups:startAcceptingApplications WGOPENINGID`](#joystream-cli-working-groupsstartacceptingapplications-wgopeningid)
 * [`joystream-cli working-groups:startAcceptingApplications WGOPENINGID`](#joystream-cli-working-groupsstartacceptingapplications-wgopeningid)
 * [`joystream-cli working-groups:startReviewPeriod WGOPENINGID`](#joystream-cli-working-groupsstartreviewperiod-wgopeningid)
 * [`joystream-cli working-groups:startReviewPeriod WGOPENINGID`](#joystream-cli-working-groupsstartreviewperiod-wgopeningid)
@@ -126,7 +136,8 @@ USAGE
   $ joystream-cli account:choose
   $ joystream-cli account:choose
 
 
 OPTIONS
 OPTIONS
-  --showSpecial  Whether to show special (DEV chain) accounts
+  -S, --showSpecial      Whether to show special (DEV chain) accounts
+  -a, --address=address  Select account by address (if available)
 ```
 ```
 
 
 _See code: [src/commands/account/choose.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/account/choose.ts)_
 _See code: [src/commands/account/choose.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/account/choose.ts)_
@@ -319,7 +330,9 @@ USAGE
 
 
 OPTIONS
 OPTIONS
   -i, --input=input    Path to JSON file to use as input (if not specified - the input can be provided interactively)
   -i, --input=input    Path to JSON file to use as input (if not specified - the input can be provided interactively)
-  -o, --output=output  Path where the output JSON file should be placed (can be then reused as input)
+
+  -o, --output=output  Path to the directory where the output JSON file should be placed (the output file can be then
+                       reused as input)
 ```
 ```
 
 
 _See code: [src/commands/content-directory/addClassSchema.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/addClassSchema.ts)_
 _See code: [src/commands/content-directory/addClassSchema.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/addClassSchema.ts)_
@@ -389,7 +402,9 @@ USAGE
 
 
 OPTIONS
 OPTIONS
   -i, --input=input    Path to JSON file to use as input (if not specified - the input can be provided interactively)
   -i, --input=input    Path to JSON file to use as input (if not specified - the input can be provided interactively)
-  -o, --output=output  Path where the output JSON file should be placed (can be then reused as input)
+
+  -o, --output=output  Path to the directory where the output JSON file should be placed (the output file can be then
+                       reused as input)
 ```
 ```
 
 
 _See code: [src/commands/content-directory/createClass.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/createClass.ts)_
 _See code: [src/commands/content-directory/createClass.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/createClass.ts)_
@@ -469,6 +484,35 @@ ARGUMENTS
 
 
 _See code: [src/commands/content-directory/entity.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/entity.ts)_
 _See code: [src/commands/content-directory/entity.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/entity.ts)_
 
 
+## `joystream-cli content-directory:initialize`
+
+Initialize content directory with input data from @joystream/content library or custom, provided one. Requires lead access.
+
+```
+USAGE
+  $ joystream-cli content-directory:initialize
+
+OPTIONS
+  --rootInputsDir=rootInputsDir  Custom inputs directory (must follow @joystream/content directory structure)
+```
+
+_See code: [src/commands/content-directory/initialize.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/initialize.ts)_
+
+## `joystream-cli content-directory:removeCuratorFromGroup [GROUPID] [CURATORID]`
+
+Remove Curator from Curator Group.
+
+```
+USAGE
+  $ joystream-cli content-directory:removeCuratorFromGroup [GROUPID] [CURATORID]
+
+ARGUMENTS
+  GROUPID    ID of the Curator Group
+  CURATORID  ID of the curator
+```
+
+_See code: [src/commands/content-directory/removeCuratorFromGroup.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/removeCuratorFromGroup.ts)_
+
 ## `joystream-cli content-directory:removeCuratorGroup [ID]`
 ## `joystream-cli content-directory:removeCuratorGroup [ID]`
 
 
 Remove existing Curator Group.
 Remove existing Curator Group.
@@ -483,6 +527,23 @@ ARGUMENTS
 
 
 _See code: [src/commands/content-directory/removeCuratorGroup.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/removeCuratorGroup.ts)_
 _See code: [src/commands/content-directory/removeCuratorGroup.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/removeCuratorGroup.ts)_
 
 
+## `joystream-cli content-directory:removeEntity ID`
+
+Removes a single entity by id (can be executed in Member, Curator or Lead context)
+
+```
+USAGE
+  $ joystream-cli content-directory:removeEntity ID
+
+ARGUMENTS
+  ID  ID of the entity to remove
+
+OPTIONS
+  --context=(Member|Curator|Lead)  Actor context to execute the command in (Member/Curator/Lead)
+```
+
+_See code: [src/commands/content-directory/removeEntity.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/content-directory/removeEntity.ts)_
+
 ## `joystream-cli content-directory:removeMaintainerFromClass [CLASSNAME] [GROUPID]`
 ## `joystream-cli content-directory:removeMaintainerFromClass [CLASSNAME] [GROUPID]`
 
 
 Remove maintainer (Curator Group) from class.
 Remove maintainer (Curator Group) from class.
@@ -565,11 +626,42 @@ USAGE
 
 
 OPTIONS
 OPTIONS
   -i, --input=input    Path to JSON file to use as input (if not specified - the input can be provided interactively)
   -i, --input=input    Path to JSON file to use as input (if not specified - the input can be provided interactively)
-  -o, --output=output  Path where the output JSON file should be placed (can be then reused as input)
+
+  -o, --output=output  Path to the directory where the output JSON file should be placed (the output file can be then
+                       reused as input)
+
+  -y, --confirm        Confirm the provided input
 ```
 ```
 
 
 _See code: [src/commands/media/createChannel.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/createChannel.ts)_
 _See code: [src/commands/media/createChannel.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/createChannel.ts)_
 
 
+## `joystream-cli media:curateContent`
+
+Set the curation status of given entity (Channel/Video). Requires Curator access.
+
+```
+USAGE
+  $ joystream-cli media:curateContent
+
+OPTIONS
+  -c, --className=(Channel|Video)   (required) Name of the class of the entity to curate (Channel/Video)
+  -s, --status=(Accepted|Censored)  (required) Specifies the curation status (Accepted/Censored)
+  --id=id                           (required) ID of the entity to curate
+```
+
+_See code: [src/commands/media/curateContent.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/curateContent.ts)_
+
+## `joystream-cli media:featuredVideos`
+
+Show a list of currently featured videos.
+
+```
+USAGE
+  $ joystream-cli media:featuredVideos
+```
+
+_See code: [src/commands/media/featuredVideos.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/featuredVideos.ts)_
+
 ## `joystream-cli media:myChannels`
 ## `joystream-cli media:myChannels`
 
 
 Show the list of channels associated with current account's membership.
 Show the list of channels associated with current account's membership.
@@ -595,6 +687,51 @@ OPTIONS
 
 
 _See code: [src/commands/media/myVideos.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/myVideos.ts)_
 _See code: [src/commands/media/myVideos.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/myVideos.ts)_
 
 
+## `joystream-cli media:removeChannel [ID]`
+
+Removes a channel (required controller access).
+
+```
+USAGE
+  $ joystream-cli media:removeChannel [ID]
+
+ARGUMENTS
+  ID  ID of the Channel entity
+```
+
+_See code: [src/commands/media/removeChannel.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/removeChannel.ts)_
+
+## `joystream-cli media:removeVideo [ID]`
+
+Remove given Video entity and associated entities (VideoMedia, License) from content directory.
+
+```
+USAGE
+  $ joystream-cli media:removeVideo [ID]
+
+ARGUMENTS
+  ID  ID of the Video entity
+```
+
+_See code: [src/commands/media/removeVideo.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/removeVideo.ts)_
+
+## `joystream-cli media:setFeaturedVideos VIDEOIDS`
+
+Set currently featured videos (requires lead/maintainer access).
+
+```
+USAGE
+  $ joystream-cli media:setFeaturedVideos VIDEOIDS
+
+ARGUMENTS
+  VIDEOIDS  Comma-separated video ids
+
+OPTIONS
+  --add  If provided - currently featured videos will not be removed.
+```
+
+_See code: [src/commands/media/setFeaturedVideos.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/setFeaturedVideos.ts)_
+
 ## `joystream-cli media:updateChannel [ID]`
 ## `joystream-cli media:updateChannel [ID]`
 
 
 Update one of the owned channels on Joystream (requires a membership).
 Update one of the owned channels on Joystream (requires a membership).
@@ -608,14 +745,18 @@ ARGUMENTS
 
 
 OPTIONS
 OPTIONS
   -i, --input=input    Path to JSON file to use as input (if not specified - the input can be provided interactively)
   -i, --input=input    Path to JSON file to use as input (if not specified - the input can be provided interactively)
-  -o, --output=output  Path where the output JSON file should be placed (can be then reused as input)
+
+  -o, --output=output  Path to the directory where the output JSON file should be placed (the output file can be then
+                       reused as input)
+
+  --asCurator          Provide this flag in order to use Curator context for the update
 ```
 ```
 
 
 _See code: [src/commands/media/updateChannel.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/updateChannel.ts)_
 _See code: [src/commands/media/updateChannel.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/updateChannel.ts)_
 
 
 ## `joystream-cli media:updateVideo [ID]`
 ## `joystream-cli media:updateVideo [ID]`
 
 
-Update existing video information (requires a membership).
+Update existing video information (requires controller/maintainer access).
 
 
 ```
 ```
 USAGE
 USAGE
@@ -623,10 +764,27 @@ USAGE
 
 
 ARGUMENTS
 ARGUMENTS
   ID  ID of the Video to update
   ID  ID of the Video to update
+
+OPTIONS
+  --asCurator  Specify in order to update the video as curator
 ```
 ```
 
 
 _See code: [src/commands/media/updateVideo.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/updateVideo.ts)_
 _See code: [src/commands/media/updateVideo.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/updateVideo.ts)_
 
 
+## `joystream-cli media:updateVideoLicense [ID]`
+
+Update existing video license (requires controller/maintainer access).
+
+```
+USAGE
+  $ joystream-cli media:updateVideoLicense [ID]
+
+ARGUMENTS
+  ID  ID of the Video
+```
+
+_See code: [src/commands/media/updateVideoLicense.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/updateVideoLicense.ts)_
+
 ## `joystream-cli media:uploadVideo FILEPATH`
 ## `joystream-cli media:uploadVideo FILEPATH`
 
 
 Upload a new Video to a channel (requires a membership).
 Upload a new Video to a channel (requires a membership).
@@ -641,6 +799,10 @@ ARGUMENTS
 OPTIONS
 OPTIONS
   -c, --channel=channel  ID of the channel to assign the video to (if omitted - one of the owned channels can be
   -c, --channel=channel  ID of the channel to assign the video to (if omitted - one of the owned channels can be
                          selected from the list)
                          selected from the list)
+
+  -i, --input=input      Path to JSON file to use as input (if not specified - the input can be provided interactively)
+
+  -y, --confirm          Confirm the provided input
 ```
 ```
 
 
 _See code: [src/commands/media/uploadVideo.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/uploadVideo.ts)_
 _See code: [src/commands/media/uploadVideo.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/media/uploadVideo.ts)_
@@ -657,9 +819,8 @@ ARGUMENTS
   WGAPPLICATIONID  Working Group Application ID
   WGAPPLICATIONID  Working Group Application ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/application.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/application.ts)_
 _See code: [src/commands/working-groups/application.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/application.ts)_
@@ -673,19 +834,20 @@ USAGE
   $ joystream-cli working-groups:createOpening
   $ joystream-cli working-groups:createOpening
 
 
 OPTIONS
 OPTIONS
-  -c, --createDraftOnly      If provided - the extrinsic will not be executed. Use this flag if you only want to create
-                             a draft.
+  -e, --edit                               If provided along with --input - launches in edit mode allowing to modify the
+                                           input before sending the exstinsic
 
 
-  -d, --useDraft             Whether to create the opening from existing draft.
-                             If provided without --draftName - the list of choices will be displayed.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 
 
-  -g, --group=group          (required) [default: storageProviders] The working group context in which the command
-                             should be executed
-                             Available values are: storageProviders, curators.
+  -i, --input=input                        Path to JSON file to use as input (if not specified - the input can be
+                                           provided interactively)
 
 
-  -n, --draftName=draftName  Name of the draft to create the opening from.
+  -o, --output=output                      Path to the file where the output JSON should be saved (this output can be
+                                           then reused as input)
 
 
-  -s, --skipPrompts          Whether to skip all prompts when adding from draft (will use all default values)
+  --dryRun                                 If provided along with --output - skips sending the actual extrinsic(can be
+                                           used to generate a "draft" which can be provided as input later)
 ```
 ```
 
 
 _See code: [src/commands/working-groups/createOpening.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/createOpening.ts)_
 _See code: [src/commands/working-groups/createOpening.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/createOpening.ts)_
@@ -702,9 +864,8 @@ ARGUMENTS
   WORKERID  Worker ID
   WORKERID  Worker ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/decreaseWorkerStake.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/decreaseWorkerStake.ts)_
 _See code: [src/commands/working-groups/decreaseWorkerStake.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/decreaseWorkerStake.ts)_
@@ -721,9 +882,8 @@ ARGUMENTS
   WORKERID  Worker ID
   WORKERID  Worker ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/evictWorker.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/evictWorker.ts)_
 _See code: [src/commands/working-groups/evictWorker.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/evictWorker.ts)_
@@ -740,9 +900,8 @@ ARGUMENTS
   WGOPENINGID  Working Group Opening ID
   WGOPENINGID  Working Group Opening ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/fillOpening.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/fillOpening.ts)_
 _See code: [src/commands/working-groups/fillOpening.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/fillOpening.ts)_
@@ -756,9 +915,8 @@ USAGE
   $ joystream-cli working-groups:increaseStake
   $ joystream-cli working-groups:increaseStake
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/increaseStake.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/increaseStake.ts)_
 _See code: [src/commands/working-groups/increaseStake.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/increaseStake.ts)_
@@ -772,9 +930,8 @@ USAGE
   $ joystream-cli working-groups:leaveRole
   $ joystream-cli working-groups:leaveRole
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/leaveRole.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/leaveRole.ts)_
 _See code: [src/commands/working-groups/leaveRole.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/leaveRole.ts)_
@@ -791,9 +948,8 @@ ARGUMENTS
   WGOPENINGID  Working Group Opening ID
   WGOPENINGID  Working Group Opening ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/opening.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/opening.ts)_
 _See code: [src/commands/working-groups/opening.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/opening.ts)_
@@ -807,9 +963,8 @@ USAGE
   $ joystream-cli working-groups:openings
   $ joystream-cli working-groups:openings
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/openings.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/openings.ts)_
 _See code: [src/commands/working-groups/openings.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/openings.ts)_
@@ -823,13 +978,27 @@ USAGE
   $ joystream-cli working-groups:overview
   $ joystream-cli working-groups:overview
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/overview.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/overview.ts)_
 _See code: [src/commands/working-groups/overview.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/overview.ts)_
 
 
+## `joystream-cli working-groups:setDefaultGroup`
+
+Change the default group context for working-groups commands.
+
+```
+USAGE
+  $ joystream-cli working-groups:setDefaultGroup
+
+OPTIONS
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
+```
+
+_See code: [src/commands/working-groups/setDefaultGroup.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/setDefaultGroup.ts)_
+
 ## `joystream-cli working-groups:slashWorker WORKERID`
 ## `joystream-cli working-groups:slashWorker WORKERID`
 
 
 Slashes given worker stake. Requires lead access.
 Slashes given worker stake. Requires lead access.
@@ -842,9 +1011,8 @@ ARGUMENTS
   WORKERID  Worker ID
   WORKERID  Worker ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/slashWorker.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/slashWorker.ts)_
 _See code: [src/commands/working-groups/slashWorker.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/slashWorker.ts)_
@@ -861,9 +1029,8 @@ ARGUMENTS
   WGOPENINGID  Working Group Opening ID
   WGOPENINGID  Working Group Opening ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/startAcceptingApplications.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/startAcceptingApplications.ts)_
 _See code: [src/commands/working-groups/startAcceptingApplications.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/startAcceptingApplications.ts)_
@@ -880,9 +1047,8 @@ ARGUMENTS
   WGOPENINGID  Working Group Opening ID
   WGOPENINGID  Working Group Opening ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/startReviewPeriod.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/startReviewPeriod.ts)_
 _See code: [src/commands/working-groups/startReviewPeriod.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/startReviewPeriod.ts)_
@@ -899,9 +1065,8 @@ ARGUMENTS
   WGAPPLICATIONID  Working Group Application ID
   WGAPPLICATIONID  Working Group Application ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/terminateApplication.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/terminateApplication.ts)_
 _See code: [src/commands/working-groups/terminateApplication.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/terminateApplication.ts)_
@@ -918,9 +1083,8 @@ ARGUMENTS
   ACCOUNTADDRESS  New reward account address (if omitted, one of the existing CLI accounts can be selected)
   ACCOUNTADDRESS  New reward account address (if omitted, one of the existing CLI accounts can be selected)
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/updateRewardAccount.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/updateRewardAccount.ts)_
 _See code: [src/commands/working-groups/updateRewardAccount.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/updateRewardAccount.ts)_
@@ -937,9 +1101,8 @@ ARGUMENTS
   ACCOUNTADDRESS  New role account address (if omitted, one of the existing CLI accounts can be selected)
   ACCOUNTADDRESS  New role account address (if omitted, one of the existing CLI accounts can be selected)
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/updateRoleAccount.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/updateRoleAccount.ts)_
 _See code: [src/commands/working-groups/updateRoleAccount.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/updateRoleAccount.ts)_
@@ -956,9 +1119,8 @@ ARGUMENTS
   WORKERID  Worker ID
   WORKERID  Worker ID
 
 
 OPTIONS
 OPTIONS
-  -g, --group=group  (required) [default: storageProviders] The working group context in which the command should be
-                     executed
-                     Available values are: storageProviders, curators.
+  -g, --group=(storageProviders|curators)  The working group context in which the command should be executed
+                                           Available values are: storageProviders, curators.
 ```
 ```
 
 
 _See code: [src/commands/working-groups/updateWorkerReward.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/updateWorkerReward.ts)_
 _See code: [src/commands/working-groups/updateWorkerReward.ts](https://github.com/Joystream/joystream/blob/master/cli/src/commands/working-groups/updateWorkerReward.ts)_

+ 1 - 1
cli/package.json

@@ -9,7 +9,7 @@
   "bugs": "https://github.com/Joystream/joystream/issues",
   "bugs": "https://github.com/Joystream/joystream/issues",
   "dependencies": {
   "dependencies": {
     "@apidevtools/json-schema-ref-parser": "^9.0.6",
     "@apidevtools/json-schema-ref-parser": "^9.0.6",
-    "@ffmpeg-installer/ffmpeg": "^1.0.20",
+    "@ffprobe-installer/ffprobe": "^1.1.0",
     "@joystream/types": "^0.14.0",
     "@joystream/types": "^0.14.0",
     "@oclif/command": "^1.5.19",
     "@oclif/command": "^1.5.19",
     "@oclif/config": "^1.14.0",
     "@oclif/config": "^1.14.0",

+ 0 - 3
cli/src/@types/@ffmpeg-installer/ffmpeg/index.d.ts

@@ -1,3 +0,0 @@
-declare module '@ffmpeg-installer/ffmpeg' {
-  export const path: string
-}

+ 3 - 0
cli/src/@types/@ffprobe-installer/ffprobe/index.d.ts

@@ -0,0 +1,3 @@
+declare module '@ffprobe-installer/ffprobe' {
+  export const path: string
+}

+ 5 - 2
cli/src/base/AccountsCommandBase.ts

@@ -177,8 +177,11 @@ export default abstract class AccountsCommandBase extends ApiCommandBase {
     return password
     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 }])
+  async requireConfirmation(
+    message = 'Are you sure you want to execute this action?',
+    defaultVal = false
+  ): Promise<void> {
+    const { confirmed } = await inquirer.prompt([{ type: 'confirm', name: 'confirmed', message, default: defaultVal }])
     if (!confirmed) this.exit(ExitCodes.OK)
     if (!confirmed) this.exit(ExitCodes.OK)
   }
   }
 
 

+ 33 - 13
cli/src/base/ContentDirectoryCommandBase.ts

@@ -1,7 +1,7 @@
 import ExitCodes from '../ExitCodes'
 import ExitCodes from '../ExitCodes'
 import { WorkingGroups } from '../Types'
 import { WorkingGroups } from '../Types'
-import { ReferenceProperty } from 'cd-schemas/types/extrinsics/AddClassSchema'
-import { FlattenRelations } from 'cd-schemas/types/utility'
+import { ReferenceProperty } from '@joystream/cd-schemas/types/extrinsics/AddClassSchema'
+import { FlattenRelations } from '@joystream/cd-schemas/types/utility'
 import { BOOL_PROMPT_OPTIONS } from '../helpers/prompting'
 import { BOOL_PROMPT_OPTIONS } from '../helpers/prompting'
 import {
 import {
   Class,
   Class,
@@ -11,10 +11,13 @@ import {
   Entity,
   Entity,
   EntityId,
   EntityId,
   Actor,
   Actor,
+  PropertyType,
 } from '@joystream/types/content-directory'
 } from '@joystream/types/content-directory'
 import { Worker } from '@joystream/types/working-group'
 import { Worker } from '@joystream/types/working-group'
 import { CLIError } from '@oclif/errors'
 import { CLIError } from '@oclif/errors'
 import { Codec } from '@polkadot/types/types'
 import { Codec } from '@polkadot/types/types'
+import AbstractInt from '@polkadot/types/codec/AbstractInt'
+import { AnyJson } from '@polkadot/types/types/helpers'
 import _ from 'lodash'
 import _ from 'lodash'
 import { RolesCommandBase } from './WorkingGroupsCommandBase'
 import { RolesCommandBase } from './WorkingGroupsCommandBase'
 import { createType } from '@joystream/types'
 import { createType } from '@joystream/types'
@@ -24,6 +27,8 @@ import { flags } from '@oclif/command'
 const CONTEXTS = ['Member', 'Curator', 'Lead'] as const
 const CONTEXTS = ['Member', 'Curator', 'Lead'] as const
 type Context = typeof CONTEXTS[number]
 type Context = typeof CONTEXTS[number]
 
 
+type ParsedPropertyValue = { value: Codec | null; type: PropertyType['type']; subtype: PropertyType['subtype'] }
+
 /**
 /**
  * Abstract base class for commands related to content directory
  * Abstract base class for commands related to content directory
  */
  */
@@ -234,14 +239,14 @@ export default abstract class ContentDirectoryCommandBase extends RolesCommandBa
     }
     }
 
 
     if (requireSchema && !entity.supported_schemas.toArray().length) {
     if (requireSchema && !entity.supported_schemas.toArray().length) {
-      this.error(`${requiredClass || ''}Entity of id ${id} has no schema support added!`)
+      this.error(`${requiredClass || ''} entity of id ${id} has no schema support added!`)
     }
     }
 
 
     return entity
     return entity
   }
   }
 
 
-  async getAndParseKnownEntity<T>(id: string | number): Promise<FlattenRelations<T>> {
-    const entity = await this.getEntity(id)
+  async getAndParseKnownEntity<T>(id: string | number, className?: string): Promise<FlattenRelations<T>> {
+    const entity = await this.getEntity(id, className)
     return this.parseToKnownEntityJson<T>(entity)
     return this.parseToKnownEntityJson<T>(entity)
   }
   }
 
 
@@ -278,7 +283,7 @@ export default abstract class ContentDirectoryCommandBase extends RolesCommandBa
       choices: entityEntries.map(([id, entity]) => {
       choices: entityEntries.map(([id, entity]) => {
         const parsedEntityPropertyValues = this.parseEntityPropertyValues(entity, entityClass)
         const parsedEntityPropertyValues = this.parseEntityPropertyValues(entity, entityClass)
         return {
         return {
-          name: (propName && parsedEntityPropertyValues[propName]?.value.toString()) || `ID:${id.toString()}`,
+          name: (propName && parsedEntityPropertyValues[propName]?.value?.toString()) || `ID:${id.toString()}`,
           value: id.toString(), // With numbers there are issues with "default"
           value: id.toString(), // With numbers there are issues with "default"
         }
         }
       }),
       }),
@@ -298,31 +303,46 @@ export default abstract class ContentDirectoryCommandBase extends RolesCommandBa
     return (await this.promptForEntityEntry(message, className, propName, ownerMemberId, defaultId))[0].toNumber()
     return (await this.promptForEntityEntry(message, className, propName, ownerMemberId, defaultId))[0].toNumber()
   }
   }
 
 
+  parseStoredPropertyInnerValue(value: Codec | null): AnyJson {
+    if (value === null) {
+      return null
+    }
+
+    if (value instanceof AbstractInt) {
+      return value.toNumber() // Integers (signed ones) are by default converted to hex when using .toJson()
+    }
+
+    return value.toJSON()
+  }
+
   parseEntityPropertyValues(
   parseEntityPropertyValues(
     entity: Entity,
     entity: Entity,
     entityClass: Class,
     entityClass: Class,
     includedProperties?: string[]
     includedProperties?: string[]
-  ): Record<string, { value: Codec; type: string }> {
+  ): Record<string, ParsedPropertyValue> {
     const { properties } = entityClass
     const { properties } = entityClass
     return Array.from(entity.getField('values').entries()).reduce((columns, [propId, propValue]) => {
     return Array.from(entity.getField('values').entries()).reduce((columns, [propId, propValue]) => {
       const prop = properties[propId.toNumber()]
       const prop = properties[propId.toNumber()]
       const propName = prop.name.toString()
       const propName = prop.name.toString()
       const included = !includedProperties || includedProperties.some((p) => p.toLowerCase() === propName.toLowerCase())
       const included = !includedProperties || includedProperties.some((p) => p.toLowerCase() === propName.toLowerCase())
+      const { type: propType, subtype: propSubtype } = prop.property_type
 
 
       if (included) {
       if (included) {
         columns[propName] = {
         columns[propName] = {
-          value: propValue.getValue(),
-          type: `${prop.property_type.type}<${prop.property_type.subtype}>`,
+          // If type doesn't match (Boolean(false) for optional fields case) - use "null" as value
+          value: propType !== propValue.type || propSubtype !== propValue.subtype ? null : propValue.getValue(),
+          type: propType,
+          subtype: propSubtype,
         }
         }
       }
       }
       return columns
       return columns
-    }, {} as Record<string, { value: Codec; type: string }>)
+    }, {} as Record<string, ParsedPropertyValue>)
   }
   }
 
 
   async parseToKnownEntityJson<T>(entity: Entity): Promise<FlattenRelations<T>> {
   async parseToKnownEntityJson<T>(entity: Entity): Promise<FlattenRelations<T>> {
     const entityClass = (await this.classEntryByNameOrId(entity.class_id.toString()))[1]
     const entityClass = (await this.classEntryByNameOrId(entity.class_id.toString()))[1]
     return (_.mapValues(this.parseEntityPropertyValues(entity, entityClass), (v) =>
     return (_.mapValues(this.parseEntityPropertyValues(entity, entityClass), (v) =>
-      v.type !== 'Single<Bool>' && v.value.toJSON() === false ? null : v.value.toJSON()
+      this.parseStoredPropertyInnerValue(v.value)
     ) as unknown) as FlattenRelations<T>
     ) as unknown) as FlattenRelations<T>
   }
   }
 
 
@@ -337,7 +357,7 @@ export default abstract class ContentDirectoryCommandBase extends RolesCommandBa
     const defaultValues = entityClass.properties
     const defaultValues = entityClass.properties
       .map((p) => p.name.toString())
       .map((p) => p.name.toString())
       .reduce((d, propName) => {
       .reduce((d, propName) => {
-        if (includedProps?.includes(propName)) {
+        if (!includedProps || includedProps.includes(propName)) {
           d[propName] = chalk.grey('[not set]')
           d[propName] = chalk.grey('[not set]')
         }
         }
         return d
         return d
@@ -349,7 +369,7 @@ export default abstract class ContentDirectoryCommandBase extends RolesCommandBa
         'ID': id.toString(),
         'ID': id.toString(),
         ...defaultValues,
         ...defaultValues,
         ..._.mapValues(this.parseEntityPropertyValues(entity, entityClass, includedProps), (v) =>
         ..._.mapValues(this.parseEntityPropertyValues(entity, entityClass, includedProps), (v) =>
-          v.value.toJSON() === false && v.type !== 'Single<Bool>' ? chalk.grey('[not set]') : v.value.toString()
+          v.value === null ? chalk.grey('[not set]') : v.value.toString()
         ),
         ),
       }))
       }))
     )) as Record<string, string>[]
     )) as Record<string, string>[]

+ 10 - 5
cli/src/base/MediaCommandBase.ts

@@ -1,5 +1,5 @@
 import ContentDirectoryCommandBase from './ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from './ContentDirectoryCommandBase'
-import { VideoEntity } from 'cd-schemas/types/entities'
+import { VideoEntity, KnownLicenseEntity, LicenseEntity } from '@joystream/cd-schemas/types/entities'
 import fs from 'fs'
 import fs from 'fs'
 import { DistinctQuestion } from 'inquirer'
 import { DistinctQuestion } from 'inquirer'
 import path from 'path'
 import path from 'path'
@@ -12,7 +12,7 @@ const MAX_USER_LICENSE_CONTENT_LENGTH = 4096
  */
  */
 export default abstract class MediaCommandBase extends ContentDirectoryCommandBase {
 export default abstract class MediaCommandBase extends ContentDirectoryCommandBase {
   async promptForNewLicense(): Promise<VideoEntity['license']> {
   async promptForNewLicense(): Promise<VideoEntity['license']> {
-    let license: VideoEntity['license']
+    let licenseInput: LicenseEntity
     const licenseType: 'known' | 'custom' = await this.simplePrompt({
     const licenseType: 'known' | 'custom' = await this.simplePrompt({
       type: 'list',
       type: 'list',
       message: 'Choose license type',
       message: 'Choose license type',
@@ -22,7 +22,12 @@ export default abstract class MediaCommandBase extends ContentDirectoryCommandBa
       ],
       ],
     })
     })
     if (licenseType === 'known') {
     if (licenseType === 'known') {
-      license = { new: { knownLicense: await this.promptForEntityId('Choose License', 'KnownLicense', 'code') } }
+      const [id, knownLicenseEntity] = await this.promptForEntityEntry('Choose License', 'KnownLicense', 'code')
+      const knownLicense = await this.parseToKnownEntityJson<KnownLicenseEntity>(knownLicenseEntity)
+      licenseInput = { knownLicense: id.toNumber() }
+      if (knownLicense.attributionRequired) {
+        licenseInput.attribution = await this.simplePrompt({ message: 'Attribution' })
+      }
     } else {
     } else {
       let licenseContent: null | string = null
       let licenseContent: null | string = null
       while (licenseContent === null) {
       while (licenseContent === null) {
@@ -38,10 +43,10 @@ export default abstract class MediaCommandBase extends ContentDirectoryCommandBa
           licenseContent = null
           licenseContent = null
         }
         }
       }
       }
-      license = { new: { userDefinedLicense: { new: { content: licenseContent } } } }
+      licenseInput = { userDefinedLicense: { new: { content: licenseContent } } }
     }
     }
 
 
-    return license
+    return { new: licenseInput }
   }
   }
 
 
   async promptForPublishedBeforeJoystream(current?: number | null): Promise<number | null> {
   async promptForPublishedBeforeJoystream(current?: number | null): Promise<number | null> {

+ 19 - 4
cli/src/commands/account/choose.ts

@@ -9,13 +9,19 @@ export default class AccountChoose extends AccountsCommandBase {
   static flags = {
   static flags = {
     showSpecial: flags.boolean({
     showSpecial: flags.boolean({
       description: 'Whether to show special (DEV chain) accounts',
       description: 'Whether to show special (DEV chain) accounts',
+      char: 'S',
+      required: false,
+    }),
+    address: flags.string({
+      description: 'Select account by address (if available)',
+      char: 'a',
       required: false,
       required: false,
     }),
     }),
   }
   }
 
 
   async run() {
   async run() {
-    const { showSpecial } = this.parse(AccountChoose).flags
-    const accounts: NamedKeyringPair[] = this.fetchAccounts(showSpecial)
+    const { showSpecial, address } = this.parse(AccountChoose).flags
+    const accounts: NamedKeyringPair[] = this.fetchAccounts(!!address || showSpecial)
     const selectedAccount: NamedKeyringPair | null = this.getSelectedAccount()
     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`))
@@ -25,9 +31,18 @@ export default class AccountChoose extends AccountsCommandBase {
       this.exit(ExitCodes.NoAccountFound)
       this.exit(ExitCodes.NoAccountFound)
     }
     }
 
 
-    const choosenAccount: NamedKeyringPair = await this.promptForAccount(accounts, selectedAccount)
+    let choosenAccount: NamedKeyringPair
+    if (address) {
+      const matchingAccount = accounts.find((a) => a.address === address)
+      if (!matchingAccount) {
+        this.error(`No matching account found by address: ${address}`, { exit: ExitCodes.InvalidInput })
+      }
+      choosenAccount = matchingAccount
+    } else {
+      choosenAccount = await this.promptForAccount(accounts, selectedAccount)
+    }
 
 
     await this.setSelectedAccount(choosenAccount)
     await this.setSelectedAccount(choosenAccount)
-    this.log(chalk.greenBright('\nAccount switched!'))
+    this.log(chalk.greenBright(`\nAccount switched to ${chalk.white(choosenAccount.address)}!`))
   }
   }
 }
 }

+ 3 - 3
cli/src/commands/content-directory/addClassSchema.ts

@@ -1,7 +1,7 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import AddClassSchemaSchema from 'cd-schemas/schemas/extrinsics/AddClassSchema.schema.json'
-import { AddClassSchema } from 'cd-schemas/types/extrinsics/AddClassSchema'
-import { InputParser } from 'cd-schemas'
+import AddClassSchemaSchema from '@joystream/cd-schemas/schemas/extrinsics/AddClassSchema.schema.json'
+import { AddClassSchema } from '@joystream/cd-schemas/types/extrinsics/AddClassSchema'
+import { InputParser } from '@joystream/cd-schemas'
 import { JsonSchemaPrompter, JsonSchemaCustomPrompts } from '../../helpers/JsonSchemaPrompt'
 import { JsonSchemaPrompter, JsonSchemaCustomPrompts } from '../../helpers/JsonSchemaPrompt'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'

+ 3 - 3
cli/src/commands/content-directory/createClass.ts

@@ -1,7 +1,7 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import CreateClassSchema from 'cd-schemas/schemas/extrinsics/CreateClass.schema.json'
-import { CreateClass } from 'cd-schemas/types/extrinsics/CreateClass'
-import { InputParser } from 'cd-schemas'
+import CreateClassSchema from '@joystream/cd-schemas/schemas/extrinsics/CreateClass.schema.json'
+import { CreateClass } from '@joystream/cd-schemas/types/extrinsics/CreateClass'
+import { InputParser } from '@joystream/cd-schemas'
 import { JsonSchemaPrompter, JsonSchemaCustomPrompts } from '../../helpers/JsonSchemaPrompt'
 import { JsonSchemaPrompter, JsonSchemaCustomPrompts } from '../../helpers/JsonSchemaPrompt'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'

+ 2 - 2
cli/src/commands/content-directory/entity.ts

@@ -36,8 +36,8 @@ export default class EntityCommand extends ContentDirectoryCommandBase {
       _.mapValues(
       _.mapValues(
         propertyValues,
         propertyValues,
         (v) =>
         (v) =>
-          (v.value.toJSON() === false && v.type !== 'Single<Bool>' ? chalk.grey('[not set]') : v.value.toString()) +
-          ` ${chalk.green(`${v.type}`)}`
+          (v.value === null ? chalk.grey('[not set]') : v.value.toString()) +
+          ` ${chalk.green(`${v.type}<${v.subtype}>`)}`
       )
       )
     )
     )
   }
   }

+ 15 - 8
cli/src/commands/content-directory/initialize.ts

@@ -1,21 +1,28 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import { CreateClass } from 'cd-schemas/types/extrinsics/CreateClass'
-import { getInputs, InputParser, ExtrinsicsHelper } from 'cd-schemas'
-import { AddClassSchema } from 'cd-schemas/types/extrinsics/AddClassSchema'
-import { EntityBatch } from 'cd-schemas/types/EntityBatch'
+import { InputParser, ExtrinsicsHelper, getInitializationInputs } from '@joystream/cd-schemas'
+import { flags } from '@oclif/command'
 
 
 export default class InitializeCommand extends ContentDirectoryCommandBase {
 export default class InitializeCommand extends ContentDirectoryCommandBase {
   static description =
   static description =
-    'Initialize content directory with input data from @joystream/content library. Requires lead access.'
+    'Initialize content directory with input data from @joystream/content library or custom, provided one. Requires lead access.'
+
+  static flags = {
+    rootInputsDir: flags.string({
+      required: false,
+      description: 'Custom inputs directory (must follow @joystream/content directory structure)',
+    }),
+  }
 
 
   async run() {
   async run() {
     const account = await this.getRequiredSelectedAccount()
     const account = await this.getRequiredSelectedAccount()
     await this.requireLead()
     await this.requireLead()
     await this.requestAccountDecoding(account)
     await this.requestAccountDecoding(account)
 
 
-    const classInputs = getInputs<CreateClass>('classes').map(({ data }) => data)
-    const schemaInputs = getInputs<AddClassSchema>('schemas').map(({ data }) => data)
-    const entityBatchInputs = getInputs<EntityBatch>('entityBatches').map(({ data }) => data)
+    const {
+      flags: { rootInputsDir },
+    } = this.parse(InitializeCommand)
+
+    const { classInputs, schemaInputs, entityBatchInputs } = getInitializationInputs(rootInputsDir)
 
 
     const currentClasses = await this.getApi().availableClasses()
     const currentClasses = await this.getApi().availableClasses()
 
 

+ 2 - 2
cli/src/commands/content-directory/updateClassPermissions.ts

@@ -1,8 +1,8 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import CreateClassSchema from 'cd-schemas/schemas/extrinsics/CreateClass.schema.json'
+import CreateClassSchema from '@joystream/cd-schemas/schemas/extrinsics/CreateClass.schema.json'
 import chalk from 'chalk'
 import chalk from 'chalk'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
-import { CreateClass } from 'cd-schemas/types/extrinsics/CreateClass'
+import { CreateClass } from '@joystream/cd-schemas/types/extrinsics/CreateClass'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 
 
 export default class UpdateClassPermissionsCommand extends ContentDirectoryCommandBase {
 export default class UpdateClassPermissionsCommand extends ContentDirectoryCommandBase {

+ 12 - 7
cli/src/commands/media/createChannel.ts

@@ -1,15 +1,19 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import ChannelEntitySchema from 'cd-schemas/schemas/entities/ChannelEntity.schema.json'
-import { ChannelEntity } from 'cd-schemas/types/entities/ChannelEntity'
-import { InputParser } from 'cd-schemas'
+import ChannelEntitySchema from '@joystream/cd-schemas/schemas/entities/ChannelEntity.schema.json'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
+import { InputParser } from '@joystream/cd-schemas'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 
 
+import { flags } from '@oclif/command'
+import _ from 'lodash'
+
 export default class CreateChannelCommand extends ContentDirectoryCommandBase {
 export default class CreateChannelCommand extends ContentDirectoryCommandBase {
   static description = 'Create a new channel on Joystream (requires a membership).'
   static description = 'Create a new channel on Joystream (requires a membership).'
   static flags = {
   static flags = {
     ...IOFlags,
     ...IOFlags,
+    confirm: flags.boolean({ char: 'y', name: 'confirm', required: false, description: 'Confirm the provided input' }),
   }
   }
 
 
   async run() {
   async run() {
@@ -21,7 +25,7 @@ export default class CreateChannelCommand extends ContentDirectoryCommandBase {
 
 
     const channelJsonSchema = (ChannelEntitySchema as unknown) as JSONSchema
     const channelJsonSchema = (ChannelEntitySchema as unknown) as JSONSchema
 
 
-    const { input, output } = this.parse(CreateChannelCommand).flags
+    const { input, output, confirm } = this.parse(CreateChannelCommand).flags
 
 
     let inputJson = await getInputJson<ChannelEntity>(input, channelJsonSchema)
     let inputJson = await getInputJson<ChannelEntity>(input, channelJsonSchema)
     if (!inputJson) {
     if (!inputJson) {
@@ -32,14 +36,15 @@ export default class CreateChannelCommand extends ContentDirectoryCommandBase {
 
 
       const prompter = new JsonSchemaPrompter<ChannelEntity>(channelJsonSchema, undefined, customPrompts)
       const prompter = new JsonSchemaPrompter<ChannelEntity>(channelJsonSchema, undefined, customPrompts)
 
 
-      inputJson = await prompter.promptAll(true)
+      inputJson = await prompter.promptAll()
     }
     }
 
 
     this.jsonPrettyPrint(JSON.stringify(inputJson))
     this.jsonPrettyPrint(JSON.stringify(inputJson))
-    const confirmed = await this.simplePrompt({ type: 'confirm', message: 'Do you confirm the provided input?' })
+    const confirmed =
+      confirm || (await this.simplePrompt({ type: 'confirm', message: 'Do you confirm the provided input?' }))
 
 
     if (confirmed) {
     if (confirmed) {
-      saveOutputJson(output, `${inputJson.title}Channel.json`, inputJson)
+      saveOutputJson(output, `${_.startCase(inputJson.handle)}Channel.json`, inputJson)
       const inputParser = InputParser.createWithKnownSchemas(this.getOriginalApi(), [
       const inputParser = InputParser.createWithKnownSchemas(this.getOriginalApi(), [
         {
         {
           className: 'Channel',
           className: 'Channel',

+ 3 - 3
cli/src/commands/media/curateContent.ts

@@ -1,8 +1,8 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import { InputParser } from 'cd-schemas'
+import { InputParser } from '@joystream/cd-schemas'
 import { flags } from '@oclif/command'
 import { flags } from '@oclif/command'
-import { ChannelEntity } from 'cd-schemas/types/entities/ChannelEntity'
-import { VideoEntity } from 'cd-schemas/types/entities/VideoEntity'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
+import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
 
 
 const CLASSES = ['Channel', 'Video'] as const
 const CLASSES = ['Channel', 'Video'] as const
 const STATUSES = ['Accepted', 'Censored'] as const
 const STATUSES = ['Accepted', 'Censored'] as const

+ 36 - 0
cli/src/commands/media/featuredVideos.ts

@@ -0,0 +1,36 @@
+import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
+import { displayTable } from '../../helpers/display'
+import { FeaturedVideoEntity, VideoEntity } from '@joystream/cd-schemas/types/entities'
+import chalk from 'chalk'
+
+export default class FeaturedVideosCommand extends ContentDirectoryCommandBase {
+  static description = 'Show a list of currently featured videos.'
+
+  async run() {
+    const featuredEntries = await this.entitiesByClassAndOwner('FeaturedVideo')
+    const featured = await Promise.all(
+      featuredEntries
+        .filter(([, entity]) => entity.supported_schemas.toArray().length) // Ignore FeaturedVideo entities without schema
+        .map(([, entity]) => this.parseToKnownEntityJson<FeaturedVideoEntity>(entity))
+    )
+
+    const videoIds: number[] = featured.map(({ video: videoId }) => videoId)
+
+    const videos = await Promise.all(videoIds.map((videoId) => this.getAndParseKnownEntity<VideoEntity>(videoId)))
+
+    if (videos.length) {
+      displayTable(
+        videos.map(({ title, channel }, index) => ({
+          featuredVideoEntityId: featuredEntries[index][0].toNumber(),
+          videoId: videoIds[index],
+          channelId: channel,
+          title,
+        })),
+        3
+      )
+      this.log(`\nTIP: Use ${chalk.bold('content-directory:entity ID')} command to see more details about given video`)
+    } else {
+      this.log(`No videos have been featured yet! Set some with ${chalk.bold('media:setFeaturedVideos')}`)
+    }
+  }
+}

+ 2 - 2
cli/src/commands/media/myChannels.ts

@@ -1,5 +1,5 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import { ChannelEntity } from 'cd-schemas/types/entities/ChannelEntity'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
 import { displayTable } from '../../helpers/display'
 import { displayTable } from '../../helpers/display'
 import chalk from 'chalk'
 import chalk from 'chalk'
 
 
@@ -9,7 +9,7 @@ export default class MyChannelsCommand extends ContentDirectoryCommandBase {
   async run() {
   async run() {
     const memberId = await this.getRequiredMemberId()
     const memberId = await this.getRequiredMemberId()
 
 
-    const props: (keyof ChannelEntity)[] = ['title', 'isPublic']
+    const props: (keyof ChannelEntity)[] = ['handle', 'isPublic']
 
 
     const list = await this.createEntityList('Channel', props, [], memberId)
     const list = await this.createEntityList('Channel', props, [], memberId)
 
 

+ 1 - 1
cli/src/commands/media/myVideos.ts

@@ -1,5 +1,5 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import { VideoEntity } from 'cd-schemas/types/entities/VideoEntity'
+import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
 import { displayTable } from '../../helpers/display'
 import { displayTable } from '../../helpers/display'
 import chalk from 'chalk'
 import chalk from 'chalk'
 import { flags } from '@oclif/command'
 import { flags } from '@oclif/command'

+ 3 - 3
cli/src/commands/media/removeChannel.ts

@@ -1,7 +1,7 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import { Entity } from '@joystream/types/content-directory'
 import { Entity } from '@joystream/types/content-directory'
 import { createType } from '@joystream/types'
 import { createType } from '@joystream/types'
-import { ChannelEntity } from 'cd-schemas/types/entities'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities'
 
 
 export default class RemoveChannelCommand extends ContentDirectoryCommandBase {
 export default class RemoveChannelCommand extends ContentDirectoryCommandBase {
   static description = 'Removes a channel (required controller access).'
   static description = 'Removes a channel (required controller access).'
@@ -29,13 +29,13 @@ export default class RemoveChannelCommand extends ContentDirectoryCommandBase {
       channelId = parseInt(id)
       channelId = parseInt(id)
       channelEntity = await this.getEntity(channelId, 'Channel', memberId)
       channelEntity = await this.getEntity(channelId, 'Channel', memberId)
     } else {
     } else {
-      const [id, channel] = await this.promptForEntityEntry('Select a channel to remove', 'Channel', 'title', memberId)
+      const [id, channel] = await this.promptForEntityEntry('Select a channel to remove', 'Channel', 'handle', memberId)
       channelId = id.toNumber()
       channelId = id.toNumber()
       channelEntity = channel
       channelEntity = channel
     }
     }
     const channel = await this.parseToKnownEntityJson<ChannelEntity>(channelEntity)
     const channel = await this.parseToKnownEntityJson<ChannelEntity>(channelEntity)
 
 
-    await this.requireConfirmation(`Are you sure you want to remove "${channel.title}" channel?`)
+    await this.requireConfirmation(`Are you sure you want to remove "${channel.handle}" channel?`)
 
 
     const api = this.getOriginalApi()
     const api = this.getOriginalApi()
     this.log(`Removing Channel entity (ID: ${channelId})...`)
     this.log(`Removing Channel entity (ID: ${channelId})...`)

+ 1 - 1
cli/src/commands/media/removeVideo.ts

@@ -1,6 +1,6 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import { Entity } from '@joystream/types/content-directory'
 import { Entity } from '@joystream/types/content-directory'
-import { VideoEntity } from 'cd-schemas/types/entities'
+import { VideoEntity } from '@joystream/cd-schemas/types/entities'
 import { createType } from '@joystream/types'
 import { createType } from '@joystream/types'
 
 
 export default class RemoveVideoCommand extends ContentDirectoryCommandBase {
 export default class RemoveVideoCommand extends ContentDirectoryCommandBase {

+ 79 - 0
cli/src/commands/media/setFeaturedVideos.ts

@@ -0,0 +1,79 @@
+import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
+import { VideoEntity } from '@joystream/cd-schemas/types/entities'
+import { InputParser, ExtrinsicsHelper } from '@joystream/cd-schemas'
+import { FlattenRelations } from '@joystream/cd-schemas/types/utility'
+import { flags } from '@oclif/command'
+import { createType } from '@joystream/types'
+
+export default class SetFeaturedVideosCommand extends ContentDirectoryCommandBase {
+  static description = 'Set currently featured videos (requires lead/maintainer access).'
+  static args = [
+    {
+      name: 'videoIds',
+      required: true,
+      description: 'Comma-separated video ids',
+    },
+  ]
+
+  static flags = {
+    add: flags.boolean({
+      description: 'If provided - currently featured videos will not be removed.',
+      required: false,
+    }),
+  }
+
+  async run() {
+    const account = await this.getRequiredSelectedAccount()
+    let actor = createType('Actor', { Lead: null })
+    try {
+      await this.getRequiredLead()
+    } catch (e) {
+      actor = await this.getCuratorContext(['FeaturedVideo'])
+    }
+
+    await this.requestAccountDecoding(account)
+
+    const {
+      args: { videoIds },
+      flags: { add },
+    } = this.parse(SetFeaturedVideosCommand)
+
+    const ids: number[] = videoIds.split(',').map((id: string) => parseInt(id))
+
+    const videos: [number, FlattenRelations<VideoEntity>][] = (
+      await Promise.all(ids.map((id) => this.getAndParseKnownEntity<VideoEntity>(id, 'Video')))
+    ).map((video, index) => [ids[index], video])
+
+    this.log(
+      `Featured videos that will ${add ? 'be added to' : 'replace'} existing ones:`,
+      videos.map(([id, { title }]) => ({ id, title }))
+    )
+
+    await this.requireConfirmation('Do you confirm the provided input?')
+
+    if (!add) {
+      const currentlyFeaturedIds = (await this.entitiesByClassAndOwner('FeaturedVideo')).map(([id]) => id.toNumber())
+      const removeTxs = currentlyFeaturedIds.map((id) =>
+        this.getOriginalApi().tx.contentDirectory.removeEntity(actor, id)
+      )
+
+      if (currentlyFeaturedIds.length) {
+        this.log(`Removing existing FeaturedVideo entities (${currentlyFeaturedIds.join(', ')})...`)
+
+        const txHelper = new ExtrinsicsHelper(this.getOriginalApi())
+        await txHelper.sendAndCheck(account, removeTxs, 'The removal of existing FeaturedVideo entities failed')
+      }
+    }
+
+    this.log('Adding new FeaturedVideo entities...')
+    const featuredVideoEntries = videos.map(([id]) => ({ video: id }))
+    const inputParser = InputParser.createWithKnownSchemas(this.getOriginalApi(), [
+      {
+        className: 'FeaturedVideo',
+        entries: featuredVideoEntries,
+      },
+    ])
+    const operations = await inputParser.getEntityBatchOperations()
+    await this.sendAndFollowNamedTx(account, 'contentDirectory', 'transaction', [actor, operations])
+  }
+}

+ 7 - 6
cli/src/commands/media/updateChannel.ts

@@ -1,13 +1,14 @@
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
 import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
-import ChannelEntitySchema from 'cd-schemas/schemas/entities/ChannelEntity.schema.json'
-import { ChannelEntity } from 'cd-schemas/types/entities/ChannelEntity'
-import { InputParser } from 'cd-schemas'
+import ChannelEntitySchema from '@joystream/cd-schemas/schemas/entities/ChannelEntity.schema.json'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
+import { InputParser } from '@joystream/cd-schemas'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 import { Actor, Entity } from '@joystream/types/content-directory'
 import { Actor, Entity } from '@joystream/types/content-directory'
 import { flags } from '@oclif/command'
 import { flags } from '@oclif/command'
 import { createType } from '@joystream/types'
 import { createType } from '@joystream/types'
+import _ from 'lodash'
 
 
 export default class UpdateChannelCommand extends ContentDirectoryCommandBase {
 export default class UpdateChannelCommand extends ContentDirectoryCommandBase {
   static description = 'Update one of the owned channels on Joystream (requires a membership).'
   static description = 'Update one of the owned channels on Joystream (requires a membership).'
@@ -51,7 +52,7 @@ export default class UpdateChannelCommand extends ContentDirectoryCommandBase {
       channelId = parseInt(id)
       channelId = parseInt(id)
       channelEntity = await this.getEntity(channelId, 'Channel', memberId)
       channelEntity = await this.getEntity(channelId, 'Channel', memberId)
     } else {
     } else {
-      const [id, channel] = await this.promptForEntityEntry('Select a channel to update', 'Channel', 'title', memberId)
+      const [id, channel] = await this.promptForEntityEntry('Select a channel to update', 'Channel', 'handle', memberId)
       channelId = id.toNumber()
       channelId = id.toNumber()
       channelEntity = channel
       channelEntity = channel
     }
     }
@@ -80,14 +81,14 @@ export default class UpdateChannelCommand extends ContentDirectoryCommandBase {
 
 
       const prompter = new JsonSchemaPrompter<ChannelEntity>(channelJsonSchema, currentValues, customPrompts)
       const prompter = new JsonSchemaPrompter<ChannelEntity>(channelJsonSchema, currentValues, customPrompts)
 
 
-      inputJson = await prompter.promptAll(true)
+      inputJson = await prompter.promptAll()
     }
     }
 
 
     this.jsonPrettyPrint(JSON.stringify(inputJson))
     this.jsonPrettyPrint(JSON.stringify(inputJson))
     const confirmed = await this.simplePrompt({ type: 'confirm', message: 'Do you confirm the provided input?' })
     const confirmed = await this.simplePrompt({ type: 'confirm', message: 'Do you confirm the provided input?' })
 
 
     if (confirmed) {
     if (confirmed) {
-      saveOutputJson(output, `${inputJson.title}Channel.json`, inputJson)
+      saveOutputJson(output, `${_.startCase(inputJson.handle)}Channel.json`, inputJson)
       const inputParser = InputParser.createWithKnownSchemas(this.getOriginalApi())
       const inputParser = InputParser.createWithKnownSchemas(this.getOriginalApi())
       const updateOperations = await inputParser.getEntityUpdateOperations(inputJson, 'Channel', channelId)
       const updateOperations = await inputParser.getEntityUpdateOperations(inputJson, 'Channel', channelId)
       this.log('Sending the extrinsic...')
       this.log('Sending the extrinsic...')

+ 4 - 4
cli/src/commands/media/updateVideo.ts

@@ -1,6 +1,6 @@
-import VideoEntitySchema from 'cd-schemas/schemas/entities/VideoEntity.schema.json'
-import { VideoEntity } from 'cd-schemas/types/entities/VideoEntity'
-import { InputParser } from 'cd-schemas'
+import VideoEntitySchema from '@joystream/cd-schemas/schemas/entities/VideoEntity.schema.json'
+import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
+import { InputParser } from '@joystream/cd-schemas'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 import { Actor, Entity } from '@joystream/types/content-directory'
 import { Actor, Entity } from '@joystream/types/content-directory'
@@ -83,7 +83,7 @@ export default class UpdateVideoCommand extends MediaCommandBase {
       'category',
       'category',
       'title',
       'title',
       'description',
       'description',
-      'thumbnailURL',
+      'thumbnailUrl',
       'duration',
       'duration',
       'isPublic',
       'isPublic',
       'isExplicit',
       'isExplicit',

+ 2 - 2
cli/src/commands/media/updateVideoLicense.ts

@@ -1,6 +1,6 @@
 import MediaCommandBase from '../../base/MediaCommandBase'
 import MediaCommandBase from '../../base/MediaCommandBase'
-import { LicenseEntity, VideoEntity } from 'cd-schemas/types/entities'
-import { InputParser } from 'cd-schemas'
+import { LicenseEntity, VideoEntity } from '@joystream/cd-schemas/types/entities'
+import { InputParser } from '@joystream/cd-schemas'
 import { Entity } from '@joystream/types/content-directory'
 import { Entity } from '@joystream/types/content-directory'
 import { createType } from '@joystream/types'
 import { createType } from '@joystream/types'
 
 

+ 131 - 73
cli/src/commands/media/uploadVideo.ts

@@ -1,8 +1,8 @@
-import VideoEntitySchema from 'cd-schemas/schemas/entities/VideoEntity.schema.json'
-import VideoMediaEntitySchema from 'cd-schemas/schemas/entities/VideoMediaEntity.schema.json'
-import { VideoEntity } from 'cd-schemas/types/entities/VideoEntity'
-import { VideoMediaEntity } from 'cd-schemas/types/entities/VideoMediaEntity'
-import { InputParser } from 'cd-schemas'
+import VideoEntitySchema from '@joystream/cd-schemas/schemas/entities/VideoEntity.schema.json'
+import VideoMediaEntitySchema from '@joystream/cd-schemas/schemas/entities/VideoMediaEntity.schema.json'
+import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
+import { VideoMediaEntity } from '@joystream/cd-schemas/types/entities/VideoMediaEntity'
+import { InputParser } from '@joystream/cd-schemas'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 import { JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
 import { flags } from '@oclif/command'
 import { flags } from '@oclif/command'
@@ -17,14 +17,15 @@ import ipfsHttpClient from 'ipfs-http-client'
 import first from 'it-first'
 import first from 'it-first'
 import last from 'it-last'
 import last from 'it-last'
 import toBuffer from 'it-to-buffer'
 import toBuffer from 'it-to-buffer'
-import ffmpegInstaller from '@ffmpeg-installer/ffmpeg'
+import ffprobeInstaller from '@ffprobe-installer/ffprobe'
 import ffmpeg from 'fluent-ffmpeg'
 import ffmpeg from 'fluent-ffmpeg'
 import MediaCommandBase from '../../base/MediaCommandBase'
 import MediaCommandBase from '../../base/MediaCommandBase'
+import { getInputJson, validateInput, IOFlags } from '../../helpers/InputOutput'
 
 
-ffmpeg.setFfmpegPath(ffmpegInstaller.path)
+ffmpeg.setFfprobePath(ffprobeInstaller.path)
 
 
 const DATA_OBJECT_TYPE_ID = 1
 const DATA_OBJECT_TYPE_ID = 1
-const MAX_FILE_SIZE = 500 * 1024 * 1024
+const MAX_FILE_SIZE = 2000 * 1024 * 1024
 
 
 type VideoMetadata = {
 type VideoMetadata = {
   width?: number
   width?: number
@@ -37,13 +38,14 @@ type VideoMetadata = {
 export default class UploadVideoCommand extends MediaCommandBase {
 export default class UploadVideoCommand extends MediaCommandBase {
   static description = 'Upload a new Video to a channel (requires a membership).'
   static description = 'Upload a new Video to a channel (requires a membership).'
   static flags = {
   static flags = {
-    // TODO: ...IOFlags, - providing input as json
+    input: IOFlags.input,
     channel: flags.integer({
     channel: flags.integer({
       char: 'c',
       char: 'c',
       required: false,
       required: false,
       description:
       description:
         'ID of the channel to assign the video to (if omitted - one of the owned channels can be selected from the list)',
         'ID of the channel to assign the video to (if omitted - one of the owned channels can be selected from the list)',
     }),
     }),
+    confirm: flags.boolean({ char: 'y', name: 'confirm', required: false, description: 'Confirm the provided input' }),
   }
   }
 
 
   static args = [
   static args = [
@@ -217,6 +219,117 @@ export default class UploadVideoCommand extends MediaCommandBase {
     }
     }
   }
   }
 
 
+  private async promptForVideoInput(
+    channelId: number,
+    fileSize: number,
+    contentId: ContentId,
+    videoMetadata: VideoMetadata | null
+  ) {
+    // Set the defaults
+    const videoMediaDefaults: Partial<VideoMediaEntity> = {
+      pixelWidth: videoMetadata?.width,
+      pixelHeight: videoMetadata?.height,
+    }
+    const videoDefaults: Partial<VideoEntity> = {
+      duration: videoMetadata?.duration,
+      skippableIntroDuration: 0,
+    }
+
+    // Prompt for data
+    const videoJsonSchema = (VideoEntitySchema as unknown) as JSONSchema
+    const videoMediaJsonSchema = (VideoMediaEntitySchema as unknown) as JSONSchema
+
+    const videoMediaPrompter = new JsonSchemaPrompter<VideoMediaEntity>(videoMediaJsonSchema, videoMediaDefaults)
+    const videoPrompter = new JsonSchemaPrompter<VideoEntity>(videoJsonSchema, videoDefaults)
+
+    // Prompt for the data
+    const encodingSuggestion =
+      videoMetadata && videoMetadata.codecFullName ? ` (suggested: ${videoMetadata.codecFullName})` : ''
+    const encoding = await this.promptForEntityId(
+      `Choose Video encoding${encodingSuggestion}`,
+      'VideoMediaEncoding',
+      'name'
+    )
+    const { pixelWidth, pixelHeight } = await videoMediaPrompter.promptMultipleProps(['pixelWidth', 'pixelHeight'])
+    const language = await this.promptForEntityId('Choose Video language', 'Language', 'name')
+    const category = await this.promptForEntityId('Choose Video category', 'ContentCategory', 'name')
+    const videoProps = await videoPrompter.promptMultipleProps([
+      'title',
+      'description',
+      'thumbnailUrl',
+      'duration',
+      'isPublic',
+      'isExplicit',
+      'hasMarketing',
+      'skippableIntroDuration',
+    ])
+
+    const license = await videoPrompter.promptSingleProp('license', () => this.promptForNewLicense())
+    const publishedBeforeJoystream = await videoPrompter.promptSingleProp('publishedBeforeJoystream', () =>
+      this.promptForPublishedBeforeJoystream()
+    )
+
+    // Create final inputs
+    const videoMediaInput: VideoMediaEntity = {
+      encoding,
+      pixelWidth,
+      pixelHeight,
+      size: fileSize,
+      location: { new: { joystreamMediaLocation: { new: { dataObjectId: contentId.encode() } } } },
+    }
+    return {
+      ...videoProps,
+      channel: channelId,
+      language,
+      category,
+      license,
+      media: { new: videoMediaInput },
+      publishedBeforeJoystream,
+    }
+  }
+
+  private async getVideoInputFromFile(
+    filePath: string,
+    channelId: number,
+    fileSize: number,
+    contentId: ContentId,
+    videoMetadata: VideoMetadata | null
+  ) {
+    let videoInput = await getInputJson<any>(filePath)
+    if (typeof videoInput !== 'object' || videoInput === null) {
+      this.error('Invalid input json - expected an object', { exit: ExitCodes.InvalidInput })
+    }
+    const videoMediaDefaults: Partial<VideoMediaEntity> = {
+      pixelWidth: videoMetadata?.width,
+      pixelHeight: videoMetadata?.height,
+      size: fileSize,
+    }
+    const videoDefaults: Partial<VideoEntity> = {
+      channel: channelId,
+      duration: videoMetadata?.duration,
+    }
+    const inputVideoMedia =
+      videoInput.media && typeof videoInput.media === 'object' && (videoInput.media as any).new
+        ? (videoInput.media as any).new
+        : {}
+    videoInput = {
+      ...videoDefaults,
+      ...videoInput,
+      media: {
+        new: {
+          ...videoMediaDefaults,
+          ...inputVideoMedia,
+          location: { new: { joystreamMediaLocation: { new: { dataObjectId: contentId.encode() } } } },
+        },
+      },
+    }
+
+    const videoJsonSchema = (VideoEntitySchema as unknown) as JSONSchema
+    await validateInput(videoInput, videoJsonSchema)
+
+    return videoInput as VideoEntity
+  }
+
   async run() {
   async run() {
     const account = await this.getRequiredSelectedAccount()
     const account = await this.getRequiredSelectedAccount()
     const memberId = await this.getRequiredMemberId()
     const memberId = await this.getRequiredMemberId()
@@ -226,7 +339,7 @@ export default class UploadVideoCommand extends MediaCommandBase {
 
 
     const {
     const {
       args: { filePath },
       args: { filePath },
-      flags: { channel: inputChannelId },
+      flags: { channel: inputChannelId, input, confirm },
     } = this.parse(UploadVideoCommand)
     } = this.parse(UploadVideoCommand)
 
 
     // Basic file validation
     // Basic file validation
@@ -255,7 +368,7 @@ export default class UploadVideoCommand extends MediaCommandBase {
       channelId = await this.promptForEntityId(
       channelId = await this.promptForEntityId(
         'Select a channel to publish the video under',
         'Select a channel to publish the video under',
         'Channel',
         'Channel',
-        'title',
+        'handle',
         memberId
         memberId
       )
       )
     } else {
     } else {
@@ -303,71 +416,16 @@ export default class UploadVideoCommand extends MediaCommandBase {
 
 
     await this.uploadVideo(filePath, fileSize, uploadUrl)
     await this.uploadVideo(filePath, fileSize, uploadUrl)
 
 
-    // Prompting for the data:
-
-    // Set the defaults
-    const videoMediaDefaults: Partial<VideoMediaEntity> = {
-      pixelWidth: videoMetadata?.width,
-      pixelHeight: videoMetadata?.height,
-    }
-    const videoDefaults: Partial<VideoEntity> = {
-      duration: videoMetadata?.duration,
-      skippableIntroDuration: 0,
-    }
-    // Create prompting helpers
-    const videoJsonSchema = (VideoEntitySchema as unknown) as JSONSchema
-    const videoMediaJsonSchema = (VideoMediaEntitySchema as unknown) as JSONSchema
-
-    const videoMediaPrompter = new JsonSchemaPrompter<VideoMediaEntity>(videoMediaJsonSchema, videoMediaDefaults)
-    const videoPrompter = new JsonSchemaPrompter<VideoEntity>(videoJsonSchema, videoDefaults)
-
-    // Prompt for the data
-    const encodingSuggestion =
-      videoMetadata && videoMetadata.codecFullName ? ` (suggested: ${videoMetadata.codecFullName})` : ''
-    const encoding = await this.promptForEntityId(
-      `Choose Video encoding${encodingSuggestion}`,
-      'VideoMediaEncoding',
-      'name'
-    )
-    const { pixelWidth, pixelHeight } = await videoMediaPrompter.promptMultipleProps(['pixelWidth', 'pixelHeight'])
-    const language = await this.promptForEntityId('Choose Video language', 'Language', 'name')
-    const category = await this.promptForEntityId('Choose Video category', 'ContentCategory', 'name')
-    const videoProps = await videoPrompter.promptMultipleProps([
-      'title',
-      'description',
-      'thumbnailURL',
-      'duration',
-      'isPublic',
-      'isExplicit',
-      'hasMarketing',
-      'skippableIntroDuration',
-    ])
+    // No input, create prompting helpers
+    const videoInput = input
+      ? await this.getVideoInputFromFile(input, channelId, fileSize, contentId, videoMetadata)
+      : await this.promptForVideoInput(channelId, fileSize, contentId, videoMetadata)
 
 
-    const license = await videoPrompter.promptSingleProp('license', () => this.promptForNewLicense())
-    const publishedBeforeJoystream = await videoPrompter.promptSingleProp('publishedBeforeJoystream', () =>
-      this.promptForPublishedBeforeJoystream()
-    )
+    this.jsonPrettyPrint(JSON.stringify(videoInput))
 
 
-    // Create final inputs
-    const videoMediaInput: VideoMediaEntity = {
-      encoding,
-      pixelWidth,
-      pixelHeight,
-      size: fileSize,
-      location: { new: { joystreamMediaLocation: { new: { dataObjectId: contentId.encode() } } } },
+    if (!confirm) {
+      await this.requireConfirmation('Do you confirm the provided input?', true)
     }
     }
-    const videoInput: VideoEntity = {
-      ...videoProps,
-      channel: channelId,
-      language,
-      category,
-      license,
-      media: { new: videoMediaInput },
-      publishedBeforeJoystream,
-    }
-
-    this.jsonPrettyPrint(JSON.stringify(videoInput))
-    await this.requireConfirmation('Do you confirm the provided input?')
 
 
     // Parse inputs into operations and send final extrinsic
     // Parse inputs into operations and send final extrinsic
     const inputParser = InputParser.createWithKnownSchemas(this.getOriginalApi(), [
     const inputParser = InputParser.createWithKnownSchemas(this.getOriginalApi(), [

+ 11 - 7
cli/src/helpers/InputOutput.ts

@@ -5,7 +5,7 @@ import fs from 'fs'
 import path from 'path'
 import path from 'path'
 import Ajv from 'ajv'
 import Ajv from 'ajv'
 import $RefParser, { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import $RefParser, { JSONSchema } from '@apidevtools/json-schema-ref-parser'
-import { getSchemasLocation } from 'cd-schemas'
+import { getSchemasLocation } from '@joystream/cd-schemas'
 import chalk from 'chalk'
 import chalk from 'chalk'
 
 
 // Default schema path for resolving refs
 // Default schema path for resolving refs
@@ -39,12 +39,7 @@ export async function getInputJson<T>(inputPath?: string, schema?: JSONSchema, s
       throw new CLIError(`JSON parsing failed for file: ${inputPath}`, { exit: ExitCodes.InvalidInput })
       throw new CLIError(`JSON parsing failed for file: ${inputPath}`, { exit: ExitCodes.InvalidInput })
     }
     }
     if (schema) {
     if (schema) {
-      const ajv = new Ajv()
-      schema = await $RefParser.dereference(schemaPath || DEFAULT_SCHEMA_PATH, schema, {})
-      const valid = ajv.validate(schema, jsonObj) as boolean
-      if (!valid) {
-        throw new CLIError(`Input JSON file is not valid: ${ajv.errorsText()}`)
-      }
+      await validateInput(jsonObj, schema, schemaPath)
     }
     }
 
 
     return jsonObj as T
     return jsonObj as T
@@ -53,6 +48,15 @@ export async function getInputJson<T>(inputPath?: string, schema?: JSONSchema, s
   return null
   return null
 }
 }
 
 
+export async function validateInput(input: unknown, schema: JSONSchema, schemaPath?: string): Promise<void> {
+  const ajv = new Ajv({ allErrors: true })
+  schema = await $RefParser.dereference(schemaPath || DEFAULT_SCHEMA_PATH, schema, {})
+  const valid = ajv.validate(schema, input) as boolean
+  if (!valid) {
+    throw new CLIError(`Input JSON file is not valid: ${ajv.errorsText()}`)
+  }
+}
+
 export function saveOutputJson(outputPath: string | undefined, fileName: string, data: any): void {
 export function saveOutputJson(outputPath: string | undefined, fileName: string, data: any): void {
   if (outputPath) {
   if (outputPath) {
     let outputFilePath = path.join(outputPath, fileName)
     let outputFilePath = path.join(outputPath, fileName)

+ 40 - 35
cli/src/helpers/JsonSchemaPrompt.ts

@@ -4,7 +4,7 @@ import _ from 'lodash'
 import RefParser, { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import RefParser, { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import chalk from 'chalk'
 import chalk from 'chalk'
 import { BOOL_PROMPT_OPTIONS } from './prompting'
 import { BOOL_PROMPT_OPTIONS } from './prompting'
-import { getSchemasLocation } from 'cd-schemas'
+import { getSchemasLocation } from '@joystream/cd-schemas'
 import path from 'path'
 import path from 'path'
 
 
 type CustomPromptMethod = () => Promise<any>
 type CustomPromptMethod = () => Promise<any>
@@ -106,7 +106,11 @@ export class JsonSchemaPrompter<JsonResult> {
     if (schema.oneOf) {
     if (schema.oneOf) {
       const oneOf = schema.oneOf as JSONSchema[]
       const oneOf = schema.oneOf as JSONSchema[]
       const options = this.oneOfToOptions(oneOf, currentValue)
       const options = this.oneOfToOptions(oneOf, currentValue)
-      const { choosen } = await inquirer.prompt({ name: 'choosen', message: propDisplayName, type: 'list', ...options })
+      const choosen = await this.inquirerSinglePrompt({
+        message: propDisplayName,
+        type: 'list',
+        ...options,
+      })
       if (choosen !== options.default) {
       if (choosen !== options.default) {
         _.set(this.filledObject, propertyPath, undefined) // Clear any previous value if different variant selected
         _.set(this.filledObject, propertyPath, undefined) // Clear any previous value if different variant selected
       }
       }
@@ -128,18 +132,13 @@ export class JsonSchemaPrompter<JsonResult> {
         const required = allPropsRequired || (Array.isArray(schema.required) && schema.required.includes(pName))
         const required = allPropsRequired || (Array.isArray(schema.required) && schema.required.includes(pName))
 
 
         if (!required) {
         if (!required) {
-          confirmed = (
-            await inquirer.prompt([
-              {
-                message: `Do you want to provide optional ${chalk.greenBright(objectPropertyPath)}?`,
-                type: 'confirm',
-                name: 'confirmed',
-                default:
-                  _.get(this.filledObject, objectPropertyPath) !== undefined &&
-                  _.get(this.filledObject, objectPropertyPath) !== null,
-              },
-            ])
-          ).confirmed
+          confirmed = await this.inquirerSinglePrompt({
+            message: `Do you want to provide optional ${chalk.greenBright(objectPropertyPath)}?`,
+            type: 'confirm',
+            default:
+              _.get(this.filledObject, objectPropertyPath) !== undefined &&
+              _.get(this.filledObject, objectPropertyPath) !== null,
+          })
         }
         }
         if (confirmed) {
         if (confirmed) {
           value[pName] = await this.prompt(pSchema, objectPropertyPath)
           value[pName] = await this.prompt(pSchema, objectPropertyPath)
@@ -207,14 +206,11 @@ export class JsonSchemaPrompter<JsonResult> {
     let currItem = 0
     let currItem = 0
     const result = []
     const result = []
     while (currItem < maxItems) {
     while (currItem < maxItems) {
-      const { next } = await inquirer.prompt([
-        {
-          ...BOOL_PROMPT_OPTIONS,
-          name: 'next',
-          message: `Do you want to add another item to ${this.propertyDisplayName(propertyPath)} array?`,
-          default: _.get(this.filledObject, `${propertyPath}[${currItem}]`) !== undefined,
-        },
-      ])
+      const next = await this.inquirerSinglePrompt({
+        ...BOOL_PROMPT_OPTIONS,
+        message: `Do you want to add another item to ${this.propertyDisplayName(propertyPath)} array?`,
+        default: _.get(this.filledObject, `${propertyPath}[${currItem}]`) !== undefined,
+      })
       if (!next) {
       if (!next) {
         break
         break
       }
       }
@@ -228,20 +224,17 @@ export class JsonSchemaPrompter<JsonResult> {
   }
   }
 
 
   private async promptSimple(promptOptions: DistinctQuestion, propertyPath: string, normalize?: (v: any) => any) {
   private async promptSimple(promptOptions: DistinctQuestion, propertyPath: string, normalize?: (v: any) => any) {
-    const { result } = await inquirer.prompt([
-      {
-        ...promptOptions,
-        name: 'result',
-        validate: (v) => {
-          v = normalize ? normalize(v) : v
-          return (
-            this.setValueAndGetError(propertyPath, v) ||
-            (promptOptions.validate ? promptOptions.validate(v) : true) ||
-            true
-          )
-        },
+    const result = await this.inquirerSinglePrompt({
+      ...promptOptions,
+      validate: (v) => {
+        v = normalize ? normalize(v) : v
+        return (
+          this.setValueAndGetError(propertyPath, v) ||
+          (promptOptions.validate ? promptOptions.validate(v) : true) ||
+          true
+        )
       },
       },
-    ])
+    })
 
 
     return result
     return result
   }
   }
@@ -291,4 +284,16 @@ export class JsonSchemaPrompter<JsonResult> {
     await this.prompt(mainSchema.properties![p] as JSONSchema, p, customPrompt)
     await this.prompt(mainSchema.properties![p] as JSONSchema, p, customPrompt)
     return this.filledObject[p] as Exclude<JsonResult[P], undefined>
     return this.filledObject[p] as Exclude<JsonResult[P], undefined>
   }
   }
+
+  async inquirerSinglePrompt(question: DistinctQuestion) {
+    const { result } = await inquirer.prompt([
+      {
+        ...question,
+        name: 'result',
+        prefix: '',
+      },
+    ])
+
+    return result
+  }
 }
 }

+ 1 - 1
cli/src/helpers/display.ts

@@ -44,7 +44,7 @@ export function displayTable(rows: { [k: string]: string | number }[], cellHoriz
   const maxLength = (columnName: string) =>
   const maxLength = (columnName: string) =>
     rows.reduce((maxLength, row) => {
     rows.reduce((maxLength, row) => {
       const val = row[columnName]
       const val = row[columnName]
-      const valLength = typeof val === 'string' ? val.length : val.toString().length
+      const valLength = typeof val === 'string' ? val.length : val !== undefined ? val.toString().length : 0
       return Math.max(maxLength, valLength)
       return Math.max(maxLength, valLength)
     }, columnName.length)
     }, columnName.length)
   const columnDef = (columnName: string) => ({
   const columnDef = (columnName: string) => ({

+ 20 - 20
content-directory-schemas/README.md

@@ -14,7 +14,7 @@ In order to make this documentation as clear as possible it is important to make
 In order to intialize the content directory on a development chain based on data that is provided in form of json files inside `/inputs` directory (`classes`, `schemas` and example entities - `entityBatches`), we can run:
 In order to intialize the content directory on a development chain based on data that is provided in form of json files inside `/inputs` directory (`classes`, `schemas` and example entities - `entityBatches`), we can run:
 
 
 ```
 ```
-yarn workspace cd-schemas initialize:dev
+yarn workspace @joystream/cd-schemas initialize:dev
 ```
 ```
 
 
 This will handle:
 This will handle:
@@ -51,7 +51,7 @@ For more context, see: https://code.visualstudio.com/docs/languages/json
 
 
 ### Validate inputs and `json-schemas` via a command
 ### Validate inputs and `json-schemas` via a command
 
 
-All inputs inside `inputs` directory and `json-schemas` used to validate those inputs can also be validated using `yarn workspace cd-schemas validate` command. This is mainly to facilitate checking the validity of `.json` and `.schema.json` files inside `content-directory-schemas` through CI.
+All inputs inside `inputs` directory and `json-schemas` used to validate those inputs can also be validated using `yarn workspace @joystream/cd-schemas validate` command. This is mainly to facilitate checking the validity of `.json` and `.schema.json` files inside `content-directory-schemas` through CI.
 
 
 ### Entity batches
 ### Entity batches
 
 
@@ -109,7 +109,7 @@ We can do it by either using `"new"` or `"existing"` keyword.
 There is a script that provides an easy way of converting `runtime-schemas` (based on inputs from `inputs/schemas`) to `json-schemas` (`.schema.json` files) which allow validating the input (ie. json files) describing some specific entities. It can be run with:
 There is a script that provides an easy way of converting `runtime-schemas` (based on inputs from `inputs/schemas`) to `json-schemas` (`.schema.json` files) which allow validating the input (ie. json files) describing some specific entities. It can be run with:
 
 
 ```
 ```
-yarn workspace cd-schemas generate:entity-schemas
+yarn workspace @joystream/cd-schemas generate:entity-schemas
 ```
 ```
 
 
 Those `json-schemas` are currently mainly used for validating the inputs inside `inputs/entityBatches`.
 Those `json-schemas` are currently mainly used for validating the inputs inside `inputs/entityBatches`.
@@ -125,7 +125,7 @@ The generated `json-schemas` include:
 Thanks to the `json-schema-to-typescript` library, we can very simply generate Typescript interfaces based on existing `json-schemas`. This can be done via:
 Thanks to the `json-schema-to-typescript` library, we can very simply generate Typescript interfaces based on existing `json-schemas`. This can be done via:
 
 
 ```
 ```
-yarn workspace cd-schemas generate:types
+yarn workspace @joystream/cd-schemas generate:types
 ```
 ```
 
 
 This command will generate:
 This command will generate:
@@ -153,19 +153,19 @@ The best way to ilustrate this would be by providing some examples:
 
 
 #### Creating a channel
 #### Creating a channel
 ```
 ```
-  import { InputParser } from 'cd-schemas'
-  import { ChannelEntity } from 'cd-schemas/types/entities/ChannelEntity'
+  import { InputParser } from '@joystream/cd-schemas'
+  import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
   // Other imports...
   // Other imports...
 
 
   async main() {
   async main() {
     // Initialize the api, SENDER_KEYPAIR and SENDER_MEMBER_ID...
     // Initialize the api, SENDER_KEYPAIR and SENDER_MEMBER_ID...
 
 
     const channel: ChannelEntity = {
     const channel: ChannelEntity = {
-      title: 'Example channel',
+      handle: 'Example channel',
       description: 'This is an example channel',
       description: 'This is an example channel',
       language: { existing: { code: 'EN' } },
       language: { existing: { code: 'EN' } },
       coverPhotoUrl: '',
       coverPhotoUrl: '',
-      avatarPhotoURL: '',
+      avatarPhotoUrl: '',
       isPublic: true,
       isPublic: true,
     }
     }
 
 
@@ -182,12 +182,12 @@ The best way to ilustrate this would be by providing some examples:
       .signAndSend(SENDER_KEYPAIR)
       .signAndSend(SENDER_KEYPAIR)
   }
   }
 ```
 ```
-_Full example with comments can be found in `content-directory-schemas/examples/createChannel.ts` and ran with `yarn workspace cd-schemas example:createChannel`_
+_Full example with comments can be found in `content-directory-schemas/examples/createChannel.ts` and ran with `yarn workspace @joystream/cd-schemas example:createChannel`_
 
 
 #### Creating a video
 #### Creating a video
 ```
 ```
-import { InputParser } from 'cd-schemas'
-import { VideoEntity } from 'cd-schemas/types/entities/VideoEntity'
+import { InputParser } from '@joystream/cd-schemas'
+import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
 // ...
 // ...
 
 
 async main() {
 async main() {
@@ -198,7 +198,7 @@ async main() {
     description: 'This is an example video',
     description: 'This is an example video',
     language: { existing: { code: 'EN' } },
     language: { existing: { code: 'EN' } },
     category: { existing: { name: 'Education' } },
     category: { existing: { name: 'Education' } },
-    channel: { existing: { title: 'Example channel' } },
+    channel: { existing: { handle: 'Example channel' } },
     media: {
     media: {
       new: {
       new: {
         encoding: { existing: { name: 'H.263_MP4' } },
         encoding: { existing: { name: 'H.263_MP4' } },
@@ -221,7 +221,7 @@ async main() {
       },
       },
     },
     },
     duration: 3600,
     duration: 3600,
-    thumbnailURL: '',
+    thumbnailUrl: '',
     isExplicit: false,
     isExplicit: false,
     isPublic: true,
     isPublic: true,
   }
   }
@@ -239,25 +239,25 @@ async main() {
     .signAndSend(SENDER_KEYPAIR)
     .signAndSend(SENDER_KEYPAIR)
 }
 }
 ```
 ```
-_Full example with comments can be found in `content-directory-schemas/examples/createVideo.ts` and ran with `yarn workspace cd-schemas example:createChannel`_
+_Full example with comments can be found in `content-directory-schemas/examples/createVideo.ts` and ran with `yarn workspace @joystream/cd-schemas example:createChannel`_
 
 
-#### Update channel title
+#### Update channel handle
 
 
 ```
 ```
-import { InputParser } from 'cd-schemas'
-import { ChannelEntity } from 'cd-schemas/types/entities/ChannelEntity'
+import { InputParser } from '@joystream/cd-schemas'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
 // ...
 // ...
 
 
 async function main() {
 async function main() {
   // ...
   // ...
 
 
   const channelUpdateInput: Partial<ChannelEntity> = {
   const channelUpdateInput: Partial<ChannelEntity> = {
-    title: 'Updated channel title',
+    handle: 'Updated channel handle',
   }
   }
 
 
   const parser = InputParser.createWithKnownSchemas(api)
   const parser = InputParser.createWithKnownSchemas(api)
 
 
-  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ title: 'Example channel' }, 'Channel')
+  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ handle: 'Example channel' }, 'Channel')
 
 
   const updateOperations = await parser.getEntityUpdateOperations(channelUpdateInput, 'Channel', CHANNEL_ID)
   const updateOperations = await parser.getEntityUpdateOperations(channelUpdateInput, 'Channel', CHANNEL_ID)
 
 
@@ -266,7 +266,7 @@ async function main() {
     .signAndSend(SENDER_KEYPAIR)
     .signAndSend(SENDER_KEYPAIR)
 }
 }
 ```
 ```
-_Full example with comments can be found in `content-directory-schemas/examples/updateChannelTitle.ts` and ran with `yarn workspace cd-schemas example:updateChannelTitle`_
+_Full example with comments can be found in `content-directory-schemas/examples/updateChannelHandle.ts` and ran with `yarn workspace @joystream/cd-schemas example:updateChannelHandle`_
 
 
 Note: Updates can also inlucde `new` and `existing` keywords. In case `new` is specified inside the update - `CreateEntity` and `AddSchemaSupportToEntity` operations will be included as part of the operations returned by `InputParser.getEntityUpdateOperations`.
 Note: Updates can also inlucde `new` and `existing` keywords. In case `new` is specified inside the update - `CreateEntity` and `AddSchemaSupportToEntity` operations will be included as part of the operations returned by `InputParser.getEntityUpdateOperations`.
 
 

+ 5 - 5
content-directory-schemas/examples/createChannel.ts

@@ -1,9 +1,9 @@
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { types as joyTypes } from '@joystream/types'
 import { types as joyTypes } from '@joystream/types'
 import { Keyring } from '@polkadot/keyring'
 import { Keyring } from '@polkadot/keyring'
-// Import input parser and channel entity from cd-schemas (we use it as library here)
-import { InputParser } from 'cd-schemas'
-import { ChannelEntity } from 'cd-schemas/types/entities'
+// Import input parser and channel entity from @joystream/cd-schemas (we use it as library here)
+import { InputParser } from '@joystream/cd-schemas'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities'
 
 
 async function main() {
 async function main() {
   // Initialize the api
   // Initialize the api
@@ -16,14 +16,14 @@ async function main() {
   const [ALICE] = keyring.getPairs()
   const [ALICE] = keyring.getPairs()
 
 
   const channel: ChannelEntity = {
   const channel: ChannelEntity = {
-    title: 'Example channel',
+    handle: 'Example channel',
     description: 'This is an example channel',
     description: 'This is an example channel',
     // We can use "existing" syntax to reference either an on-chain entity or other entity that's part of the same batch.
     // We can use "existing" syntax to reference either an on-chain entity or other entity that's part of the same batch.
     // Here we reference language that we assume was added by initialization script (initialize:dev), as it is part of
     // Here we reference language that we assume was added by initialization script (initialize:dev), as it is part of
     // input/entityBatches/LanguageBatch.json
     // input/entityBatches/LanguageBatch.json
     language: { existing: { code: 'EN' } },
     language: { existing: { code: 'EN' } },
     coverPhotoUrl: '',
     coverPhotoUrl: '',
-    avatarPhotoURL: '',
+    avatarPhotoUrl: '',
     isPublic: true,
     isPublic: true,
   }
   }
   // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
   // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)

+ 6 - 6
content-directory-schemas/examples/createChannelWithoutTransaction.ts

@@ -1,10 +1,10 @@
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { types as joyTypes } from '@joystream/types'
 import { types as joyTypes } from '@joystream/types'
 import { Keyring } from '@polkadot/keyring'
 import { Keyring } from '@polkadot/keyring'
-// Import input parser and channel entity from cd-schemas (we use it as library here)
-import { InputParser } from 'cd-schemas'
-import { ChannelEntity } from 'cd-schemas/types/entities'
-import { FlattenRelations } from 'cd-schemas/types/utility'
+// Import input parser and channel entity from @joystream/cd-schemas (we use it as library here)
+import { InputParser } from '@joystream/cd-schemas'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities'
+import { FlattenRelations } from '@joystream/cd-schemas/types/utility'
 import { EntityId } from '@joystream/types/content-directory'
 import { EntityId } from '@joystream/types/content-directory'
 
 
 // Alternative way of creating a channel using separate extrinsics (instead of contentDirectory.transaction)
 // Alternative way of creating a channel using separate extrinsics (instead of contentDirectory.transaction)
@@ -26,11 +26,11 @@ async function main() {
 
 
   // We use FlattenRelations to exlude { new } and { existing } (which are not allowed if we want to parse only a single entity)
   // We use FlattenRelations to exlude { new } and { existing } (which are not allowed if we want to parse only a single entity)
   const channel: FlattenRelations<ChannelEntity> = {
   const channel: FlattenRelations<ChannelEntity> = {
-    title: 'Example channel 2',
+    handle: 'Example channel 2',
     description: 'This is an example channel',
     description: 'This is an example channel',
     language: languageEntityId,
     language: languageEntityId,
     coverPhotoUrl: '',
     coverPhotoUrl: '',
-    avatarPhotoURL: '',
+    avatarPhotoUrl: '',
     isPublic: true,
     isPublic: true,
   }
   }
 
 

+ 6 - 6
content-directory-schemas/examples/createVideo.ts

@@ -1,9 +1,9 @@
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { types as joyTypes } from '@joystream/types'
 import { types as joyTypes } from '@joystream/types'
 import { Keyring } from '@polkadot/keyring'
 import { Keyring } from '@polkadot/keyring'
-// Import input parser and video entity from cd-schemas (we use it as library here)
-import { InputParser } from 'cd-schemas'
-import { VideoEntity } from 'cd-schemas/types/entities/VideoEntity'
+// Import input parser and video entity from @joystream/cd-schemas (we use it as library here)
+import { InputParser } from '@joystream/cd-schemas'
+import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
 
 
 async function main() {
 async function main() {
   // Initialize the api
   // Initialize the api
@@ -22,9 +22,9 @@ async function main() {
     // (those referenced here are part of inputs/entityBatches)
     // (those referenced here are part of inputs/entityBatches)
     language: { existing: { code: 'EN' } },
     language: { existing: { code: 'EN' } },
     category: { existing: { name: 'Education' } },
     category: { existing: { name: 'Education' } },
-    // We use the same "existing" syntax to reference a channel by unique property (title)
+    // We use the same "existing" syntax to reference a channel by unique property (handle)
     // In this case it's a channel that we created in createChannel example
     // In this case it's a channel that we created in createChannel example
-    channel: { existing: { title: 'Example channel' } },
+    channel: { existing: { handle: 'Example channel' } },
     media: {
     media: {
       // We use "new" syntax to sygnalize we want to create a new VideoMedia entity that will be related to this Video entity
       // We use "new" syntax to sygnalize we want to create a new VideoMedia entity that will be related to this Video entity
       new: {
       new: {
@@ -46,7 +46,7 @@ async function main() {
       },
       },
     },
     },
     duration: 3600,
     duration: 3600,
-    thumbnailURL: '',
+    thumbnailUrl: '',
     isExplicit: false,
     isExplicit: false,
     isPublic: true,
     isPublic: true,
   }
   }

+ 5 - 5
content-directory-schemas/examples/updateChannelTitle.ts

@@ -1,9 +1,9 @@
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { types as joyTypes } from '@joystream/types'
 import { types as joyTypes } from '@joystream/types'
 import { Keyring } from '@polkadot/keyring'
 import { Keyring } from '@polkadot/keyring'
-// Import input parser and channel entity from cd-schemas (we use it as library here)
-import { InputParser } from 'cd-schemas'
-import { ChannelEntity } from 'cd-schemas/types/entities/ChannelEntity'
+// Import input parser and channel entity from @joystream/cd-schemas (we use it as library here)
+import { InputParser } from '@joystream/cd-schemas'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
 
 
 async function main() {
 async function main() {
   // Initialize the api
   // Initialize the api
@@ -17,7 +17,7 @@ async function main() {
 
 
   // Create partial channel entity, only containing the fields we wish to update
   // Create partial channel entity, only containing the fields we wish to update
   const channelUpdateInput: Partial<ChannelEntity> = {
   const channelUpdateInput: Partial<ChannelEntity> = {
-    title: 'Updated channel title',
+    handle: 'Updated channel handle',
   }
   }
 
 
   // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
   // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
@@ -25,7 +25,7 @@ async function main() {
 
 
   // We can reuse InputParser's `findEntityIdByUniqueQuery` method to find entityId of the channel we
   // We can reuse InputParser's `findEntityIdByUniqueQuery` method to find entityId of the channel we
   // created in ./createChannel.ts example (normally we would probably use some other way to do it, ie.: query node)
   // created in ./createChannel.ts example (normally we would probably use some other way to do it, ie.: query node)
-  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ title: 'Example channel' }, 'Channel')
+  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ handle: 'Example channel' }, 'Channel')
 
 
   // Use getEntityUpdateOperations to parse the update input
   // Use getEntityUpdateOperations to parse the update input
   const updateOperations = await parser.getEntityUpdateOperations(
   const updateOperations = await parser.getEntityUpdateOperations(

+ 6 - 6
content-directory-schemas/examples/updateChannelTitleWithoutTransaction.ts

@@ -1,10 +1,10 @@
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { types as joyTypes } from '@joystream/types'
 import { types as joyTypes } from '@joystream/types'
 import { Keyring } from '@polkadot/keyring'
 import { Keyring } from '@polkadot/keyring'
-// Import input parser and channel entity from cd-schemas (we use it as library here)
-import { InputParser } from 'cd-schemas'
-import { ChannelEntity } from 'cd-schemas/types/entities'
-import { FlattenRelations } from 'cd-schemas/types/utility'
+// Import input parser and channel entity from @joystream/cd-schemas (we use it as library here)
+import { InputParser } from '@joystream/cd-schemas'
+import { ChannelEntity } from '@joystream/cd-schemas/types/entities'
+import { FlattenRelations } from '@joystream/cd-schemas/types/utility'
 
 
 // Alternative way of update a channel using updateEntityPropertyValues extrinsic
 // Alternative way of update a channel using updateEntityPropertyValues extrinsic
 async function main() {
 async function main() {
@@ -19,7 +19,7 @@ async function main() {
 
 
   // Create partial channel entity, only containing the fields we wish to update
   // Create partial channel entity, only containing the fields we wish to update
   const channelUpdateInput: Partial<FlattenRelations<ChannelEntity>> = {
   const channelUpdateInput: Partial<FlattenRelations<ChannelEntity>> = {
-    title: 'Updated channel title 2',
+    handle: 'Updated channel handle 2',
   }
   }
 
 
   // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
   // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
@@ -28,7 +28,7 @@ async function main() {
   // We can reuse InputParser's `findEntityIdByUniqueQuery` method to find entityId of the channel we
   // We can reuse InputParser's `findEntityIdByUniqueQuery` method to find entityId of the channel we
   // created in ./createChannelWithoutTransaction.ts example
   // created in ./createChannelWithoutTransaction.ts example
   // (normally we would probably use some other way to do it, ie.: query node)
   // (normally we would probably use some other way to do it, ie.: query node)
-  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ title: 'Example channel 2' }, 'Channel')
+  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ handle: 'Example channel 2' }, 'Channel')
 
 
   // We use parser to create input property values map
   // We use parser to create input property values map
   const newPropertyValues = await parser.parseToInputEntityValuesMap(channelUpdateInput, 'Channel')
   const newPropertyValues = await parser.parseToInputEntityValuesMap(channelUpdateInput, 'Channel')

+ 6 - 0
content-directory-schemas/inputs/classes/FeaturedVideoClass.json

@@ -0,0 +1,6 @@
+{
+  "name": "FeaturedVideo",
+  "description": "Featured video references",
+  "maximum_entities_count": 400,
+  "default_entity_creation_voucher_upper_bound": 50
+}

+ 18 - 0
content-directory-schemas/inputs/classes/index.js

@@ -0,0 +1,18 @@
+const EXPECTED_CLASS_ORDER = [
+  'Channel',
+  'ContentCategory',
+  'HttpMediaLocation',
+  'JoystreamMediaLocation',
+  'KnownLicense',
+  'Language',
+  'License',
+  'MediaLocation',
+  'UserDefinedLicense',
+  'Video',
+  'VideoMedia',
+  'VideoMediaEncoding',
+  'FeaturedVideo',
+]
+
+// Exports class input jsons in a predictable order
+module.exports = EXPECTED_CLASS_ORDER.map((className) => require(`./${className}Class.json`))

+ 0 - 13
content-directory-schemas/inputs/entityBatches/ChannelBatch.json

@@ -1,13 +0,0 @@
-{
-  "className": "Channel",
-  "entries": [
-    {
-      "title": "Joystream Cartoons",
-      "description": "Joystream Cartoons channel",
-      "language": { "existing": { "code": "EN" } },
-      "coverPhotoUrl": "https://user-images.githubusercontent.com/4144334/91547902-7e90db00-e91c-11ea-9f5c-45d4921928d5.png",
-      "avatarPhotoURL": "https://user-images.githubusercontent.com/4144334/91546674-ba2aa580-e91a-11ea-96e2-abc7654c0461.png",
-      "isPublic": true
-    }
-  ]
-}

+ 48 - 6
content-directory-schemas/inputs/entityBatches/KnownLicenseBatch.json

@@ -1,11 +1,53 @@
 {
 {
   "className": "KnownLicense",
   "className": "KnownLicense",
   "entries": [
   "entries": [
-    { "code": "CC_BY" },
-    { "code": "CC_BY_SA" },
-    { "code": "CC_BY_ND" },
-    { "code": "CC_BY_NC" },
-    { "code": "CC_BY_NC_SA" },
-    { "code": "CC_BY_NC_ND" }
+    {
+      "code": "PDM",
+      "name": "Public Domain",
+      "url": "https://creativecommons.org/share-your-work/public-domain/pdm",
+      "attributionRequired": false
+    },
+    {
+      "code": "CC0",
+      "name": "Public Domain Dedication",
+      "url": "https://creativecommons.org/share-your-work/public-domain/cc0",
+      "attributionRequired": true
+    },
+    {
+      "code": "CC_BY",
+      "name": "Creative Commons Attribution License",
+      "url": "https://creativecommons.org/licenses/by/4.0",
+      "attributionRequired": true
+    },
+    {
+      "code": "CC_BY_SA",
+      "name": "Creative Commons Attribution-ShareAlike License",
+      "url": "https://creativecommons.org/licenses/by-sa/4.0",
+      "attributionRequired": true
+    },
+    {
+      "code": "CC_BY_ND",
+      "name": "Creative Commons Attribution-NoDerivs License",
+      "url": "https://creativecommons.org/licenses/by-nd/4.0",
+      "attributionRequired": true
+    },
+    {
+      "code": "CC_BY_NC",
+      "name": "Creative Commons Attribution-NonCommercial License",
+      "url": "https://creativecommons.org/licenses/by-nc/4.0",
+      "attributionRequired": true
+    },
+    {
+      "code": "CC_BY_NC_SA",
+      "name": "Creative Commons Attribution-NonCommercial-ShareAlike License",
+      "url": "https://creativecommons.org/licenses/by-nc-sa/4.0",
+      "attributionRequired": true
+    },
+    {
+      "code": "CC_BY_NC_ND",
+      "name": "Creative Commons Attribution-NonCommercial-NoDerivs License",
+      "url": "https://creativecommons.org/licenses/by-nc-nd/4.0",
+      "attributionRequired": true
+    }
   ]
   ]
 }
 }

+ 0 - 63
content-directory-schemas/inputs/entityBatches/VideoBatch.json

@@ -1,63 +0,0 @@
-{
-  "className": "Video",
-  "entries": [
-    {
-      "title": "Caminades 2",
-      "description": "Caminandes 2: Gran Dillama",
-      "language": { "existing": { "code": "EN" } },
-      "category": { "existing": { "name": "Film & Animation" } },
-      "channel": { "existing": { "title": "Joystream Cartoons" } },
-      "duration": 146,
-      "hasMarketing": false,
-      "isPublic": true,
-      "media": {
-        "new": {
-          "encoding": { "existing": { "name": "H.264_MP4" } },
-          "location": {
-            "new": {
-              "httpMediaLocation": {
-                "new": {
-                  "url": "http://www.caminandes.com/download/02_gran_dillama_1080p.zip"
-                }
-              }
-            }
-          },
-          "pixelWidth": 1920,
-          "pixelHeight": 1080
-        }
-      },
-      "thumbnailURL": "http://www.caminandes.com/wp-content/uploads/2016/02/web_header4.png",
-      "isExplicit": false,
-      "license": { "new": { "knownLicense": { "existing": { "code": "CC_BY" } } } }
-    },
-    {
-      "title": "Caminades 3",
-      "description": "Caminandes 3: Llamigos",
-      "language": { "existing": { "code": "EN" } },
-      "category": { "existing": { "name": "Film & Animation" } },
-      "channel": { "existing": { "title": "Joystream Cartoons" } },
-      "duration": 150,
-      "hasMarketing": false,
-      "isPublic": true,
-      "media": {
-        "new": {
-          "encoding": { "existing": { "name": "H.264_MP4" } },
-          "location": {
-            "new": {
-              "httpMediaLocation": {
-                "new": {
-                  "url": "http://www.caminandes.com/download/03_caminandes_llamigos_1080p.mp4"
-                }
-              }
-            }
-          },
-          "pixelWidth": 1920,
-          "pixelHeight": 1080
-        }
-      },
-      "thumbnailURL": "http://www.caminandes.com/wp-content/uploads/2016/02/web_header4.png",
-      "isExplicit": false,
-      "license": { "new": { "knownLicense": { "existing": { "code": "CC_BY" } } } }
-    }
-  ]
-}

+ 5 - 6
content-directory-schemas/inputs/schemas/ChannelSchema.json

@@ -2,8 +2,8 @@
   "className": "Channel",
   "className": "Channel",
   "newProperties": [
   "newProperties": [
     {
     {
-      "name": "title",
-      "description": "The title of the Channel",
+      "name": "handle",
+      "description": "The handle of the Channel",
       "required": true,
       "required": true,
       "unique": true,
       "unique": true,
       "property_type": { "Single": { "Text": 64 } }
       "property_type": { "Single": { "Text": 64 } }
@@ -17,13 +17,13 @@
     {
     {
       "name": "coverPhotoUrl",
       "name": "coverPhotoUrl",
       "description": "Url for Channel's cover (background) photo. Recommended ratio: 16:9.",
       "description": "Url for Channel's cover (background) photo. Recommended ratio: 16:9.",
-      "required": true,
+      "required": false,
       "property_type": { "Single": { "Text": 256 } }
       "property_type": { "Single": { "Text": 256 } }
     },
     },
     {
     {
-      "name": "avatarPhotoURL",
+      "name": "avatarPhotoUrl",
       "description": "Channel's avatar photo.",
       "description": "Channel's avatar photo.",
-      "required": true,
+      "required": false,
       "property_type": { "Single": { "Text": 256 } }
       "property_type": { "Single": { "Text": 256 } }
     },
     },
     {
     {
@@ -36,7 +36,6 @@
       "name": "isCensored",
       "name": "isCensored",
       "description": "Channel censorship status set by the Curator.",
       "description": "Channel censorship status set by the Curator.",
       "required": false,
       "required": false,
-      "unique": true,
       "property_type": { "Single": "Bool" },
       "property_type": { "Single": "Bool" },
       "locking_policy": { "is_locked_from_controller": true }
       "locking_policy": { "is_locked_from_controller": true }
     },
     },

+ 12 - 0
content-directory-schemas/inputs/schemas/FeaturedVideoSchema.json

@@ -0,0 +1,12 @@
+{
+  "className": "FeaturedVideo",
+  "newProperties": [
+    {
+      "name": "video",
+      "description": "Reference to a video",
+      "required": true,
+      "unique": true,
+      "property_type": { "Single": { "Reference": { "className": "Video" } } }
+    }
+  ]
+}

+ 9 - 0
content-directory-schemas/inputs/schemas/KnownLicenseSchema.json

@@ -38,6 +38,15 @@
         "Single": { "Text": 256 }
         "Single": { "Text": 256 }
       },
       },
       "locking_policy": { "is_locked_from_controller": true }
       "locking_policy": { "is_locked_from_controller": true }
+    },
+    {
+      "name": "attributionRequired",
+      "description": "Whether this license requires an attribution",
+      "required": false,
+      "property_type": {
+        "Single": "Bool"
+      },
+      "locking_policy": { "is_locked_from_controller": true }
     }
     }
   ]
   ]
 }
 }

+ 6 - 0
content-directory-schemas/inputs/schemas/LicenseSchema.json

@@ -12,6 +12,12 @@
       "description": "Reference to user-defined license",
       "description": "Reference to user-defined license",
       "required": false,
       "required": false,
       "property_type": { "Single": { "Reference": { "className": "UserDefinedLicense", "sameOwner": true } } }
       "property_type": { "Single": { "Reference": { "className": "UserDefinedLicense", "sameOwner": true } } }
+    },
+    {
+      "name": "attribution",
+      "description": "Attribution (if required by the license)",
+      "required": false,
+      "property_type": { "Single": { "Text": 512 } }
     }
     }
   ]
   ]
 }
 }

+ 2 - 3
content-directory-schemas/inputs/schemas/VideoSchema.json

@@ -38,7 +38,7 @@
       "property_type": { "Single": "Uint16" }
       "property_type": { "Single": "Uint16" }
     },
     },
     {
     {
-      "name": "thumbnailURL",
+      "name": "thumbnailUrl",
       "description": "Video thumbnail url (recommended ratio: 16:9)",
       "description": "Video thumbnail url (recommended ratio: 16:9)",
       "required": true,
       "required": true,
       "property_type": { "Single": { "Text": 256 } }
       "property_type": { "Single": { "Text": 256 } }
@@ -67,7 +67,7 @@
       "name": "publishedBeforeJoystream",
       "name": "publishedBeforeJoystream",
       "description": "If the Video was published on other platform before beeing published on Joystream - the original publication date",
       "description": "If the Video was published on other platform before beeing published on Joystream - the original publication date",
       "required": false,
       "required": false,
-      "property_type": { "Single": "Uint32" }
+      "property_type": { "Single": "Int32" }
     },
     },
     {
     {
       "name": "isPublic",
       "name": "isPublic",
@@ -92,7 +92,6 @@
       "name": "isCensored",
       "name": "isCensored",
       "description": "Video censorship status set by the Curator.",
       "description": "Video censorship status set by the Curator.",
       "required": false,
       "required": false,
-      "unique": true,
       "property_type": { "Single": "Bool" },
       "property_type": { "Single": "Bool" },
       "locking_policy": { "is_locked_from_controller": true }
       "locking_policy": { "is_locked_from_controller": true }
     }
     }

+ 3 - 3
content-directory-schemas/package.json

@@ -1,5 +1,5 @@
 {
 {
-  "name": "cd-schemas",
+  "name": "@joystream/cd-schemas",
   "version": "0.1.0",
   "version": "0.1.0",
   "description": "JSON schemas, inputs and related tooling for Joystream content directory 2.0",
   "description": "JSON schemas, inputs and related tooling for Joystream content directory 2.0",
   "author": "Joystream contributors",
   "author": "Joystream contributors",
@@ -19,9 +19,9 @@
     "initialize:dev": "yarn initialize:alice-as-lead && yarn initialize:content-dir",
     "initialize:dev": "yarn initialize:alice-as-lead && yarn initialize:content-dir",
     "example:createChannel": "ts-node ./examples/createChannel.ts",
     "example:createChannel": "ts-node ./examples/createChannel.ts",
     "example:createVideo": "ts-node ./examples/createVideo.ts",
     "example:createVideo": "ts-node ./examples/createVideo.ts",
-    "example:updateChannelTitle": "ts-node ./examples/updateChannelTitle.ts",
+    "example:updateChannelHandle": "ts-node ./examples/updateChannelHandle.ts",
     "example:createChannelWithoutTransaction": "ts-node ./examples/createChannelWithoutTransaction.ts",
     "example:createChannelWithoutTransaction": "ts-node ./examples/createChannelWithoutTransaction.ts",
-    "example:updateChannelTitlelWithoutTransaction": "ts-node ./examples/updateChannelTitleWithoutTransaction.ts"
+    "example:updateChannelHandlelWithoutTransaction": "ts-node ./examples/updateChannelHandleWithoutTransaction.ts"
   },
   },
   "dependencies": {
   "dependencies": {
     "ajv": "6.12.5",
     "ajv": "6.12.5",

+ 2 - 7
content-directory-schemas/scripts/initializeContentDir.ts

@@ -1,20 +1,15 @@
-import { CreateClass } from '../types/extrinsics/CreateClass'
-import { AddClassSchema } from '../types/extrinsics/AddClassSchema'
 import { types } from '@joystream/types'
 import { types } from '@joystream/types'
 import { ApiPromise, WsProvider } from '@polkadot/api'
 import { ApiPromise, WsProvider } from '@polkadot/api'
-import { getInputs } from '../src/helpers/inputs'
+import { getInitializationInputs } from '../src/helpers/inputs'
 import fs from 'fs'
 import fs from 'fs'
 import path from 'path'
 import path from 'path'
-import { EntityBatch } from '../types/EntityBatch'
 import { InputParser } from '../src/helpers/InputParser'
 import { InputParser } from '../src/helpers/InputParser'
 import { ExtrinsicsHelper, getAlicePair } from '../src/helpers/extrinsics'
 import { ExtrinsicsHelper, getAlicePair } from '../src/helpers/extrinsics'
 
 
 // Save entity operations output here for easier debugging
 // Save entity operations output here for easier debugging
 const ENTITY_OPERATIONS_OUTPUT_PATH = path.join(__dirname, '../operations.json')
 const ENTITY_OPERATIONS_OUTPUT_PATH = path.join(__dirname, '../operations.json')
 
 
-const classInputs = getInputs<CreateClass>('classes').map(({ data }) => data)
-const schemaInputs = getInputs<AddClassSchema>('schemas').map(({ data }) => data)
-const entityBatchInputs = getInputs<EntityBatch>('entityBatches').map(({ data }) => data)
+const { classInputs, schemaInputs, entityBatchInputs } = getInitializationInputs()
 
 
 async function main() {
 async function main() {
   // Init api
   // Init api

+ 1 - 1
content-directory-schemas/scripts/inputSchemasToEntitySchemas.ts

@@ -42,7 +42,7 @@ const HashPropertyDef = ({ Hash: maxLength }: HashProperty): JSONSchema7 => ({
 
 
 const ReferencePropertyDef = ({ Reference: ref }: ReferenceProperty): JSONSchema7 => ({
 const ReferencePropertyDef = ({ Reference: ref }: ReferenceProperty): JSONSchema7 => ({
   'oneOf': [
   'oneOf': [
-    onePropertyObjectDef('new', { '$ref': `./${ref.className}Entity.schema.json` }),
+    onePropertyObjectDef('new', { '$ref': `../entities/${ref.className}Entity.schema.json` }),
     onePropertyObjectDef('existing', { '$ref': `../entityReferences/${ref.className}Ref.schema.json` }),
     onePropertyObjectDef('existing', { '$ref': `../entityReferences/${ref.className}Ref.schema.json` }),
     PRIMITIVE_PROPERTY_DEFS.definitions.Uint64 as JSONSchema7,
     PRIMITIVE_PROPERTY_DEFS.definitions.Uint64 as JSONSchema7,
   ],
   ],

+ 4 - 8
content-directory-schemas/src/helpers/InputParser.ts

@@ -18,7 +18,7 @@ import { ApiPromise } from '@polkadot/api'
 import { JoyBTreeSet } from '@joystream/types/common'
 import { JoyBTreeSet } from '@joystream/types/common'
 import { CreateClass } from '../../types/extrinsics/CreateClass'
 import { CreateClass } from '../../types/extrinsics/CreateClass'
 import { EntityBatch } from '../../types/EntityBatch'
 import { EntityBatch } from '../../types/EntityBatch'
-import { getInputs } from './inputs'
+import { getInitializationInputs, getInputs } from './inputs'
 
 
 type SimpleEntityValue = string | boolean | number | string[] | boolean[] | number[] | undefined | null
 type SimpleEntityValue = string | boolean | number | string[] | boolean[] | number[] | undefined | null
 // Input without "new" or "extising" keywords
 // Input without "new" or "extising" keywords
@@ -38,12 +38,8 @@ export class InputParser {
   private classIdByNameMap = new Map<string, number>()
   private classIdByNameMap = new Map<string, number>()
 
 
   static createWithInitialInputs(api: ApiPromise): InputParser {
   static createWithInitialInputs(api: ApiPromise): InputParser {
-    return new InputParser(
-      api,
-      getInputs<CreateClass>('classes').map(({ data }) => data),
-      getInputs<AddClassSchema>('schemas').map(({ data }) => data),
-      getInputs<EntityBatch>('entityBatches').map(({ data }) => data)
-    )
+    const { classInputs, schemaInputs, entityBatchInputs } = getInitializationInputs()
+    return new InputParser(api, classInputs, schemaInputs, entityBatchInputs)
   }
   }
 
 
   static createWithKnownSchemas(api: ApiPromise, entityBatches?: EntityBatch[]): InputParser {
   static createWithKnownSchemas(api: ApiPromise, entityBatches?: EntityBatch[]): InputParser {
@@ -198,7 +194,7 @@ export class InputParser {
         const schemaPropertyType = schema.newProperties.find((p) => p.name === propertyName)!.property_type
         const schemaPropertyType = schema.newProperties.find((p) => p.name === propertyName)!.property_type
         // Handle entities "nested" via "new"
         // Handle entities "nested" via "new"
         if (isSingle(schemaPropertyType) && isReference(schemaPropertyType.Single)) {
         if (isSingle(schemaPropertyType) && isReference(schemaPropertyType.Single)) {
-          if (Object.keys(propertyValue).includes('new')) {
+          if (propertyValue !== null && Object.keys(propertyValue).includes('new')) {
             const refEntitySchema = this.schemaByClassName(schemaPropertyType.Single.Reference.className)
             const refEntitySchema = this.schemaByClassName(schemaPropertyType.Single.Reference.className)
             this.includeEntityInputInUniqueQueryMap(propertyValue.new, refEntitySchema)
             this.includeEntityInputInUniqueQueryMap(propertyValue.new, refEntitySchema)
           }
           }

+ 25 - 5
content-directory-schemas/src/helpers/inputs.ts

@@ -1,5 +1,7 @@
 import path from 'path'
 import path from 'path'
 import fs from 'fs'
 import fs from 'fs'
+import { CreateClass, AddClassSchema } from '../../types/extrinsics'
+import { EntityBatch } from '../../types/EntityBatch'
 
 
 export const INPUTS_LOCATION = path.join(__dirname, '../../inputs')
 export const INPUTS_LOCATION = path.join(__dirname, '../../inputs')
 export const INPUT_TYPES = ['classes', 'schemas', 'entityBatches'] as const
 export const INPUT_TYPES = ['classes', 'schemas', 'entityBatches'] as const
@@ -9,12 +11,30 @@ export type FetchedInput<Schema = any> = { fileName: string; data: Schema }
 
 
 export const getInputsLocation = (inputType: InputType) => path.join(INPUTS_LOCATION, inputType)
 export const getInputsLocation = (inputType: InputType) => path.join(INPUTS_LOCATION, inputType)
 
 
-export function getInputs<Schema = any>(inputType: InputType): FetchedInput<Schema>[] {
-  return fs.readdirSync(getInputsLocation(inputType)).map((fileName) => {
-    const inputJson = fs.readFileSync(path.join(INPUTS_LOCATION, inputType, fileName)).toString()
-    return {
+export function getInputs<Schema = any>(
+  inputType: InputType,
+  rootInputsLocation = INPUTS_LOCATION
+): FetchedInput<Schema>[] {
+  const inputs: FetchedInput<Schema>[] = []
+  fs.readdirSync(path.join(rootInputsLocation, inputType)).forEach((fileName) => {
+    const inputFilePath = path.join(rootInputsLocation, inputType, fileName)
+    if (path.extname(inputFilePath) !== '.json') {
+      return
+    }
+    const inputJson = fs.readFileSync(inputFilePath).toString()
+    inputs.push({
       fileName,
       fileName,
       data: JSON.parse(inputJson) as Schema,
       data: JSON.parse(inputJson) as Schema,
-    }
+    })
   })
   })
+  return inputs
+}
+
+export function getInitializationInputs(rootInputsLocation = INPUTS_LOCATION) {
+  return {
+    // eslint-disable-next-line @typescript-eslint/no-var-requires
+    classInputs: require('../../inputs/classes/index.js') as CreateClass[],
+    schemaInputs: getInputs<AddClassSchema>('schemas').map(({ data }) => data),
+    entityBatchInputs: getInputs<EntityBatch>('entityBatches').map(({ data }) => data),
+  }
 }
 }

+ 1 - 1
content-directory-schemas/src/index.ts

@@ -1,6 +1,6 @@
 export { ExtrinsicsHelper, getAlicePair } from './helpers/extrinsics'
 export { ExtrinsicsHelper, getAlicePair } from './helpers/extrinsics'
 export { InputParser } from './helpers/InputParser'
 export { InputParser } from './helpers/InputParser'
-export { getInputs, getInputsLocation } from './helpers/inputs'
+export { getInputs, getInitializationInputs, getInputsLocation } from './helpers/inputs'
 export { isReference, isSingle } from './helpers/propertyType'
 export { isReference, isSingle } from './helpers/propertyType'
 export { getSchemasLocation } from './helpers/schemas'
 export { getSchemasLocation } from './helpers/schemas'
 export { default as initializeContentDir } from './helpers/initialize'
 export { default as initializeContentDir } from './helpers/initialize'

+ 25 - 15
docker-compose.yml

@@ -44,7 +44,7 @@ services:
       dockerfile: apps.Dockerfile
       dockerfile: apps.Dockerfile
     ports:
     ports:
       - '127.0.0.1:3001:3001'
       - '127.0.0.1:3001:3001'
-    command: colossus --dev --ws-provider ${WS_PROVIDER_ENDPOINT_URI} --ipfs-host ipfs
+    command: colossus --dev --ws-provider ws://joystream-node:9944 --ipfs-host ipfs
     environment:
     environment:
       - DEBUG=*
       - DEBUG=*
 
 
@@ -55,10 +55,13 @@ services:
       - "127.0.0.1:${DB_PORT}:5432"
       - "127.0.0.1:${DB_PORT}:5432"
     volumes:
     volumes:
       - /var/lib/postgresql/data
       - /var/lib/postgresql/data
+    env_file:
+      # relative to working directory where docker-compose was run from
+      - .env
     environment:
     environment:
       POSTGRES_USER: ${DB_USER}
       POSTGRES_USER: ${DB_USER}
       POSTGRES_PASSWORD: ${DB_PASS}
       POSTGRES_PASSWORD: ${DB_PASS}
-      POSTGRES_DB: ${DB_NAME}
+      POSTGRES_DB: ${INDEXER_DB_NAME}
 
 
   graphql-server:
   graphql-server:
     image: joystream/apps
     image: joystream/apps
@@ -67,10 +70,11 @@ services:
       context: .
       context: .
       dockerfile: apps.Dockerfile
       dockerfile: apps.Dockerfile
     env_file:
     env_file:
-      # relative to working directory where docker-compose was run from 
+      # relative to working directory where docker-compose was run from
       - .env
       - .env
     environment:
     environment:
       - DB_HOST=db
       - DB_HOST=db
+      - DB_NAME=${PROCESSOR_DB_NAME}
     ports:
     ports:
       - "127.0.0.1:8081:${GRAPHQL_SERVER_PORT}"
       - "127.0.0.1:8081:${GRAPHQL_SERVER_PORT}"
     depends_on: 
     depends_on: 
@@ -84,14 +88,14 @@ services:
       context: .
       context: .
       dockerfile: apps.Dockerfile
       dockerfile: apps.Dockerfile
     env_file:
     env_file:
-      # relative to working directory where docker-compose was run from 
+      # relative to working directory where docker-compose was run from
       - .env
       - .env
     environment:
     environment:
-      - INDEXER_ENDPOINT_URL=http://indexer-api-gateway:4000/graphql
-      - DB_HOST=db
+      - INDEXER_ENDPOINT_URL=http://indexer-api-gateway:${WARTHOG_APP_PORT}/graphql
       - TYPEORM_HOST=db
       - TYPEORM_HOST=db
+      - TYPEORM_DATABASE=${PROCESSOR_DB_NAME}
       - DEBUG=index-builder:*
       - DEBUG=index-builder:*
-      - WS_PROVIDER_ENDPOINT_URI=${WS_PROVIDER_ENDPOINT_URI}
+      - WS_PROVIDER_ENDPOINT_URI=ws://joystream-node:9944
     depends_on:
     depends_on:
       - indexer-api-gateway
       - indexer-api-gateway
     command: ["workspace", "query-node-root", "processor:start"]
     command: ["workspace", "query-node-root", "processor:start"]
@@ -103,15 +107,16 @@ services:
       context: .
       context: .
       dockerfile: apps.Dockerfile
       dockerfile: apps.Dockerfile
     env_file:
     env_file:
-      # relative to working directory where docker-compose was run from 
-      - .env 
+      # relative to working directory where docker-compose was run from
+      - .env
     environment:
     environment:
       - TYPEORM_HOST=db
       - TYPEORM_HOST=db
+      - TYPEORM_DATABASE=${INDEXER_DB_NAME}
       - INDEXER_WORKERS=5
       - INDEXER_WORKERS=5
       - PROCESSOR_POLL_INTERVAL=1000 # refresh every second 
       - PROCESSOR_POLL_INTERVAL=1000 # refresh every second 
       - REDIS_URI=redis://redis:6379/0
       - REDIS_URI=redis://redis:6379/0
       - DEBUG=index-builder:*
       - DEBUG=index-builder:*
-      - WS_PROVIDER_ENDPOINT_URI=${WS_PROVIDER_ENDPOINT_URI}
+      - WS_PROVIDER_ENDPOINT_URI=ws://joystream-node:9944
     depends_on: 
     depends_on: 
       - db
       - db
     command: ["workspace", "query-node-root", "indexer:start"] 
     command: ["workspace", "query-node-root", "indexer:start"] 
@@ -119,16 +124,21 @@ services:
   indexer-api-gateway:
   indexer-api-gateway:
     image: joystream/hydra-indexer-gateway:latest
     image: joystream/hydra-indexer-gateway:latest
     restart: unless-stopped
     restart: unless-stopped
+    env_file:
+      # relative to working directory where docker-compose was run from
+      - .env
     environment:
     environment:
-      - WARTHOG_STARTER_DB_DATABASE=${DB_NAME}
-      - WARTHOG_STARTER_DB_HOST=db 
+      - WARTHOG_STARTER_DB_DATABASE=${INDEXER_DB_NAME}
+      - WARTHOG_STARTER_DB_HOST=db
       - WARTHOG_STARTER_DB_PASSWORD=${DB_PASS}
       - WARTHOG_STARTER_DB_PASSWORD=${DB_PASS}
       - WARTHOG_STARTER_DB_PORT=${DB_PORT}
       - WARTHOG_STARTER_DB_PORT=${DB_PORT}
       - WARTHOG_STARTER_DB_USERNAME=${DB_USER}
       - WARTHOG_STARTER_DB_USERNAME=${DB_USER}
-      - WARTHOG_STARTER_REDIS_URI=redis://redis:6379/0 
-      - PORT=4000
+      - WARTHOG_STARTER_REDIS_URI=redis://redis:6379/0
+      - WARTHOG_APP_PORT=${WARTHOG_APP_PORT}
+      - PORT=${WARTHOG_APP_PORT}
+      - DEBUG=*
     ports:
     ports:
-      - "127.0.0.1:4000:4000"
+      - "127.0.0.1:4000:4002"
     depends_on:
     depends_on:
       - redis
       - redis
       - db
       - db

+ 0 - 391
node/src/chain_spec/content_config.rs

@@ -1,391 +0,0 @@
-use codec::Decode;
-use node_runtime::common::constraints::InputValidationLengthConstraint;
-use node_runtime::{
-    content_wg::{Channel, ChannelId, Principal, PrincipalId},
-    data_directory::DataObject,
-    primitives::{AccountId, BlockNumber, Credential},
-    versioned_store::{Class, ClassId, Entity, EntityId},
-    versioned_store_permissions::ClassPermissions,
-    ContentId, ContentWorkingGroupConfig, DataDirectoryConfig, Runtime, VersionedStoreConfig,
-    VersionedStorePermissionsConfig,
-};
-use serde::Deserialize;
-use std::{fs, path::Path};
-
-// Because of the way that the @joystream/types were implemented the getters for
-// the string types return a `string` not the `Text` type so when we are serializing
-// them to json we get a string rather than an array of bytes, so deserializing them
-// is failing. So we are relying on parity codec encoding instead..
-#[derive(Decode)]
-struct ClassAndPermissions {
-    class: Class,
-    permissions: ClassPermissions<ClassId, Credential, u16, BlockNumber>,
-}
-
-#[derive(Decode)]
-struct EntityAndMaintainer {
-    entity: Entity,
-    maintainer: Option<Credential>,
-}
-
-#[derive(Decode)]
-struct DataObjectAndContentId {
-    content_id: ContentId,
-    data_object: DataObject<Runtime>,
-}
-
-#[derive(Decode)]
-struct ContentData {
-    /// classes and their associted permissions
-    classes: Vec<ClassAndPermissions>,
-    /// entities and their associated maintainer
-    entities: Vec<EntityAndMaintainer>,
-    /// DataObject(s) and ContentId
-    data_objects: Vec<DataObjectAndContentId>,
-    /// Media Channels
-    channels: Vec<ChannelAndId>,
-}
-
-#[derive(Deserialize)]
-struct EncodedClassAndPermissions {
-    /// hex encoded Class
-    class: String,
-    /// hex encoded ClassPermissions<ClassId, Credential, u16, BlockNumber>,
-    permissions: String,
-}
-
-impl EncodedClassAndPermissions {
-    fn decode(&self) -> ClassAndPermissions {
-        // hex string must not include '0x' prefix!
-        let encoded_class =
-            hex::decode(&self.class[2..].as_bytes()).expect("failed to parse class hex string");
-        let encoded_permissions = hex::decode(&self.permissions[2..].as_bytes())
-            .expect("failed to parse class permissions hex string");
-        ClassAndPermissions {
-            class: Decode::decode(&mut encoded_class.as_slice()).unwrap(),
-            permissions: Decode::decode(&mut encoded_permissions.as_slice()).unwrap(),
-        }
-    }
-}
-
-#[derive(Deserialize)]
-struct EncodedEntityAndMaintainer {
-    /// hex encoded Entity
-    entity: String,
-    /// hex encoded Option<Credential>
-    maintainer: Option<String>,
-}
-
-impl EncodedEntityAndMaintainer {
-    fn decode(&self) -> EntityAndMaintainer {
-        // hex string must not include '0x' prefix!
-        let encoded_entity =
-            hex::decode(&self.entity[2..].as_bytes()).expect("failed to parse entity hex string");
-        let encoded_maintainer = self.maintainer.as_ref().map(|maintainer| {
-            hex::decode(&maintainer[2..].as_bytes()).expect("failed to parse maintainer hex string")
-        });
-        EntityAndMaintainer {
-            entity: Decode::decode(&mut encoded_entity.as_slice()).unwrap(),
-            maintainer: encoded_maintainer
-                .map(|maintainer| Decode::decode(&mut maintainer.as_slice()).unwrap()),
-        }
-    }
-}
-
-#[derive(Deserialize)]
-struct EncodedDataObjectAndContentId {
-    /// hex encoded ContentId
-    content_id: String,
-    /// hex encoded DataObject<Runtime>
-    data_object: String,
-}
-
-impl EncodedDataObjectAndContentId {
-    fn decode(&self) -> DataObjectAndContentId {
-        // hex string must not include '0x' prefix!
-        let encoded_content_id = hex::decode(&self.content_id[2..].as_bytes())
-            .expect("failed to parse content_id hex string");
-        let encoded_data_object = hex::decode(&self.data_object[2..].as_bytes())
-            .expect("failed to parse data_object hex string");
-        DataObjectAndContentId {
-            content_id: Decode::decode(&mut encoded_content_id.as_slice()).unwrap(),
-            data_object: Decode::decode(&mut encoded_data_object.as_slice()).unwrap(),
-        }
-    }
-}
-
-#[derive(Decode)]
-struct ChannelAndId {
-    id: ChannelId<Runtime>,
-    channel: Channel<u64, AccountId, BlockNumber, PrincipalId<Runtime>>,
-}
-
-#[derive(Deserialize)]
-struct EncodedChannelAndId {
-    /// ChannelId number
-    id: u64,
-    /// hex encoded Channel
-    channel: String,
-}
-
-impl EncodedChannelAndId {
-    fn decode(&self) -> ChannelAndId {
-        let id = self.id;
-        let encoded_channel =
-            hex::decode(&self.channel[2..].as_bytes()).expect("failed to parse channel hex string");
-        ChannelAndId {
-            id: id as ChannelId<Runtime>,
-            channel: Decode::decode(&mut encoded_channel.as_slice()).unwrap(),
-        }
-    }
-}
-
-#[derive(Deserialize)]
-struct EncodedContentData {
-    /// classes and their associted permissions
-    classes: Vec<EncodedClassAndPermissions>,
-    /// entities and their associated maintainer
-    entities: Vec<EncodedEntityAndMaintainer>,
-    /// DataObject(s) and ContentId
-    data_objects: Vec<EncodedDataObjectAndContentId>,
-    /// Media Channels
-    channels: Vec<EncodedChannelAndId>,
-}
-
-fn parse_content_data(data_file: &Path) -> EncodedContentData {
-    let data = fs::read_to_string(data_file).expect("Failed reading file");
-    serde_json::from_str(&data).expect("failed parsing content data")
-}
-
-impl EncodedContentData {
-    pub fn decode(&self) -> ContentData {
-        ContentData {
-            classes: self
-                .classes
-                .iter()
-                .map(|class_and_perm| class_and_perm.decode())
-                .collect(),
-            entities: self
-                .entities
-                .iter()
-                .map(|entities_and_maintainer| entities_and_maintainer.decode())
-                .collect(),
-            data_objects: self
-                .data_objects
-                .iter()
-                .map(|data_objects| data_objects.decode())
-                .collect(),
-            channels: self
-                .channels
-                .iter()
-                .map(|channel_and_id| channel_and_id.decode())
-                .collect(),
-        }
-    }
-}
-
-/// Generates a VersionedStoreConfig genesis config
-/// with pre-populated classes and entities parsed from a json file serialized
-/// as a ContentData struct.
-pub fn versioned_store_config_from_json(data_file: &Path) -> VersionedStoreConfig {
-    let content = parse_content_data(data_file).decode();
-    let base_config = empty_versioned_store_config();
-    let first_id = 1;
-
-    let next_class_id: ClassId = content
-        .classes
-        .last()
-        .map_or(first_id, |class_and_perm| class_and_perm.class.id + 1);
-    assert_eq!(next_class_id, (content.classes.len() + 1) as ClassId);
-
-    let next_entity_id: EntityId = content
-        .entities
-        .last()
-        .map_or(first_id, |entity_and_maintainer| {
-            entity_and_maintainer.entity.id + 1
-        });
-
-    VersionedStoreConfig {
-        class_by_id: content
-            .classes
-            .into_iter()
-            .map(|class_and_permissions| {
-                (class_and_permissions.class.id, class_and_permissions.class)
-            })
-            .collect(),
-        entity_by_id: content
-            .entities
-            .into_iter()
-            .map(|entity_and_maintainer| {
-                (
-                    entity_and_maintainer.entity.id,
-                    entity_and_maintainer.entity,
-                )
-            })
-            .collect(),
-        next_class_id,
-        next_entity_id,
-        ..base_config
-    }
-}
-
-/// Generates basic empty VersionedStoreConfig genesis config
-pub fn empty_versioned_store_config() -> VersionedStoreConfig {
-    VersionedStoreConfig {
-        class_by_id: vec![],
-        entity_by_id: vec![],
-        next_class_id: 1,
-        next_entity_id: 1,
-        property_name_constraint: InputValidationLengthConstraint::new(1, 99),
-        property_description_constraint: InputValidationLengthConstraint::new(1, 999),
-        class_name_constraint: InputValidationLengthConstraint::new(1, 99),
-        class_description_constraint: InputValidationLengthConstraint::new(1, 999),
-    }
-}
-
-/// Generates a basic empty VersionedStorePermissionsConfig genesis config
-pub fn empty_versioned_store_permissions_config() -> VersionedStorePermissionsConfig {
-    VersionedStorePermissionsConfig {
-        class_permissions_by_class_id: vec![],
-        entity_maintainer_by_entity_id: vec![],
-    }
-}
-
-/// Generates a `VersionedStorePermissionsConfig` genesis config
-/// pre-populated with permissions and entity maintainers parsed from
-/// a json file serialized as a `ContentData` struct.
-pub fn versioned_store_permissions_config_from_json(
-    data_file: &Path,
-) -> VersionedStorePermissionsConfig {
-    let content = parse_content_data(data_file).decode();
-
-    VersionedStorePermissionsConfig {
-        class_permissions_by_class_id: content
-            .classes
-            .into_iter()
-            .map(|class_and_perm| (class_and_perm.class.id, class_and_perm.permissions))
-            .collect(),
-        entity_maintainer_by_entity_id: content
-            .entities
-            .into_iter()
-            .filter_map(|entity_and_maintainer| {
-                entity_and_maintainer
-                    .maintainer
-                    .map(|maintainer| (entity_and_maintainer.entity.id, maintainer))
-            })
-            .collect(),
-    }
-}
-
-/// Generates a basic empty `DataDirectoryConfig` genesis config
-pub fn empty_data_directory_config() -> DataDirectoryConfig {
-    DataDirectoryConfig {
-        data_object_by_content_id: vec![],
-        known_content_ids: vec![],
-    }
-}
-
-/// Generates a `DataDirectoryConfig` genesis config
-/// pre-populated with data objects and known content ids parsed from
-/// a json file serialized as a `ContentData` struct
-pub fn data_directory_config_from_json(data_file: &Path) -> DataDirectoryConfig {
-    let content = parse_content_data(data_file).decode();
-
-    DataDirectoryConfig {
-        data_object_by_content_id: content
-            .data_objects
-            .iter()
-            .map(|object| (object.content_id, object.data_object.clone()))
-            .collect(),
-        known_content_ids: content
-            .data_objects
-            .into_iter()
-            .map(|object| object.content_id)
-            .collect(),
-    }
-}
-
-/// Generates a basic `ContentWorkingGroupConfig` genesis config without any active curators
-/// curator lead or channels.
-pub fn empty_content_working_group_config() -> ContentWorkingGroupConfig {
-    ContentWorkingGroupConfig {
-        mint_capacity: 0,
-        curator_opening_by_id: vec![],
-        next_curator_opening_id: 0,
-        curator_application_by_id: vec![],
-        next_curator_application_id: 0,
-        channel_by_id: vec![],
-        next_channel_id: 1,
-        channel_id_by_handle: vec![],
-        curator_by_id: vec![],
-        next_curator_id: 0,
-        principal_by_id: vec![],
-        next_principal_id: 0,
-        channel_creation_enabled: true, // there is no extrinsic to change it so enabling at genesis
-        unstaker_by_stake_id: vec![],
-        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),
-    }
-}
-
-/// Generates a `ContentWorkingGroupConfig` genesis config
-/// pre-populated with channels and corresponding princial channel owners
-/// parsed from a json file serialized as a `ContentData` struct
-pub fn content_working_group_config_from_json(data_file: &Path) -> ContentWorkingGroupConfig {
-    let content = parse_content_data(data_file).decode();
-    let first_channel_id = 1;
-    let first_principal_id = 0;
-
-    let next_channel_id: ChannelId<Runtime> = content
-        .channels
-        .last()
-        .map_or(first_channel_id, |channel_and_id| channel_and_id.id + 1);
-    assert_eq!(
-        next_channel_id,
-        (content.channels.len() + 1) as ChannelId<Runtime>
-    );
-
-    let base_config = empty_content_working_group_config();
-
-    ContentWorkingGroupConfig {
-        channel_by_id: content
-            .channels
-            .iter()
-            .enumerate()
-            .map(|(ix, channel_and_id)| {
-                (
-                    channel_and_id.id,
-                    Channel {
-                        principal_id: first_principal_id + ix as PrincipalId<Runtime>,
-                        ..channel_and_id.channel.clone()
-                    },
-                )
-            })
-            .collect(),
-        next_channel_id,
-        channel_id_by_handle: content
-            .channels
-            .iter()
-            .map(|channel_and_id| (channel_and_id.channel.handle.clone(), channel_and_id.id))
-            .collect(),
-        principal_by_id: content
-            .channels
-            .iter()
-            .enumerate()
-            .map(|(ix, channel_and_id)| {
-                (
-                    first_principal_id + ix as PrincipalId<Runtime>,
-                    Principal::ChannelOwner(channel_and_id.id),
-                )
-            })
-            .collect(),
-        next_principal_id: first_principal_id + content.channels.len() as PrincipalId<Runtime>,
-        ..base_config
-    }
-}

+ 2 - 1
node/src/chain_spec/forum_config.rs

@@ -108,7 +108,8 @@ pub fn empty(forum_sudo: AccountId) -> ForumConfig {
         threads: vec![],
         threads: vec![],
         posts: vec![],
         posts: vec![],
         category_by_moderator: vec![],
         category_by_moderator: vec![],
-        data_migration_done: String::new(),
+        // true
+        data_migration_done: String::from("0x01"),
     };
     };
     create(forum_sudo, forum_data)
     create(forum_sudo, forum_data)
 }
 }

+ 5 - 58
node/src/chain_spec/mod.rs

@@ -30,18 +30,15 @@ use sp_runtime::Perbill;
 
 
 use node_runtime::{
 use node_runtime::{
     membership, wasm_binary_unwrap, AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig,
     membership, wasm_binary_unwrap, AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig,
-    ContentDirectoryConfig, ContentDirectoryWorkingGroupConfig, ContentWorkingGroupConfig,
-    CouncilConfig, CouncilElectionConfig, DataDirectoryConfig, DataObjectStorageRegistryConfig,
-    DataObjectTypeRegistryConfig, ElectionParameters, ForumConfig, ForumWorkingGroupConfig,
-    GrandpaConfig, ImOnlineConfig, MembersConfig, Moment, SessionConfig, SessionKeys, Signature,
-    StakerStatus, StakingConfig, StorageWorkingGroupConfig, SudoConfig, SystemConfig,
-    VersionedStoreConfig, VersionedStorePermissionsConfig, DAYS,
+    ContentDirectoryConfig, CouncilConfig, CouncilElectionConfig, DataObjectStorageRegistryConfig,
+    DataObjectTypeRegistryConfig, ElectionParameters, ForumConfig, GrandpaConfig, ImOnlineConfig,
+    MembersConfig, Moment, SessionConfig, SessionKeys, Signature, StakerStatus, StakingConfig,
+    SudoConfig, SystemConfig, DAYS,
 };
 };
 
 
 // Exported to be used by chain-spec-builder
 // Exported to be used by chain-spec-builder
 pub use node_runtime::{AccountId, GenesisConfig};
 pub use node_runtime::{AccountId, GenesisConfig};
 
 
-pub mod content_config;
 pub mod forum_config;
 pub mod forum_config;
 pub mod initial_balances;
 pub mod initial_balances;
 pub mod initial_members;
 pub mod initial_members;
@@ -134,10 +131,6 @@ impl Alternative {
                         ],
                         ],
                         initial_members::none(),
                         initial_members::none(),
                         forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
                         forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
-                        content_config::empty_versioned_store_config(),
-                        content_config::empty_versioned_store_permissions_config(),
-                        content_config::empty_data_directory_config(),
-                        content_config::empty_content_working_group_config(),
                         vec![],
                         vec![],
                     )
                     )
                 },
                 },
@@ -174,10 +167,6 @@ impl Alternative {
                         ],
                         ],
                         initial_members::none(),
                         initial_members::none(),
                         forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
                         forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
-                        content_config::empty_versioned_store_config(),
-                        content_config::empty_versioned_store_permissions_config(),
-                        content_config::empty_data_directory_config(),
-                        content_config::empty_content_working_group_config(),
                         vec![],
                         vec![],
                     )
                     )
                 },
                 },
@@ -219,17 +208,11 @@ pub fn testnet_genesis(
     endowed_accounts: Vec<AccountId>,
     endowed_accounts: Vec<AccountId>,
     members: Vec<membership::genesis::Member<u64, AccountId, Moment>>,
     members: Vec<membership::genesis::Member<u64, AccountId, Moment>>,
     forum_config: ForumConfig,
     forum_config: ForumConfig,
-    versioned_store_config: VersionedStoreConfig,
-    versioned_store_permissions_config: VersionedStorePermissionsConfig,
-    data_directory_config: DataDirectoryConfig,
-    content_working_group_config: ContentWorkingGroupConfig,
     initial_balances: Vec<(AccountId, Balance)>,
     initial_balances: Vec<(AccountId, Balance)>,
 ) -> GenesisConfig {
 ) -> GenesisConfig {
     const STASH: Balance = 5_000;
     const STASH: Balance = 5_000;
     const ENDOWMENT: Balance = 100_000_000;
     const ENDOWMENT: Balance = 100_000_000;
 
 
-    let default_text_constraint = node_runtime::working_group::default_text_constraint();
-
     GenesisConfig {
     GenesisConfig {
         frame_system: Some(SystemConfig {
         frame_system: Some(SystemConfig {
             code: wasm_binary_unwrap().to_vec(),
             code: wasm_binary_unwrap().to_vec(),
@@ -298,39 +281,14 @@ pub fn testnet_genesis(
                 min_voting_stake: 100,
                 min_voting_stake: 100,
             },
             },
         }),
         }),
-        membership: Some(MembersConfig {
-            default_paid_membership_fee: 100u128,
-            members,
-        }),
+        membership: Some(MembersConfig { members }),
         forum: Some(forum_config),
         forum: Some(forum_config),
-        data_directory: Some(data_directory_config),
         data_object_type_registry: Some(DataObjectTypeRegistryConfig {
         data_object_type_registry: Some(DataObjectTypeRegistryConfig {
             first_data_object_type_id: 1,
             first_data_object_type_id: 1,
         }),
         }),
         data_object_storage_registry: Some(DataObjectStorageRegistryConfig {
         data_object_storage_registry: Some(DataObjectStorageRegistryConfig {
             first_relationship_id: 1,
             first_relationship_id: 1,
         }),
         }),
-        working_group_Instance1: Some(ForumWorkingGroupConfig {
-            phantom: Default::default(),
-            working_group_mint_capacity: 0,
-            opening_human_readable_text_constraint: default_text_constraint,
-            worker_application_human_readable_text_constraint: default_text_constraint,
-            worker_exit_rationale_text_constraint: default_text_constraint,
-        }),
-        working_group_Instance2: Some(StorageWorkingGroupConfig {
-            phantom: Default::default(),
-            working_group_mint_capacity: 0,
-            opening_human_readable_text_constraint: default_text_constraint,
-            worker_application_human_readable_text_constraint: default_text_constraint,
-            worker_exit_rationale_text_constraint: default_text_constraint,
-        }),
-        working_group_Instance3: Some(ContentDirectoryWorkingGroupConfig {
-            phantom: Default::default(),
-            working_group_mint_capacity: 0,
-            opening_human_readable_text_constraint: default_text_constraint,
-            worker_application_human_readable_text_constraint: default_text_constraint,
-            worker_exit_rationale_text_constraint: default_text_constraint,
-        }),
         content_directory: Some({
         content_directory: Some({
             ContentDirectoryConfig {
             ContentDirectoryConfig {
                 class_by_id: vec![],
                 class_by_id: vec![],
@@ -341,9 +299,6 @@ pub fn testnet_genesis(
                 next_curator_group_id: 1,
                 next_curator_group_id: 1,
             }
             }
         }),
         }),
-        versioned_store: Some(versioned_store_config),
-        versioned_store_permissions: Some(versioned_store_permissions_config),
-        content_wg: Some(content_working_group_config),
     }
     }
 }
 }
 
 
@@ -360,10 +315,6 @@ pub(crate) mod tests {
             vec![get_authority_keys_from_seed("Alice").0],
             vec![get_authority_keys_from_seed("Alice").0],
             initial_members::none(),
             initial_members::none(),
             forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
             forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
-            content_config::empty_versioned_store_config(),
-            content_config::empty_versioned_store_permissions_config(),
-            content_config::empty_data_directory_config(),
-            content_config::empty_content_working_group_config(),
             vec![],
             vec![],
         )
         )
     }
     }
@@ -396,10 +347,6 @@ pub(crate) mod tests {
             ],
             ],
             initial_members::none(),
             initial_members::none(),
             forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
             forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
-            content_config::empty_versioned_store_config(),
-            content_config::empty_versioned_store_permissions_config(),
-            content_config::empty_data_directory_config(),
-            content_config::empty_content_working_group_config(),
             vec![],
             vec![],
         )
         )
     }
     }

+ 2 - 2
package.json

@@ -4,7 +4,7 @@
   "version": "1.0.0",
   "version": "1.0.0",
   "license": "GPL-3.0-only",
   "license": "GPL-3.0-only",
   "scripts": {
   "scripts": {
-    "postinstall": "yarn workspace @joystream/types build && yarn workspace cd-schemas generate:all && yarn workspace cd-schemas build && yarn workspace @joystream/cli build",
+    "postinstall": "yarn workspace @joystream/types build && yarn workspace @joystream/cd-schemas generate:all && yarn workspace @joystream/cd-schemas build && yarn workspace @joystream/cli build",
     "build": "./build.sh",
     "build": "./build.sh",
     "start": "./start.sh",
     "start": "./start.sh",
     "cargo-checks": "devops/git-hooks/pre-commit && devops/git-hooks/pre-push",
     "cargo-checks": "devops/git-hooks/pre-commit && devops/git-hooks/pre-push",
@@ -36,7 +36,7 @@
     "babel-core": "^7.0.0-bridge.0",
     "babel-core": "^7.0.0-bridge.0",
     "typescript": "^3.9.7",
     "typescript": "^3.9.7",
     "bn.js": "^5.1.2",
     "bn.js": "^5.1.2",
-    "@dzlzv/hydra-indexer-lib": "0.0.19-legacy.1.26.1"
+    "@dzlzv/hydra-indexer-lib": "0.0.21-legacy.1.26.1"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "eslint": "^7.6.0",
     "eslint": "^7.6.0",

+ 0 - 62
query-node/.env

@@ -1,62 +0,0 @@
-COMPOSE_PROJECT_NAME=joystream
-
-# Project name
-PROJECT_NAME=query_node
-
-###########################
-#     Common settings     #
-###########################
-
-# The env variables below are by default used by all services and should be
-# overriden in local env files (e.g. ./generated/indexer) if needed
-# DB config
-DB_NAME=query_node
-DB_USER=postgres
-DB_PASS=postgres
-DB_HOST=localhost
-DB_PORT=5432
-DEBUG=index-builder:*
-TYPEORM_LOGGING=error
-
-###########################
-#    Indexer options      #
-###########################
-
-# Substrate endpoint to source events from
-WS_PROVIDER_ENDPOINT_URI=ws://localhost:9944/
-# Block height to start indexing from.
-# Note, that if there are already some indexed events, this setting is ignored
-BLOCK_HEIGHT=0
-
-# Custom types to register for Substrate API
-# TYPE_REGISTER_PACKAGE_NAME=
-# TYPE_REGISTER_PACKAGE_VERSION=
-# TYPE_REGISTER_FUNCTION=
-
-# Redis cache server
-REDIS_URI=redis://localhost:6379/0
-
-###########################
-#    Processor options    #
-###########################
-
-# Where the mapping scripts are located, relative to ./generated/indexer
-# this env var is deprecated!
-MAPPINGS_LOCATION=../../src
-TYPES_JSON=../../typedefs.json
-
-# Indexer GraphQL API endpoint to fetch indexed events
-INDEXER_ENDPOINT_URL=http://localhost:4100/graphql
-
-# Block height from which the processor starts. Note that if
-# there are already processed events in the database, this setting is ignored
-BLOCK_HEIGHT=0
-
-###############################
-#    Processor GraphQL API    #
-###############################
-
-GRAPHQL_SERVER_PORT=4002
-GRAPHQL_SERVER_HOST=localhost
-WARTHOG_APP_PORT=4002
-WARTHOG_APP_HOST=localhost

+ 5 - 1
query-node/README.md

@@ -11,6 +11,10 @@ $ cd query-node
 $ yarn build
 $ yarn build
 ```
 ```
 
 
+## Starting services
+
+To start services defined in the project docker-compose.yml, you should run docker-compose from the project root folder to use the correct .env file
+
 ## Run mapping processor
 ## Run mapping processor
 
 
 Before running mappings make sure indexer(`yarn indexer:start`) and indexer-api-server (mappings get the chain data from this graphql server) are both running:
 Before running mappings make sure indexer(`yarn indexer:start`) and indexer-api-server (mappings get the chain data from this graphql server) are both running:
@@ -26,7 +30,7 @@ Once processor start to store event data you will be able to query this data fro
 ```graphql
 ```graphql
 query {
 query {
   channels {
   channels {
-    title
+    handle
   }
   }
 }
 }
 ```
 ```

+ 19 - 1
query-node/build.sh

@@ -4,8 +4,26 @@ set -e
 SCRIPT_PATH="$(dirname "${BASH_SOURCE[0]}")"
 SCRIPT_PATH="$(dirname "${BASH_SOURCE[0]}")"
 cd $SCRIPT_PATH
 cd $SCRIPT_PATH
 
 
+# Load and export variables from root .env file into shell environment
+set -a
+. ../.env
+set +a
+
 yarn clean
 yarn clean
-yarn codegen:all
+
+# We generate the code for each service separately to be able to specify
+# separate database names.
+
+# Build indexer customizing DB name
+DB_NAME=${INDEXER_DB_NAME} yarn codegen:indexer
+
+# Build graphql-server customizing DB name
+DB_NAME=${PROCESSOR_DB_NAME} yarn codegen:server
+
+# We run yarn again to ensure processor and indexer dependencies are installed
+# and are inline with root workspace resolutions
 yarn
 yarn
+
 ln -s ../../../../../node_modules/typeorm/cli.js generated/graphql-server/node_modules/.bin/typeorm || :
 ln -s ../../../../../node_modules/typeorm/cli.js generated/graphql-server/node_modules/.bin/typeorm || :
+
 yarn tsc --build tsconfig.json
 yarn tsc --build tsconfig.json

+ 13 - 0
query-node/db-migrate.sh

@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+set -e
+
+SCRIPT_PATH="$(dirname "${BASH_SOURCE[0]}")"
+cd $SCRIPT_PATH
+
+set -a
+. ../.env
+set +a
+
+yarn workspace query-node-root db:indexer:migrate
+yarn workspace query-node-root db:schema:migrate
+TYPEORM_DATABASE=${PROCESSOR_DB_NAME} yarn workspace query-node-root db:indexer:migrate

+ 64 - 57
query-node/mappings/content-directory/content-dir-consts.ts

@@ -1,4 +1,4 @@
-import { IPropertyIdWithName } from '../types'
+import { IPropertyWithId } from '../types'
 
 
 // Content directory predefined class names
 // Content directory predefined class names
 export enum ContentDirectoryKnownClasses {
 export enum ContentDirectoryKnownClasses {
@@ -14,6 +14,7 @@ export enum ContentDirectoryKnownClasses {
   VIDEO = 'Video',
   VIDEO = 'Video',
   VIDEOMEDIA = 'VideoMedia',
   VIDEOMEDIA = 'VideoMedia',
   VIDEOMEDIAENCODING = 'VideoMediaEncoding',
   VIDEOMEDIAENCODING = 'VideoMediaEncoding',
+  FEATUREDVIDEOS = 'FeaturedVideo',
 }
 }
 
 
 // Predefined content-directory classes, classId may change after the runtime seeding
 // Predefined content-directory classes, classId may change after the runtime seeding
@@ -30,87 +31,93 @@ export const contentDirectoryClassNamesWithId: { classId: number; name: string }
   { name: ContentDirectoryKnownClasses.VIDEO, classId: 10 },
   { name: ContentDirectoryKnownClasses.VIDEO, classId: 10 },
   { name: ContentDirectoryKnownClasses.VIDEOMEDIA, classId: 11 },
   { name: ContentDirectoryKnownClasses.VIDEOMEDIA, classId: 11 },
   { name: ContentDirectoryKnownClasses.VIDEOMEDIAENCODING, classId: 12 },
   { name: ContentDirectoryKnownClasses.VIDEOMEDIAENCODING, classId: 12 },
+  { name: ContentDirectoryKnownClasses.FEATUREDVIDEOS, classId: 13 },
 ]
 ]
 
 
-export const CategoryPropertyNamesWithId: IPropertyIdWithName = {
-  0: 'name',
-  1: 'description',
+export const categoryPropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'name', type: 'string', required: true },
+  1: { name: 'description', type: 'string', required: false },
 }
 }
 
 
-export const channelPropertyNamesWithId: IPropertyIdWithName = {
-  0: 'title',
-  1: 'description',
-  2: 'coverPhotoURL',
-  3: 'avatarPhotoURL',
-  4: 'isPublic',
-  5: 'isCurated',
-  6: 'language',
+export const channelPropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'handle', type: 'string', required: true },
+  1: { name: 'description', type: 'string', required: false },
+  2: { name: 'coverPhotoUrl', type: 'string', required: false },
+  3: { name: 'avatarPhotoUrl', type: 'string', required: false },
+  4: { name: 'isPublic', type: 'boolean', required: true },
+  5: { name: 'isCurated', type: 'boolean', required: false },
+  6: { name: 'language', type: 'number', required: false },
 }
 }
 
 
-export const licensePropertyNamesWithId: IPropertyIdWithName = {
-  0: 'knownLicense',
-  1: 'userDefinedLicense',
+export const licensePropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'knownLicense', type: 'number', required: false },
+  1: { name: 'userDefinedLicense', type: 'number', required: false },
+  2: { name: 'attribution', type: 'string', required: false },
 }
 }
 
 
-export const knownLicensePropertyNamesWIthId: IPropertyIdWithName = {
-  0: 'code',
-  1: 'name',
-  2: 'description',
-  3: 'url',
+export const knownLicensePropertyNamesWIthId: IPropertyWithId = {
+  0: { name: 'code', type: 'string', required: true },
+  1: { name: 'name', type: 'string', required: false },
+  2: { name: 'description', type: 'string', required: false },
+  3: { name: 'url', type: 'string', required: false },
 }
 }
 
 
-export const languagePropertyNamesWIthId: IPropertyIdWithName = {
-  0: 'name',
-  1: 'code',
+export const languagePropertyNamesWIthId: IPropertyWithId = {
+  0: { name: 'name', type: 'string', required: true },
+  1: { name: 'code', type: 'string', required: true },
 }
 }
 
 
-export const userDefinedLicensePropertyNamesWithId: IPropertyIdWithName = {
-  0: 'content',
+export const userDefinedLicensePropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'content', type: 'string', required: false },
 }
 }
 
 
-export const mediaLocationPropertyNamesWithId: IPropertyIdWithName = {
-  0: 'httpMediaLocation',
-  1: 'joystreamMediaLocation',
+export const mediaLocationPropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'httpMediaLocation', type: 'number', required: false },
+  1: { name: 'joystreamMediaLocation', type: 'number', required: false },
 }
 }
 
 
-export const joystreamMediaLocationPropertyNamesWithId: IPropertyIdWithName = {
-  0: 'dataObjectId',
+export const joystreamMediaLocationPropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'dataObjectId', type: 'string', required: true },
 }
 }
 
 
-export const httpMediaLocationPropertyNamesWithId: IPropertyIdWithName = {
-  0: 'url',
-  1: 'port',
+export const httpMediaLocationPropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'url', type: 'string', required: false },
+  1: { name: 'port', type: 'number', required: false },
 }
 }
 
 
-export const videoMediaEncodingPropertyNamesWithId: IPropertyIdWithName = {
-  0: 'name',
+export const videoMediaEncodingPropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'name', type: 'string', required: true },
 }
 }
 
 
-export const videoMediaPropertyNamesWithId: IPropertyIdWithName = {
-  0: 'encoding',
-  1: 'pixelWidth',
-  2: 'pixelHeight',
-  3: 'size',
-  4: 'location',
+export const videoMediaPropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'encoding', type: 'number', required: true },
+  1: { name: 'pixelWidth', type: 'number', required: true },
+  2: { name: 'pixelHeight', type: 'number', required: true },
+  3: { name: 'size', type: 'number', required: false },
+  4: { name: 'location', type: 'number', required: true },
 }
 }
 
 
-export const videoPropertyNamesWithId: IPropertyIdWithName = {
+export const videoPropertyNamesWithId: IPropertyWithId = {
   // referenced entity's id
   // referenced entity's id
-  0: 'channel',
+  0: { name: 'channel', type: 'number', required: true },
   // referenced entity's id
   // referenced entity's id
-  1: 'category',
-  2: 'title',
-  3: 'description',
-  4: 'duration',
-  5: 'skippableIntroDuration',
-  6: 'thumbnailURL',
-  7: 'language',
+  1: { name: 'category', type: 'number', required: true },
+  2: { name: 'title', type: 'string', required: false },
+  3: { name: 'description', type: 'string', required: false },
+  4: { name: 'duration', type: 'number', required: true },
+  5: { name: 'skippableIntroDuration', type: 'number', required: false },
+  6: { name: 'thumbnailUrl', type: 'string', required: true },
+  7: { name: 'language', type: 'number', required: false },
   // referenced entity's id
   // referenced entity's id
-  8: 'media',
-  9: 'hasMarketing',
-  10: 'publishedBeforeJoystream',
-  11: 'isPublic',
-  12: 'isExplicit',
-  13: 'license',
-  14: 'isCurated',
+  8: { name: 'media', type: 'number', required: true },
+  9: { name: 'hasMarketing', type: 'boolean', required: false },
+  10: { name: 'publishedBeforeJoystream', type: 'number', required: false },
+  11: { name: 'isPublic', type: 'boolean', required: true },
+  12: { name: 'isExplicit', type: 'boolean', required: true },
+  13: { name: 'license', type: 'number', required: true },
+  14: { name: 'isCurated', type: 'boolean', required: true },
+}
+
+export const featuredVideoPropertyNamesWithId: IPropertyWithId = {
+  0: { name: 'video', type: 'number', required: true },
 }
 }

+ 29 - 13
query-node/mappings/content-directory/decode.ts

@@ -1,17 +1,22 @@
 import { SubstrateEvent } from '../../generated/indexer'
 import { SubstrateEvent } from '../../generated/indexer'
 import {
 import {
-  IPropertyIdWithName,
   IClassEntity,
   IClassEntity,
   IProperty,
   IProperty,
   IBatchOperation,
   IBatchOperation,
   ICreateEntityOperation,
   ICreateEntityOperation,
   IEntity,
   IEntity,
   IReference,
   IReference,
+  IPropertyWithId,
 } from '../types'
 } from '../types'
 import Debug from 'debug'
 import Debug from 'debug'
 
 
-import { ParametrizedClassPropertyValue, UpdatePropertyValuesOperation } from '@joystream/types/content-directory'
+import {
+  OperationType,
+  ParametrizedClassPropertyValue,
+  UpdatePropertyValuesOperation,
+} from '@joystream/types/content-directory'
 import { createType } from '@joystream/types'
 import { createType } from '@joystream/types'
+import { Vec } from '@polkadot/types'
 
 
 const debug = Debug('mappings:cd:decode')
 const debug = Debug('mappings:cd:decode')
 
 
@@ -20,18 +25,23 @@ function stringIfyEntityId(event: SubstrateEvent): string {
   return entityId.value as string
   return entityId.value as string
 }
 }
 
 
-function setProperties<T>({ extrinsic, blockNumber }: SubstrateEvent, propNamesWithId: IPropertyIdWithName): T {
+function setProperties<T>({ extrinsic, blockNumber }: SubstrateEvent, propNamesWithId: IPropertyWithId): T {
   if (extrinsic === undefined) throw Error('Undefined extrinsic')
   if (extrinsic === undefined) throw Error('Undefined extrinsic')
 
 
   const { 3: newPropertyValues } = extrinsic!.args
   const { 3: newPropertyValues } = extrinsic!.args
   const properties: { [key: string]: any; reference?: IReference } = {}
   const properties: { [key: string]: any; reference?: IReference } = {}
 
 
   for (const [k, v] of Object.entries(newPropertyValues.value)) {
   for (const [k, v] of Object.entries(newPropertyValues.value)) {
-    const propertyName = propNamesWithId[k]
+    const prop = propNamesWithId[k]
     const singlePropVal = createType('InputPropertyValue', v as any).asType('Single')
     const singlePropVal = createType('InputPropertyValue', v as any).asType('Single')
-    properties[propertyName] = singlePropVal.isOfType('Reference')
-      ? { entityId: singlePropVal.asType('Reference').toJSON(), existing: true }
-      : singlePropVal.value.toJSON()
+
+    if (singlePropVal.isOfType('Reference')) {
+      properties[prop.name] = { entityId: singlePropVal.asType('Reference').toJSON(), existing: true }
+    } else {
+      const val = singlePropVal.value.toJSON()
+      if (typeof val !== prop.type && !prop.required) properties[prop.name] = undefined
+      else properties[prop.name] = val
+    }
   }
   }
   properties.version = blockNumber
   properties.version = blockNumber
 
 
@@ -54,16 +64,18 @@ function getClassEntity(event: SubstrateEvent): IClassEntity {
  * @param properties
  * @param properties
  * @param propertyNamesWithId
  * @param propertyNamesWithId
  */
  */
-function setEntityPropertyValues<T>(properties: IProperty[], propertyNamesWithId: IPropertyIdWithName): T {
+function setEntityPropertyValues<T>(properties: IProperty[], propertyNamesWithId: IPropertyWithId): T {
   const entityProperties: { [key: string]: any; reference?: IReference } = {}
   const entityProperties: { [key: string]: any; reference?: IReference } = {}
 
 
   for (const [propId, propName] of Object.entries(propertyNamesWithId)) {
   for (const [propId, propName] of Object.entries(propertyNamesWithId)) {
     // get the property value by id
     // get the property value by id
     const p = properties.find((p) => p.id === propId)
     const p = properties.find((p) => p.id === propId)
     if (!p) continue
     if (!p) continue
-    entityProperties[propName] = p.reference ? p.reference : p.value
+
+    if (typeof p.value !== propName.type && !propName.required) entityProperties[propName.name] = undefined
+    else entityProperties[propName.name] = p.reference ? p.reference : p.value
   }
   }
-  // debug(`Entity properties ${JSON.stringify(entityProperties)}`)
+  debug(`Entity properties: ${JSON.stringify(entityProperties)}`)
   return entityProperties as T
   return entityProperties as T
 }
 }
 
 
@@ -101,9 +113,12 @@ function getEntityProperties(propertyValues: ParametrizedClassPropertyValue[]):
   return properties
   return properties
 }
 }
 
 
-function getOperations({ extrinsic }: SubstrateEvent): IBatchOperation {
-  const operations = createType('Vec<OperationType>', extrinsic!.args[1].value as any)
+function getOperations(event: SubstrateEvent): Vec<OperationType> {
+  if (!event.extrinsic) throw Error(`No extrinsic found for ${event.id}`)
+  return createType('Vec<OperationType>', (event.extrinsic.args[1].value as unknown) as Vec<OperationType>)
+}
 
 
+function getOperationsByTypes(operations: OperationType[]): IBatchOperation {
   const updatePropertyValuesOperations: IEntity[] = []
   const updatePropertyValuesOperations: IEntity[] = []
   const addSchemaSupportToEntityOperations: IEntity[] = []
   const addSchemaSupportToEntityOperations: IEntity[] = []
   const createEntityOperations: ICreateEntityOperation[] = []
   const createEntityOperations: ICreateEntityOperation[] = []
@@ -153,6 +168,7 @@ export const decode = {
   getClassEntity,
   getClassEntity,
   setEntityPropertyValues,
   setEntityPropertyValues,
   getEntityProperties,
   getEntityProperties,
-  getOperations,
+  getOperationsByTypes,
   setProperties,
   setProperties,
+  getOperations,
 }
 }

+ 105 - 46
query-node/mappings/content-directory/entity/create.ts

@@ -1,18 +1,19 @@
 import { DB } from '../../../generated/indexer'
 import { DB } from '../../../generated/indexer'
 import { Channel } from '../../../generated/graphql-server/src/modules/channel/channel.model'
 import { Channel } from '../../../generated/graphql-server/src/modules/channel/channel.model'
 import { Category } from '../../../generated/graphql-server/src/modules/category/category.model'
 import { Category } from '../../../generated/graphql-server/src/modules/category/category.model'
-import { KnownLicense } from '../../../generated/graphql-server/src/modules/known-license/known-license.model'
-import { UserDefinedLicense } from '../../../generated/graphql-server/src/modules/user-defined-license/user-defined-license.model'
-import { JoystreamMediaLocation } from '../../../generated/graphql-server/src/modules/joystream-media-location/joystream-media-location.model'
-import { HttpMediaLocation } from '../../../generated/graphql-server/src/modules/http-media-location/http-media-location.model'
+import { KnownLicenseEntity } from '../../../generated/graphql-server/src/modules/known-license-entity/known-license-entity.model'
+import { UserDefinedLicenseEntity } from '../../../generated/graphql-server/src/modules/user-defined-license-entity/user-defined-license-entity.model'
+import { JoystreamMediaLocationEntity } from '../../../generated/graphql-server/src/modules/joystream-media-location-entity/joystream-media-location-entity.model'
+import { HttpMediaLocationEntity } from '../../../generated/graphql-server/src/modules/http-media-location-entity/http-media-location-entity.model'
 import { VideoMedia } from '../../../generated/graphql-server/src/modules/video-media/video-media.model'
 import { VideoMedia } from '../../../generated/graphql-server/src/modules/video-media/video-media.model'
 import { Video } from '../../../generated/graphql-server/src/modules/video/video.model'
 import { Video } from '../../../generated/graphql-server/src/modules/video/video.model'
 import { Block, Network } from '../../../generated/graphql-server/src/modules/block/block.model'
 import { Block, Network } from '../../../generated/graphql-server/src/modules/block/block.model'
 import { Language } from '../../../generated/graphql-server/src/modules/language/language.model'
 import { Language } from '../../../generated/graphql-server/src/modules/language/language.model'
 import { VideoMediaEncoding } from '../../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
 import { VideoMediaEncoding } from '../../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
 import { ClassEntity } from '../../../generated/graphql-server/src/modules/class-entity/class-entity.model'
 import { ClassEntity } from '../../../generated/graphql-server/src/modules/class-entity/class-entity.model'
-import { License } from '../../../generated/graphql-server/src/modules/license/license.model'
-import { MediaLocation } from '../../../generated/graphql-server/src/modules/media-location/media-location.model'
+import { LicenseEntity } from '../../../generated/graphql-server/src/modules/license-entity/license-entity.model'
+import { MediaLocationEntity } from '../../../generated/graphql-server/src/modules/media-location-entity/media-location-entity.model'
+import { FeaturedVideo } from '../../../generated/graphql-server/src/modules/featured-video/featured-video.model'
 
 
 import { contentDirectoryClassNamesWithId } from '../content-dir-consts'
 import { contentDirectoryClassNamesWithId } from '../content-dir-consts'
 import {
 import {
@@ -22,6 +23,7 @@ import {
   ICreateEntityOperation,
   ICreateEntityOperation,
   IDBBlockId,
   IDBBlockId,
   IEntity,
   IEntity,
+  IFeaturedVideo,
   IHttpMediaLocation,
   IHttpMediaLocation,
   IJoystreamMediaLocation,
   IJoystreamMediaLocation,
   IKnownLicense,
   IKnownLicense,
@@ -35,6 +37,12 @@ import {
 } from '../../types'
 } from '../../types'
 import { getOrCreate } from '../get-or-create'
 import { getOrCreate } from '../get-or-create'
 import BN from 'bn.js'
 import BN from 'bn.js'
+import {
+  HttpMediaLocation,
+  JoystreamMediaLocation,
+  KnownLicense,
+  UserDefinedLicense,
+} from '../../../generated/graphql-server/src/modules/variants/variants.model'
 
 
 async function createBlockOrGetFromDatabase(db: DB, blockNumber: number): Promise<Block> {
 async function createBlockOrGetFromDatabase(db: DB, blockNumber: number): Promise<Block> {
   let b = await db.get(Block, { where: { block: blockNumber } })
   let b = await db.get(Block, { where: { block: blockNumber } })
@@ -59,16 +67,16 @@ async function createChannel(
 
 
   channel.version = block
   channel.version = block
   channel.id = id
   channel.id = id
-  channel.title = p.title
+  channel.handle = p.handle
   channel.description = p.description
   channel.description = p.description
-  channel.isCurated = p.isCurated || false
+  channel.isCurated = !!p.isCurated
   channel.isPublic = p.isPublic
   channel.isPublic = p.isPublic
-  channel.coverPhotoUrl = p.coverPhotoURL
-  channel.avatarPhotoUrl = p.avatarPhotoURL
+  channel.coverPhotoUrl = p.coverPhotoUrl
+  channel.avatarPhotoUrl = p.avatarPhotoUrl
 
 
   channel.happenedIn = await createBlockOrGetFromDatabase(db, block)
   channel.happenedIn = await createBlockOrGetFromDatabase(db, block)
   const { language } = p
   const { language } = p
-  if (language !== undefined) {
+  if (language) {
     channel.language = await getOrCreate.language(
     channel.language = await getOrCreate.language(
       { db, block, id },
       { db, block, id },
       classEntityMap,
       classEntityMap,
@@ -95,11 +103,11 @@ async function createCategory({ db, block, id }: IDBBlockId, p: ICategory): Prom
   return category
   return category
 }
 }
 
 
-async function createKnownLicense({ db, block, id }: IDBBlockId, p: IKnownLicense): Promise<KnownLicense> {
-  const record = await db.get(KnownLicense, { where: { id } })
+async function createKnownLicense({ db, block, id }: IDBBlockId, p: IKnownLicense): Promise<KnownLicenseEntity> {
+  const record = await db.get(KnownLicenseEntity, { where: { id } })
   if (record) return record
   if (record) return record
 
 
-  const knownLicence = new KnownLicense()
+  const knownLicence = new KnownLicenseEntity()
 
 
   knownLicence.id = id
   knownLicence.id = id
   knownLicence.code = p.code
   knownLicence.code = p.code
@@ -115,28 +123,28 @@ async function createKnownLicense({ db, block, id }: IDBBlockId, p: IKnownLicens
 async function createUserDefinedLicense(
 async function createUserDefinedLicense(
   { db, block, id }: IDBBlockId,
   { db, block, id }: IDBBlockId,
   p: IUserDefinedLicense
   p: IUserDefinedLicense
-): Promise<UserDefinedLicense> {
-  const record = await db.get(UserDefinedLicense, { where: { id } })
+): Promise<UserDefinedLicenseEntity> {
+  const record = await db.get(UserDefinedLicenseEntity, { where: { id } })
   if (record) return record
   if (record) return record
 
 
-  const userDefinedLicense = new UserDefinedLicense()
+  const userDefinedLicense = new UserDefinedLicenseEntity()
 
 
   userDefinedLicense.id = id
   userDefinedLicense.id = id
   userDefinedLicense.content = p.content
   userDefinedLicense.content = p.content
   userDefinedLicense.version = block
   userDefinedLicense.version = block
   userDefinedLicense.happenedIn = await createBlockOrGetFromDatabase(db, block)
   userDefinedLicense.happenedIn = await createBlockOrGetFromDatabase(db, block)
-  await db.save<UserDefinedLicense>(userDefinedLicense)
+  await db.save<UserDefinedLicenseEntity>(userDefinedLicense)
   return userDefinedLicense
   return userDefinedLicense
 }
 }
 
 
 async function createJoystreamMediaLocation(
 async function createJoystreamMediaLocation(
   { db, block, id }: IDBBlockId,
   { db, block, id }: IDBBlockId,
   p: IJoystreamMediaLocation
   p: IJoystreamMediaLocation
-): Promise<JoystreamMediaLocation> {
-  const record = await db.get(JoystreamMediaLocation, { where: { id } })
+): Promise<JoystreamMediaLocationEntity> {
+  const record = await db.get(JoystreamMediaLocationEntity, { where: { id } })
   if (record) return record
   if (record) return record
 
 
-  const joyMediaLoc = new JoystreamMediaLocation()
+  const joyMediaLoc = new JoystreamMediaLocationEntity()
 
 
   joyMediaLoc.id = id
   joyMediaLoc.id = id
   joyMediaLoc.dataObjectId = p.dataObjectId
   joyMediaLoc.dataObjectId = p.dataObjectId
@@ -149,11 +157,11 @@ async function createJoystreamMediaLocation(
 async function createHttpMediaLocation(
 async function createHttpMediaLocation(
   { db, block, id }: IDBBlockId,
   { db, block, id }: IDBBlockId,
   p: IHttpMediaLocation
   p: IHttpMediaLocation
-): Promise<HttpMediaLocation> {
-  const record = await db.get(HttpMediaLocation, { where: { id } })
+): Promise<HttpMediaLocationEntity> {
+  const record = await db.get(HttpMediaLocationEntity, { where: { id } })
   if (record) return record
   if (record) return record
 
 
-  const httpMediaLoc = new HttpMediaLocation()
+  const httpMediaLoc = new HttpMediaLocationEntity()
 
 
   httpMediaLoc.id = id
   httpMediaLoc.id = id
   httpMediaLoc.url = p.url
   httpMediaLoc.url = p.url
@@ -187,16 +195,29 @@ async function createVideoMedia(
     )
     )
   }
   }
   if (location !== undefined) {
   if (location !== undefined) {
-    videoMedia.location = await getOrCreate.mediaLocation(
+    const m = await getOrCreate.mediaLocation(
       { db, block, id },
       { db, block, id },
       classEntityMap,
       classEntityMap,
       location,
       location,
       nextEntityIdBeforeTransaction
       nextEntityIdBeforeTransaction
     )
     )
+    videoMedia.locationEntity = m
+    const { httpMediaLocation, joystreamMediaLocation } = m
+    if (httpMediaLocation) {
+      const mediaLoc = new HttpMediaLocation()
+      mediaLoc.port = httpMediaLocation.port
+      mediaLoc.url = httpMediaLocation.url
+      videoMedia.location = mediaLoc
+    }
+    if (joystreamMediaLocation) {
+      const mediaLoc = new JoystreamMediaLocation()
+      mediaLoc.dataObjectId = joystreamMediaLocation.dataObjectId
+      videoMedia.location = mediaLoc
+    }
   }
   }
 
 
   videoMedia.happenedIn = await createBlockOrGetFromDatabase(db, block)
   videoMedia.happenedIn = await createBlockOrGetFromDatabase(db, block)
-  await db.save(videoMedia)
+  await db.save<VideoMedia>(videoMedia)
   return videoMedia
   return videoMedia
 }
 }
 
 
@@ -216,14 +237,14 @@ async function createVideo(
   video.description = p.description
   video.description = p.description
   video.duration = p.duration
   video.duration = p.duration
   video.hasMarketing = p.hasMarketing
   video.hasMarketing = p.hasMarketing
-  // TODO: needs to be handled correctly, from runtime CurationStatus is coming
-  video.isCurated = p.isCurated || true
+  video.isCurated = !!p.isCurated
   video.isExplicit = p.isExplicit
   video.isExplicit = p.isExplicit
   video.isPublic = p.isPublic
   video.isPublic = p.isPublic
   video.publishedBeforeJoystream = p.publishedBeforeJoystream
   video.publishedBeforeJoystream = p.publishedBeforeJoystream
   video.skippableIntroDuration = p.skippableIntroDuration
   video.skippableIntroDuration = p.skippableIntroDuration
-  video.thumbnailUrl = p.thumbnailURL
+  video.thumbnailUrl = p.thumbnailUrl
   video.version = block
   video.version = block
+  video.isFeatured = false
 
 
   const { language, license, category, channel, media } = p
   const { language, license, category, channel, media } = p
   if (language !== undefined) {
   if (language !== undefined) {
@@ -234,8 +255,9 @@ async function createVideo(
       nextEntityIdBeforeTransaction
       nextEntityIdBeforeTransaction
     )
     )
   }
   }
-  if (license !== undefined) {
-    video.license = await getOrCreate.license({ db, block, id }, classEntityMap, license, nextEntityIdBeforeTransaction)
+  if (license) {
+    const lic = await getOrCreate.license({ db, block, id }, classEntityMap, license, nextEntityIdBeforeTransaction)
+    video.license = lic
   }
   }
   if (category !== undefined) {
   if (category !== undefined) {
     video.category = await getOrCreate.category(
     video.category = await getOrCreate.category(
@@ -293,32 +315,45 @@ async function createLicense(
   classEntityMap: ClassEntityMap,
   classEntityMap: ClassEntityMap,
   p: ILicense,
   p: ILicense,
   nextEntityIdBeforeTransaction: number
   nextEntityIdBeforeTransaction: number
-): Promise<License> {
-  const record = await db.get(License, { where: { id } })
+): Promise<LicenseEntity> {
+  const record = await db.get(LicenseEntity, { where: { id } })
   if (record) return record
   if (record) return record
 
 
-  const { knownLicense, userDefinedLicense } = p
+  const license = new LicenseEntity()
 
 
-  const license = new License()
-  license.id = id
-  if (knownLicense !== undefined) {
-    license.knownLicense = await getOrCreate.knownLicense(
+  if (p.knownLicense) {
+    const kLicense = await getOrCreate.knownLicense(
       { db, block, id },
       { db, block, id },
       classEntityMap,
       classEntityMap,
-      knownLicense,
+      p.knownLicense,
       nextEntityIdBeforeTransaction
       nextEntityIdBeforeTransaction
     )
     )
+    const k = new KnownLicense()
+    k.code = kLicense.code
+    k.description = kLicense.description
+    k.name = kLicense.name
+    k.url = kLicense.url
+    // Set the license type
+    license.type = k
   }
   }
-  if (userDefinedLicense !== undefined) {
-    license.userdefinedLicense = await getOrCreate.userDefinedLicense(
+  if (p.userDefinedLicense) {
+    const { content } = await getOrCreate.userDefinedLicense(
       { db, block, id },
       { db, block, id },
       classEntityMap,
       classEntityMap,
-      userDefinedLicense,
+      p.userDefinedLicense,
       nextEntityIdBeforeTransaction
       nextEntityIdBeforeTransaction
     )
     )
+    const u = new UserDefinedLicense()
+    u.content = content
+    // Set the license type
+    license.type = u
   }
   }
+
+  license.id = id
+  license.attribution = p.attribution
   license.happenedIn = await createBlockOrGetFromDatabase(db, block)
   license.happenedIn = await createBlockOrGetFromDatabase(db, block)
-  await db.save<License>(license)
+
+  await db.save<LicenseEntity>(license)
   return license
   return license
 }
 }
 
 
@@ -327,10 +362,10 @@ async function createMediaLocation(
   classEntityMap: ClassEntityMap,
   classEntityMap: ClassEntityMap,
   p: IMediaLocation,
   p: IMediaLocation,
   nextEntityIdBeforeTransaction: number
   nextEntityIdBeforeTransaction: number
-): Promise<MediaLocation> {
+): Promise<MediaLocationEntity> {
   const { httpMediaLocation, joystreamMediaLocation } = p
   const { httpMediaLocation, joystreamMediaLocation } = p
 
 
-  const location = new MediaLocation()
+  const location = new MediaLocationEntity()
   location.id = id
   location.id = id
   if (httpMediaLocation !== undefined) {
   if (httpMediaLocation !== undefined) {
     location.httpMediaLocation = await getOrCreate.httpMediaLocation(
     location.httpMediaLocation = await getOrCreate.httpMediaLocation(
@@ -349,10 +384,33 @@ async function createMediaLocation(
     )
     )
   }
   }
   location.happenedIn = await createBlockOrGetFromDatabase(db, block)
   location.happenedIn = await createBlockOrGetFromDatabase(db, block)
-  await db.save<License>(location)
+  await db.save<MediaLocationEntity>(location)
   return location
   return location
 }
 }
 
 
+async function createFeaturedVideo(
+  { db, block, id }: IDBBlockId,
+  classEntityMap: ClassEntityMap,
+  p: IFeaturedVideo,
+  nextEntityIdBeforeTransaction: number
+): Promise<void> {
+  const featuredVideo = new FeaturedVideo()
+
+  featuredVideo.video = await getOrCreate.video(
+    { db, block, id },
+    classEntityMap,
+    p.video!,
+    nextEntityIdBeforeTransaction
+  )
+
+  featuredVideo.id = id
+  featuredVideo.version = block
+  featuredVideo.video.isFeatured = true
+
+  await db.save<Video>(featuredVideo.video)
+  await db.save<FeaturedVideo>(featuredVideo)
+}
+
 async function getClassName(
 async function getClassName(
   db: DB,
   db: DB,
   entity: IEntity,
   entity: IEntity,
@@ -394,4 +452,5 @@ export {
   createMediaLocation,
   createMediaLocation,
   createBlockOrGetFromDatabase,
   createBlockOrGetFromDatabase,
   getClassName,
   getClassName,
+  createFeaturedVideo,
 }
 }

+ 29 - 3
query-node/mappings/content-directory/entity/index.ts

@@ -16,6 +16,7 @@ import {
   updateVideoMediaEncodingEntityPropertyValues,
   updateVideoMediaEncodingEntityPropertyValues,
   updateLicenseEntityPropertyValues,
   updateLicenseEntityPropertyValues,
   updateMediaLocationEntityPropertyValues,
   updateMediaLocationEntityPropertyValues,
+  updateFeaturedVideoEntityPropertyValues,
 } from './update'
 } from './update'
 import {
 import {
   removeCategory,
   removeCategory,
@@ -30,6 +31,7 @@ import {
   removeVideoMediaEncoding,
   removeVideoMediaEncoding,
   removeLicense,
   removeLicense,
   removeMediaLocation,
   removeMediaLocation,
+  removeFeaturedVideo,
 } from './remove'
 } from './remove'
 import {
 import {
   createCategory,
   createCategory,
@@ -43,9 +45,10 @@ import {
   createLanguage,
   createLanguage,
   createVideoMediaEncoding,
   createVideoMediaEncoding,
   createBlockOrGetFromDatabase,
   createBlockOrGetFromDatabase,
+  createFeaturedVideo,
 } from './create'
 } from './create'
 import {
 import {
-  CategoryPropertyNamesWithId,
+  categoryPropertyNamesWithId,
   channelPropertyNamesWithId,
   channelPropertyNamesWithId,
   httpMediaLocationPropertyNamesWithId,
   httpMediaLocationPropertyNamesWithId,
   joystreamMediaLocationPropertyNamesWithId,
   joystreamMediaLocationPropertyNamesWithId,
@@ -56,6 +59,7 @@ import {
   videoPropertyNamesWithId,
   videoPropertyNamesWithId,
   contentDirectoryClassNamesWithId,
   contentDirectoryClassNamesWithId,
   ContentDirectoryKnownClasses,
   ContentDirectoryKnownClasses,
+  featuredVideoPropertyNamesWithId,
 } from '../content-dir-consts'
 } from '../content-dir-consts'
 
 
 import {
 import {
@@ -74,6 +78,7 @@ import {
   IEntity,
   IEntity,
   ILicense,
   ILicense,
   IMediaLocation,
   IMediaLocation,
+  IFeaturedVideo,
 } from '../../types'
 } from '../../types'
 import { getOrCreate } from '../get-or-create'
 import { getOrCreate } from '../get-or-create'
 
 
@@ -112,7 +117,7 @@ async function contentDirectory_EntitySchemaSupportAdded(db: DB, event: Substrat
       break
       break
 
 
     case ContentDirectoryKnownClasses.CATEGORY:
     case ContentDirectoryKnownClasses.CATEGORY:
-      await createCategory(arg, decode.setProperties<ICategory>(event, CategoryPropertyNamesWithId))
+      await createCategory(arg, decode.setProperties<ICategory>(event, categoryPropertyNamesWithId))
       break
       break
 
 
     case ContentDirectoryKnownClasses.KNOWNLICENSE:
     case ContentDirectoryKnownClasses.KNOWNLICENSE:
@@ -168,6 +173,14 @@ async function contentDirectory_EntitySchemaSupportAdded(db: DB, event: Substrat
         decode.setProperties<IVideoMediaEncoding>(event, videoMediaEncodingPropertyNamesWithId)
         decode.setProperties<IVideoMediaEncoding>(event, videoMediaEncodingPropertyNamesWithId)
       )
       )
       break
       break
+    case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
+      await createFeaturedVideo(
+        arg,
+        new Map<string, IEntity[]>(),
+        decode.setProperties<IFeaturedVideo>(event, featuredVideoPropertyNamesWithId),
+        0
+      )
+      break
 
 
     default:
     default:
       throw new Error(`Unknown class name: ${cls.name}`)
       throw new Error(`Unknown class name: ${cls.name}`)
@@ -241,6 +254,10 @@ async function contentDirectory_EntityRemoved(db: DB, event: SubstrateEvent): Pr
       await removeMediaLocation(db, where)
       await removeMediaLocation(db, where)
       break
       break
 
 
+    case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
+      await removeFeaturedVideo(db, where)
+      break
+
     default:
     default:
       throw new Error(`Unknown class name: ${cls.name}`)
       throw new Error(`Unknown class name: ${cls.name}`)
   }
   }
@@ -296,7 +313,7 @@ async function contentDirectory_EntityPropertyValuesUpdated(db: DB, event: Subst
       await updateCategoryEntityPropertyValues(
       await updateCategoryEntityPropertyValues(
         db,
         db,
         where,
         where,
-        decode.setProperties<ICategory>(event, CategoryPropertyNamesWithId)
+        decode.setProperties<ICategory>(event, categoryPropertyNamesWithId)
       )
       )
       break
       break
 
 
@@ -379,6 +396,15 @@ async function contentDirectory_EntityPropertyValuesUpdated(db: DB, event: Subst
       )
       )
       break
       break
 
 
+    case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
+      await updateFeaturedVideoEntityPropertyValues(
+        db,
+        where,
+        decode.setProperties<IFeaturedVideo>(event, featuredVideoPropertyNamesWithId),
+        0
+      )
+      break
+
     default:
     default:
       throw new Error(`Unknown class name: ${cls.name}`)
       throw new Error(`Unknown class name: ${cls.name}`)
   }
   }

+ 69 - 46
query-node/mappings/content-directory/entity/remove.ts

@@ -1,97 +1,119 @@
+import assert from 'assert'
+
 import { DB } from '../../../generated/indexer'
 import { DB } from '../../../generated/indexer'
 import { Channel } from '../../../generated/graphql-server/src/modules/channel/channel.model'
 import { Channel } from '../../../generated/graphql-server/src/modules/channel/channel.model'
 import { Category } from '../../../generated/graphql-server/src/modules/category/category.model'
 import { Category } from '../../../generated/graphql-server/src/modules/category/category.model'
-import { KnownLicense } from '../../../generated/graphql-server/src/modules/known-license/known-license.model'
-import { UserDefinedLicense } from '../../../generated/graphql-server/src/modules/user-defined-license/user-defined-license.model'
-import { JoystreamMediaLocation } from '../../../generated/graphql-server/src/modules/joystream-media-location/joystream-media-location.model'
-import { HttpMediaLocation } from '../../../generated/graphql-server/src/modules/http-media-location/http-media-location.model'
+import { KnownLicenseEntity } from '../../../generated/graphql-server/src/modules/known-license-entity/known-license-entity.model'
+import { UserDefinedLicenseEntity } from '../../../generated/graphql-server/src/modules/user-defined-license-entity/user-defined-license-entity.model'
+import { JoystreamMediaLocationEntity } from '../../../generated/graphql-server/src/modules/joystream-media-location-entity/joystream-media-location-entity.model'
+import { HttpMediaLocationEntity } from '../../../generated/graphql-server/src/modules/http-media-location-entity/http-media-location-entity.model'
 import { VideoMedia } from '../../../generated/graphql-server/src/modules/video-media/video-media.model'
 import { VideoMedia } from '../../../generated/graphql-server/src/modules/video-media/video-media.model'
 import { Video } from '../../../generated/graphql-server/src/modules/video/video.model'
 import { Video } from '../../../generated/graphql-server/src/modules/video/video.model'
 import { Language } from '../../../generated/graphql-server/src/modules/language/language.model'
 import { Language } from '../../../generated/graphql-server/src/modules/language/language.model'
 import { VideoMediaEncoding } from '../../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
 import { VideoMediaEncoding } from '../../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
-import { License } from '../../../generated/graphql-server/src/modules/license/license.model'
-import { MediaLocation } from '../../../generated/graphql-server/src/modules/media-location/media-location.model'
+import { LicenseEntity } from '../../../generated/graphql-server/src/modules/license-entity/license-entity.model'
+import { MediaLocationEntity } from '../../../generated/graphql-server/src/modules/media-location-entity/media-location-entity.model'
+import { FeaturedVideo } from '../../../generated/graphql-server/src/modules/featured-video/featured-video.model'
 
 
 import { IWhereCond } from '../../types'
 import { IWhereCond } from '../../types'
 
 
+function assertKeyViolation(entityName: string, entityId: string) {
+  assert(false, `Can not remove ${entityName}(${entityId})! There are references to this entity`)
+}
+
 async function removeChannel(db: DB, where: IWhereCond): Promise<void> {
 async function removeChannel(db: DB, where: IWhereCond): Promise<void> {
   const record = await db.get(Channel, where)
   const record = await db.get(Channel, where)
-  if (record === undefined) throw Error(`Channel not found`)
-  if (record.videos) record.videos.map(async (v) => await removeVideo(db, { where: { id: v.id } }))
+  if (!record) throw Error(`Channel(${where.where.id}) not found`)
+  if (record.videos && record.videos.length) assertKeyViolation(`Channel`, record.id)
   await db.remove<Channel>(record)
   await db.remove<Channel>(record)
 }
 }
+
 async function removeCategory(db: DB, where: IWhereCond): Promise<void> {
 async function removeCategory(db: DB, where: IWhereCond): Promise<void> {
   const record = await db.get(Category, where)
   const record = await db.get(Category, where)
-  if (record === undefined) throw Error(`Category not found`)
-  if (record.videos) record.videos.map(async (v) => await removeVideo(db, { where: { id: v.id } }))
+  if (!record) throw Error(`Category(${where.where.id}) not found`)
+  if (record.videos && record.videos.length) assertKeyViolation(`Category`, record.id)
   await db.remove<Category>(record)
   await db.remove<Category>(record)
 }
 }
 async function removeVideoMedia(db: DB, where: IWhereCond): Promise<void> {
 async function removeVideoMedia(db: DB, where: IWhereCond): Promise<void> {
   const record = await db.get(VideoMedia, where)
   const record = await db.get(VideoMedia, where)
-  if (record === undefined) throw Error(`VideoMedia not found`)
-  if (record.video) await db.remove<Video>(record.video)
+  if (!record) throw Error(`VideoMedia(${where.where.id}) not found`)
+  if (record.video) assertKeyViolation(`VideoMedia`, record.id)
   await db.remove<VideoMedia>(record)
   await db.remove<VideoMedia>(record)
 }
 }
 async function removeVideo(db: DB, where: IWhereCond): Promise<void> {
 async function removeVideo(db: DB, where: IWhereCond): Promise<void> {
   const record = await db.get(Video, where)
   const record = await db.get(Video, where)
-  if (record === undefined) throw Error(`Video not found`)
+  if (!record) throw Error(`Video(${where.where.id}) not found`)
   await db.remove<Video>(record)
   await db.remove<Video>(record)
 }
 }
 
 
 async function removeLicense(db: DB, where: IWhereCond): Promise<void> {
 async function removeLicense(db: DB, where: IWhereCond): Promise<void> {
-  const record = await db.get(License, where)
-  if (record === undefined) throw Error(`License not found`)
-  // Remove all the videos under this license
-  if (record.videolicense) record.videolicense.map(async (v) => await removeVideo(db, { where: { id: v.id } }))
-  await db.remove<License>(record)
+  const record = await db.get(LicenseEntity, where)
+  if (!record) throw Error(`License(${where.where.id}) not found`)
+  if (record.videolicense && record.videolicense.length) assertKeyViolation(`License`, record.id)
+  await db.remove<LicenseEntity>(record)
 }
 }
+
 async function removeUserDefinedLicense(db: DB, where: IWhereCond): Promise<void> {
 async function removeUserDefinedLicense(db: DB, where: IWhereCond): Promise<void> {
-  const record = await db.get(UserDefinedLicense, where)
-  if (record === undefined) throw Error(`UserDefinedLicense not found`)
-  if (record.licenseuserdefinedLicense)
-    record.licenseuserdefinedLicense.map(async (l) => await removeLicense(db, { where: { id: l.id } }))
-  await db.remove<UserDefinedLicense>(record)
+  const record = await db.get(UserDefinedLicenseEntity, where)
+  if (!record) throw Error(`UserDefinedLicense(${where.where.id}) not found`)
+  await db.remove<UserDefinedLicenseEntity>(record)
 }
 }
+
 async function removeKnownLicense(db: DB, where: IWhereCond): Promise<void> {
 async function removeKnownLicense(db: DB, where: IWhereCond): Promise<void> {
-  const record = await db.get(KnownLicense, where)
-  if (record === undefined) throw Error(`KnownLicense not found`)
-  if (record.licenseknownLicense)
-    record.licenseknownLicense.map(async (k) => await removeLicense(db, { where: { id: k.id } }))
-  await db.remove<KnownLicense>(record)
+  const record = await db.get(KnownLicenseEntity, where)
+  if (!record) throw Error(`KnownLicense(${where.where.id}) not found`)
+  await db.remove<KnownLicenseEntity>(record)
 }
 }
 async function removeMediaLocation(db: DB, where: IWhereCond): Promise<void> {
 async function removeMediaLocation(db: DB, where: IWhereCond): Promise<void> {
-  const record = await db.get(MediaLocation, where)
-  if (record === undefined) throw Error(`MediaLocation not found`)
-  if (record.videoMedia) await removeVideo(db, { where: { id: record.videoMedia.id } })
-  await db.remove<MediaLocation>(record)
+  const record = await db.get(MediaLocationEntity, where)
+  if (!record) throw Error(`MediaLocation(${where.where.id}) not found`)
+  if (record.videoMedia) assertKeyViolation('MediaLocation', record.id)
+  await db.remove<MediaLocationEntity>(record)
 }
 }
+
 async function removeHttpMediaLocation(db: DB, where: IWhereCond): Promise<void> {
 async function removeHttpMediaLocation(db: DB, where: IWhereCond): Promise<void> {
-  const record = await db.get(HttpMediaLocation, where)
-  if (record === undefined) throw Error(`HttpMediaLocation not found`)
-  if (record.medialocationhttpMediaLocation)
-    record.medialocationhttpMediaLocation.map(async (v) => await removeMediaLocation(db, { where: { id: v.id } }))
-  await db.remove<HttpMediaLocation>(record)
+  const record = await db.get(HttpMediaLocationEntity, where)
+  if (!record) throw Error(`HttpMediaLocation(${where.where.id}) not found`)
+  if (record.medialocationentityhttpMediaLocation && record.medialocationentityhttpMediaLocation.length) {
+    assertKeyViolation('HttpMediaLocation', record.id)
+  }
+  await db.remove<HttpMediaLocationEntity>(record)
 }
 }
+
 async function removeJoystreamMediaLocation(db: DB, where: IWhereCond): Promise<void> {
 async function removeJoystreamMediaLocation(db: DB, where: IWhereCond): Promise<void> {
-  const record = await db.get(JoystreamMediaLocation, where)
-  if (record === undefined) throw Error(`JoystreamMediaLocation not found`)
-  if (record.medialocationjoystreamMediaLocation)
-    record.medialocationjoystreamMediaLocation.map(async (v) => await removeVideo(db, { where: { id: v.id } }))
-  await db.remove<JoystreamMediaLocation>(record)
+  const record = await db.get(JoystreamMediaLocationEntity, where)
+  if (!record) throw Error(`JoystreamMediaLocation(${where.where.id}) not found`)
+  if (record.medialocationentityjoystreamMediaLocation && record.medialocationentityjoystreamMediaLocation.length) {
+    assertKeyViolation('JoystreamMediaLocation', record.id)
+  }
+  await db.remove<JoystreamMediaLocationEntity>(record)
 }
 }
+
 async function removeLanguage(db: DB, where: IWhereCond): Promise<void> {
 async function removeLanguage(db: DB, where: IWhereCond): Promise<void> {
   const record = await db.get(Language, where)
   const record = await db.get(Language, where)
-  if (record === undefined) throw Error(`Language not found`)
-  if (record.channellanguage) record.channellanguage.map(async (c) => await removeChannel(db, { where: { id: c.id } }))
-  if (record.videolanguage) record.videolanguage.map(async (v) => await removeVideo(db, { where: { id: v.id } }))
+  if (!record) throw Error(`Language(${where.where.id}) not found`)
+  if (record.channellanguage && record.channellanguage.length) assertKeyViolation('Language', record.id)
+  if (record.videolanguage && record.videolanguage.length) assertKeyViolation('Language', record.id)
   await db.remove<Language>(record)
   await db.remove<Language>(record)
 }
 }
+
 async function removeVideoMediaEncoding(db: DB, where: IWhereCond): Promise<void> {
 async function removeVideoMediaEncoding(db: DB, where: IWhereCond): Promise<void> {
   const record = await db.get(VideoMediaEncoding, where)
   const record = await db.get(VideoMediaEncoding, where)
-  if (record === undefined) throw Error(`Language not found`)
+  if (!record) throw Error(`VideoMediaEncoding(${where.where.id}) not found`)
   await db.remove<VideoMediaEncoding>(record)
   await db.remove<VideoMediaEncoding>(record)
 }
 }
 
 
+async function removeFeaturedVideo(db: DB, where: IWhereCond): Promise<void> {
+  const record = await db.get(FeaturedVideo, { ...where, relations: ['video'] })
+  if (!record) throw Error(`FeaturedVideo(${where.where.id}) not found`)
+
+  record.video.isFeatured = false
+  record.video.featured = undefined
+
+  await db.save<Video>(record.video)
+  await db.remove<FeaturedVideo>(record)
+}
+
 export {
 export {
   removeCategory,
   removeCategory,
   removeChannel,
   removeChannel,
@@ -105,4 +127,5 @@ export {
   removeVideoMediaEncoding,
   removeVideoMediaEncoding,
   removeMediaLocation,
   removeMediaLocation,
   removeLicense,
   removeLicense,
+  removeFeaturedVideo,
 }
 }

+ 105 - 33
query-node/mappings/content-directory/entity/update.ts

@@ -1,20 +1,22 @@
 import { DB } from '../../../generated/indexer'
 import { DB } from '../../../generated/indexer'
 import { Channel } from '../../../generated/graphql-server/src/modules/channel/channel.model'
 import { Channel } from '../../../generated/graphql-server/src/modules/channel/channel.model'
 import { Category } from '../../../generated/graphql-server/src/modules/category/category.model'
 import { Category } from '../../../generated/graphql-server/src/modules/category/category.model'
-import { KnownLicense } from '../../../generated/graphql-server/src/modules/known-license/known-license.model'
-import { UserDefinedLicense } from '../../../generated/graphql-server/src/modules/user-defined-license/user-defined-license.model'
-import { JoystreamMediaLocation } from '../../../generated/graphql-server/src/modules/joystream-media-location/joystream-media-location.model'
-import { HttpMediaLocation } from '../../../generated/graphql-server/src/modules/http-media-location/http-media-location.model'
+import { KnownLicenseEntity } from '../../../generated/graphql-server/src/modules/known-license-entity/known-license-entity.model'
+import { UserDefinedLicenseEntity } from '../../../generated/graphql-server/src/modules/user-defined-license-entity/user-defined-license-entity.model'
 import { VideoMedia } from '../../../generated/graphql-server/src/modules/video-media/video-media.model'
 import { VideoMedia } from '../../../generated/graphql-server/src/modules/video-media/video-media.model'
 import { Video } from '../../../generated/graphql-server/src/modules/video/video.model'
 import { Video } from '../../../generated/graphql-server/src/modules/video/video.model'
 import { Language } from '../../../generated/graphql-server/src/modules/language/language.model'
 import { Language } from '../../../generated/graphql-server/src/modules/language/language.model'
 import { VideoMediaEncoding } from '../../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
 import { VideoMediaEncoding } from '../../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
-import { License } from '../../../generated/graphql-server/src/modules/license/license.model'
-import { MediaLocation } from '../../../generated/graphql-server/src/modules/media-location/media-location.model'
+import { LicenseEntity } from '../../../generated/graphql-server/src/modules/license-entity/license-entity.model'
+import { MediaLocationEntity } from '../../../generated/graphql-server/src/modules/media-location-entity/media-location-entity.model'
+import { HttpMediaLocationEntity } from '../../../generated/graphql-server/src/modules/http-media-location-entity/http-media-location-entity.model'
+import { JoystreamMediaLocationEntity } from '../../../generated/graphql-server/src/modules/joystream-media-location-entity/joystream-media-location-entity.model'
+import { FeaturedVideo } from '../../../generated/graphql-server/src/modules/featured-video/featured-video.model'
 
 
 import {
 import {
   ICategory,
   ICategory,
   IChannel,
   IChannel,
+  IFeaturedVideo,
   IHttpMediaLocation,
   IHttpMediaLocation,
   IJoystreamMediaLocation,
   IJoystreamMediaLocation,
   IKnownLicense,
   IKnownLicense,
@@ -28,6 +30,12 @@ import {
   IVideoMediaEncoding,
   IVideoMediaEncoding,
   IWhereCond,
   IWhereCond,
 } from '../../types'
 } from '../../types'
+import {
+  HttpMediaLocation,
+  JoystreamMediaLocation,
+  KnownLicense,
+  UserDefinedLicense,
+} from '../../../generated/graphql-server/src/modules/variants/variants.model'
 
 
 function getEntityIdFromReferencedField(ref: IReference, entityIdBeforeTransaction: number): string {
 function getEntityIdFromReferencedField(ref: IReference, entityIdBeforeTransaction: number): string {
   const { entityId, existing } = ref
   const { entityId, existing } = ref
@@ -42,18 +50,18 @@ async function updateMediaLocationEntityPropertyValues(
   entityIdBeforeTransaction: number
   entityIdBeforeTransaction: number
 ): Promise<void> {
 ): Promise<void> {
   const { httpMediaLocation, joystreamMediaLocation } = props
   const { httpMediaLocation, joystreamMediaLocation } = props
-  const record = await db.get(MediaLocation, where)
+  const record = await db.get(MediaLocationEntity, where)
   if (record === undefined) throw Error(`MediaLocation entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`MediaLocation entity not found: ${where.where.id}`)
 
 
   if (httpMediaLocation) {
   if (httpMediaLocation) {
     const id = getEntityIdFromReferencedField(httpMediaLocation, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(httpMediaLocation, entityIdBeforeTransaction)
-    record.httpMediaLocation = await db.get(HttpMediaLocation, { where: { id } })
+    record.httpMediaLocation = await db.get(HttpMediaLocationEntity, { where: { id } })
   }
   }
   if (joystreamMediaLocation) {
   if (joystreamMediaLocation) {
     const id = getEntityIdFromReferencedField(joystreamMediaLocation, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(joystreamMediaLocation, entityIdBeforeTransaction)
-    record.joystreamMediaLocation = await db.get(JoystreamMediaLocation, { where: { id } })
+    record.joystreamMediaLocation = await db.get(JoystreamMediaLocationEntity, { where: { id } })
   }
   }
-  await db.save<MediaLocation>(record)
+  await db.save<MediaLocationEntity>(record)
 }
 }
 
 
 async function updateLicenseEntityPropertyValues(
 async function updateLicenseEntityPropertyValues(
@@ -62,19 +70,36 @@ async function updateLicenseEntityPropertyValues(
   props: ILicense,
   props: ILicense,
   entityIdBeforeTransaction: number
   entityIdBeforeTransaction: number
 ): Promise<void> {
 ): Promise<void> {
-  const record = await db.get(License, where)
+  const record = await db.get(LicenseEntity, where)
   if (record === undefined) throw Error(`License entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`License entity not found: ${where.where.id}`)
 
 
   const { knownLicense, userDefinedLicense } = props
   const { knownLicense, userDefinedLicense } = props
   if (knownLicense) {
   if (knownLicense) {
     const id = getEntityIdFromReferencedField(knownLicense, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(knownLicense, entityIdBeforeTransaction)
-    record.knownLicense = await db.get(KnownLicense, { where: { id } })
+    const kLicense = await db.get(KnownLicenseEntity, { where: { id } })
+    if (!kLicense) throw Error(`KnownLicense not found ${id}`)
+
+    const k = new KnownLicense()
+    k.code = kLicense.code
+    k.description = kLicense.description
+    k.name = kLicense.name
+    k.url = kLicense.url
+    // Set the license type
+    record.type = k
   }
   }
   if (userDefinedLicense) {
   if (userDefinedLicense) {
     const id = getEntityIdFromReferencedField(userDefinedLicense, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(userDefinedLicense, entityIdBeforeTransaction)
-    record.userdefinedLicense = await db.get(UserDefinedLicense, { where: { id } })
+    const udl = await db.get(UserDefinedLicenseEntity, { where: { id } })
+    if (!udl) throw Error(`UserDefinedLicense not found ${id}`)
+
+    const u = new UserDefinedLicense()
+    u.content = udl.content
+    // Set the license type
+    record.type = u
   }
   }
-  await db.save<License>(record)
+
+  record.attribution = props.attribution || record.attribution
+  await db.save<LicenseEntity>(record)
 }
 }
 
 
 async function updateCategoryEntityPropertyValues(db: DB, where: IWhereCond, props: ICategory): Promise<void> {
 async function updateCategoryEntityPropertyValues(db: DB, where: IWhereCond, props: ICategory): Promise<void> {
@@ -83,6 +108,7 @@ async function updateCategoryEntityPropertyValues(db: DB, where: IWhereCond, pro
   Object.assign(record, props)
   Object.assign(record, props)
   await db.save<Category>(record)
   await db.save<Category>(record)
 }
 }
+
 async function updateChannelEntityPropertyValues(
 async function updateChannelEntityPropertyValues(
   db: DB,
   db: DB,
   where: IWhereCond,
   where: IWhereCond,
@@ -92,8 +118,8 @@ async function updateChannelEntityPropertyValues(
   const record = await db.get(Channel, where)
   const record = await db.get(Channel, where)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
 
 
-  let lang: Language | undefined
-  if (props.language !== undefined) {
+  let lang: Language | undefined = record.language
+  if (props.language) {
     const id = getEntityIdFromReferencedField(props.language, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(props.language, entityIdBeforeTransaction)
     lang = await db.get(Language, { where: { id } })
     lang = await db.get(Language, { where: { id } })
     if (lang === undefined) throw Error(`Language entity not found: ${id}`)
     if (lang === undefined) throw Error(`Language entity not found: ${id}`)
@@ -101,9 +127,10 @@ async function updateChannelEntityPropertyValues(
   }
   }
   Object.assign(record, props)
   Object.assign(record, props)
 
 
-  record.language = lang || record.language
+  record.language = lang
   await db.save<Channel>(record)
   await db.save<Channel>(record)
 }
 }
+
 async function updateVideoMediaEntityPropertyValues(
 async function updateVideoMediaEntityPropertyValues(
   db: DB,
   db: DB,
   where: IWhereCond,
   where: IWhereCond,
@@ -114,7 +141,7 @@ async function updateVideoMediaEntityPropertyValues(
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
 
 
   let enco: VideoMediaEncoding | undefined
   let enco: VideoMediaEncoding | undefined
-  let mediaLoc: MediaLocation | undefined
+  let mediaLoc: HttpMediaLocation | JoystreamMediaLocation = record.location
   const { encoding, location } = props
   const { encoding, location } = props
   if (encoding) {
   if (encoding) {
     const id = getEntityIdFromReferencedField(encoding, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(encoding, entityIdBeforeTransaction)
@@ -122,18 +149,31 @@ async function updateVideoMediaEntityPropertyValues(
     if (enco === undefined) throw Error(`VideoMediaEncoding entity not found: ${id}`)
     if (enco === undefined) throw Error(`VideoMediaEncoding entity not found: ${id}`)
     props.encoding = undefined
     props.encoding = undefined
   }
   }
+
   if (location) {
   if (location) {
     const id = getEntityIdFromReferencedField(location, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(location, entityIdBeforeTransaction)
-    mediaLoc = await db.get(MediaLocation, { where: { id } })
-    if (!mediaLoc) throw Error(`MediaLocation entity not found: ${id}`)
+    const mLoc = await db.get(MediaLocationEntity, { where: { id } })
+    if (!mLoc) throw Error(`MediaLocation entity not found: ${id}`)
+    const { httpMediaLocation, joystreamMediaLocation } = mLoc
+
+    if (httpMediaLocation) {
+      mediaLoc = new HttpMediaLocation()
+      mediaLoc.url = httpMediaLocation.url
+      mediaLoc.port = httpMediaLocation.port
+    }
+    if (joystreamMediaLocation) {
+      mediaLoc = new JoystreamMediaLocation()
+      mediaLoc.dataObjectId = joystreamMediaLocation.dataObjectId
+    }
     props.location = undefined
     props.location = undefined
   }
   }
   Object.assign(record, props)
   Object.assign(record, props)
 
 
   record.encoding = enco || record.encoding
   record.encoding = enco || record.encoding
-  record.location = mediaLoc || record.location
+  record.location = mediaLoc
   await db.save<VideoMedia>(record)
   await db.save<VideoMedia>(record)
 }
 }
+
 async function updateVideoEntityPropertyValues(
 async function updateVideoEntityPropertyValues(
   db: DB,
   db: DB,
   where: IWhereCond,
   where: IWhereCond,
@@ -147,7 +187,7 @@ async function updateVideoEntityPropertyValues(
   let cat: Category | undefined
   let cat: Category | undefined
   let lang: Language | undefined
   let lang: Language | undefined
   let vMedia: VideoMedia | undefined
   let vMedia: VideoMedia | undefined
-  let lic: License | undefined
+
   const { channel, category, language, media, license } = props
   const { channel, category, language, media, license } = props
   if (channel) {
   if (channel) {
     const id = getEntityIdFromReferencedField(channel, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(channel, entityIdBeforeTransaction)
@@ -169,8 +209,9 @@ async function updateVideoEntityPropertyValues(
   }
   }
   if (license) {
   if (license) {
     const id = getEntityIdFromReferencedField(license, entityIdBeforeTransaction)
     const id = getEntityIdFromReferencedField(license, entityIdBeforeTransaction)
-    lic = await db.get(License, { where: { id } })
-    if (!lic) throw Error(`License entity not found: ${id}`)
+    const licenseEntity = await db.get(LicenseEntity, { where: { id } })
+    if (!licenseEntity) throw Error(`License entity not found: ${id}`)
+    record.license = licenseEntity
     props.license = undefined
     props.license = undefined
   }
   }
   if (language) {
   if (language) {
@@ -185,36 +226,38 @@ async function updateVideoEntityPropertyValues(
   record.channel = chann || record.channel
   record.channel = chann || record.channel
   record.category = cat || record.category
   record.category = cat || record.category
   record.media = vMedia || record.media
   record.media = vMedia || record.media
-  record.license = lic || record.license
   record.language = lang
   record.language = lang
 
 
   await db.save<Video>(record)
   await db.save<Video>(record)
 }
 }
+
 async function updateUserDefinedLicenseEntityPropertyValues(
 async function updateUserDefinedLicenseEntityPropertyValues(
   db: DB,
   db: DB,
   where: IWhereCond,
   where: IWhereCond,
   props: IUserDefinedLicense
   props: IUserDefinedLicense
 ): Promise<void> {
 ): Promise<void> {
-  const record = await db.get(UserDefinedLicense, where)
+  const record = await db.get(UserDefinedLicenseEntity, where)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   Object.assign(record, props)
   Object.assign(record, props)
-  await db.save<UserDefinedLicense>(record)
+  await db.save<UserDefinedLicenseEntity>(record)
 }
 }
+
 async function updateKnownLicenseEntityPropertyValues(db: DB, where: IWhereCond, props: IKnownLicense): Promise<void> {
 async function updateKnownLicenseEntityPropertyValues(db: DB, where: IWhereCond, props: IKnownLicense): Promise<void> {
-  const record = await db.get(KnownLicense, where)
+  const record = await db.get(KnownLicenseEntity, where)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   Object.assign(record, props)
   Object.assign(record, props)
-  await db.save<KnownLicense>(record)
+  await db.save<KnownLicenseEntity>(record)
 }
 }
+
 async function updateHttpMediaLocationEntityPropertyValues(
 async function updateHttpMediaLocationEntityPropertyValues(
   db: DB,
   db: DB,
   where: IWhereCond,
   where: IWhereCond,
   props: IHttpMediaLocation
   props: IHttpMediaLocation
 ): Promise<void> {
 ): Promise<void> {
-  const record = await db.get(HttpMediaLocation, where)
+  const record = await db.get(HttpMediaLocationEntity, where)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   Object.assign(record, props)
   Object.assign(record, props)
-  await db.save<HttpMediaLocation>(record)
+  await db.save<HttpMediaLocationEntity>(record)
 }
 }
 
 
 async function updateJoystreamMediaLocationEntityPropertyValues(
 async function updateJoystreamMediaLocationEntityPropertyValues(
@@ -222,17 +265,19 @@ async function updateJoystreamMediaLocationEntityPropertyValues(
   where: IWhereCond,
   where: IWhereCond,
   props: IJoystreamMediaLocation
   props: IJoystreamMediaLocation
 ): Promise<void> {
 ): Promise<void> {
-  const record = await db.get(JoystreamMediaLocation, where)
+  const record = await db.get(JoystreamMediaLocationEntity, where)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   Object.assign(record, props)
   Object.assign(record, props)
-  await db.save<JoystreamMediaLocation>(record)
+  await db.save<JoystreamMediaLocationEntity>(record)
 }
 }
+
 async function updateLanguageEntityPropertyValues(db: DB, where: IWhereCond, props: ILanguage): Promise<void> {
 async function updateLanguageEntityPropertyValues(db: DB, where: IWhereCond, props: ILanguage): Promise<void> {
   const record = await db.get(Language, where)
   const record = await db.get(Language, where)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   if (record === undefined) throw Error(`Entity not found: ${where.where.id}`)
   Object.assign(record, props)
   Object.assign(record, props)
   await db.save<Language>(record)
   await db.save<Language>(record)
 }
 }
+
 async function updateVideoMediaEncodingEntityPropertyValues(
 async function updateVideoMediaEncodingEntityPropertyValues(
   db: DB,
   db: DB,
   where: IWhereCond,
   where: IWhereCond,
@@ -244,6 +289,32 @@ async function updateVideoMediaEncodingEntityPropertyValues(
   await db.save<VideoMediaEncoding>(record)
   await db.save<VideoMediaEncoding>(record)
 }
 }
 
 
+async function updateFeaturedVideoEntityPropertyValues(
+  db: DB,
+  where: IWhereCond,
+  props: IFeaturedVideo,
+  entityIdBeforeTransaction: number
+): Promise<void> {
+  const record = await db.get(FeaturedVideo, { ...where, relations: ['video'] })
+  if (record === undefined) throw Error(`FeaturedVideo entity not found: ${where.where.id}`)
+
+  if (props.video) {
+    const id = getEntityIdFromReferencedField(props.video, entityIdBeforeTransaction)
+    const video = await db.get(Video, { where: { id } })
+    if (!video) throw Error(`Video entity not found: ${id}`)
+
+    // Update old video isFeatured to false
+    record.video.isFeatured = false
+    await db.save<Video>(record.video)
+
+    video.isFeatured = true
+    record.video = video
+
+    await db.save<Video>(video)
+    await db.save<FeaturedVideo>(record)
+  }
+}
+
 export {
 export {
   updateCategoryEntityPropertyValues,
   updateCategoryEntityPropertyValues,
   updateChannelEntityPropertyValues,
   updateChannelEntityPropertyValues,
@@ -257,4 +328,5 @@ export {
   updateVideoMediaEncodingEntityPropertyValues,
   updateVideoMediaEncodingEntityPropertyValues,
   updateLicenseEntityPropertyValues,
   updateLicenseEntityPropertyValues,
   updateMediaLocationEntityPropertyValues,
   updateMediaLocationEntityPropertyValues,
+  updateFeaturedVideoEntityPropertyValues,
 }
 }

+ 69 - 40
query-node/mappings/content-directory/get-or-create.ts

@@ -1,19 +1,20 @@
 import { Channel } from '../../generated/graphql-server/src/modules/channel/channel.model'
 import { Channel } from '../../generated/graphql-server/src/modules/channel/channel.model'
 import { Category } from '../../generated/graphql-server/src/modules/category/category.model'
 import { Category } from '../../generated/graphql-server/src/modules/category/category.model'
-import { KnownLicense } from '../../generated/graphql-server/src/modules/known-license/known-license.model'
-import { UserDefinedLicense } from '../../generated/graphql-server/src/modules/user-defined-license/user-defined-license.model'
-import { JoystreamMediaLocation } from '../../generated/graphql-server/src/modules/joystream-media-location/joystream-media-location.model'
-import { HttpMediaLocation } from '../../generated/graphql-server/src/modules/http-media-location/http-media-location.model'
+import { KnownLicenseEntity } from '../../generated/graphql-server/src/modules/known-license-entity/known-license-entity.model'
+import { UserDefinedLicenseEntity } from '../../generated/graphql-server/src/modules/user-defined-license-entity/user-defined-license-entity.model'
+import { JoystreamMediaLocationEntity } from '../../generated/graphql-server/src/modules/joystream-media-location-entity/joystream-media-location-entity.model'
+import { HttpMediaLocationEntity } from '../../generated/graphql-server/src/modules/http-media-location-entity/http-media-location-entity.model'
 import { VideoMedia } from '../../generated/graphql-server/src/modules/video-media/video-media.model'
 import { VideoMedia } from '../../generated/graphql-server/src/modules/video-media/video-media.model'
 import { Language } from '../../generated/graphql-server/src/modules/language/language.model'
 import { Language } from '../../generated/graphql-server/src/modules/language/language.model'
 import { VideoMediaEncoding } from '../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
 import { VideoMediaEncoding } from '../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
-import { License } from '../../generated/graphql-server/src/modules/license/license.model'
-import { MediaLocation } from '../../generated/graphql-server/src/modules/media-location/media-location.model'
+import { LicenseEntity } from '../../generated/graphql-server/src/modules/license-entity/license-entity.model'
+import { MediaLocationEntity } from '../../generated/graphql-server/src/modules/media-location-entity/media-location-entity.model'
+import { Video } from '../../generated/graphql-server/src/modules/video/video.model'
 import { NextEntityId } from '../../generated/graphql-server/src/modules/next-entity-id/next-entity-id.model'
 import { NextEntityId } from '../../generated/graphql-server/src/modules/next-entity-id/next-entity-id.model'
 
 
 import { decode } from './decode'
 import { decode } from './decode'
 import {
 import {
-  CategoryPropertyNamesWithId,
+  categoryPropertyNamesWithId,
   channelPropertyNamesWithId,
   channelPropertyNamesWithId,
   httpMediaLocationPropertyNamesWithId,
   httpMediaLocationPropertyNamesWithId,
   joystreamMediaLocationPropertyNamesWithId,
   joystreamMediaLocationPropertyNamesWithId,
@@ -39,6 +40,7 @@ import {
   IMediaLocation,
   IMediaLocation,
   IReference,
   IReference,
   IUserDefinedLicense,
   IUserDefinedLicense,
+  IVideo,
   IVideoMedia,
   IVideoMedia,
   IVideoMediaEncoding,
   IVideoMediaEncoding,
 } from '../types'
 } from '../types'
@@ -55,6 +57,7 @@ import {
   createVideoMediaEncoding,
   createVideoMediaEncoding,
   createLicense,
   createLicense,
   createMediaLocation,
   createMediaLocation,
+  createVideo,
 } from './entity/create'
 } from './entity/create'
 
 
 import { DB } from '../../generated/indexer'
 import { DB } from '../../generated/indexer'
@@ -76,7 +79,12 @@ function findEntity(entityId: number, className: string, classEntityMap: ClassEn
   if (newlyCreatedEntities === undefined) throw Error(`Couldn't find '${className}' entities in the classEntityMap`)
   if (newlyCreatedEntities === undefined) throw Error(`Couldn't find '${className}' entities in the classEntityMap`)
   const entity = newlyCreatedEntities.find((e) => e.indexOf === entityId)
   const entity = newlyCreatedEntities.find((e) => e.indexOf === entityId)
   if (!entity) throw Error(`Unknown ${className} entity id: ${entityId}`)
   if (!entity) throw Error(`Unknown ${className} entity id: ${entityId}`)
-  removeInsertedEntity(className, entityId, classEntityMap)
+
+  // Remove the inserted entity from the list
+  classEntityMap.set(
+    className,
+    newlyCreatedEntities.filter((e) => e.entityId !== entityId)
+  )
   return entity
   return entity
 }
 }
 
 
@@ -167,17 +175,17 @@ async function knownLicense(
   classEntityMap: ClassEntityMap,
   classEntityMap: ClassEntityMap,
   knownLicense: IReference,
   knownLicense: IReference,
   nextEntityIdBeforeTransaction: number
   nextEntityIdBeforeTransaction: number
-): Promise<KnownLicense> {
-  let kLicense: KnownLicense | undefined
+): Promise<KnownLicenseEntity> {
+  let kLicense: KnownLicenseEntity | undefined
   const { entityId, existing } = knownLicense
   const { entityId, existing } = knownLicense
   if (existing) {
   if (existing) {
-    kLicense = await db.get(KnownLicense, { where: { id: entityId.toString() } })
+    kLicense = await db.get(KnownLicenseEntity, { where: { id: entityId.toString() } })
     if (!kLicense) throw Error(`KnownLicense entity not found`)
     if (!kLicense) throw Error(`KnownLicense entity not found`)
     return kLicense
     return kLicense
   }
   }
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   // could be created in the transaction
   // could be created in the transaction
-  kLicense = await db.get(KnownLicense, { where: { id } })
+  kLicense = await db.get(KnownLicenseEntity, { where: { id } })
   if (kLicense) return kLicense
   if (kLicense) return kLicense
 
 
   const { properties } = findEntity(entityId, 'KnownLicense', classEntityMap)
   const { properties } = findEntity(entityId, 'KnownLicense', classEntityMap)
@@ -191,17 +199,17 @@ async function userDefinedLicense(
   classEntityMap: ClassEntityMap,
   classEntityMap: ClassEntityMap,
   userDefinedLicense: IReference,
   userDefinedLicense: IReference,
   nextEntityIdBeforeTransaction: number
   nextEntityIdBeforeTransaction: number
-): Promise<UserDefinedLicense> {
-  let udLicense: UserDefinedLicense | undefined
+): Promise<UserDefinedLicenseEntity> {
+  let udLicense: UserDefinedLicenseEntity | undefined
   const { entityId, existing } = userDefinedLicense
   const { entityId, existing } = userDefinedLicense
   if (existing) {
   if (existing) {
-    udLicense = await db.get(UserDefinedLicense, { where: { id: entityId.toString() } })
+    udLicense = await db.get(UserDefinedLicenseEntity, { where: { id: entityId.toString() } })
     if (!udLicense) throw Error(`UserDefinedLicense entity not found`)
     if (!udLicense) throw Error(`UserDefinedLicense entity not found`)
     return udLicense
     return udLicense
   }
   }
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   // could be created in the transaction
   // could be created in the transaction
-  udLicense = await db.get(UserDefinedLicense, {
+  udLicense = await db.get(UserDefinedLicenseEntity, {
     where: { id },
     where: { id },
   })
   })
   if (udLicense) return udLicense
   if (udLicense) return udLicense
@@ -264,7 +272,7 @@ async function category(
   const { properties } = findEntity(entityId, 'Category', classEntityMap)
   const { properties } = findEntity(entityId, 'Category', classEntityMap)
   return await createCategory(
   return await createCategory(
     { db, block, id },
     { db, block, id },
-    decode.setEntityPropertyValues<ICategory>(properties, CategoryPropertyNamesWithId)
+    decode.setEntityPropertyValues<ICategory>(properties, categoryPropertyNamesWithId)
   )
   )
 }
 }
 
 
@@ -273,19 +281,19 @@ async function httpMediaLocation(
   classEntityMap: ClassEntityMap,
   classEntityMap: ClassEntityMap,
   httpMediaLoc: IReference,
   httpMediaLoc: IReference,
   nextEntityIdBeforeTransaction: number
   nextEntityIdBeforeTransaction: number
-): Promise<HttpMediaLocation | undefined> {
-  let loc: HttpMediaLocation | undefined
+): Promise<HttpMediaLocationEntity | undefined> {
+  let loc: HttpMediaLocationEntity | undefined
   const { entityId, existing } = httpMediaLoc
   const { entityId, existing } = httpMediaLoc
 
 
   if (existing) {
   if (existing) {
-    loc = await db.get(HttpMediaLocation, { where: { id: entityId.toString() } })
+    loc = await db.get(HttpMediaLocationEntity, { where: { id: entityId.toString() } })
     if (!loc) throw Error(`HttpMediaLocation entity not found`)
     if (!loc) throw Error(`HttpMediaLocation entity not found`)
     return loc
     return loc
   }
   }
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
 
 
   // could be created in the transaction
   // could be created in the transaction
-  loc = await db.get(HttpMediaLocation, {
+  loc = await db.get(HttpMediaLocationEntity, {
     where: { id },
     where: { id },
   })
   })
   if (loc) return loc
   if (loc) return loc
@@ -302,12 +310,12 @@ async function joystreamMediaLocation(
   classEntityMap: ClassEntityMap,
   classEntityMap: ClassEntityMap,
   joyMediaLoc: IReference,
   joyMediaLoc: IReference,
   nextEntityIdBeforeTransaction: number
   nextEntityIdBeforeTransaction: number
-): Promise<JoystreamMediaLocation | undefined> {
-  let loc: JoystreamMediaLocation | undefined
+): Promise<JoystreamMediaLocationEntity | undefined> {
+  let loc: JoystreamMediaLocationEntity | undefined
   const { entityId, existing } = joyMediaLoc
   const { entityId, existing } = joyMediaLoc
 
 
   if (existing) {
   if (existing) {
-    loc = await db.get(JoystreamMediaLocation, { where: { id: entityId.toString() } })
+    loc = await db.get(JoystreamMediaLocationEntity, { where: { id: entityId.toString() } })
     if (!loc) throw Error(`JoystreamMediaLocation entity not found`)
     if (!loc) throw Error(`JoystreamMediaLocation entity not found`)
     return loc
     return loc
   }
   }
@@ -315,7 +323,7 @@ async function joystreamMediaLocation(
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
 
 
   // could be created in the transaction
   // could be created in the transaction
-  loc = await db.get(JoystreamMediaLocation, {
+  loc = await db.get(JoystreamMediaLocationEntity, {
     where: { id },
     where: { id },
   })
   })
   if (loc) return loc
   if (loc) return loc
@@ -332,19 +340,19 @@ async function license(
   classEntityMap: ClassEntityMap,
   classEntityMap: ClassEntityMap,
   license: IReference,
   license: IReference,
   nextEntityIdBeforeTransaction: number
   nextEntityIdBeforeTransaction: number
-): Promise<License> {
-  let lic: License | undefined
+): Promise<LicenseEntity> {
+  let lic: LicenseEntity | undefined
   const { entityId, existing } = license
   const { entityId, existing } = license
 
 
   if (existing) {
   if (existing) {
-    lic = await db.get(License, { where: { id: entityId.toString() } })
+    lic = await db.get(LicenseEntity, { where: { id: entityId.toString() } })
     if (!lic) throw Error(`License entity not found`)
     if (!lic) throw Error(`License entity not found`)
     return lic
     return lic
   }
   }
 
 
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   // could be created in the transaction
   // could be created in the transaction
-  lic = await db.get(License, { where: { id } })
+  lic = await db.get(LicenseEntity, { where: { id } })
   if (lic) return lic
   if (lic) return lic
 
 
   const { properties } = findEntity(entityId, 'License', classEntityMap)
   const { properties } = findEntity(entityId, 'License', classEntityMap)
@@ -361,21 +369,24 @@ async function mediaLocation(
   classEntityMap: ClassEntityMap,
   classEntityMap: ClassEntityMap,
   location: IReference,
   location: IReference,
   nextEntityIdBeforeTransaction: number
   nextEntityIdBeforeTransaction: number
-): Promise<MediaLocation> {
-  let loc: MediaLocation | undefined
+): Promise<MediaLocationEntity> {
+  let loc: MediaLocationEntity | undefined
   const { entityId, existing } = location
   const { entityId, existing } = location
   if (existing) {
   if (existing) {
-    loc = await db.get(MediaLocation, { where: { id: entityId.toString() } })
+    loc = await db.get(MediaLocationEntity, { where: { id: entityId.toString() } })
     if (!loc) throw Error(`MediaLocation entity not found`)
     if (!loc) throw Error(`MediaLocation entity not found`)
     return loc
     return loc
   }
   }
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
   const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
 
 
   // could be created in the transaction
   // could be created in the transaction
-  loc = await db.get(MediaLocation, {
+  loc = await db.get(MediaLocationEntity, {
     where: { id },
     where: { id },
+    relations: ['httpMediaLocation', 'joystreamMediaLocation'],
   })
   })
-  if (loc) return loc
+  if (loc) {
+    return loc
+  }
 
 
   const { properties } = findEntity(entityId, 'MediaLocation', classEntityMap)
   const { properties } = findEntity(entityId, 'MediaLocation', classEntityMap)
   return await createMediaLocation(
   return await createMediaLocation(
@@ -386,12 +397,29 @@ async function mediaLocation(
   )
   )
 }
 }
 
 
-function removeInsertedEntity(key: string, insertedEntityId: number, classEntityMap: ClassEntityMap) {
-  const newlyCreatedEntities = classEntityMap.get(key)
-  // Remove the inserted entity from the list
-  classEntityMap.set(
-    key,
-    newlyCreatedEntities!.filter((e) => e.entityId !== insertedEntityId)
+async function video(
+  { db, block }: IDBBlockId,
+  classEntityMap: ClassEntityMap,
+  video: IReference,
+  nextEntityIdBeforeTransaction: number
+): Promise<Video> {
+  const { existing, entityId } = video
+  if (existing) {
+    const v = await db.get(Video, { where: { id: entityId.toString() } })
+    if (!v) throw Error(`Video not found. id ${entityId}`)
+    return v
+  }
+
+  const id = generateEntityIdFromIndex(nextEntityIdBeforeTransaction + entityId)
+  const v = await db.get(Video, { where: { id } })
+  if (v) return v
+
+  const { properties } = findEntity(entityId, 'MediaVideo', classEntityMap)
+  return await createVideo(
+    { db, block, id },
+    classEntityMap,
+    decode.setEntityPropertyValues<IVideo>(properties, videoPropertyNamesWithId),
+    nextEntityIdBeforeTransaction
   )
   )
 }
 }
 
 
@@ -408,4 +436,5 @@ export const getOrCreate = {
   license,
   license,
   mediaLocation,
   mediaLocation,
   nextEntityId,
   nextEntityId,
+  video,
 }
 }

+ 1 - 1
query-node/mappings/content-directory/mapping.ts

@@ -4,4 +4,4 @@ export {
   contentDirectory_EntityCreated,
   contentDirectory_EntityCreated,
   contentDirectory_EntityPropertyValuesUpdated,
   contentDirectory_EntityPropertyValuesUpdated,
 } from './entity'
 } from './entity'
-export { contentDirectory_TransactionCompleted } from './transaction'
+export { contentDirectory_TransactionCompleted, contentDirectory_TransactionFailed } from './transaction'

+ 45 - 21
query-node/mappings/content-directory/transaction.ts

@@ -7,11 +7,13 @@ import { ClassEntity } from '../../generated/graphql-server/src/modules/class-en
 import { decode } from './decode'
 import { decode } from './decode'
 import {
 import {
   ClassEntityMap,
   ClassEntityMap,
+  IBatchOperation,
   ICategory,
   ICategory,
   IChannel,
   IChannel,
   ICreateEntityOperation,
   ICreateEntityOperation,
   IDBBlockId,
   IDBBlockId,
   IEntity,
   IEntity,
+  IFeaturedVideo,
   IHttpMediaLocation,
   IHttpMediaLocation,
   IJoystreamMediaLocation,
   IJoystreamMediaLocation,
   IKnownLicense,
   IKnownLicense,
@@ -25,7 +27,7 @@ import {
   IWhereCond,
   IWhereCond,
 } from '../types'
 } from '../types'
 import {
 import {
-  CategoryPropertyNamesWithId,
+  categoryPropertyNamesWithId,
   channelPropertyNamesWithId,
   channelPropertyNamesWithId,
   knownLicensePropertyNamesWIthId,
   knownLicensePropertyNamesWIthId,
   userDefinedLicensePropertyNamesWithId,
   userDefinedLicensePropertyNamesWithId,
@@ -38,6 +40,7 @@ import {
   ContentDirectoryKnownClasses,
   ContentDirectoryKnownClasses,
   licensePropertyNamesWithId,
   licensePropertyNamesWithId,
   mediaLocationPropertyNamesWithId,
   mediaLocationPropertyNamesWithId,
+  featuredVideoPropertyNamesWithId,
 } from './content-dir-consts'
 } from './content-dir-consts'
 import {
 import {
   updateCategoryEntityPropertyValues,
   updateCategoryEntityPropertyValues,
@@ -52,6 +55,7 @@ import {
   updateVideoMediaEncodingEntityPropertyValues,
   updateVideoMediaEncodingEntityPropertyValues,
   updateLicenseEntityPropertyValues,
   updateLicenseEntityPropertyValues,
   updateMediaLocationEntityPropertyValues,
   updateMediaLocationEntityPropertyValues,
+  updateFeaturedVideoEntityPropertyValues,
 } from './entity/update'
 } from './entity/update'
 
 
 import {
 import {
@@ -69,6 +73,7 @@ import {
   createLicense,
   createLicense,
   createMediaLocation,
   createMediaLocation,
   createBlockOrGetFromDatabase,
   createBlockOrGetFromDatabase,
+  createFeaturedVideo,
 } from './entity/create'
 } from './entity/create'
 import { getOrCreate } from './get-or-create'
 import { getOrCreate } from './get-or-create'
 
 
@@ -81,33 +86,35 @@ async function getNextEntityId(db: DB): Promise<number> {
   return e.nextId
   return e.nextId
 }
 }
 
 
+// eslint-disable-next-line @typescript-eslint/naming-convention
+export async function contentDirectory_TransactionFailed(db: DB, event: SubstrateEvent): Promise<void> {
+  debug(`TransactionFailed event: ${JSON.stringify(event)}`)
+
+  const failedOperationIndex = event.params[1].value as number
+  const operations = decode.getOperations(event)
+
+  const successfulOperations = operations.toArray().slice(0, failedOperationIndex)
+  if (!successfulOperations.length) return // No succesfull operations
+
+  await applyOperations(decode.getOperationsByTypes(successfulOperations), db, event)
+}
+
 // eslint-disable-next-line @typescript-eslint/naming-convention
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function contentDirectory_TransactionCompleted(db: DB, event: SubstrateEvent): Promise<void> {
 export async function contentDirectory_TransactionCompleted(db: DB, event: SubstrateEvent): Promise<void> {
   debug(`TransactionCompleted event: ${JSON.stringify(event)}`)
   debug(`TransactionCompleted event: ${JSON.stringify(event)}`)
 
 
-  const { extrinsic, blockNumber: block } = event
-  if (!extrinsic) {
-    throw Error(`No extrinsic found for the event: ${event.id}`)
-  }
-
-  const { 1: operations } = extrinsic.args
-  if (operations.name.toString() !== 'operations') {
-    throw Error(`Could not found 'operations' in the extrinsic.args[1]`)
-  }
+  const operations = decode.getOperations(event)
 
 
-  const {
-    addSchemaSupportToEntityOperations,
-    createEntityOperations,
-    updatePropertyValuesOperations,
-  } = decode.getOperations(event)
+  await applyOperations(decode.getOperationsByTypes(operations), db, event)
+}
 
 
+async function applyOperations(operations: IBatchOperation, db: DB, event: SubstrateEvent) {
+  const { addSchemaSupportToEntityOperations, createEntityOperations, updatePropertyValuesOperations } = operations
   // Create entities before adding schema support
   // Create entities before adding schema support
   // We need this to know which entity belongs to which class(we will need to know to update/create
   // We need this to know which entity belongs to which class(we will need to know to update/create
   // Channel, Video etc.). For example if there is a property update operation there is no class id
   // Channel, Video etc.). For example if there is a property update operation there is no class id
-  await batchCreateClassEntities(db, block, createEntityOperations)
-
-  await batchAddSchemaSupportToEntity(db, createEntityOperations, addSchemaSupportToEntityOperations, block)
-
+  await batchCreateClassEntities(db, event.blockNumber, createEntityOperations)
+  await batchAddSchemaSupportToEntity(db, createEntityOperations, addSchemaSupportToEntityOperations, event.blockNumber)
   await batchUpdatePropertyValue(db, createEntityOperations, updatePropertyValuesOperations)
   await batchUpdatePropertyValue(db, createEntityOperations, updatePropertyValuesOperations)
 }
 }
 
 
@@ -167,7 +174,7 @@ async function batchAddSchemaSupportToEntity(
 
 
       switch (className) {
       switch (className) {
         case ContentDirectoryKnownClasses.CATEGORY:
         case ContentDirectoryKnownClasses.CATEGORY:
-          await createCategory(arg, decode.setEntityPropertyValues<ICategory>(properties, CategoryPropertyNamesWithId))
+          await createCategory(arg, decode.setEntityPropertyValues<ICategory>(properties, categoryPropertyNamesWithId))
           break
           break
 
 
         case ContentDirectoryKnownClasses.CHANNEL:
         case ContentDirectoryKnownClasses.CHANNEL:
@@ -256,6 +263,15 @@ async function batchAddSchemaSupportToEntity(
           )
           )
           break
           break
 
 
+        case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
+          await createFeaturedVideo(
+            arg,
+            classEntityMap,
+            decode.setEntityPropertyValues<IFeaturedVideo>(properties, featuredVideoPropertyNamesWithId),
+            nextEntityIdBeforeTransaction
+          )
+          break
+
         default:
         default:
           console.log(`Unknown class name: ${className}`)
           console.log(`Unknown class name: ${className}`)
           break
           break
@@ -299,7 +315,7 @@ async function batchUpdatePropertyValue(db: DB, createEntityOperations: ICreateE
         await updateCategoryEntityPropertyValues(
         await updateCategoryEntityPropertyValues(
           db,
           db,
           where,
           where,
-          decode.setEntityPropertyValues<ICategory>(properties, CategoryPropertyNamesWithId)
+          decode.setEntityPropertyValues<ICategory>(properties, categoryPropertyNamesWithId)
         )
         )
         break
         break
 
 
@@ -384,6 +400,14 @@ async function batchUpdatePropertyValue(db: DB, createEntityOperations: ICreateE
           entityIdBeforeTransaction
           entityIdBeforeTransaction
         )
         )
         break
         break
+      case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
+        await updateFeaturedVideoEntityPropertyValues(
+          db,
+          where,
+          decode.setEntityPropertyValues<IFeaturedVideo>(properties, featuredVideoPropertyNamesWithId),
+          entityIdBeforeTransaction
+        )
+        break
 
 
       default:
       default:
         console.log(`Unknown class name: ${className}`)
         console.log(`Unknown class name: ${className}`)

+ 19 - 9
query-node/mappings/types.ts

@@ -40,12 +40,12 @@ export interface IReference {
 }
 }
 
 
 export interface IChannel {
 export interface IChannel {
-  title: string
+  handle: string
   description: string
   description: string
-  coverPhotoURL: string
-  avatarPhotoURL: string
+  coverPhotoUrl: string
+  avatarPhotoUrl: string
   isPublic: boolean
   isPublic: boolean
-  isCurated: boolean
+  isCurated?: boolean
   language?: IReference
   language?: IReference
 }
 }
 
 
@@ -100,14 +100,14 @@ export interface IVideo {
   description: string
   description: string
   duration: number
   duration: number
   skippableIntroDuration?: number
   skippableIntroDuration?: number
-  thumbnailURL: string
+  thumbnailUrl: string
   language?: IReference
   language?: IReference
   // referenced entity's id
   // referenced entity's id
   media?: IReference
   media?: IReference
   hasMarketing?: boolean
   hasMarketing?: boolean
   publishedBeforeJoystream?: number
   publishedBeforeJoystream?: number
   isPublic: boolean
   isPublic: boolean
-  isCurated: boolean
+  isCurated?: boolean
   isExplicit: boolean
   isExplicit: boolean
   license?: IReference
   license?: IReference
 }
 }
@@ -115,6 +115,7 @@ export interface IVideo {
 export interface ILicense {
 export interface ILicense {
   knownLicense?: IReference
   knownLicense?: IReference
   userDefinedLicense?: IReference
   userDefinedLicense?: IReference
+  attribution?: string
 }
 }
 
 
 export interface IMediaLocation {
 export interface IMediaLocation {
@@ -170,9 +171,14 @@ export interface IEntity {
   properties: IProperty[]
   properties: IProperty[]
 }
 }
 
 
-export interface IPropertyIdWithName {
-  // propertyId - property name
-  [propertyId: string]: string
+export interface IPropertyDef {
+  name: string
+  type: string
+  required: boolean
+}
+
+export interface IPropertyWithId {
+  [inClassIndex: string]: IPropertyDef
 }
 }
 
 
 export interface IWhereCond {
 export interface IWhereCond {
@@ -192,3 +198,7 @@ export interface IDBBlockId {
 }
 }
 
 
 export type ClassEntityMap = Map<string, IEntity[]>
 export type ClassEntityMap = Map<string, IEntity[]>
+
+export interface IFeaturedVideo {
+  video?: IReference
+}

+ 6 - 7
query-node/package.json

@@ -6,17 +6,16 @@
 		"build": "./build.sh",
 		"build": "./build.sh",
 		"test": "echo \"Error: no test specified\" && exit 1",
 		"test": "echo \"Error: no test specified\" && exit 1",
 		"clean": "rm -rf ./generated",
 		"clean": "rm -rf ./generated",
-		"processor:start": "(cd ./generated/indexer && yarn && DEBUG=${DEBUG} yarn start:processor)",
-		"indexer:start": "(cd ./generated/indexer && yarn && DEBUG=${DEBUG} yarn start:indexer)",
+		"processor:start": "./processor-start.sh",
+		"indexer:start": "(cd ./generated/indexer && yarn && DEBUG=${DEBUG} yarn start:indexer --env ../../../.env)",
 		"server:start:dev": "(cd ./generated/graphql-server && yarn start:dev)",
 		"server:start:dev": "(cd ./generated/graphql-server && yarn start:dev)",
 		"server:start:prod": "(cd ./generated/graphql-server && yarn start:prod)",
 		"server:start:prod": "(cd ./generated/graphql-server && yarn start:prod)",
 		"configure": "(cd ./generated/graphql-server && yarn config:dev)",
 		"configure": "(cd ./generated/graphql-server && yarn config:dev)",
-		"db:up": "docker-compose up -d db",
+		"db:up": "(cd ../ && docker-compose up -d db)",
 		"db:drop": "(cd ./generated/graphql-server && yarn db:drop)",
 		"db:drop": "(cd ./generated/graphql-server && yarn db:drop)",
+		"db:migrate": "./db-migrate.sh",
 		"db:schema:migrate": "(cd ./generated/graphql-server && yarn db:create && yarn db:sync && yarn db:migrate)",
 		"db:schema:migrate": "(cd ./generated/graphql-server && yarn db:create && yarn db:sync && yarn db:migrate)",
 		"db:indexer:migrate": "(cd ./generated/indexer && yarn db:migrate)",
 		"db:indexer:migrate": "(cd ./generated/indexer && yarn db:migrate)",
-		"db:migrate": "yarn db:schema:migrate && yarn db:indexer:migrate",
-		"codegen:all": "yarn hydra-cli codegen --no-install && cp indexer-tsconfig.json generated/indexer/tsconfig.json",
 		"codegen:indexer": "yarn hydra-cli codegen --no-install --no-graphql && cp indexer-tsconfig.json generated/indexer/tsconfig.json",
 		"codegen:indexer": "yarn hydra-cli codegen --no-install --no-graphql && cp indexer-tsconfig.json generated/indexer/tsconfig.json",
 		"codegen:server": "yarn hydra-cli codegen --no-install --no-indexer",
 		"codegen:server": "yarn hydra-cli codegen --no-install --no-indexer",
 		"cd-classes": "ts-node scripts/get-class-id-and-name.ts"
 		"cd-classes": "ts-node scripts/get-class-id-and-name.ts"
@@ -24,10 +23,10 @@
 	"author": "",
 	"author": "",
 	"license": "ISC",
 	"license": "ISC",
 	"devDependencies": {
 	"devDependencies": {
-		"@dzlzv/hydra-cli": "^0.0.20"
+		"@dzlzv/hydra-cli": "^0.0.24"
 	},
 	},
 	"dependencies": {
 	"dependencies": {
-		"@dzlzv/hydra-indexer-lib": "^0.0.19-legacy.1.26.1",
+		"@dzlzv/hydra-indexer-lib": "^0.0.21-legacy.1.26.1",
 		"@joystream/types": "^0.14.0",
 		"@joystream/types": "^0.14.0",
 		"@types/bn.js": "^4.11.6",
 		"@types/bn.js": "^4.11.6",
 		"@types/debug": "^4.1.5",
 		"@types/debug": "^4.1.5",

+ 15 - 0
query-node/processor-start.sh

@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+set -e
+
+SCRIPT_PATH="$(dirname "${BASH_SOURCE[0]}")"
+cd $SCRIPT_PATH
+
+# set +a
+# . ../.env
+# export TYPEORM_DATABASE=${PROCESSOR_DB_NAME}
+
+export TYPEORM_DATABASE=${PROCESSOR_DB_NAME:=query_node_processor}
+
+cd ./generated/indexer
+yarn
+DEBUG=${DEBUG} yarn start:processor --env ../../../.env

+ 21 - 10
query-node/run-tests.sh

@@ -4,31 +4,42 @@ set -e
 SCRIPT_PATH="$(dirname "${BASH_SOURCE[0]}")"
 SCRIPT_PATH="$(dirname "${BASH_SOURCE[0]}")"
 cd $SCRIPT_PATH
 cd $SCRIPT_PATH
 
 
+# Only run codegen if no generated files found
+[ ! -d "generated/" ] && yarn build
+
+# Make sure typeorm is available.. it get removed when yarn is run again
+# typeorm commandline is used by db:migrate step below.
+ln -s ../../../../../node_modules/typeorm/cli.js generated/graphql-server/node_modules/.bin/typeorm || :
+
+set -a
+. ../.env
+set +a
+
+# Clean start
+docker-compose down -v
+
 function cleanup() {
 function cleanup() {
     # Show tail end of logs for the processor and indexer containers to
     # Show tail end of logs for the processor and indexer containers to
     # see any possible errors
     # see any possible errors
     (echo "## Processor Logs ##" && docker logs joystream_processor_1 --tail 50) || :
     (echo "## Processor Logs ##" && docker logs joystream_processor_1 --tail 50) || :
     (echo "## Indexer Logs ##" && docker logs joystream_indexer_1 --tail 50) || :
     (echo "## Indexer Logs ##" && docker logs joystream_indexer_1 --tail 50) || :
+    (echo "## Indexer API Gateway Logs ##" && docker logs joystream_indexer-api-gateway_1 --tail 50) || :
     docker-compose down -v
     docker-compose down -v
 }
 }
 
 
 trap cleanup EXIT
 trap cleanup EXIT
 
 
+# We expect docker image to be started by test runner
 export WS_PROVIDER_ENDPOINT_URI=ws://joystream-node:9944/
 export WS_PROVIDER_ENDPOINT_URI=ws://joystream-node:9944/
 
 
-# Only run codegen if no generated files found
-[ ! -d "generated/" ] && yarn build
-
-# Make sure typeorm is available.. it get removed again when yarn is run again
-# typeorm commandline is used by db:migrate step below.
-ln -s ../../../../../node_modules/typeorm/cli.js generated/graphql-server/node_modules/.bin/typeorm || :
+# Bring up db
+docker-compose up -d db
 
 
-# clean start
-docker-compose down -v
+# Migrate the databases
+yarn workspace query-node-root db:migrate
 
 
-docker-compose up -d db
-yarn db:migrate
 docker-compose up -d graphql-server
 docker-compose up -d graphql-server
+
 # Starting up processor will bring up all services it depends on
 # Starting up processor will bring up all services it depends on
 docker-compose up -d processor
 docker-compose up -d processor
 
 

+ 80 - 32
query-node/schema.graphql

@@ -18,7 +18,7 @@ type Member @entity {
   id: ID!
   id: ID!
 
 
   "The unique handle chosen by member"
   "The unique handle chosen by member"
-  handle: String @unique @fulltext(query: "handles")
+  handle: String @unique @fulltext(query: "membersByHandle")
 
 
   "A Url to member's Avatar image"
   "A Url to member's Avatar image"
   avatarUri: String
   avatarUri: String
@@ -84,16 +84,16 @@ type Channel @entity {
   # owner: Member!
   # owner: Member!
 
 
   "The title of the Channel"
   "The title of the Channel"
-  title: String! @fulltext(query: "titles")
+  handle: String! @fulltext(query: "search")
 
 
   "The description of a Channel"
   "The description of a Channel"
   description: String!
   description: String!
 
 
   "Url for Channel's cover (background) photo. Recommended ratio: 16:9."
   "Url for Channel's cover (background) photo. Recommended ratio: 16:9."
-  coverPhotoURL: String!
+  coverPhotoUrl: String
 
 
   "Channel's avatar photo."
   "Channel's avatar photo."
-  avatarPhotoURL: String!
+  avatarPhotoUrl: String
 
 
   "Flag signaling whether a channel is public."
   "Flag signaling whether a channel is public."
   isPublic: Boolean!
   isPublic: Boolean!
@@ -102,7 +102,7 @@ type Channel @entity {
   isCurated: Boolean!
   isCurated: Boolean!
 
 
   "The primary langauge of the channel's content"
   "The primary langauge of the channel's content"
-  language: Language!
+  language: Language
 
 
   videos: [Video!] @derivedFrom(field: "channel")
   videos: [Video!] @derivedFrom(field: "channel")
 
 
@@ -114,7 +114,7 @@ type Category @entity {
   id: ID!
   id: ID!
 
 
   "The name of the category"
   "The name of the category"
-  name: String! @unique @fulltext(query: "names")
+  name: String! @unique @fulltext(query: "categoriesByName")
 
 
   "The description of the category"
   "The description of the category"
   description: String
   description: String
@@ -134,7 +134,7 @@ type VideoMediaEncoding @entity {
   happenedIn: Block!
   happenedIn: Block!
 }
 }
 
 
-type KnownLicense @entity {
+type KnownLicenseEntity @entity {
   "Runtime entity identifier (EntityId)"
   "Runtime entity identifier (EntityId)"
   id: ID!
   id: ID!
 
 
@@ -153,7 +153,7 @@ type KnownLicense @entity {
   happenedIn: Block!
   happenedIn: Block!
 }
 }
 
 
-type UserDefinedLicense @entity {
+type UserDefinedLicenseEntity @entity {
   "Runtime entity identifier (EntityId)"
   "Runtime entity identifier (EntityId)"
   id: ID!
   id: ID!
 
 
@@ -163,39 +163,24 @@ type UserDefinedLicense @entity {
   happenedIn: Block!
   happenedIn: Block!
 }
 }
 
 
-type License @entity {
-  "Runtime entity identifier (EntityId)"
-  id: ID!
-
-  # One of the following field will be non-null
-
-  "Reference to a known license"
-  knownLicense: KnownLicense
-
-  "Reference to user-defined license"
-  userdefinedLicense: UserDefinedLicense
-
-  happenedIn: Block!
-}
-
-type MediaLocation @entity {
+type MediaLocationEntity @entity {
   "Runtime entity identifier (EntityId)"
   "Runtime entity identifier (EntityId)"
   id: ID!
   id: ID!
 
 
   # One of the following field will be non-null
   # One of the following field will be non-null
 
 
   "A reference to HttpMediaLocation"
   "A reference to HttpMediaLocation"
-  httpMediaLocation: HttpMediaLocation
+  httpMediaLocation: HttpMediaLocationEntity
 
 
   "A reference to JoystreamMediaLocation"
   "A reference to JoystreamMediaLocation"
-  joystreamMediaLocation: JoystreamMediaLocation
+  joystreamMediaLocation: JoystreamMediaLocationEntity
 
 
-  videoMedia: VideoMedia @derivedFrom(field: "location")
+  videoMedia: VideoMedia @derivedFrom(field: "locationEntity")
 
 
   happenedIn: Block!
   happenedIn: Block!
 }
 }
 
 
-type JoystreamMediaLocation @entity {
+type JoystreamMediaLocationEntity @entity {
   "Runtime entity identifier (EntityId)"
   "Runtime entity identifier (EntityId)"
   id: ID!
   id: ID!
 
 
@@ -205,7 +190,7 @@ type JoystreamMediaLocation @entity {
   happenedIn: Block!
   happenedIn: Block!
 }
 }
 
 
-type HttpMediaLocation @entity {
+type HttpMediaLocationEntity @entity {
   "Runtime entity identifier (EntityId)"
   "Runtime entity identifier (EntityId)"
   id: ID!
   id: ID!
 
 
@@ -239,6 +224,8 @@ type VideoMedia @entity {
   "Location of the video media object"
   "Location of the video media object"
   location: MediaLocation!
   location: MediaLocation!
 
 
+  locationEntity: MediaLocationEntity
+
   happenedIn: Block!
   happenedIn: Block!
 }
 }
 
 
@@ -253,7 +240,7 @@ type Video @entity {
   category: Category!
   category: Category!
 
 
   "The title of the video"
   "The title of the video"
-  title: String! @fulltext(query: "titles")
+  title: String! @fulltext(query: "search")
 
 
   "The description of the Video"
   "The description of the Video"
   description: String!
   description: String!
@@ -265,7 +252,7 @@ type Video @entity {
   skippableIntroDuration: Int
   skippableIntroDuration: Int
 
 
   "Video thumbnail url (recommended ratio: 16:9)"
   "Video thumbnail url (recommended ratio: 16:9)"
-  thumbnailURL: String!
+  thumbnailUrl: String!
 
 
   "Video's main langauge"
   "Video's main langauge"
   language: Language
   language: Language
@@ -288,7 +275,68 @@ type Video @entity {
   "Whether the Video contains explicit material."
   "Whether the Video contains explicit material."
   isExplicit: Boolean!
   isExplicit: Boolean!
 
 
-  license: License!
+  license: LicenseEntity!
+
+  happenedIn: Block!
+
+  "Is video featured or not"
+  isFeatured: Boolean!
+
+  featured: FeaturedVideo @derivedFrom(field: "video")
+}
+
+type JoystreamMediaLocation @variant {
+  "Id of the data object in the Joystream runtime dataDirectory module"
+  dataObjectId: String!
+}
+
+type HttpMediaLocation @variant {
+  "The http url pointing to the media"
+  url: String!
+
+  "The port to use when connecting to the http url (defaults to 80)"
+  port: Int
+}
+
+union MediaLocation = HttpMediaLocation | JoystreamMediaLocation
+
+type KnownLicense @variant {
+  "Short, commonly recognized code of the licence (ie. CC_BY_SA)"
+  code: String!
+
+  "Full, descriptive name of the license (ie. Creative Commons - Attribution-NonCommercial-NoDerivs)"
+  name: String
+
+  "Short description of the license conditions"
+  description: String
+
+  "An url pointing to full license content"
+  url: String
+}
+
+type UserDefinedLicense @variant {
+  "Custom license content"
+  content: String!
+}
+
+union License = KnownLicense | UserDefinedLicense
+
+type LicenseEntity @entity {
+  "Runtime entity identifier (EntityId)"
+  id: ID!
+
+  type: License!
+
+  "Attribution (if required by the license)"
+  attribution: String
 
 
   happenedIn: Block!
   happenedIn: Block!
 }
 }
+
+type FeaturedVideo @entity {
+  "Runtime entity identifier (EntityId)"
+  id: ID!
+
+  "Reference to a video"
+  video: Video!
+}

+ 0 - 974
query-node/typedefs.json

@@ -1,974 +0,0 @@
-{
-    "Credential": "u64",
-    "CredentialSet": "BTreeSet<Credential>",
-    "BlockAndTime": {
-        "block": "u32",
-        "time": "u64"
-    },
-    "ThreadId": "u64",
-    "PostId": "u64",
-    "InputValidationLengthConstraint": {
-        "min": "u16",
-        "max_min_diff": "u16"
-    },
-    "WorkingGroup": {
-        "_enum": [
-            "Storage",
-            "Content"
-        ]
-    },
-    "SlashingTerms": {
-        "_enum": {
-            "Unslashable": "Null",
-            "Slashable": "SlashableTerms"
-        }
-    },
-    "SlashableTerms": {
-        "max_count": "u16",
-        "max_percent_pts_per_time": "u16"
-    },
-    "MemoText": "Text",
-    "Address": "AccountId",
-    "LookupSource": "AccountId",
-    "EntryMethod": {
-        "_enum": {
-            "Paid": "u64",
-            "Screening": "AccountId",
-            "Genesis": "Null"
-        }
-    },
-    "MemberId": "u64",
-    "PaidTermId": "u64",
-    "SubscriptionId": "u64",
-    "Membership": {
-        "handle": "Text",
-        "avatar_uri": "Text",
-        "about": "Text",
-        "registered_at_block": "u32",
-        "registered_at_time": "u64",
-        "entry": "EntryMethod",
-        "suspended": "bool",
-        "subscription": "Option<SubscriptionId>",
-        "root_account": "GenericAccountId",
-        "controller_account": "GenericAccountId"
-    },
-    "PaidMembershipTerms": {
-        "fee": "u128",
-        "text": "Text"
-    },
-    "ActorId": "u64",
-    "ElectionStage": {
-        "_enum": {
-            "Announcing": "u32",
-            "Voting": "u32",
-            "Revealing": "u32"
-        }
-    },
-    "ElectionStake": {
-        "new": "u128",
-        "transferred": "u128"
-    },
-    "SealedVote": {
-        "voter": "GenericAccountId",
-        "commitment": "Hash",
-        "stake": "ElectionStake",
-        "vote": "Option<GenericAccountId>"
-    },
-    "TransferableStake": {
-        "seat": "u128",
-        "backing": "u128"
-    },
-    "ElectionParameters": {
-        "announcing_period": "u32",
-        "voting_period": "u32",
-        "revealing_period": "u32",
-        "council_size": "u32",
-        "candidacy_limit": "u32",
-        "new_term_duration": "u32",
-        "min_council_stake": "u128",
-        "min_voting_stake": "u128"
-    },
-    "Seat": {
-        "member": "GenericAccountId",
-        "stake": "u128",
-        "backers": "Backers"
-    },
-    "Seats": "Vec<Seat>",
-    "Backer": {
-        "member": "GenericAccountId",
-        "stake": "u128"
-    },
-    "Backers": "Vec<Backer>",
-    "RoleParameters": {
-        "min_stake": "u128",
-        "min_actors": "u32",
-        "max_actors": "u32",
-        "reward": "u128",
-        "reward_period": "u32",
-        "bonding_period": "u32",
-        "unbonding_period": "u32",
-        "min_service_period": "u32",
-        "startup_grace_period": "u32",
-        "entry_request_fee": "u128"
-    },
-    "PostTextChange": {
-        "expired_at": "BlockAndTime",
-        "text": "Text"
-    },
-    "ModerationAction": {
-        "moderated_at": "BlockAndTime",
-        "moderator_id": "GenericAccountId",
-        "rationale": "Text"
-    },
-    "ChildPositionInParentCategory": {
-        "parent_id": "CategoryId",
-        "child_nr_in_parent_category": "u32"
-    },
-    "CategoryId": "u64",
-    "Category": {
-        "id": "CategoryId",
-        "title": "Text",
-        "description": "Text",
-        "created_at": "BlockAndTime",
-        "deleted": "bool",
-        "archived": "bool",
-        "num_direct_subcategories": "u32",
-        "num_direct_unmoderated_threads": "u32",
-        "num_direct_moderated_threads": "u32",
-        "position_in_parent_category": "Option<ChildPositionInParentCategory>",
-        "moderator_id": "GenericAccountId"
-    },
-    "Thread": {
-        "id": "ThreadId",
-        "title": "Text",
-        "category_id": "CategoryId",
-        "nr_in_category": "u32",
-        "moderation": "Option<ModerationAction>",
-        "num_unmoderated_posts": "u32",
-        "num_moderated_posts": "u32",
-        "created_at": "BlockAndTime",
-        "author_id": "GenericAccountId"
-    },
-    "Post": {
-        "id": "PostId",
-        "thread_id": "ThreadId",
-        "nr_in_thread": "u32",
-        "current_text": "Text",
-        "moderation": "Option<ModerationAction>",
-        "text_change_history": "Vec<PostTextChange>",
-        "created_at": "BlockAndTime",
-        "author_id": "GenericAccountId"
-    },
-    "ReplyId": "u64",
-    "Reply": {
-        "owner": "GenericAccountId",
-        "thread_id": "ThreadId",
-        "text": "Text",
-        "moderation": "Option<ModerationAction>"
-    },
-    "StakeId": "u64",
-    "Stake": {
-        "created": "u32",
-        "staking_status": "StakingStatus"
-    },
-    "StakingStatus": {
-        "_enum": {
-            "NotStaked": "Null",
-            "Staked": "Staked"
-        }
-    },
-    "Staked": {
-        "staked_amount": "u128",
-        "staked_status": "StakedStatus",
-        "next_slash_id": "u64",
-        "ongoing_slashes": "BTreeMap<u64,Slash>"
-    },
-    "StakedStatus": {
-        "_enum": {
-            "Normal": "Null",
-            "Unstaking": "Unstaking"
-        }
-    },
-    "Unstaking": {
-        "started_at_block": "u32",
-        "is_active": "bool",
-        "blocks_remaining_in_active_period_for_unstaking": "u32"
-    },
-    "Slash": {
-        "started_at_block": "u32",
-        "is_active": "bool",
-        "blocks_remaining_in_active_period_for_slashing": "u32",
-        "slash_amount": "u128"
-    },
-    "MintId": "u64",
-    "Mint": {
-        "capacity": "u128",
-        "next_adjustment": "Option<NextAdjustment>",
-        "created_at": "u32",
-        "total_minted": "u128"
-    },
-    "MintBalanceOf": "u128",
-    "BalanceOfMint": "u128",
-    "NextAdjustment": {
-        "adjustment": "AdjustOnInterval",
-        "at_block": "u32"
-    },
-    "AdjustOnInterval": {
-        "block_interval": "u32",
-        "adjustment_type": "AdjustCapacityBy"
-    },
-    "AdjustCapacityBy": {
-        "_enum": {
-            "Setting": "u128",
-            "Adding": "u128",
-            "Reducing": "u128"
-        }
-    },
-    "RecipientId": "u64",
-    "RewardRelationshipId": "u64",
-    "Recipient": {
-        "total_reward_received": "u128",
-        "total_reward_missed": "u128"
-    },
-    "RewardRelationship": {
-        "recipient": "RecipientId",
-        "mint_id": "MintId",
-        "account": "GenericAccountId",
-        "amount_per_payout": "u128",
-        "next_payment_at_block": "Option<u32>",
-        "payout_interval": "Option<u32>",
-        "total_reward_received": "u128",
-        "total_reward_missed": "u128"
-    },
-    "ApplicationId": "u64",
-    "OpeningId": "u64",
-    "Application": {
-        "opening_id": "OpeningId",
-        "application_index_in_opening": "u32",
-        "add_to_opening_in_block": "u32",
-        "active_role_staking_id": "Option<StakeId>",
-        "active_application_staking_id": "Option<StakeId>",
-        "stage": "ApplicationStage",
-        "human_readable_text": "Text"
-    },
-    "ApplicationStage": {
-        "_enum": {
-            "Active": "Null",
-            "Unstaking": "UnstakingApplicationStage",
-            "Inactive": "InactiveApplicationStage"
-        }
-    },
-    "ActivateOpeningAt": {
-        "_enum": {
-            "CurrentBlock": "Null",
-            "ExactBlock": "u32"
-        }
-    },
-    "ApplicationRationingPolicy": {
-        "max_active_applicants": "u32"
-    },
-    "OpeningStage": {
-        "_enum": {
-            "WaitingToBegin": "WaitingToBeingOpeningStageVariant",
-            "Active": "ActiveOpeningStageVariant"
-        }
-    },
-    "StakingPolicy": {
-        "amount": "u128",
-        "amount_mode": "StakingAmountLimitMode",
-        "crowded_out_unstaking_period_length": "Option<u32>",
-        "review_period_expired_unstaking_period_length": "Option<u32>"
-    },
-    "Opening": {
-        "created": "u32",
-        "stage": "OpeningStage",
-        "max_review_period_length": "u32",
-        "application_rationing_policy": "Option<ApplicationRationingPolicy>",
-        "application_staking_policy": "Option<StakingPolicy>",
-        "role_staking_policy": "Option<StakingPolicy>",
-        "human_readable_text": "Text"
-    },
-    "WaitingToBeingOpeningStageVariant": {
-        "begins_at_block": "u32"
-    },
-    "ActiveOpeningStageVariant": {
-        "stage": "ActiveOpeningStage",
-        "applications_added": "Vec<ApplicationId>",
-        "active_application_count": "u32",
-        "unstaking_application_count": "u32",
-        "deactivated_application_count": "u32"
-    },
-    "ActiveOpeningStage": {
-        "_enum": {
-            "AcceptingApplications": "AcceptingApplications",
-            "ReviewPeriod": "ReviewPeriod",
-            "Deactivated": "Deactivated"
-        }
-    },
-    "AcceptingApplications": {
-        "started_accepting_applicants_at_block": "u32"
-    },
-    "ReviewPeriod": {
-        "started_accepting_applicants_at_block": "u32",
-        "started_review_period_at_block": "u32"
-    },
-    "Deactivated": {
-        "cause": "OpeningDeactivationCause",
-        "deactivated_at_block": "u32",
-        "started_accepting_applicants_at_block": "u32",
-        "started_review_period_at_block": "Option<u32>"
-    },
-    "OpeningDeactivationCause": {
-        "_enum": [
-            "CancelledBeforeActivation",
-            "CancelledAcceptingApplications",
-            "CancelledInReviewPeriod",
-            "ReviewPeriodExpired",
-            "Filled"
-        ]
-    },
-    "InactiveApplicationStage": {
-        "deactivation_initiated": "u32",
-        "deactivated": "u32",
-        "cause": "ApplicationDeactivationCause"
-    },
-    "UnstakingApplicationStage": {
-        "deactivation_initiated": "u32",
-        "cause": "ApplicationDeactivationCause"
-    },
-    "ApplicationDeactivationCause": {
-        "_enum": [
-            "External",
-            "Hired",
-            "NotHired",
-            "CrowdedOut",
-            "OpeningCancelled",
-            "ReviewPeriodExpired",
-            "OpeningFilled"
-        ]
-    },
-    "StakingAmountLimitMode": {
-        "_enum": [
-            "AtLeast",
-            "Exact"
-        ]
-    },
-    "ChannelId": "u64",
-    "CuratorId": "u64",
-    "CuratorOpeningId": "u64",
-    "CuratorApplicationId": "u64",
-    "LeadId": "u64",
-    "PrincipalId": "u64",
-    "OptionalText": "Option<Text>",
-    "Channel": {
-        "verified": "bool",
-        "handle": "Text",
-        "title": "OptionalText",
-        "description": "OptionalText",
-        "avatar": "OptionalText",
-        "banner": "OptionalText",
-        "content": "ChannelContentType",
-        "owner": "MemberId",
-        "role_account": "GenericAccountId",
-        "publication_status": "ChannelPublicationStatus",
-        "curation_status": "ChannelCurationStatus",
-        "created": "u32",
-        "principal_id": "PrincipalId"
-    },
-    "ChannelContentType": {
-        "_enum": [
-            "Video",
-            "Music",
-            "Ebook"
-        ]
-    },
-    "ChannelCurationStatus": {
-        "_enum": [
-            "Normal",
-            "Censored"
-        ]
-    },
-    "ChannelPublicationStatus": {
-        "_enum": [
-            "Public",
-            "Unlisted"
-        ]
-    },
-    "CurationActor": {
-        "_enum": {
-            "Lead": "Null",
-            "Curator": "CuratorId"
-        }
-    },
-    "Curator": {
-        "role_account": "GenericAccountId",
-        "reward_relationship": "Option<RewardRelationshipId>",
-        "role_stake_profile": "Option<CuratorRoleStakeProfile>",
-        "stage": "CuratorRoleStage",
-        "induction": "CuratorInduction",
-        "principal_id": "PrincipalId"
-    },
-    "CuratorApplication": {
-        "role_account": "GenericAccountId",
-        "curator_opening_id": "CuratorOpeningId",
-        "member_id": "MemberId",
-        "application_id": "ApplicationId"
-    },
-    "CuratorOpening": {
-        "opening_id": "OpeningId",
-        "curator_applications": "Vec<CuratorApplicationId>",
-        "policy_commitment": "OpeningPolicyCommitment"
-    },
-    "Lead": {
-        "member_id": "MemberId",
-        "role_account": "GenericAccountId",
-        "reward_relationship": "Option<RewardRelationshipId>",
-        "inducted": "u32",
-        "stage": "LeadRoleState"
-    },
-    "OpeningPolicyCommitment": {
-        "application_rationing_policy": "Option<ApplicationRationingPolicy>",
-        "max_review_period_length": "u32",
-        "application_staking_policy": "Option<StakingPolicy>",
-        "role_staking_policy": "Option<StakingPolicy>",
-        "role_slashing_terms": "SlashingTerms",
-        "fill_opening_successful_applicant_application_stake_unstaking_period": "Option<u32>",
-        "fill_opening_failed_applicant_application_stake_unstaking_period": "Option<u32>",
-        "fill_opening_failed_applicant_role_stake_unstaking_period": "Option<u32>",
-        "terminate_curator_application_stake_unstaking_period": "Option<u32>",
-        "terminate_curator_role_stake_unstaking_period": "Option<u32>",
-        "exit_curator_role_application_stake_unstaking_period": "Option<u32>",
-        "exit_curator_role_stake_unstaking_period": "Option<u32>"
-    },
-    "Principal": {
-        "_enum": {
-            "Lead": "Null",
-            "Curator": "CuratorId",
-            "ChannelOwner": "ChannelId"
-        }
-    },
-    "WorkingGroupUnstaker": {
-        "_enum": {
-            "Lead": "LeadId",
-            "Curator": "CuratorId"
-        }
-    },
-    "CuratorApplicationIdToCuratorIdMap": "BTreeMap<ApplicationId,CuratorId>",
-    "CuratorApplicationIdSet": "BTreeSet<CuratorApplicationId>",
-    "CuratorRoleStakeProfile": {
-        "stake_id": "StakeId",
-        "termination_unstaking_period": "Option<u32>",
-        "exit_unstaking_period": "Option<u32>"
-    },
-    "CuratorRoleStage": {
-        "_enum": {
-            "Active": "Null",
-            "Unstaking": "CuratorExitSummary",
-            "Exited": "CuratorExitSummary"
-        }
-    },
-    "CuratorExitSummary": {
-        "origin": "CuratorExitInitiationOrigin",
-        "initiated_at_block_number": "u32",
-        "rationale_text": "Text"
-    },
-    "CuratorExitInitiationOrigin": {
-        "_enum": [
-            "Lead",
-            "Curator"
-        ]
-    },
-    "LeadRoleState": {
-        "_enum": {
-            "Active": "Null",
-            "Exited": "ExitedLeadRole"
-        }
-    },
-    "ExitedLeadRole": {
-        "initiated_at_block_number": "u32"
-    },
-    "CuratorInduction": {
-        "lead": "LeadId",
-        "curator_application_id": "CuratorApplicationId",
-        "at_block": "u32"
-    },
-    "RationaleText": "Bytes",
-    "ApplicationOf": {
-        "role_account_id": "GenericAccountId",
-        "opening_id": "OpeningId",
-        "member_id": "MemberId",
-        "application_id": "ApplicationId"
-    },
-    "ApplicationIdSet": "BTreeSet<ApplicationId>",
-    "ApplicationIdToWorkerIdMap": "BTreeMap<ApplicationId,WorkerId>",
-    "WorkerId": "u64",
-    "WorkerOf": {
-        "member_id": "MemberId",
-        "role_account_id": "GenericAccountId",
-        "reward_relationship": "Option<RewardRelationshipId>",
-        "role_stake_profile": "Option<RoleStakeProfile>"
-    },
-    "OpeningOf": {
-        "hiring_opening_id": "OpeningId",
-        "applications": "Vec<ApplicationId>",
-        "policy_commitment": "WorkingGroupOpeningPolicyCommitment",
-        "opening_type": "OpeningType"
-    },
-    "StorageProviderId": "u64",
-    "OpeningType": {
-        "_enum": {
-            "Leader": "Null",
-            "Worker": "Null"
-        }
-    },
-    "HiringApplicationId": "u64",
-    "RewardPolicy": {
-        "amount_per_payout": "u128",
-        "next_payment_at_block": "u32",
-        "payout_interval": "Option<u32>"
-    },
-    "WorkingGroupOpeningPolicyCommitment": {
-        "application_rationing_policy": "Option<ApplicationRationingPolicy>",
-        "max_review_period_length": "u32",
-        "application_staking_policy": "Option<StakingPolicy>",
-        "role_staking_policy": "Option<StakingPolicy>",
-        "role_slashing_terms": "SlashingTerms",
-        "fill_opening_successful_applicant_application_stake_unstaking_period": "Option<u32>",
-        "fill_opening_failed_applicant_application_stake_unstaking_period": "Option<u32>",
-        "fill_opening_failed_applicant_role_stake_unstaking_period": "Option<u32>",
-        "terminate_application_stake_unstaking_period": "Option<u32>",
-        "terminate_role_stake_unstaking_period": "Option<u32>",
-        "exit_role_application_stake_unstaking_period": "Option<u32>",
-        "exit_role_stake_unstaking_period": "Option<u32>"
-    },
-    "RoleStakeProfile": {
-        "stake_id": "StakeId",
-        "termination_unstaking_period": "Option<u32>",
-        "exit_unstaking_period": "Option<u32>"
-    },
-    "Url": "Text",
-    "IPNSIdentity": "Text",
-    "ServiceProviderRecord": {
-        "identity": "IPNSIdentity",
-        "expires_at": "u32"
-    },
-    "ContentId": "[u8;32]",
-    "LiaisonJudgement": {
-        "_enum": [
-            "Pending",
-            "Accepted",
-            "Rejected"
-        ]
-    },
-    "DataObject": {
-        "owner": "MemberId",
-        "added_at": "BlockAndTime",
-        "type_id": "DataObjectTypeId",
-        "size": "u64",
-        "liaison": "StorageProviderId",
-        "liaison_judgement": "LiaisonJudgement",
-        "ipfs_content_id": "Text"
-    },
-    "DataObjectStorageRelationshipId": "u64",
-    "DataObjectStorageRelationship": {
-        "content_id": "ContentId",
-        "storage_provider": "StorageProviderId",
-        "ready": "bool"
-    },
-    "DataObjectTypeId": "u64",
-    "DataObjectType": {
-        "description": "Text",
-        "active": "bool"
-    },
-    "DataObjectsMap": "BTreeMap<ContentId,DataObject>",
-    "ProposalId": "u32",
-    "ProposalStatus": {
-        "_enum": {
-            "Active": "Option<ActiveStake>",
-            "Finalized": "Finalized"
-        }
-    },
-    "ProposalOf": {
-        "parameters": "ProposalParameters",
-        "proposerId": "MemberId",
-        "title": "Text",
-        "description": "Text",
-        "createdAt": "u32",
-        "status": "ProposalStatus",
-        "votingResults": "VotingResults"
-    },
-    "ProposalDetails": {
-        "_enum": {
-            "Text": "Text",
-            "RuntimeUpgrade": "Bytes",
-            "SetElectionParameters": "ElectionParameters",
-            "Spending": "(Balance,AccountId)",
-            "SetLead": "Option<SetLeadParams>",
-            "SetContentWorkingGroupMintCapacity": "u128",
-            "EvictStorageProvider": "GenericAccountId",
-            "SetValidatorCount": "u32",
-            "SetStorageRoleParameters": "RoleParameters",
-            "AddWorkingGroupLeaderOpening": "AddOpeningParameters",
-            "BeginReviewWorkingGroupLeaderApplication": "(OpeningId,WorkingGroup)",
-            "FillWorkingGroupLeaderOpening": "FillOpeningParameters",
-            "SetWorkingGroupMintCapacity": "(Balance,WorkingGroup)",
-            "DecreaseWorkingGroupLeaderStake": "(WorkerId,Balance,WorkingGroup)",
-            "SlashWorkingGroupLeaderStake": "(WorkerId,Balance,WorkingGroup)",
-            "SetWorkingGroupLeaderReward": "(WorkerId,Balance,WorkingGroup)",
-            "TerminateWorkingGroupLeaderRole": "TerminateRoleParameters"
-        }
-    },
-    "ProposalDetailsOf": {
-        "_enum": {
-            "Text": "Text",
-            "RuntimeUpgrade": "Bytes",
-            "SetElectionParameters": "ElectionParameters",
-            "Spending": "(Balance,AccountId)",
-            "SetLead": "Option<SetLeadParams>",
-            "SetContentWorkingGroupMintCapacity": "u128",
-            "EvictStorageProvider": "GenericAccountId",
-            "SetValidatorCount": "u32",
-            "SetStorageRoleParameters": "RoleParameters",
-            "AddWorkingGroupLeaderOpening": "AddOpeningParameters",
-            "BeginReviewWorkingGroupLeaderApplication": "(OpeningId,WorkingGroup)",
-            "FillWorkingGroupLeaderOpening": "FillOpeningParameters",
-            "SetWorkingGroupMintCapacity": "(Balance,WorkingGroup)",
-            "DecreaseWorkingGroupLeaderStake": "(WorkerId,Balance,WorkingGroup)",
-            "SlashWorkingGroupLeaderStake": "(WorkerId,Balance,WorkingGroup)",
-            "SetWorkingGroupLeaderReward": "(WorkerId,Balance,WorkingGroup)",
-            "TerminateWorkingGroupLeaderRole": "TerminateRoleParameters"
-        }
-    },
-    "VotingResults": {
-        "abstensions": "u32",
-        "approvals": "u32",
-        "rejections": "u32",
-        "slashes": "u32"
-    },
-    "ProposalParameters": {
-        "votingPeriod": "u32",
-        "gracePeriod": "u32",
-        "approvalQuorumPercentage": "u32",
-        "approvalThresholdPercentage": "u32",
-        "slashingQuorumPercentage": "u32",
-        "slashingThresholdPercentage": "u32",
-        "requiredStake": "Option<u128>"
-    },
-    "VoteKind": {
-        "_enum": [
-            "Approve",
-            "Reject",
-            "Slash",
-            "Abstain"
-        ]
-    },
-    "ThreadCounter": {
-        "author_id": "MemberId",
-        "counter": "u32"
-    },
-    "DiscussionThread": {
-        "title": "Bytes",
-        "created_at": "u32",
-        "author_id": "MemberId"
-    },
-    "DiscussionPost": {
-        "text": "Bytes",
-        "created_at": "u32",
-        "updated_at": "u32",
-        "author_id": "MemberId",
-        "thread_id": "ThreadId",
-        "edition_number": "u32"
-    },
-    "AddOpeningParameters": {
-        "activate_at": "ActivateOpeningAt",
-        "commitment": "WorkingGroupOpeningPolicyCommitment",
-        "human_readable_text": "Bytes",
-        "working_group": "WorkingGroup"
-    },
-    "FillOpeningParameters": {
-        "opening_id": "OpeningId",
-        "successful_application_id": "ApplicationId",
-        "reward_policy": "Option<RewardPolicy>",
-        "working_group": "WorkingGroup"
-    },
-    "TerminateRoleParameters": {
-        "worker_id": "WorkerId",
-        "rationale": "Bytes",
-        "slash": "bool",
-        "working_group": "WorkingGroup"
-    },
-    "ActiveStake": {
-        "stake_id": "StakeId",
-        "source_account_id": "GenericAccountId"
-    },
-    "Finalized": {
-        "proposalStatus": "ProposalDecisionStatus",
-        "finalizedAt": "u32",
-        "encodedUnstakingErrorDueToBrokenRuntime": "Option<Vec<u8>>",
-        "stakeDataAfterUnstakingError": "Option<ActiveStake>"
-    },
-    "ProposalDecisionStatus": {
-        "_enum": {
-            "Canceled": "Null",
-            "Vetoed": "Null",
-            "Rejected": "Null",
-            "Slashed": "Null",
-            "Expired": "Null",
-            "Approved": "Approved"
-        }
-    },
-    "ExecutionFailed": {
-        "error": "Text"
-    },
-    "Approved": {
-        "_enum": {
-            "PendingExecution": "Null",
-            "Executed": "Null",
-            "ExecutionFailed": "ExecutionFailed"
-        }
-    },
-    "SetLeadParams": "(MemberId,GenericAccountId)",
-    "Nonce": "u64",
-    "EntityId": "u64",
-    "ClassId": "u64",
-    "CuratorGroupId": "u64",
-    "VecMaxLength": "u16",
-    "TextMaxLength": "u16",
-    "HashedTextMaxLength": "Option<u16>",
-    "PropertyId": "u16",
-    "SchemaId": "u16",
-    "SameController": "bool",
-    "ClassPermissions": {
-        "any_member": "bool",
-        "entity_creation_blocked": "bool",
-        "all_entity_property_values_locked": "bool",
-        "maintainers": "Vec<CuratorGroupId>"
-    },
-    "PropertyTypeSingle": {
-        "_enum": {
-            "Bool": "Null",
-            "Uint16": "Null",
-            "Uint32": "Null",
-            "Uint64": "Null",
-            "Int16": "Null",
-            "Int32": "Null",
-            "Int64": "Null",
-            "Text": "TextMaxLength",
-            "Hash": "HashedTextMaxLength",
-            "Reference": "(ClassId,SameController)"
-        }
-    },
-    "PropertyTypeVector": {
-        "vec_type": "PropertyTypeSingle",
-        "max_length": "VecMaxLength"
-    },
-    "PropertyType": {
-        "_enum": {
-            "Single": "PropertyTypeSingle",
-            "Vector": "PropertyTypeVector"
-        }
-    },
-    "PropertyLockingPolicy": {
-        "is_locked_from_maintainer": "bool",
-        "is_locked_from_controller": "bool"
-    },
-    "Property": {
-        "property_type": "PropertyType",
-        "required": "bool",
-        "unique": "bool",
-        "name": "Text",
-        "description": "Text",
-        "locking_policy": "PropertyLockingPolicy"
-    },
-    "Schema": {
-        "properties": "Vec<PropertyId>",
-        "is_active": "bool"
-    },
-    "Class": {
-        "class_permissions": "ClassPermissions",
-        "properties": "Vec<Property>",
-        "schemas": "Vec<Schema>",
-        "name": "Text",
-        "description": "Text",
-        "maximum_entities_count": "EntityId",
-        "current_number_of_entities": "EntityId",
-        "default_entity_creation_voucher_upper_bound": "EntityId"
-    },
-    "ClassOf": {
-        "class_permissions": "ClassPermissions",
-        "properties": "Vec<Property>",
-        "schemas": "Vec<Schema>",
-        "name": "Text",
-        "description": "Text",
-        "maximum_entities_count": "EntityId",
-        "current_number_of_entities": "EntityId",
-        "default_entity_creation_voucher_upper_bound": "EntityId"
-    },
-    "EntityController": {
-        "_enum": {
-            "Maintainers": "Null",
-            "Member": "MemberId",
-            "Lead": "Null"
-        }
-    },
-    "EntityPermissions": {
-        "controller": "EntityController",
-        "frozen": "bool",
-        "referenceable": "bool"
-    },
-    "StoredValue": {
-        "_enum": {
-            "Bool": "bool",
-            "Uint16": "u16",
-            "Uint32": "u32",
-            "Uint64": "u64",
-            "Int16": "i16",
-            "Int32": "i32",
-            "Int64": "i64",
-            "Text": "Text",
-            "Hash": "Hash",
-            "Reference": "EntityId"
-        }
-    },
-    "VecStoredValue": {
-        "_enum": {
-            "Bool": "Vec<bool>",
-            "Uint16": "Vec<u16>",
-            "Uint32": "Vec<u32>",
-            "Uint64": "Vec<u64>",
-            "Int16": "Vec<i16>",
-            "Int32": "Vec<i32>",
-            "Int64": "Vec<i64>",
-            "Hash": "Vec<Hash>",
-            "Text": "Vec<Text>",
-            "Reference": "Vec<EntityId>"
-        }
-    },
-    "VecStoredPropertyValue": {
-        "vec_value": "VecStoredValue",
-        "nonce": "Nonce"
-    },
-    "StoredPropertyValue": {
-        "_enum": {
-            "Single": "StoredValue",
-            "Vector": "VecStoredPropertyValue"
-        }
-    },
-    "InboundReferenceCounter": {
-        "total": "u32",
-        "same_owner": "u32"
-    },
-    "Entity": {
-        "entity_permissions": "EntityPermissions",
-        "class_id": "ClassId",
-        "supported_schemas": "Vec<SchemaId>",
-        "values": "BTreeMap<PropertyId,StoredPropertyValue>",
-        "reference_counter": "InboundReferenceCounter"
-    },
-    "EntityOf": {
-        "entity_permissions": "EntityPermissions",
-        "class_id": "ClassId",
-        "supported_schemas": "Vec<SchemaId>",
-        "values": "BTreeMap<PropertyId,StoredPropertyValue>",
-        "reference_counter": "InboundReferenceCounter"
-    },
-    "CuratorGroup": {
-        "curators": "Vec<u64>",
-        "active": "bool",
-        "number_of_classes_maintained": "u32"
-    },
-    "EntityCreationVoucher": {
-        "maximum_entities_count": "EntityId",
-        "entities_created": "EntityId"
-    },
-    "Actor": {
-        "_enum": {
-            "Curator": "(CuratorGroupId,u64)",
-            "Member": "MemberId",
-            "Lead": "Null"
-        }
-    },
-    "EntityReferenceCounterSideEffect": {
-        "total": "i32",
-        "same_owner": "i32"
-    },
-    "ReferenceCounterSideEffects": "BTreeMap<EntityId,EntityReferenceCounterSideEffect>",
-    "SideEffects": "Option<ReferenceCounterSideEffects>",
-    "SideEffect": "Option<(EntityId,EntityReferenceCounterSideEffect)>",
-    "Status": "bool",
-    "InputValue": {
-        "_enum": {
-            "Bool": "bool",
-            "Uint16": "u16",
-            "Uint32": "u32",
-            "Uint64": "u64",
-            "Int16": "i16",
-            "Int32": "i32",
-            "Int64": "i64",
-            "Text": "Text",
-            "TextToHash": "Text",
-            "Reference": "EntityId"
-        }
-    },
-    "VecInputValue": {
-        "_enum": {
-            "Bool": "Vec<bool>",
-            "Uint16": "Vec<u16>",
-            "Uint32": "Vec<u32>",
-            "Uint64": "Vec<u64>",
-            "Int16": "Vec<i16>",
-            "Int32": "Vec<i32>",
-            "Int64": "Vec<i64>",
-            "TextToHash": "Vec<Text>",
-            "Text": "Vec<Text>",
-            "Reference": "Vec<EntityId>"
-        }
-    },
-    "InputPropertyValue": {
-        "_enum": {
-            "Single": "InputValue",
-            "Vector": "VecInputValue"
-        }
-    },
-    "ParameterizedEntity": {
-        "_enum": {
-            "InternalEntityJustAdded": "u32",
-            "ExistingEntity": "EntityId"
-        }
-    },
-    "ParametrizedPropertyValue": {
-        "_enum": {
-            "InputPropertyValue": "InputPropertyValue",
-            "InternalEntityJustAdded": "u32",
-            "InternalEntityVec": "Vec<ParameterizedEntity>"
-        }
-    },
-    "ParametrizedClassPropertyValue": {
-        "in_class_index": "PropertyId",
-        "value": "ParametrizedPropertyValue"
-    },
-    "CreateEntityOperation": {
-        "class_id": "ClassId"
-    },
-    "UpdatePropertyValuesOperation": {
-        "entity_id": "ParameterizedEntity",
-        "new_parametrized_property_values": "Vec<ParametrizedClassPropertyValue>"
-    },
-    "AddSchemaSupportToEntityOperation": {
-        "entity_id": "ParameterizedEntity",
-        "schema_id": "SchemaId",
-        "parametrized_property_values": "Vec<ParametrizedClassPropertyValue>"
-    },
-    "OperationType": {
-        "_enum": {
-            "CreateEntity": "CreateEntityOperation",
-            "UpdatePropertyValues": "UpdatePropertyValuesOperation",
-            "AddSchemaSupportToEntity": "AddSchemaSupportToEntityOperation"
-        }
-    },
-    "InputEntityValuesMap": "BTreeMap<PropertyId,InputPropertyValue>",
-    "ClassPermissionsType": "Null",
-    "ClassPropertyValue": "Null",
-    "Operation": "Null",
-    "ReferenceConstraint": "Null"
-}

+ 2 - 1
runtime-modules/constitution/Cargo.toml

@@ -11,14 +11,15 @@ sp-std = { package = 'sp-std', default-features = false, git = 'https://github.c
 frame-support = { package = 'frame-support', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 frame-support = { package = 'frame-support', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 frame_system = { package = 'frame-system', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 frame_system = { package = 'frame-system', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 sp-runtime = { package = 'sp-runtime', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 sp-runtime = { package = 'sp-runtime', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
+frame-benchmarking = { package = 'frame-benchmarking', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca', optional = true}
 
 
 [dev-dependencies]
 [dev-dependencies]
 sp-io = { package = 'sp-io', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 sp-io = { package = 'sp-io', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 sp-core = { package = 'sp-core', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 sp-core = { package = 'sp-core', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 
 
-
 [features]
 [features]
 default = ['std']
 default = ['std']
+runtime-benchmarks = ["frame-benchmarking"]
 std = [
 std = [
     'serde',
     'serde',
     'codec/std',
     'codec/std',

+ 55 - 0
runtime-modules/constitution/src/benchmarking.rs

@@ -0,0 +1,55 @@
+#![cfg(feature = "runtime-benchmarks")]
+
+use crate::{Call, ConstitutionInfo, Event, Module, Trait};
+use frame_benchmarking::benchmarks;
+use frame_system::Module as System;
+use frame_system::{EventRecord, RawOrigin};
+use sp_runtime::traits::Hash;
+use sp_std::boxed::Box;
+use sp_std::vec;
+use sp_std::vec::Vec;
+
+fn assert_last_event<T: Trait>(generic_event: <T as Trait>::Event) {
+    let events = System::<T>::events();
+    let system_event: <T as frame_system::Trait>::Event = generic_event.into();
+    // compare to the last event record
+    let EventRecord { event, .. } = &events[events.len() - 1];
+    assert_eq!(event, &system_event);
+}
+
+const MAX_BYTES: u32 = 50000;
+
+benchmarks! {
+    _{ }
+
+    amend_constitution{
+        let i in 1 .. MAX_BYTES;
+        let text = vec![0u8].repeat(i as usize);
+
+    }: _ (RawOrigin::Root, text.clone())
+    verify {
+            let hashed = T::Hashing::hash(&text);
+            let hash = hashed.as_ref().to_vec();
+
+            let constitution_info = ConstitutionInfo{
+                text_hash: hash.clone(),
+            };
+
+            assert_eq!(Module::<T>::constitution(), constitution_info);
+            assert_last_event::<T>(Event::ConstutionAmended(hash).into());
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::tests::mocks::{build_test_externalities, Test};
+    use frame_support::assert_ok;
+
+    #[test]
+    fn amend_constitution() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_amend_constitution::<Test>());
+        });
+    }
+}

+ 22 - 2
runtime-modules/constitution/src/lib.rs

@@ -8,18 +8,33 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 #![cfg_attr(not(feature = "std"), no_std)]
 
 
 #[cfg(test)]
 #[cfg(test)]
-mod tests;
+pub(crate) mod tests;
+
+mod benchmarking;
 
 
 use codec::{Decode, Encode};
 use codec::{Decode, Encode};
+use frame_support::weights::Weight;
 use frame_support::{decl_event, decl_module, decl_storage};
 use frame_support::{decl_event, decl_module, decl_storage};
 use frame_system::ensure_root;
 use frame_system::ensure_root;
 #[cfg(feature = "std")]
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 use serde::{Deserialize, Serialize};
 use sp_runtime::traits::Hash;
 use sp_runtime::traits::Hash;
+use sp_runtime::SaturatedConversion;
 use sp_std::vec::Vec;
 use sp_std::vec::Vec;
 
 
+/// pallet_constitution WeightInfo.
+/// Note: This was auto generated through the benchmark CLI using the `--weight-trait` flag
+pub trait WeightInfo {
+    fn amend_constitution(i: u32) -> Weight;
+}
+
+type WeightInfoConstitution<T> = <T as Trait>::WeightInfo;
+
 pub trait Trait: frame_system::Trait {
 pub trait Trait: frame_system::Trait {
     type Event: From<Event> + Into<<Self as frame_system::Trait>::Event>;
     type Event: From<Event> + Into<<Self as frame_system::Trait>::Event>;
+
+    /// Weight information for extrinsics in this pallet.
+    type WeightInfo: WeightInfo;
 }
 }
 
 
 /// Contains constitution text hash and its amendment number.
 /// Contains constitution text hash and its amendment number.
@@ -50,7 +65,12 @@ decl_module! {
         fn deposit_event() = default;
         fn deposit_event() = default;
 
 
         /// Sets the current constitution hash. Requires root origin.
         /// Sets the current constitution hash. Requires root origin.
-        #[weight = 10_000_000] // TODO: adjust weight
+        /// # <weight>
+        /// - Complexity: `O(C)` where C is the length of the constitution text.
+        /// - Db reads: 0
+        /// - Db writes: 1 (constant value)
+        /// # </weight>
+        #[weight = WeightInfoConstitution::<T>::amend_constitution(constitution_text.len().saturated_into())]
         fn amend_constitution(origin, constitution_text: Vec<u8>) {
         fn amend_constitution(origin, constitution_text: Vec<u8>) {
             ensure_root(origin)?;
             ensure_root(origin)?;
 
 

+ 7 - 0
runtime-modules/constitution/src/tests/mocks.rs

@@ -64,6 +64,13 @@ impl frame_system::Trait for Test {
 
 
 impl Trait for Test {
 impl Trait for Test {
     type Event = TestEvent;
     type Event = TestEvent;
+    type WeightInfo = ();
+}
+
+impl crate::WeightInfo for () {
+    fn amend_constitution(_: u32) -> u64 {
+        0
+    }
 }
 }
 
 
 pub fn build_test_externalities() -> sp_io::TestExternalities {
 pub fn build_test_externalities() -> sp_io::TestExternalities {

+ 1 - 1
runtime-modules/constitution/src/tests/mod.rs

@@ -1,6 +1,6 @@
 #![cfg(test)]
 #![cfg(test)]
 
 
-mod mocks;
+pub(crate) mod mocks;
 
 
 use crate::{ConstitutionInfo, Event};
 use crate::{ConstitutionInfo, Event};
 use frame_support::dispatch::DispatchResult;
 use frame_support::dispatch::DispatchResult;

+ 102 - 45
runtime-modules/content-directory/src/lib.rs

@@ -142,7 +142,11 @@ use codec::{Codec, Decode, Encode};
 use frame_support::storage::IterableStorageMap;
 use frame_support::storage::IterableStorageMap;
 
 
 use frame_support::{
 use frame_support::{
-    decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, Parameter,
+    decl_event, decl_module, decl_storage,
+    dispatch::{DispatchError, DispatchResult},
+    ensure,
+    traits::Get,
+    Parameter,
 };
 };
 use frame_system::ensure_signed;
 use frame_system::ensure_signed;
 #[cfg(feature = "std")]
 #[cfg(feature = "std")]
@@ -1628,64 +1632,115 @@ decl_module! {
             Ok(())
             Ok(())
         }
         }
 
 
-        /// Batch transaction
-        #[weight = 10_000_000] // TODO: adjust weight
-        pub fn transaction(origin, actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>, operations: Vec<OperationType<T>>) -> DispatchResult {
+       /// Batch transaction
+       #[weight = 10_000_000] // TODO: adjust weight
+       pub fn transaction(origin, actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>, operations: Vec<OperationType<T>>) -> DispatchResult {
 
 
-            // Ensure maximum number of operations during atomic batching limit not reached
-            Self::ensure_number_of_operations_during_atomic_batching_limit_not_reached(&operations)?;
+           // Ensure maximum number of operations during atomic batching limit not reached
+           Self::ensure_number_of_operations_during_atomic_batching_limit_not_reached(&operations)?;
 
 
-            //
-            // == MUTATION SAFE ==
-            //
+           //
+           // == MUTATION SAFE ==
+           //
 
 
-            // This BTreeMap holds the T::EntityId of the entity created as a result of executing a `CreateEntity` `Operation`
-            let mut entity_created_in_operation = BTreeMap::new();
+           // This BTreeMap holds the T::EntityId of the entity created as a result of executing a `CreateEntity` `Operation`
+           let mut entity_created_in_operation = BTreeMap::new();
 
 
-            // Create raw origin
-            let raw_origin = origin.into().map_err(|_| Error::<T>::OriginCanNotBeMadeIntoRawOrigin)?;
+           // Create raw origin
+           let raw_origin = origin.into().map_err(|_| Error::<T>::OriginCanNotBeMadeIntoRawOrigin)?;
 
 
-            for (index, operation_type) in operations.into_iter().enumerate() {
-                let origin = T::Origin::from(raw_origin.clone());
-                match operation_type {
-                    OperationType::CreateEntity(create_entity_operation) => {
-                        Self::create_entity(origin, create_entity_operation.class_id, actor)?;
+           for (index, operation_type) in operations.into_iter().enumerate() {
+               let origin = T::Origin::from(raw_origin.clone());
+               match operation_type {
+                   OperationType::CreateEntity(create_entity_operation) => {
+                        Self::ensure_transaction_failed_event(
+                            Self::create_entity(origin, create_entity_operation.class_id, actor),
+                            actor,
+                            index
+                        )?;
 
 
                         // entity id of newly created entity
                         // entity id of newly created entity
                         let entity_id = Self::next_entity_id() - T::EntityId::one();
                         let entity_id = Self::next_entity_id() - T::EntityId::one();
                         entity_created_in_operation.insert(index, entity_id);
                         entity_created_in_operation.insert(index, entity_id);
-                    },
-                    OperationType::AddSchemaSupportToEntity(add_schema_support_to_entity_operation) => {
-                        let entity_id = operations::parametrized_entity_to_entity_id(
-                            &entity_created_in_operation, add_schema_support_to_entity_operation.entity_id
+                   },
+                   OperationType::AddSchemaSupportToEntity(add_schema_support_to_entity_operation) => {
+                       let entity_id =
+                            Self::ensure_transaction_failed_event(
+                                operations::parametrized_entity_to_entity_id(
+                                    &entity_created_in_operation, add_schema_support_to_entity_operation.entity_id
+                                ),
+                                actor,
+                                index
+                            )?;
+
+                       let schema_id = add_schema_support_to_entity_operation.schema_id;
+
+                       let property_values =
+                            Self::ensure_transaction_failed_event(
+                                operations::parametrized_property_values_to_property_values(
+                                    &entity_created_in_operation, add_schema_support_to_entity_operation.parametrized_property_values
+                                ),
+                                actor,
+                                index
+                            )?;
+                        Self::ensure_transaction_failed_event(
+                            Self::add_schema_support_to_entity(origin, actor, entity_id, schema_id, property_values),
+                            actor,
+                            index
                         )?;
                         )?;
-                        let schema_id = add_schema_support_to_entity_operation.schema_id;
-                        let property_values = operations::parametrized_property_values_to_property_values(
-                            &entity_created_in_operation, add_schema_support_to_entity_operation.parametrized_property_values
-                        )?;
-                        Self::add_schema_support_to_entity(origin, actor, entity_id, schema_id, property_values)?;
-                    },
-                    OperationType::UpdatePropertyValues(update_property_values_operation) => {
-                        let entity_id = operations::parametrized_entity_to_entity_id(
-                            &entity_created_in_operation, update_property_values_operation.entity_id
-                        )?;
-                        let property_values = operations::parametrized_property_values_to_property_values(
-                            &entity_created_in_operation, update_property_values_operation.new_parametrized_property_values
-                        )?;
-                        Self::update_entity_property_values(origin, actor, entity_id, property_values)?;
-                    },
-                }
-            }
-
-            // Trigger event
-            Self::deposit_event(RawEvent::TransactionCompleted(actor));
-
-            Ok(())
-        }
+                   },
+                   OperationType::UpdatePropertyValues(update_property_values_operation) => {
+                       let entity_id =
+                            Self::ensure_transaction_failed_event(
+                                operations::parametrized_entity_to_entity_id(
+                                    &entity_created_in_operation, update_property_values_operation.entity_id
+                                ),
+                                actor,
+                                index
+                            )?;
+
+                       let property_values =
+                            Self::ensure_transaction_failed_event(
+                                operations::parametrized_property_values_to_property_values(
+                                    &entity_created_in_operation, update_property_values_operation.new_parametrized_property_values
+                                ),
+                                actor,
+                                index
+                            )?;
+
+                       Self::ensure_transaction_failed_event(
+                            Self::update_entity_property_values(origin, actor, entity_id, property_values),
+                            actor,
+                            index
+                       )?;
+                   },
+               }
+           }
+
+           // Trigger event
+           Self::deposit_event(RawEvent::TransactionCompleted(actor));
+
+           Ok(())
+       }
     }
     }
 }
 }
 
 
 impl<T: Trait> Module<T> {
 impl<T: Trait> Module<T> {
+    /// Deposits an `TransactionFailed` event if an error during `transaction` extrinsic execution occured
+    fn ensure_transaction_failed_event<R, E: Into<DispatchError>>(
+        result: Result<R, E>,
+        actor: Actor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
+        index: usize,
+    ) -> Result<R, DispatchError> {
+        match result {
+            Err(e) => {
+                Self::deposit_event(RawEvent::TransactionFailed(actor, index as u32));
+                Err(e.into())
+            }
+            Ok(result) => Ok(result),
+        }
+    }
+
     /// Updates corresponding `Entity` `reference_counter` by `reference_counter_delta`.
     /// Updates corresponding `Entity` `reference_counter` by `reference_counter_delta`.
     fn update_entity_rc(
     fn update_entity_rc(
         entity_id: T::EntityId,
         entity_id: T::EntityId,
@@ -2830,6 +2885,7 @@ decl_event!(
         Nonce = <T as Trait>::Nonce,
         Nonce = <T as Trait>::Nonce,
         SideEffects = Option<ReferenceCounterSideEffects<T>>,
         SideEffects = Option<ReferenceCounterSideEffects<T>>,
         SideEffect = Option<(<T as Trait>::EntityId, EntityReferenceCounterSideEffect)>,
         SideEffect = Option<(<T as Trait>::EntityId, EntityReferenceCounterSideEffect)>,
+        FailedAt = u32,
     {
     {
         CuratorGroupAdded(CuratorGroupId),
         CuratorGroupAdded(CuratorGroupId),
         CuratorGroupRemoved(CuratorGroupId),
         CuratorGroupRemoved(CuratorGroupId),
@@ -2854,5 +2910,6 @@ decl_event!(
         InsertedAtVectorIndex(Actor, EntityId, PropertyId, VecMaxLength, Nonce, SideEffect),
         InsertedAtVectorIndex(Actor, EntityId, PropertyId, VecMaxLength, Nonce, SideEffect),
         EntityOwnershipTransfered(EntityId, EntityController, SideEffects),
         EntityOwnershipTransfered(EntityId, EntityController, SideEffects),
         TransactionCompleted(Actor),
         TransactionCompleted(Actor),
+        TransactionFailed(Actor, FailedAt),
     }
     }
 );
 );

+ 2 - 1
runtime-modules/content-directory/src/mock.rs

@@ -434,13 +434,14 @@ type RawTestEvent = RawEvent<
     Nonce,
     Nonce,
     Option<ReferenceCounterSideEffects<Runtime>>,
     Option<ReferenceCounterSideEffects<Runtime>>,
     Option<(EntityId, EntityReferenceCounterSideEffect)>,
     Option<(EntityId, EntityReferenceCounterSideEffect)>,
+    u32,
 >;
 >;
 
 
 pub fn get_test_event(raw_event: RawTestEvent) -> TestEvent {
 pub fn get_test_event(raw_event: RawTestEvent) -> TestEvent {
     TestEvent::test_events(raw_event)
     TestEvent::test_events(raw_event)
 }
 }
 
 
-pub fn assert_event_success(tested_event: TestEvent, number_of_events_after_call: usize) {
+pub fn assert_event(tested_event: TestEvent, number_of_events_after_call: usize) {
     // Ensure  runtime events length is equal to expected number of events after call
     // Ensure  runtime events length is equal to expected number of events after call
     assert_eq!(System::events().len(), number_of_events_after_call);
     assert_eq!(System::events().len(), number_of_events_after_call);
 
 

+ 1 - 1
runtime-modules/content-directory/src/tests.rs

@@ -145,7 +145,7 @@ pub fn add_entity_schemas_support() -> (
     ));
     ));
 
 
     // Last event checked
     // Last event checked
-    assert_event_success(
+    assert_event(
         entity_schema_support_added_event,
         entity_schema_support_added_event,
         number_of_events_before_calls + 2,
         number_of_events_before_calls + 2,
     );
     );

+ 1 - 1
runtime-modules/content-directory/src/tests/add_class_schema.rs

@@ -52,7 +52,7 @@ fn add_class_schema_success() {
             get_test_event(RawEvent::ClassSchemaAdded(FIRST_CLASS_ID, SECOND_SCHEMA_ID));
             get_test_event(RawEvent::ClassSchemaAdded(FIRST_CLASS_ID, SECOND_SCHEMA_ID));
 
 
         // Last event checked
         // Last event checked
-        assert_event_success(class_schema_added_event, number_of_events_before_call + 2);
+        assert_event(class_schema_added_event, number_of_events_before_call + 2);
     })
     })
 }
 }
 
 

+ 1 - 1
runtime-modules/content-directory/src/tests/add_curator_group.rs

@@ -31,7 +31,7 @@ fn add_curator_group_success() {
             get_test_event(RawEvent::CuratorGroupAdded(FIRST_CURATOR_GROUP_ID));
             get_test_event(RawEvent::CuratorGroupAdded(FIRST_CURATOR_GROUP_ID));
 
 
         // Event checked
         // Event checked
-        assert_event_success(
+        assert_event(
             curator_group_created_event,
             curator_group_created_event,
             number_of_events_before_call + 1,
             number_of_events_before_call + 1,
         );
         );

+ 1 - 1
runtime-modules/content-directory/src/tests/add_curator_to_group.rs

@@ -31,7 +31,7 @@ fn add_curator_to_group_success() {
         ));
         ));
 
 
         // Event checked
         // Event checked
-        assert_event_success(
+        assert_event(
             curator_group_curator_added_event,
             curator_group_curator_added_event,
             number_of_events_before_call + 1,
             number_of_events_before_call + 1,
         );
         );

+ 1 - 1
runtime-modules/content-directory/src/tests/add_maintainer_to_class.rs

@@ -35,7 +35,7 @@ fn add_maintainer_to_class_success() {
         ));
         ));
 
 
         // Event checked
         // Event checked
-        assert_event_success(maintainer_added_event, number_of_events_before_call + 1);
+        assert_event(maintainer_added_event, number_of_events_before_call + 1);
     })
     })
 }
 }
 
 

+ 1 - 1
runtime-modules/content-directory/src/tests/clear_entity_property_vector.rs

@@ -53,7 +53,7 @@ fn clear_entity_property_vector_success() {
         ));
         ));
 
 
         // Last event checked
         // Last event checked
-        assert_event_success(
+        assert_event(
             entity_property_vector_cleared_event,
             entity_property_vector_cleared_event,
             number_of_events_before_calls + 1,
             number_of_events_before_calls + 1,
         );
         );

+ 1 - 1
runtime-modules/content-directory/src/tests/create_class.rs

@@ -23,7 +23,7 @@ fn create_class_success() {
         let class_created_event = get_test_event(RawEvent::ClassCreated(FIRST_CLASS_ID));
         let class_created_event = get_test_event(RawEvent::ClassCreated(FIRST_CLASS_ID));
 
 
         // Event checked
         // Event checked
-        assert_event_success(class_created_event, number_of_events_before_call + 1);
+        assert_event(class_created_event, number_of_events_before_call + 1);
     })
     })
 }
 }
 
 

+ 1 - 1
runtime-modules/content-directory/src/tests/create_entity.rs

@@ -71,7 +71,7 @@ fn create_entity_success() {
             get_test_event(RawEvent::EntityCreated(actor, next_entity_id() - 1));
             get_test_event(RawEvent::EntityCreated(actor, next_entity_id() - 1));
 
 
         // Last event checked
         // Last event checked
-        assert_event_success(entity_created_event, number_of_events_before_call + 1);
+        assert_event(entity_created_event, number_of_events_before_call + 1);
     })
     })
 }
 }
 
 

+ 1 - 1
runtime-modules/content-directory/src/tests/insert_at_entity_property_vector.rs

@@ -64,7 +64,7 @@ fn insert_at_entity_property_vector_success() {
         ));
         ));
 
 
         // Last event checked
         // Last event checked
-        assert_event_success(
+        assert_event(
             inserted_at_vector_index_event,
             inserted_at_vector_index_event,
             number_of_events_before_calls + 1,
             number_of_events_before_calls + 1,
         );
         );

+ 1 - 1
runtime-modules/content-directory/src/tests/remove_at_entity_property_vector.rs

@@ -59,7 +59,7 @@ fn remove_at_entity_property_vector_success() {
         ));
         ));
 
 
         // Last event checked
         // Last event checked
-        assert_event_success(
+        assert_event(
             removed_at_vector_index_event,
             removed_at_vector_index_event,
             number_of_events_before_calls + 1,
             number_of_events_before_calls + 1,
         );
         );

+ 1 - 1
runtime-modules/content-directory/src/tests/remove_curator_from_group.rs

@@ -44,7 +44,7 @@ fn remove_curator_from_group_success() {
         ));
         ));
 
 
         // Event checked
         // Event checked
-        assert_event_success(
+        assert_event(
             curator_group_curator_removed_event,
             curator_group_curator_removed_event,
             number_of_events_before_call + 1,
             number_of_events_before_call + 1,
         );
         );

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