assets.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. 'use strict'
  2. const debug = require('debug')('joystream:runtime:assets')
  3. const { decodeAddress } = require('@polkadot/keyring')
  4. function parseContentId (contentId) {
  5. try {
  6. return decodeAddress(contentId)
  7. } catch (err) {
  8. return contentId
  9. }
  10. }
  11. /*
  12. * Add asset related functionality to the substrate API.
  13. */
  14. class AssetsApi {
  15. static async create (base) {
  16. const ret = new AssetsApi()
  17. ret.base = base
  18. await ret.init()
  19. return ret
  20. }
  21. async init () {
  22. debug('Init')
  23. }
  24. /*
  25. * Create a data object.
  26. */
  27. async createDataObject (accountId, memberId, contentId, doTypeId, size, ipfsCid) {
  28. contentId = parseContentId(contentId)
  29. const tx = this.base.api.tx.dataDirectory.addContent(memberId, contentId, doTypeId, size, ipfsCid)
  30. await this.base.signAndSend(accountId, tx)
  31. // If the data object constructed properly, we should now be able to return
  32. // the data object from the state.
  33. return this.getDataObject(contentId)
  34. }
  35. /*
  36. * Return the Data Object for a CID
  37. */
  38. async getDataObject (contentId) {
  39. contentId = parseContentId(contentId)
  40. return this.base.api.query.dataDirectory.dataObjectByContentId(contentId)
  41. }
  42. /*
  43. * Verify the liaison state for a DO:
  44. * - Check the content ID has a DO
  45. * - Check the storageProviderId is the liaison
  46. * - Check the liaison state is pending
  47. *
  48. * Each failure errors out, success returns the data object.
  49. */
  50. async checkLiaisonForDataObject (storageProviderId, contentId) {
  51. contentId = parseContentId(contentId)
  52. let obj = await this.getDataObject(contentId)
  53. if (obj.isNone) {
  54. throw new Error(`No DataObject created for content ID: ${contentId}`)
  55. }
  56. obj = obj.unwrap()
  57. if (!obj.liaison.eq(storageProviderId)) {
  58. throw new Error(`This storage node is not liaison for the content ID: ${contentId}`)
  59. }
  60. if (obj.liaison_judgement.type !== 'Pending') {
  61. throw new Error(`Expected Pending judgement, but found: ${obj.liaison_judgement.type}`)
  62. }
  63. return obj
  64. }
  65. /*
  66. * Changes a data object liaison judgement.
  67. */
  68. async acceptContent (providerAccoundId, storageProviderId, contentId) {
  69. contentId = parseContentId(contentId)
  70. const tx = this.base.api.tx.dataDirectory.acceptContent(storageProviderId, contentId)
  71. return this.base.signAndSend(providerAccoundId, tx)
  72. }
  73. /*
  74. * Changes a data object liaison judgement.
  75. */
  76. async rejectContent (providerAccountId, storageProviderId, contentId) {
  77. contentId = parseContentId(contentId)
  78. const tx = this.base.api.tx.dataDirectory.rejectContent(storageProviderId, contentId)
  79. return this.base.signAndSend(providerAccountId, tx)
  80. }
  81. /*
  82. * Create storage relationship
  83. */
  84. async createStorageRelationship (providerAccountId, storageProviderId, contentId, callback) {
  85. contentId = parseContentId(contentId)
  86. const tx = this.base.api.tx.dataObjectStorageRegistry.addRelationship(storageProviderId, contentId)
  87. const subscribed = [['dataObjectStorageRegistry', 'DataObjectStorageRelationshipAdded']]
  88. return this.base.signAndSend(providerAccountId, tx, 3, subscribed, callback)
  89. }
  90. /*
  91. * Get storage relationship for contentId
  92. */
  93. async getStorageRelationshipAndId (storageProviderId, contentId) {
  94. contentId = parseContentId(contentId)
  95. let rids = await this.base.api.query.dataObjectStorageRegistry.relationshipsByContentId(contentId)
  96. while (rids.length) {
  97. const relationshipId = rids.shift()
  98. let relationship = await this.base.api.query.dataObjectStorageRegistry.relationships(relationshipId)
  99. relationship = relationship.unwrap()
  100. if (relationship.storage_provider.eq(storageProviderId)) {
  101. return ({ relationship, relationshipId })
  102. }
  103. }
  104. return {}
  105. }
  106. async createAndReturnStorageRelationship (providerAccountId, storageProviderId, contentId) {
  107. contentId = parseContentId(contentId)
  108. return new Promise(async (resolve, reject) => {
  109. try {
  110. await this.createStorageRelationship(providerAccountId, storageProviderId, contentId, (events) => {
  111. events.forEach((event) => {
  112. resolve(event[1].DataObjectStorageRelationshipId)
  113. })
  114. })
  115. } catch (err) {
  116. reject(err)
  117. }
  118. })
  119. }
  120. /*
  121. * Toggle ready state for DOSR.
  122. */
  123. async toggleStorageRelationshipReady (providerAccountId, storageProviderId, dosrId, ready) {
  124. var tx = ready
  125. ? this.base.api.tx.dataObjectStorageRegistry.setRelationshipReady(storageProviderId, dosrId)
  126. : this.base.api.tx.dataObjectStorageRegistry.unsetRelationshipReady(storageProviderId, dosrId)
  127. return this.base.signAndSend(providerAccountId, tx)
  128. }
  129. async getKnownContentIds () {
  130. return this.base.api.query.dataDirectory.knownContentIds()
  131. }
  132. }
  133. module.exports = {
  134. AssetsApi
  135. }