init-new-content-directory.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* global api, hashing, keyring, types, util, joy */
  2. // run this script with:
  3. // yarn script initNewContentDir
  4. //
  5. // or copy and paste the code into the pioneer javascript toolbox at:
  6. // https://testnet.joystream.org/#/js
  7. const script = async ({ api, keyring }) => {
  8. // Get sudo addr
  9. const sudoAddress = (await api.query.sudo.key()).toString()
  10. let sudo
  11. if (typeof window === 'undefined') {
  12. // In node, get the keyPair if the keyring was provided
  13. sudo = keyring.getPair(sudoAddress)
  14. } else {
  15. // Pioneer: let the UI Signer handle it
  16. sudo = sudoAddress
  17. }
  18. let nonce = (await api.query.system.account(sudoAddress)).nonce.toNumber()
  19. const NEW_OPENING_ID = await api.query.contentDirectoryWorkingGroup.nextOpeningId()
  20. const NEW_CLASS_ID = await api.query.contentDirectory.nextClassId()
  21. const ALICE_MEMBER_ID = 0 // We assume it exists
  22. const sudoCall = (tx) => api.tx.sudo.sudo(tx).signAndSend(sudo, { nonce: nonce++ })
  23. // Create curator lead opening
  24. await sudoCall(
  25. api.tx.contentDirectoryWorkingGroup.addOpening(
  26. { CurrentBlock: null }, // activate_at
  27. { commitment: { max_review_period_length: 9999 } }, // OpeningPolicyCommitment
  28. 'api-examples curator opening', // human_readable_text
  29. { Leader: null } // opening_type
  30. )
  31. )
  32. // Apply to lead opening
  33. await api.tx.contentDirectoryWorkingGroup
  34. .applyOnOpening(
  35. ALICE_MEMBER_ID, // member id
  36. NEW_OPENING_ID, // opening id
  37. sudoAddress, // address
  38. null, // opt role stake
  39. null, // opt appl. stake
  40. 'api-examples curator opening appl.' // human_readable_text
  41. )
  42. .signAndSend(sudo, { nonce: nonce++ })
  43. // Begin review period
  44. await sudoCall(api.tx.contentDirectoryWorkingGroup.beginApplicantReview(NEW_OPENING_ID))
  45. // Fill opening
  46. await sudoCall(
  47. api.tx.contentDirectoryWorkingGroup.fillOpening(
  48. NEW_OPENING_ID, // opening id
  49. [ALICE_MEMBER_ID], // succesful applicants
  50. null // reward policy
  51. )
  52. )
  53. // Create person class
  54. await api.tx.contentDirectory
  55. .createClass(
  56. 'Person',
  57. 'A class describing a person',
  58. // ClassPermissions
  59. {
  60. any_member: true,
  61. entity_creation_blocked: false,
  62. all_entity_property_values_locked: false,
  63. maintainers: [],
  64. },
  65. 10, // maximum_entities_count
  66. 5 // default_entity_creation_voucher_upper_bound
  67. )
  68. .signAndSend(sudo, { nonce: nonce++ })
  69. // Add schema to person class
  70. await api.tx.contentDirectory
  71. .addClassSchema(
  72. NEW_CLASS_ID,
  73. [], // existing_properties
  74. // new_properties:
  75. [
  76. {
  77. property_type: { Single: { Text: 64 } },
  78. required: true,
  79. unique: false,
  80. name: 'firstname',
  81. description: "Person's first name",
  82. locking_policy: { is_locked_from_maintainer: false, is_locked_from_controller: false },
  83. },
  84. {
  85. property_type: { Single: { Text: 64 } },
  86. required: true,
  87. unique: false,
  88. name: 'lastname',
  89. description: "Person's last name",
  90. locking_policy: { is_locked_from_maintainer: false, is_locked_from_controller: false },
  91. },
  92. {
  93. property_type: { Single: { Uint16: null } },
  94. required: true,
  95. unique: false,
  96. name: 'age',
  97. description: "Person's age",
  98. locking_policy: { is_locked_from_maintainer: false, is_locked_from_controller: false },
  99. },
  100. {
  101. property_type: { Vector: { vec_type: { Text: 32 }, max_length: 10 } },
  102. required: false,
  103. unique: false,
  104. name: 'hobbys',
  105. description: "Person's hobbys",
  106. locking_policy: { is_locked_from_maintainer: false, is_locked_from_controller: false },
  107. },
  108. ]
  109. )
  110. .signAndSend(sudo, { nonce: nonce++ })
  111. // Add another schema to person class
  112. await api.tx.contentDirectory
  113. .addClassSchema(
  114. NEW_CLASS_ID,
  115. [0, 1, 2, 3], // This still has to be in the right order (BTreeSet is part of the extrinsic metadata)
  116. // new_properties:
  117. [
  118. {
  119. property_type: { Single: { Text: 64 } },
  120. required: true,
  121. unique: true,
  122. name: 'uniqueIdentifier',
  123. description: "Person's unique identifier",
  124. locking_policy: { is_locked_from_maintainer: false, is_locked_from_controller: false },
  125. },
  126. ]
  127. )
  128. .signAndSend(sudo, { nonce: nonce++ })
  129. // Create person entity via "transaction" extrinsic
  130. await api.tx.contentDirectory
  131. .transaction(
  132. { Member: ALICE_MEMBER_ID }, // actor
  133. // operations:
  134. [
  135. { CreateEntity: { class_id: NEW_CLASS_ID } },
  136. {
  137. AddSchemaSupportToEntity: {
  138. entity_id: { InternalEntityJustAdded: 0 },
  139. schema_id: 1,
  140. parametrized_property_values: [
  141. {
  142. in_class_index: 0,
  143. value: { InputPropertyValue: { Single: { Text: 'John' } } },
  144. },
  145. {
  146. in_class_index: 1,
  147. value: { InputPropertyValue: { Single: { Text: 'Doe' } } },
  148. },
  149. {
  150. in_class_index: 2,
  151. value: { InputPropertyValue: { Single: { Uint16: 20 } } },
  152. },
  153. {
  154. in_class_index: 3,
  155. value: { InputPropertyValue: { Vector: { Text: ['blockchain', 'cryptocurrencies'] } } },
  156. },
  157. {
  158. in_class_index: 4,
  159. value: { InputPropertyValue: { Single: { Text: 'john_doe_unique_identifier' } } },
  160. },
  161. ],
  162. },
  163. },
  164. ]
  165. )
  166. .signAndSend(sudo, { nonce: nonce++ })
  167. }
  168. if (typeof module === 'undefined') {
  169. // Pioneer js-toolbox
  170. script({ api, hashing, keyring, types, util, joy })
  171. } else {
  172. // Node
  173. module.exports = script
  174. }