initializeContentDir.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { CreateClass } from '../types/extrinsics/CreateClass'
  2. import { AddClassSchema } from '../types/extrinsics/AddClassSchema'
  3. import { types } from '@joystream/types'
  4. import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'
  5. import { JoyBTreeSet } from '@joystream/types/common'
  6. import { PropertyId } from '@joystream/types/content-directory'
  7. import { getInputs } from './helpers/inputs'
  8. import { SubmittableExtrinsic } from '@polkadot/api/types'
  9. import { EntityBatchesParser } from './helpers/EntityBatchParser'
  10. import fs from 'fs'
  11. import path from 'path'
  12. type DescribedExtrinsic = {
  13. type: string
  14. inputFilename: string
  15. tx: SubmittableExtrinsic<'promise'>
  16. }
  17. // Classes
  18. const classInputs = getInputs<CreateClass>('classes')
  19. const schemaInputs = getInputs<AddClassSchema>('schemas')
  20. const entityBatchInputs = getInputs('entityBatches')
  21. async function main() {
  22. // Init api
  23. const WS_URI = process.env.WS_URI || 'ws://127.0.0.1:9944'
  24. console.log(`Initializing the api (${WS_URI})...`)
  25. const provider = new WsProvider(WS_URI)
  26. const api = await ApiPromise.create({ provider, types })
  27. // Init ALICE keypair
  28. const keyring = new Keyring({ type: 'sr25519' })
  29. keyring.addFromUri('//Alice', { name: 'Alice' })
  30. const ALICE = keyring.getPairs()[0]
  31. // Emptiness check
  32. if ((await api.query.contentDirectory.nextClassId()).toNumber() > 1) {
  33. console.log('Content directory is not empty! Skipping...')
  34. process.exit()
  35. }
  36. const classExtrinsics = classInputs.map(({ data, fileName }) => ({
  37. type: 'CreateClass',
  38. inputFilename: fileName,
  39. tx: api.tx.contentDirectory.createClass(
  40. data.name,
  41. data.description,
  42. data.class_permissions || {},
  43. data.maximum_entities_count,
  44. data.default_entity_creation_voucher_upper_bound
  45. ),
  46. }))
  47. // Schemas
  48. const schemaExtrinsics = schemaInputs.map(({ data, fileName }) => ({
  49. type: 'AddClassSchema',
  50. inputFilename: fileName,
  51. tx: api.tx.contentDirectory.addClassSchema(
  52. data.classId,
  53. new (JoyBTreeSet(PropertyId))(api.registry, data.existingProperties),
  54. data.newProperties || []
  55. ),
  56. }))
  57. let nonce = (await api.query.system.account(ALICE.address)).nonce.toNumber()
  58. console.log('Initializing classes and schemas...\n')
  59. const extrinsics: DescribedExtrinsic[] = [...classExtrinsics, ...schemaExtrinsics]
  60. for (const { type, inputFilename, tx } of extrinsics) {
  61. console.log(`Sending ${type} extrinsic based on input file: ${inputFilename}`)
  62. await tx.signAndSend(ALICE, { nonce: nonce++ })
  63. }
  64. console.log('Initializing entities...\n')
  65. // Entity batches
  66. const entityBatchParser = new EntityBatchesParser(schemaInputs, entityBatchInputs)
  67. console.log('Parsing input into operations...')
  68. const operations = entityBatchParser.getOperations()
  69. // Save operations in operations.json (for reference in case of errors)
  70. const outputPath = path.join(__dirname, '../operations.json')
  71. console.log(`Saving entity batch operations in ${outputPath}...`)
  72. fs.writeFileSync(
  73. outputPath,
  74. JSON.stringify(
  75. operations.map((o) => o.toJSON()),
  76. null,
  77. 4
  78. )
  79. )
  80. console.log('Sending Transaction extrinsic...')
  81. await api.tx.contentDirectory.transaction({ Lead: null }, operations).signAndSend(ALICE, { nonce: nonce++ })
  82. }
  83. main()
  84. .then(() => process.exit())
  85. .catch((e) => console.error(e))