decode.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import { SubstrateEvent } from '../../generated/indexer'
  2. import {
  3. IPropertyIdWithName,
  4. IClassEntity,
  5. IProperty,
  6. IBatchOperation,
  7. ICreateEntityOperation,
  8. IEntity,
  9. } from '../types'
  10. import {
  11. ParametrizedClassPropertyValue,
  12. ParametrizedPropertyValue,
  13. ParameterizedEntity,
  14. UpdatePropertyValuesOperation,
  15. InputPropertyValue,
  16. OperationType,
  17. } from '@joystream/types/content-directory'
  18. import { createType } from '@joystream/types'
  19. function stringIfyEntityId(event: SubstrateEvent): string {
  20. const { 1: entityId } = event.params
  21. return entityId.value as string
  22. }
  23. function setProperties<T>({ extrinsic, blockNumber }: SubstrateEvent, propNamesWithId: IPropertyIdWithName): T {
  24. if (extrinsic === undefined) throw Error('Undefined extrinsic')
  25. const { 3: newPropertyValues } = extrinsic!.args
  26. const properties: { [key: string]: any } = {}
  27. for (const [k, v] of Object.entries(newPropertyValues.value)) {
  28. const propertyName = propNamesWithId[k]
  29. const propertyValue = (createType('InputPropertyValue' as never, v as never) as InputPropertyValue)
  30. .asType('Single')
  31. .value.toJSON()
  32. properties[propertyName] = propertyValue
  33. }
  34. properties.version = blockNumber
  35. return properties as T
  36. }
  37. function getClassEntity(event: SubstrateEvent): IClassEntity {
  38. const { 0: classId } = event.extrinsic!.args
  39. const { 1: entityId } = event.params
  40. return {
  41. entityId: (entityId.value as unknown) as number,
  42. classId: (classId.value as unknown) as number,
  43. }
  44. }
  45. /**
  46. * When entity is creation through `transaction` extrinsic we use this function to parse
  47. * entity properties it looks quite similar to `setProperties` function
  48. * @param properties
  49. * @param propertyNamesWithId
  50. */
  51. function setEntityPropertyValues<T>(properties: IProperty[], propertyNamesWithId: IPropertyIdWithName): T {
  52. const entityProperties: { [key: string]: any } = {}
  53. for (const [propId, propName] of Object.entries(propertyNamesWithId)) {
  54. // get the property value by id
  55. const p = properties.find((p) => p.propertyId === propId)
  56. const propertyValue = p ? p.value : undefined
  57. entityProperties[propName] = propertyValue
  58. }
  59. // console.log(entityProperties);
  60. return entityProperties as T
  61. }
  62. // Decode entity property values
  63. function getEntityProperties(propertyValues: ParametrizedClassPropertyValue[]): IProperty[] {
  64. const properties: IProperty[] = []
  65. const entityPropertyValues = createType(
  66. 'Vec<ParametrizedClassPropertyValue>' as never,
  67. propertyValues as never
  68. ) as ParametrizedClassPropertyValue[]
  69. entityPropertyValues.map((pv: ParametrizedClassPropertyValue) => {
  70. const v = createType('ParametrizedPropertyValue' as never, pv.value as never) as ParametrizedPropertyValue
  71. const propertyId = pv.in_class_index.toJSON()
  72. let value
  73. if (v.isOfType('InputPropertyValue')) {
  74. const inputPropVal = v.asType('InputPropertyValue')
  75. value = inputPropVal.isOfType('Single')
  76. ? inputPropVal.asType('Single').value.toJSON()
  77. : inputPropVal.asType('Vector').value.toJSON()
  78. } else if (v.isOfType('InternalEntityJustAdded')) {
  79. // const inputPropVal = v.asType('InternalEntityJustAdded');
  80. value = v.asType('InternalEntityJustAdded').toJSON()
  81. } else {
  82. // TODO: Add support for v.asType('InternalEntityVec')
  83. throw Error('InternalEntityVec property type is not supported yet!')
  84. }
  85. properties.push({ propertyId: `${propertyId}`, value })
  86. })
  87. return properties
  88. }
  89. function getOperations({ extrinsic }: SubstrateEvent): IBatchOperation {
  90. const operations = createType('Vec<OperationType>' as never, extrinsic!.args[1].value as never) as OperationType[]
  91. const updatePropertyValuesOperations: IEntity[] = []
  92. const addSchemaSupportToEntityOperations: IEntity[] = []
  93. const createEntityOperations: ICreateEntityOperation[] = []
  94. for (const operation of operations) {
  95. if (operation.isOfType('CreateEntity')) {
  96. const cep = operation.asType('CreateEntity')
  97. createEntityOperations.push({ classId: cep.class_id.toJSON() })
  98. } else if (operation.isOfType('AddSchemaSupportToEntity')) {
  99. const op = operation.asType('AddSchemaSupportToEntity')
  100. const pe = createType('ParameterizedEntity' as never, op.entity_id as never) as ParameterizedEntity
  101. const entity: IEntity = {
  102. properties: getEntityProperties(op.parametrized_property_values),
  103. }
  104. if (pe.isOfType('InternalEntityJustAdded')) {
  105. entity.indexOf = pe.asType('InternalEntityJustAdded').toJSON()
  106. } else {
  107. entity.entityId = pe.asType('ExistingEntity').toJSON()
  108. }
  109. addSchemaSupportToEntityOperations.push(entity)
  110. } else {
  111. updatePropertyValuesOperations.push(makeEntity(operation.asType('UpdatePropertyValues')))
  112. }
  113. }
  114. return {
  115. updatePropertyValuesOperations,
  116. addSchemaSupportToEntityOperations,
  117. createEntityOperations,
  118. }
  119. }
  120. function makeEntity(upv: UpdatePropertyValuesOperation): IEntity {
  121. const entity: IEntity = {
  122. properties: getEntityProperties(upv.new_parametrized_property_values),
  123. }
  124. const pe = createType('ParameterizedEntity' as never, upv.entity_id as never) as ParameterizedEntity
  125. if (pe.isOfType('InternalEntityJustAdded')) {
  126. entity.indexOf = pe.asType('InternalEntityJustAdded').toJSON()
  127. } else {
  128. entity.entityId = pe.asType('ExistingEntity').toJSON()
  129. }
  130. return entity
  131. }
  132. export const decode = {
  133. stringIfyEntityId,
  134. getClassEntity,
  135. setEntityPropertyValues,
  136. getEntityProperties,
  137. getOperations,
  138. setProperties,
  139. }