dev.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. 'use strict'
  2. const debug = require('debug')('joystream:storage-cli:dev')
  3. // Derivation path appended to well known development seed used on
  4. // development chains
  5. const ALICE_URI = '//Alice'
  6. const ROLE_ACCOUNT_URI = '//Colossus'
  7. function aliceKeyPair(api) {
  8. return api.identities.keyring.addFromUri(ALICE_URI, null, 'sr25519')
  9. }
  10. function roleKeyPair(api) {
  11. return api.identities.keyring.addFromUri(ROLE_ACCOUNT_URI, null, 'sr25519')
  12. }
  13. function developmentPort() {
  14. return 3001
  15. }
  16. const dispatchCalls = async (runtimeApi, senderAddress, rawCalls, batched = false) => {
  17. const api = runtimeApi.api
  18. const numCalls = rawCalls.length
  19. debug(`processing ${numCalls} transactions...`)
  20. let lastCall
  21. for (let i = 0; i < numCalls; i++) {
  22. debug(`${i + 1}/${numCalls} processed.`)
  23. const { methodName, sectionName, args } = rawCalls[i]
  24. const tx = api.tx[sectionName][methodName](...args)
  25. lastCall = runtimeApi.signAndSend(senderAddress, tx)
  26. if (!batched) {
  27. await lastCall
  28. }
  29. }
  30. return lastCall
  31. }
  32. const initVstore = async (api, contentLead) => {
  33. const firstClass = await api.api.rpc.state.getStorage(api.api.query.versionedStore.classById.key(1))
  34. if (firstClass.isSome) {
  35. debug('Skipping Initializing Content Directory, classes already exist')
  36. return
  37. }
  38. const classes = require('../../../../devops/vstore/classes.json')
  39. const entities = require('../../../../devops/vstore/entities.json')
  40. debug('Initializing Content Directory')
  41. // batch createClass calls into a single block
  42. debug('creating classes...')
  43. const createClasses = classes.filter(call => {
  44. return call.methodName === 'createClass'
  45. })
  46. await dispatchCalls(api, contentLead, createClasses, true)
  47. // batch addClassSchema calls into a single block
  48. debug('adding schemas to classes...')
  49. const addClassSchema = classes.filter(call => {
  50. return call.methodName === 'addClassSchema'
  51. })
  52. await dispatchCalls(api, contentLead, addClassSchema, true)
  53. debug('creating entities...')
  54. // Will this not overload the node.. Might not be safe to do on production network
  55. await dispatchCalls(api, contentLead, entities, true)
  56. }
  57. const check = async api => {
  58. const roleAccountId = roleKeyPair(api).address
  59. const providerId = await api.workers.findProviderIdByRoleAccount(roleAccountId)
  60. if (providerId === null) {
  61. throw new Error('Dev storage provider not found on chain!')
  62. }
  63. console.log(`
  64. Chain is setup with Dev storage provider:
  65. providerId = ${providerId}
  66. roleAccountId = ${roleAccountId}
  67. roleKey = ${ROLE_ACCOUNT_URI}
  68. `)
  69. return providerId
  70. }
  71. // Setup Alice account on a developement chain as
  72. // a member, storage lead, and a storage provider using a deterministic
  73. // development key for the role account
  74. const init = async api => {
  75. try {
  76. await check(api)
  77. return
  78. } catch (err) {
  79. // We didn't find a storage provider with expected role account
  80. }
  81. const alice = aliceKeyPair(api).address
  82. const roleAccount = roleKeyPair(api).address
  83. debug(`Ensuring Alice is sudo`)
  84. // make sure alice is sudo - indirectly checking this is a dev chain
  85. const sudo = await api.identities.getSudoAccount()
  86. if (!sudo.eq(alice)) {
  87. throw new Error('Setup requires Alice to be sudo. Are you sure you are running a devchain?')
  88. }
  89. console.log('Running setup')
  90. debug('Ensuring Alice is as member..')
  91. let aliceMemberId = await api.identities.firstMemberIdOf(alice)
  92. if (aliceMemberId === undefined) {
  93. debug('Registering Alice as member..')
  94. aliceMemberId = await api.identities.registerMember(alice, {
  95. handle: 'alice',
  96. })
  97. } else {
  98. debug('Alice is already a member')
  99. }
  100. debug('Setting Alice as content working group lead')
  101. await api.signAndSend(alice, api.api.tx.sudo.sudo(api.api.tx.contentWorkingGroup.replaceLead([aliceMemberId, alice])))
  102. await initVstore(api, alice)
  103. // set localhost colossus as discovery provider
  104. // assuming pioneer dev server is running on port 3000 we should run
  105. // the storage dev server on a different port than the default for colossus which is also
  106. // 3000
  107. debug('Setting Local development node as bootstrap endpoint')
  108. await api.discovery.setBootstrapEndpoints(alice, [`http://localhost:${developmentPort()}/`])
  109. debug('Transferring tokens to storage role account')
  110. // Give role account some tokens to work with
  111. api.balances.transfer(alice, roleAccount, 100000)
  112. // Make alice the storage lead
  113. debug('Making Alice the storage Lead')
  114. const leadOpeningId = await api.workers.devAddStorageLeadOpening()
  115. const leadApplicationId = await api.workers.devApplyOnOpening(leadOpeningId, aliceMemberId, alice, alice)
  116. api.workers.devBeginLeadOpeningReview(leadOpeningId)
  117. await api.workers.devFillLeadOpening(leadOpeningId, leadApplicationId)
  118. const leadAccount = await api.workers.getLeadRoleAccount()
  119. if (!leadAccount.eq(alice)) {
  120. throw new Error('Setting alice as lead failed')
  121. }
  122. // Create a storage openinging, apply, start review, and fill opening
  123. debug(`Making ${ROLE_ACCOUNT_URI} account a storage provider`)
  124. const openingId = await api.workers.devAddStorageOpening()
  125. debug(`created new storage opening: ${openingId}`)
  126. const applicationId = await api.workers.devApplyOnOpening(openingId, aliceMemberId, alice, roleAccount)
  127. debug(`applied with application id: ${applicationId}`)
  128. api.workers.devBeginStorageOpeningReview(openingId)
  129. debug(`filling storage opening`)
  130. const providerId = await api.workers.devFillStorageOpening(openingId, applicationId)
  131. debug(`Assigned storage provider id: ${providerId}`)
  132. return check(api)
  133. }
  134. module.exports = {
  135. init,
  136. check,
  137. aliceKeyPair,
  138. roleKeyPair,
  139. developmentPort,
  140. }