decode.ts 5.1 KB

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