Browse Source

Merge pull request #1124 from Lezek123/joystream-types-upgrade

Joystream types - refactorization and upgrade
Mokhtar Naamani 4 years ago
parent
commit
b613ee968f
44 changed files with 2045 additions and 3360 deletions
  1. 9 8
      package.json
  2. 1 0
      types/.prettierignore
  3. 9 3
      types/package.json
  4. 22 14
      types/src/JoyEnum.ts
  5. 63 34
      types/src/JoyStruct.ts
  6. 19 79
      types/src/common.ts
  7. 193 432
      types/src/content-working-group/index.ts
  8. 72 166
      types/src/council/index.ts
  9. 26 0
      types/src/definitions/augment-types.ts
  10. 2 0
      types/src/definitions/definitions.ts
  11. 12 32
      types/src/discovery.ts
  12. 90 148
      types/src/forum.ts
  13. 132 316
      types/src/hiring/index.ts
  14. 35 41
      types/src/index.ts
  15. 47 114
      types/src/media.ts
  16. 40 127
      types/src/members.ts
  17. 32 63
      types/src/mint/index.ts
  18. 172 485
      types/src/proposals.ts
  19. 30 75
      types/src/recurring-rewards/index.ts
  20. 17 62
      types/src/roles.ts
  21. 41 0
      types/src/scripts/defsFromTypes.ts
  22. 108 0
      types/src/scripts/updateAugmentTypes.ts
  23. 47 100
      types/src/stake/index.ts
  24. 36 34
      types/src/versioned-store/EntityCodec.ts
  25. 27 76
      types/src/versioned-store/PropertyType.ts
  26. 0 22
      types/src/versioned-store/PropertyTypeName.ts
  27. 25 56
      types/src/versioned-store/PropertyValue.ts
  28. 51 105
      types/src/versioned-store/index.ts
  29. 12 45
      types/src/versioned-store/permissions/ClassPermissions.ts
  30. 7 20
      types/src/versioned-store/permissions/EntityPermissions.ts
  31. 7 20
      types/src/versioned-store/permissions/PropertyOfClass.ts
  32. 7 20
      types/src/versioned-store/permissions/batching/ParametrizedClassPropertyValue.ts
  33. 8 25
      types/src/versioned-store/permissions/batching/index.ts
  34. 19 26
      types/src/versioned-store/permissions/batching/operation-types.ts
  35. 23 57
      types/src/versioned-store/permissions/batching/operations.ts
  36. 13 22
      types/src/versioned-store/permissions/batching/parametrized-entity.ts
  37. 21 26
      types/src/versioned-store/permissions/batching/parametrized-property-value.ts
  38. 8 13
      types/src/versioned-store/permissions/index.ts
  39. 9 32
      types/src/versioned-store/permissions/reference-constraint.ts
  40. 87 238
      types/src/working-group/index.ts
  41. 29 0
      types/tsconfig-base.json
  42. 6 0
      types/tsconfig-scripts.json
  43. 3 20
      types/tsconfig.json
  44. 428 204
      yarn.lock

+ 9 - 8
package.json

@@ -6,7 +6,7 @@
   "scripts": {
     "test": "yarn && yarn workspaces run test",
     "test-migration": "yarn && yarn workspaces run test-migration",
-    "postinstall": "yarn workspace @joystream/types build && yarn workspace storage-node run build",
+    "postinstall": "yarn workspace @joystream/types build",
     "cargo-checks": "devops/git-hooks/pre-commit && devops/git-hooks/pre-push",
     "cargo-build": "scripts/cargo-build.sh",
     "lint": "yarn workspaces run lint"
@@ -23,14 +23,15 @@
     "devops/prettier-config"
   ],
   "resolutions": {
-    "@polkadot/api": "^0.96.1",
-    "@polkadot/api-contract": "^0.96.1",
-    "@polkadot/keyring": "^1.7.0-beta.5",
-    "@polkadot/types": "^0.96.1",
-    "@polkadot/util": "^1.7.0-beta.5",
-    "@polkadot/util-crypto": "^1.7.0-beta.5",
+    "@polkadot/api": "^1.26.1",
+    "@polkadot/api-contract": "^1.26.1",
+    "@polkadot/keyring": "^3.0.1",
+    "@polkadot/types": "^1.26.1",
+    "@polkadot/util": "^3.0.1",
+    "@polkadot/util-crypto": "^3.0.1",
+    "@polkadot/wasm-crypto": "^1.2.1",
     "babel-core": "^7.0.0-bridge.0",
-    "typescript": "^3.7.2"
+    "typescript": "^3.9.7"
   },
   "devDependencies": {
     "husky": "^4.2.5",

+ 1 - 0
types/.prettierignore

@@ -4,3 +4,4 @@
 hiring/schemas/role.schema.json
 lib/
 build/
+src/definitions

+ 9 - 3
types/package.json

@@ -9,13 +9,17 @@
     "build": "tsc --build tsconfig.json",
     "lint": "eslint ./ --quiet --ext .ts",
     "format": "prettier ./ --write",
-    "checks": "yarn build && madge --circular ./ && yarn lint && prettier ./ --check"
+    "checks": "yarn build && madge --circular ./ && yarn lint && prettier ./ --check",
+    "generate:defs": "ts-node node_modules/.bin/polkadot-types-from-defs --package ./src --input ./src/definitions",
+    "update:augment-types": "tsc --build tsconfig-scripts.json && node ./src/scripts/updateAugmentTypes.js",
+    "print:typedef": "tsc --build tsconfig-scripts.json && node ./src/scripts/defsFromTypes.js"
   },
   "author": "Joystream contributors",
   "maintainers": [],
   "dependencies": {
-    "@polkadot/types": "^0.96.1",
-    "@polkadot/keyring": "^1.7.0-beta.5",
+    "@polkadot/api": "^1.26.1",
+    "@polkadot/types": "^1.26.1",
+    "@polkadot/keyring": "^3.0.1",
     "@types/lodash": "^4.14.157",
     "@types/vfile": "^4.0.0",
     "ajv": "^6.11.0",
@@ -23,6 +27,8 @@
     "moment": "^2.24.0"
   },
   "devDependencies": {
+    "@polkadot/typegen": "^1.26.1",
+    "ts-node": "^8.6.2",
     "typescript": "^3.7.2"
   },
   "engines": {

+ 22 - 14
types/src/JoyEnum.ts

@@ -1,36 +1,44 @@
-import { Constructor } from '@polkadot/types/types'
+import { Constructor, Registry } from '@polkadot/types/types'
 import { Enum } from '@polkadot/types/codec'
 import { EnumConstructor } from '@polkadot/types/codec/Enum'
 
 export interface ExtendedEnum<Types extends Record<string, Constructor>> extends Enum {
   isOfType: (type: keyof Types) => boolean
   asType<TypeKey extends keyof Types>(type: TypeKey): InstanceType<Types[TypeKey]>
+  typeDefinitions: Types
+  type: keyof Types & string // More typesafe type for the original Enum property
 }
 
 export interface ExtendedEnumConstructor<Types extends Record<string, Constructor>>
   extends EnumConstructor<ExtendedEnum<Types>> {
-  create<TypeKey extends keyof Types>(typeKey: TypeKey, value: InstanceType<Types[TypeKey]>): ExtendedEnum<Types>
+  create<TypeKey extends keyof Types>(
+    registry: Registry,
+    typeKey: TypeKey,
+    value: InstanceType<Types[TypeKey]>
+  ): ExtendedEnum<Types>
+  typeDefinitions: Types
 }
 
 // Helper for creating extended Enum type with TS-compatible isOfType and asType helpers
 export function JoyEnum<Types extends Record<string, Constructor>>(types: Types): ExtendedEnumConstructor<Types> {
-  // Unique values check
-  if (Object.values(types).some((val, i) => Object.values(types).indexOf(val, i + 1) !== -1)) {
-    throw new Error('Values passed to JoyEnum are not unique. Create an individual class for each value.')
-  }
-
-  return class JoyEnumObject extends Enum {
-    public static create<TypeKey extends keyof Types>(typeKey: TypeKey, value: InstanceType<Types[TypeKey]>) {
-      return new JoyEnumObject({ [typeKey]: value })
+  return class JoyEnumObject extends Enum.with(types) {
+    static typeDefinitions = types
+    typeDefinitions = JoyEnumObject.typeDefinitions // Non-static version
+    public static create<TypeKey extends keyof Types>(
+      registry: Registry,
+      typeKey: TypeKey,
+      value: InstanceType<Types[TypeKey]>
+    ) {
+      return new JoyEnumObject(registry, { [typeKey]: value })
     }
-    constructor(value?: any, index?: number) {
-      super(types, value, index)
+    constructor(registry: Registry, value?: any, index?: number) {
+      super(registry, value, index)
     }
     public isOfType(typeKey: keyof Types) {
-      return this.value instanceof types[typeKey]
+      return this.type === typeKey
     }
     public asType<TypeKey extends keyof Types>(typeKey: TypeKey) {
-      if (!(this.value instanceof types[typeKey])) {
+      if (!this.isOfType(typeKey)) {
         throw new Error(`Enum.asType(${typeKey}) - value is not of type ${typeKey}`)
       }
       return this.value as InstanceType<Types[TypeKey]>

+ 63 - 34
types/src/JoyStruct.ts

@@ -1,44 +1,73 @@
-import { Option, Struct, Enum } from '@polkadot/types/codec'
-import { Text, bool as Bool } from '@polkadot/types'
-import { Codec } from '@polkadot/types/types'
+import { Struct } from '@polkadot/types/codec'
+import { Codec, Constructor, Registry } from '@polkadot/types/types'
 
-export class JoyStruct<
-  T extends {
-    [K: string]: Codec
-  }
-> extends Struct {
-  getField<C extends Codec>(name: keyof T): C {
-    return super.get(name as string) as C
-  }
-
-  getString(name: keyof T): string {
-    return this.getField<Text>(name).toString()
-  }
+export interface ExtendedStruct<FieldTypes extends Record<string, Constructor>> extends Struct<FieldTypes> {
+  getField<FieldKey extends keyof FieldTypes>(key: FieldKey): InstanceType<FieldTypes[FieldKey]>
+  getString<FieldKey extends keyof FieldTypes>(key: FieldKey): string
+  cloneValues(): { [k in keyof FieldTypes]: FieldTypes[k] }
+}
 
-  getBoolean(name: keyof T): boolean {
-    return this.getField<Bool>(name).valueOf()
-  }
+// Those getters are automatically added via Object.defineProperty when using Struct.with
+export type ExtendedStructGetters<FieldTypes extends Record<string, Constructor>> = {
+  [k in keyof FieldTypes]: InstanceType<FieldTypes[k]>
+}
+// More rich TypeScript definition of the Struct (includes automatically created getters)
+export type ExtendedStructDecorated<FieldTypes extends Record<string, Constructor>> = ExtendedStructGetters<
+  FieldTypes
+> &
+  ExtendedStruct<FieldTypes>
 
-  getEnumAsString<EnumValue extends string>(name: keyof T): EnumValue {
-    return this.getField<Enum>(name).toString() as EnumValue
-  }
+export interface StructConstructor<
+  FieldTypes extends Record<string, Constructor>,
+  StructType extends Struct<FieldTypes>
+> {
+  new (registry: Registry, value?: { [k in keyof FieldTypes]: InstanceType<FieldTypes[k]> }): StructType
+}
 
-  unwrapOrUndefined<C extends Codec>(name: keyof T): C | undefined {
-    return this.getField<Option<C>>(name).unwrapOr(undefined)
-  }
+export type ExtendedStructConstructor<FieldTypes extends Record<string, Constructor>> = StructConstructor<
+  FieldTypes,
+  ExtendedStruct<FieldTypes>
+>
 
-  getOptionalString(name: keyof T): string | undefined {
-    const text = this.unwrapOrUndefined<Text>(name)
-    return text ? text.toString() : undefined
-  }
+export type ExtendedStructDecoratedConstructor<FieldTypes extends Record<string, Constructor>> = StructConstructor<
+  FieldTypes,
+  ExtendedStructDecorated<FieldTypes>
+>
 
-  cloneValues(): T {
-    const objectClone = {} as { [K: string]: Codec }
+// Helper for creating extended Struct type with TS-compatible interface
+// It's called JoyStructCustom, because eventually we'd want to migrate all structs to JoyStructDecorated,
+// but the latter won't allow specifying getters that return different type than the original field type.
+// (ie. by using getString() instead of getField())
+export function JoyStructCustom<FieldTypes extends Record<string, Constructor>>(
+  fields: FieldTypes
+): ExtendedStructConstructor<FieldTypes> {
+  return class JoyStructObject extends Struct.with(fields) {
+    constructor(registry: Registry, value?: { [k in keyof FieldTypes]: InstanceType<FieldTypes[k]> }) {
+      super(registry, value)
+    }
+    getField<FieldKey extends keyof FieldTypes>(key: FieldKey): InstanceType<FieldTypes[FieldKey]> {
+      return this.get(key as string) as InstanceType<FieldTypes[FieldKey]>
+    }
+    getString<FieldKey extends keyof FieldTypes>(key: FieldKey): string {
+      return this.getField(key).toString()
+    }
+    // TODO: Check why would this ever be needed
+    cloneValues(): { [k in keyof FieldTypes]: FieldTypes[k] } {
+      const objectClone = {} as Partial<{ [k in keyof FieldTypes]: Codec }>
 
-    super.forEach((v, k) => {
-      objectClone[k] = v // shallow copy acceptable ?
-    })
+      super.forEach((v, k) => {
+        objectClone[k] = v // shallow copy acceptable ?
+      })
 
-    return objectClone as T
+      return (objectClone as unknown) as { [k in keyof FieldTypes]: FieldTypes[k] }
+    }
   }
 }
+
+// JoyStruct enriched with typescript definitions for getters automatically added by polkadot-js
+export function JoyStructDecorated<FieldTypes extends Record<string, Constructor>>(
+  fields: FieldTypes
+): ExtendedStructDecoratedConstructor<FieldTypes> {
+  // We need to cast here because there's no way to make TS aware of getters added with Object.defineProperty
+  return JoyStructCustom(fields) as ExtendedStructDecoratedConstructor<FieldTypes>
+}

+ 19 - 79
types/src/common.ts

@@ -1,15 +1,12 @@
-import { Struct, Option, Text, bool, Vec, u16, u32, u64, getTypeRegistry, Null } from '@polkadot/types'
+import { Struct, Option, Text, bool, Vec, u16, u32, u64, Null } from '@polkadot/types'
 import { BlockNumber, Moment } from '@polkadot/types/interfaces'
-import { Codec } from '@polkadot/types/types'
+import { Codec, RegistryTypes } from '@polkadot/types/types'
 // we get 'moment' because it is a dependency of @polkadot/util, via @polkadot/keyring
 import moment from 'moment'
-import { JoyStruct } from './JoyStruct'
+import { JoyStructCustom, JoyStructDecorated } from './JoyStruct'
 import { JoyEnum } from './JoyEnum'
-export { JoyStruct } from './JoyStruct'
-export { JoyEnum } from './JoyEnum'
 
-// Treat a BTreeSet as a Vec since it is encoded in the same way
-export class BTreeSet<T extends Codec> extends Vec<T> {}
+export { JoyEnum, JoyStructCustom, JoyStructDecorated }
 
 export class Credential extends u64 {}
 export class CredentialSet extends Vec.with(Credential) {} // BtreeSet ?
@@ -23,29 +20,7 @@ export type BlockAndTimeType = {
   time: Moment
 }
 
-export class BlockAndTime extends Struct {
-  constructor(value?: BlockAndTimeType) {
-    super(
-      {
-        block: u32, // BlockNumber
-        time: u64, // Moment
-      },
-      value
-    )
-  }
-
-  get block(): BlockNumber {
-    return this.get('block') as BlockNumber
-  }
-
-  get time(): Moment {
-    return this.get('time') as Moment
-  }
-
-  static newEmpty(): BlockAndTime {
-    return new BlockAndTime({} as BlockAndTime)
-  }
-
+export class BlockAndTime extends JoyStructDecorated({ block: u32, time: u64 }) implements BlockAndTimeType {
   get momentDate(): moment.Moment {
     const YEAR_2000_MILLISECONDS = 946684801000
 
@@ -76,49 +51,17 @@ export function getOptionPropOrUndefined<T extends Codec>(struct: Struct, fieldN
   return (struct.get(fieldName) as Option<T>).unwrapOr(undefined)
 }
 
-export class OptionText extends Option.with(Text) {
-  static none(): OptionText {
-    return new Option(Text, null)
-  }
-
-  static some(text: string): OptionText {
-    return new Option(Text, text)
-  }
-}
+export class OptionText extends Option.with(Text) {}
 
 export type InputValidationLengthConstraintType = {
   min: u16
   max_min_diff: u16
 }
 
-export class InputValidationLengthConstraint extends JoyStruct<InputValidationLengthConstraintType> {
-  constructor(value: InputValidationLengthConstraintType) {
-    super(
-      {
-        min: u16,
-        max_min_diff: u16,
-      },
-      value
-    )
-  }
-
-  static createWithMaxAllowed() {
-    return new InputValidationLengthConstraint({
-      min: new u16(1),
-      max_min_diff: new u16(65534), // Max allowed without causing u16 overflow
-    })
-  }
-
-  get min(): u16 {
-    return this.getField('min')
-  }
-
-  get max_min_diff(): u16 {
-    return this.getField('max_min_diff')
-  }
-
+export class InputValidationLengthConstraint extends JoyStructDecorated({ min: u16, max_min_diff: u16 })
+  implements InputValidationLengthConstraintType {
   get max(): u16 {
-    return new u16(this.min.add(this.max_min_diff))
+    return new u16(this.registry, this.min.add(this.max_min_diff))
   }
 }
 
@@ -128,17 +71,14 @@ export const WorkingGroupDef = {
 export type WorkingGroupKey = keyof typeof WorkingGroupDef
 export class WorkingGroup extends JoyEnum(WorkingGroupDef) {}
 
-export function registerCommonTypes() {
-  const typeRegistry = getTypeRegistry()
-
-  typeRegistry.register({
-    Credential,
-    CredentialSet,
-    BlockAndTime,
-    ThreadId,
-    PostId,
-    InputValidationLengthConstraint,
-    BTreeSet, // Is this even necessary?
-    WorkingGroup,
-  })
+export const commonTypes: RegistryTypes = {
+  Credential,
+  CredentialSet,
+  BlockAndTime,
+  ThreadId,
+  PostId,
+  InputValidationLengthConstraint,
+  WorkingGroup,
 }
+
+export default commonTypes

+ 193 - 432
types/src/content-working-group/index.ts

@@ -1,26 +1,13 @@
-import {
-  getTypeRegistry,
-  BTreeMap,
-  Enum,
-  bool,
-  u8,
-  u32,
-  Text,
-  GenericAccountId,
-  Null,
-  Option,
-  Vec,
-  u16,
-} from '@polkadot/types'
-import { BlockNumber, AccountId } from '@polkadot/types/interfaces'
-import { BTreeSet, JoyStruct, OptionText, Credential } from '../common'
+import { BTreeMap, BTreeSet, bool, u32, Text, Null, Option, Vec, u16 } from '@polkadot/types'
+import { BlockNumber } from '@polkadot/types/interfaces'
+import { OptionText, Credential, JoyEnum, JoyStructDecorated } from '../common'
 import { ActorId, MemberId } from '../members'
 import { StakeId } from '../stake'
 import { OpeningId, ApplicationId, ApplicationRationingPolicy, StakingPolicy } from '../hiring/index'
 import { RewardRelationshipId } from '../recurring-rewards'
-
 import ChannelId from './ChannelId'
-import { JoyEnum } from '../JoyEnum'
+import AccountId from '@polkadot/types/generic/AccountId'
+
 export { ChannelId }
 export class CuratorId extends ActorId {}
 export class CuratorOpeningId extends OpeningId {}
@@ -30,35 +17,33 @@ export class PrincipalId extends Credential {}
 
 export class OptionalText extends OptionText {}
 
-export type ChannelContentTypeValue = 'Video' | 'Music' | 'Ebook'
-
-export const ChannelContentTypeAllValues: ChannelContentTypeValue[] = ['Video', 'Music', 'Ebook']
-
-export class ChannelContentType extends Enum {
-  constructor(value?: ChannelContentTypeValue, index?: number) {
-    super(ChannelContentTypeAllValues, value, index)
-  }
-}
-
-export type ChannelPublicationStatusValue = 'Public' | 'Unlisted'
-
-export const ChannelPublicationStatusAllValues: ChannelPublicationStatusValue[] = ['Public', 'Unlisted']
-
-export class ChannelPublicationStatus extends Enum {
-  constructor(value?: ChannelPublicationStatusValue, index?: number) {
-    super(ChannelPublicationStatusAllValues, value, index)
-  }
-}
-
-export type ChannelCurationStatusValue = 'Normal' | 'Censored'
-
-export const ChannelCurationStatusAllValues: ChannelCurationStatusValue[] = ['Normal', 'Censored']
-
-export class ChannelCurationStatus extends Enum {
-  constructor(value?: ChannelCurationStatusValue, index?: number) {
-    super(ChannelCurationStatusAllValues, value, index)
-  }
-}
+export const ChannelContentTypeAllValues = ['Video', 'Music', 'Ebook'] as const
+// FIXME: Naming conventions (Keys?)
+export type ChannelContentTypeValue = typeof ChannelContentTypeAllValues[number]
+export const ChannelContentTypeDef = {
+  Video: Null,
+  Music: Null,
+  Ebook: Null,
+} as const
+export class ChannelContentType extends JoyEnum(ChannelContentTypeDef) {}
+
+export const ChannelPublicationStatusAllValues = ['Public', 'Unlisted'] as const
+// FIXME: Naming conventions (Keys?)
+export type ChannelPublicationStatusValue = typeof ChannelPublicationStatusAllValues[number]
+export const ChannelPublicationStatusDef = {
+  Public: Null,
+  Unlisted: Null,
+} as const
+export class ChannelPublicationStatus extends JoyEnum(ChannelPublicationStatusDef) {}
+
+export const ChannelCurationStatusAllValues = ['Normal', 'Censored'] as const
+// FIXME: Naming conventions (Keys?)
+export type ChannelCurationStatusValue = typeof ChannelCurationStatusAllValues[number]
+export const ChannelCurationStatusDef = {
+  Normal: Null,
+  Censored: Null,
+} as const
+export class ChannelCurationStatus extends JoyEnum(ChannelCurationStatusDef) {}
 
 export type IChannel = {
   verified: bool
@@ -75,153 +60,95 @@ export type IChannel = {
   created: BlockNumber
   principal_id: PrincipalId
 }
-export class Channel extends JoyStruct<IChannel> {
-  constructor(value?: IChannel) {
-    super(
-      {
-        verified: bool,
-        handle: Text, // Vec.with(u8),
-        title: OptionalText,
-        description: OptionalText,
-        avatar: OptionalText,
-        banner: OptionalText,
-        content: ChannelContentType,
-        owner: MemberId,
-        role_account: GenericAccountId,
-        publication_status: ChannelPublicationStatus,
-        curation_status: ChannelCurationStatus,
-        created: u32, // BlockNumber,
-        principal_id: PrincipalId,
-      },
-      value
-    )
-  }
-}
+export class Channel
+  extends JoyStructDecorated({
+    verified: bool,
+    handle: Text, // Vec.with(u8),
+    title: OptionalText,
+    description: OptionalText,
+    avatar: OptionalText,
+    banner: OptionalText,
+    content: ChannelContentType,
+    owner: MemberId,
+    role_account: AccountId,
+    publication_status: ChannelPublicationStatus,
+    curation_status: ChannelCurationStatus,
+    created: u32, // BlockNumber,
+    principal_id: PrincipalId,
+  })
+  implements IChannel {}
 
 export class CurationActor extends JoyEnum({
   Lead: Null,
   Curator: CuratorId,
-}) {}
+} as const) {}
 
-export class Principal extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Lead: Null,
-        Curator: CuratorId,
-        ChannelOwner: ChannelId,
-      },
-      value,
-      index
-    )
-  }
-}
+export class Principal extends JoyEnum({
+  Lead: Null,
+  Curator: CuratorId,
+  ChannelOwner: ChannelId,
+} as const) {}
 
 export type ICuratorRoleStakeProfile = {
   stake_id: StakeId
   termination_unstaking_period: Option<BlockNumber>
   exit_unstaking_period: Option<BlockNumber>
 }
-export class CuratorRoleStakeProfile extends JoyStruct<ICuratorRoleStakeProfile> {
-  constructor(value?: ICuratorRoleStakeProfile) {
-    super(
-      {
-        stake_id: StakeId,
-        termination_unstaking_period: Option.with(u32),
-        exit_unstaking_period: Option.with(u32),
-      },
-      value
-    )
-  }
-
-  get stake_id(): StakeId {
-    return this.getField<StakeId>('stake_id')
-  }
-}
+export class CuratorRoleStakeProfile
+  extends JoyStructDecorated({
+    stake_id: StakeId,
+    termination_unstaking_period: Option.with(u32),
+    exit_unstaking_period: Option.with(u32),
+  })
+  implements ICuratorRoleStakeProfile {}
 
-export class CuratorExitInitiationOrigin extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Lead: Null,
-        Curator: Null,
-      },
-      value,
-      index
-    )
-  }
-}
+export class CuratorExitInitiationOrigin extends JoyEnum({
+  Lead: Null,
+  Curator: Null,
+} as const) {}
 
 export type ICuratorExitSummary = {
   origin: CuratorExitInitiationOrigin
   initiated_at_block_number: BlockNumber
-  rationale_text: Vec<u8>
-}
-export class CuratorExitSummary extends JoyStruct<ICuratorExitSummary> {
-  constructor(value?: ICuratorExitSummary) {
-    super(
-      {
-        origin: CuratorExitInitiationOrigin,
-        initiated_at_block_number: u32,
-        rationale_text: Text,
-      },
-      value
-    )
-  }
-}
-
-export enum CuratorRoleStakeKeys {
+  rationale_text: Text
+}
+export class CuratorExitSummary
+  extends JoyStructDecorated({
+    origin: CuratorExitInitiationOrigin,
+    initiated_at_block_number: u32,
+    rationale_text: Text, // FIXME: Should be: Bytes
+  })
+  implements ICuratorExitSummary {}
+
+// FIXME: Replace usages with isOfType, asType wherever possible
+export enum CuratorRoleStageKeys {
   Active = 'Active',
   Unstaking = 'Unstaking',
   Exited = 'Exited',
 }
-export class CuratorRoleStage extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        [CuratorRoleStakeKeys.Active]: Null,
-        [CuratorRoleStakeKeys.Unstaking]: CuratorExitSummary,
-        [CuratorRoleStakeKeys.Exited]: CuratorExitSummary,
-      },
-      value,
-      index
-    )
-  }
-}
+export const CuratorRoleStageDef = {
+  Active: Null,
+  Unstaking: CuratorExitSummary,
+  Exited: CuratorExitSummary,
+} as const
+export class CuratorRoleStage extends JoyEnum(CuratorRoleStageDef) {}
 
 export type ICuratorInduction = {
   lead: LeadId
   curator_application_id: CuratorApplicationId
   at_block: BlockNumber
 }
-export class CuratorInduction extends JoyStruct<ICuratorInduction> {
-  constructor(value?: ICuratorInduction) {
-    super(
-      {
-        lead: LeadId,
-        curator_application_id: CuratorApplicationId,
-        at_block: u32,
-      },
-      value
-    )
-  }
-
-  get lead(): LeadId {
-    return this.getField<LeadId>('lead')
-  }
-
-  get curator_application_id(): CuratorApplicationId {
-    return this.getField<CuratorApplicationId>('curator_application_id')
-  }
-
+export class CuratorInduction
+  extends JoyStructDecorated({
+    lead: LeadId,
+    curator_application_id: CuratorApplicationId,
+    at_block: u32,
+  })
+  implements ICuratorInduction {
   // Helper for working-group compatibility
   get worker_application_id(): CuratorApplicationId {
     return this.curator_application_id
   }
-
-  get at_block(): u32 {
-    return this.getField<u32>('at_block')
-  }
 }
 
 export type ICurator = {
@@ -232,52 +159,23 @@ export type ICurator = {
   induction: CuratorInduction
   principal_id: PrincipalId
 }
-export class Curator extends JoyStruct<ICurator> {
-  constructor(value?: ICurator) {
-    super(
-      {
-        role_account: GenericAccountId,
-        reward_relationship: Option.with(RewardRelationshipId),
-        role_stake_profile: Option.with(CuratorRoleStakeProfile),
-        stage: CuratorRoleStage,
-        induction: CuratorInduction,
-        principal_id: PrincipalId,
-      },
-      value
-    )
-  }
-
-  get role_account(): GenericAccountId {
-    return this.getField<GenericAccountId>('role_account')
-  }
-
+export class Curator
+  extends JoyStructDecorated({
+    role_account: AccountId,
+    reward_relationship: Option.with(RewardRelationshipId),
+    role_stake_profile: Option.with(CuratorRoleStakeProfile),
+    stage: CuratorRoleStage,
+    induction: CuratorInduction,
+    principal_id: PrincipalId,
+  })
+  implements ICurator {
   // Helper for working-group compatibility
-  get role_account_id(): GenericAccountId {
+  get role_account_id(): AccountId {
     return this.role_account
   }
 
-  get reward_relationship(): Option<RewardRelationshipId> {
-    return this.getField<Option<RewardRelationshipId>>('reward_relationship')
-  }
-
-  get role_stake_profile(): Option<CuratorRoleStakeProfile> {
-    return this.getField<Option<CuratorRoleStakeProfile>>('role_stake_profile')
-  }
-
-  get stage(): CuratorRoleStage {
-    return this.getField<CuratorRoleStage>('stage')
-  }
-
-  get induction(): CuratorInduction {
-    return this.getField<CuratorInduction>('induction')
-  }
-
-  get principal_id(): PrincipalId {
-    return this.getField<PrincipalId>('principal_id')
-  }
-
   get is_active(): boolean {
-    return this.stage.type == CuratorRoleStakeKeys.Active
+    return this.stage.type == CuratorRoleStageKeys.Active
   }
 }
 
@@ -287,74 +185,39 @@ export type ICuratorApplication = {
   member_id: MemberId
   application_id: ApplicationId
 }
-export class CuratorApplication extends JoyStruct<ICuratorApplication> {
-  constructor(value?: ICuratorApplication) {
-    super(
-      {
-        role_account: GenericAccountId,
-        curator_opening_id: CuratorOpeningId,
-        member_id: MemberId,
-        application_id: ApplicationId,
-      },
-      value
-    )
-  }
-
-  get role_account(): GenericAccountId {
-    return this.getField<GenericAccountId>('role_account')
-  }
-
+export class CuratorApplication
+  extends JoyStructDecorated({
+    role_account: AccountId,
+    curator_opening_id: CuratorOpeningId,
+    member_id: MemberId,
+    application_id: ApplicationId,
+  })
+  implements ICuratorApplication {
   // Helper for working-group compatibility
-  get role_account_id(): GenericAccountId {
+  get role_account_id(): AccountId {
     return this.role_account
   }
-
-  get curator_opening_id(): CuratorOpeningId {
-    return this.getField<CuratorOpeningId>('curator_opening_id')
-  }
-
   // Helper for working-group compatibility
   get opening_id(): CuratorOpeningId {
     return this.curator_opening_id
   }
-
-  get member_id(): MemberId {
-    return this.getField<MemberId>('member_id')
-  }
-
-  get application_id(): ApplicationId {
-    return this.getField<ApplicationId>('application_id')
-  }
 }
 
 export type ISlashableTerms = {
   max_count: u16
   max_percent_pts_per_time: u16
 }
-export class SlashableTerms extends JoyStruct<ISlashableTerms> {
-  constructor(value?: ISlashableTerms) {
-    super(
-      {
-        max_count: u16,
-        max_percent_pts_per_time: u16,
-      },
-      value
-    )
-  }
-}
+export class SlashableTerms
+  extends JoyStructDecorated({
+    max_count: u16,
+    max_percent_pts_per_time: u16,
+  })
+  implements ISlashableTerms {}
 
-export class SlashingTerms extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Unslashable: Null,
-        Slashable: SlashableTerms,
-      },
-      value,
-      index
-    )
-  }
-}
+export class SlashingTerms extends JoyEnum({
+  Unslashable: Null,
+  Slashable: SlashableTerms,
+} as const) {}
 
 export type IOpeningPolicyCommitment = {
   application_rationing_policy: Option<ApplicationRationingPolicy>
@@ -370,75 +233,22 @@ export type IOpeningPolicyCommitment = {
   exit_curator_role_application_stake_unstaking_period: Option<BlockNumber>
   exit_curator_role_stake_unstaking_period: Option<BlockNumber>
 }
-export class OpeningPolicyCommitment extends JoyStruct<IOpeningPolicyCommitment> {
-  constructor(value?: IOpeningPolicyCommitment) {
-    super(
-      {
-        application_rationing_policy: Option.with(ApplicationRationingPolicy),
-        max_review_period_length: u32, // BlockNumber,
-        application_staking_policy: Option.with(StakingPolicy),
-        role_staking_policy: Option.with(StakingPolicy),
-        role_slashing_terms: SlashingTerms,
-        fill_opening_successful_applicant_application_stake_unstaking_period: Option.with(u32),
-        fill_opening_failed_applicant_application_stake_unstaking_period: Option.with(u32),
-        fill_opening_failed_applicant_role_stake_unstaking_period: Option.with(u32),
-        terminate_curator_application_stake_unstaking_period: Option.with(u32),
-        terminate_curator_role_stake_unstaking_period: Option.with(u32),
-        exit_curator_role_application_stake_unstaking_period: Option.with(u32),
-        exit_curator_role_stake_unstaking_period: Option.with(u32),
-      },
-      value
-    )
-  }
-
-  get application_rationing_policy(): Option<ApplicationRationingPolicy> {
-    return this.getField<Option<ApplicationRationingPolicy>>('application_rationing_policy')
-  }
-
-  get max_review_period_length(): u32 {
-    return this.getField<u32>('max_review_period_length')
-  }
-
-  get application_staking_policy(): Option<StakingPolicy> {
-    return this.getField<Option<StakingPolicy>>('application_staking_policy')
-  }
-
-  get role_staking_policy(): Option<StakingPolicy> {
-    return this.getField<Option<StakingPolicy>>('role_staking_policy')
-  }
-
-  get role_slashing_terms(): SlashingTerms {
-    return this.getField<SlashingTerms>('role_slashing_terms')
-  }
-
-  get fill_opening_successful_applicant_application_stake_unstaking_period(): Option<u32> {
-    return this.getField<Option<u32>>('fill_opening_successful_applicant_application_stake_unstaking_period')
-  }
-
-  get fill_opening_failed_applicant_application_stake_unstaking_period(): Option<u32> {
-    return this.getField<Option<u32>>('fill_opening_failed_applicant_application_stake_unstaking_period')
-  }
-
-  get fill_opening_failed_applicant_role_stake_unstaking_period(): Option<u32> {
-    return this.getField<Option<u32>>('fill_opening_failed_applicant_role_stake_unstaking_period')
-  }
-
-  get terminate_curator_application_stake_unstaking_period(): Option<u32> {
-    return this.getField<Option<u32>>('terminate_curator_application_stake_unstaking_period')
-  }
-
-  get terminate_curator_role_stake_unstaking_period(): Option<u32> {
-    return this.getField<Option<u32>>('terminate_curator_role_stake_unstaking_period')
-  }
-
-  get exit_curator_role_application_stake_unstaking_period(): Option<u32> {
-    return this.getField<Option<u32>>('exit_curator_role_application_stake_unstaking_period')
-  }
-
-  get exit_curator_role_stake_unstaking_period(): Option<u32> {
-    return this.getField<Option<u32>>('exit_curator_role_stake_unstaking_period')
-  }
-}
+export class OpeningPolicyCommitment
+  extends JoyStructDecorated({
+    application_rationing_policy: Option.with(ApplicationRationingPolicy),
+    max_review_period_length: u32, // BlockNumber,
+    application_staking_policy: Option.with(StakingPolicy),
+    role_staking_policy: Option.with(StakingPolicy),
+    role_slashing_terms: SlashingTerms,
+    fill_opening_successful_applicant_application_stake_unstaking_period: Option.with(u32),
+    fill_opening_failed_applicant_application_stake_unstaking_period: Option.with(u32),
+    fill_opening_failed_applicant_role_stake_unstaking_period: Option.with(u32),
+    terminate_curator_application_stake_unstaking_period: Option.with(u32),
+    terminate_curator_role_stake_unstaking_period: Option.with(u32),
+    exit_curator_role_application_stake_unstaking_period: Option.with(u32),
+    exit_curator_role_stake_unstaking_period: Option.with(u32),
+  })
+  implements IOpeningPolicyCommitment {}
 
 // Not entierly sure that using BTreeSet will work correctly when reading/decoding this type from chain state
 export type ICuratorOpening = {
@@ -446,22 +256,13 @@ export type ICuratorOpening = {
   curator_applications: BTreeSet<CuratorApplicationId>
   policy_commitment: OpeningPolicyCommitment
 }
-export class CuratorOpening extends JoyStruct<ICuratorOpening> {
-  constructor(value?: ICuratorOpening) {
-    super(
-      {
-        opening_id: OpeningId,
-        curator_applications: BTreeSet.with(CuratorApplicationId),
-        policy_commitment: OpeningPolicyCommitment,
-      },
-      value
-    )
-  }
-
-  get opening_id(): OpeningId {
-    return this.getField<OpeningId>('opening_id')
-  }
-
+export class CuratorOpening
+  extends JoyStructDecorated({
+    opening_id: OpeningId,
+    curator_applications: BTreeSet.with(CuratorApplicationId),
+    policy_commitment: OpeningPolicyCommitment,
+  })
+  implements ICuratorOpening {
   // Helper for working-group compatibility
   get hiring_opening_id(): OpeningId {
     return this.opening_id
@@ -471,16 +272,11 @@ export class CuratorOpening extends JoyStruct<ICuratorOpening> {
 export type IExitedLeadRole = {
   initiated_at_block_number: BlockNumber
 }
-export class ExitedLeadRole extends JoyStruct<IExitedLeadRole> {
-  constructor(value?: IExitedLeadRole) {
-    super(
-      {
-        initiated_at_block_number: u32,
-      },
-      value
-    )
-  }
-}
+export class ExitedLeadRole
+  extends JoyStructDecorated({
+    initiated_at_block_number: u32,
+  })
+  implements IExitedLeadRole {}
 
 export class LeadRoleState extends JoyEnum({
   Active: Null,
@@ -494,87 +290,52 @@ export type ILead = {
   inducted: BlockNumber
   stage: LeadRoleState
 }
-export class Lead extends JoyStruct<ILead> {
-  constructor(value?: ILead) {
-    super(
-      {
-        member_id: MemberId,
-        role_account: GenericAccountId,
-        reward_relationship: Option.with(RewardRelationshipId),
-        inducted: u32,
-        stage: LeadRoleState,
-      },
-      value
-    )
-  }
-
-  get member_id(): MemberId {
-    return this.getField<MemberId>('member_id')
-  }
-
-  get role_account(): GenericAccountId {
-    return this.getField<GenericAccountId>('role_account')
-  }
-
+export class Lead
+  extends JoyStructDecorated({
+    member_id: MemberId,
+    role_account: AccountId,
+    reward_relationship: Option.with(RewardRelationshipId),
+    inducted: u32,
+    stage: LeadRoleState,
+  })
+  implements ILead {
   // Helper for working-group compatibility
-  get role_account_id(): GenericAccountId {
+  get role_account_id(): AccountId {
     return this.role_account
   }
-
-  get reward_relationship(): Option<RewardRelationshipId> {
-    return this.getField<Option<RewardRelationshipId>>('reward_relationship')
-  }
-
-  get stage(): LeadRoleState {
-    return this.getField('stage')
-  }
-}
-
-export class WorkingGroupUnstaker extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Lead: LeadId,
-        Curator: CuratorId,
-      },
-      value,
-      index
-    )
-  }
 }
 
-export class CuratorApplicationIdToCuratorIdMap extends BTreeMap<ApplicationId, CuratorId> {
-  constructor(value?: any) {
-    super(ApplicationId, CuratorId, value)
-  }
-}
+export class WorkingGroupUnstaker extends JoyEnum({
+  Lead: LeadId,
+  Curator: CuratorId,
+}) {}
 
-export function registerContentWorkingGroupTypes() {
-  try {
-    getTypeRegistry().register({
-      ChannelId: 'u64',
-      CuratorId: 'u64',
-      CuratorOpeningId: 'u64',
-      CuratorApplicationId: 'u64',
-      LeadId: 'u64',
-      PrincipalId: 'u64',
-      OptionalText,
-      Channel,
-      ChannelContentType,
-      ChannelCurationStatus,
-      ChannelPublicationStatus,
-      CurationActor,
-      Curator,
-      CuratorApplication,
-      CuratorOpening,
-      Lead,
-      OpeningPolicyCommitment,
-      Principal,
-      WorkingGroupUnstaker,
-      CuratorApplicationIdToCuratorIdMap,
-      CuratorApplicationIdSet: Vec.with(CuratorApplicationId),
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of content working group module', err)
-  }
-}
+export class CuratorApplicationIdToCuratorIdMap extends BTreeMap.with(ApplicationId, CuratorId) {}
+
+export class CuratorApplicationIdSet extends Vec.with(CuratorApplicationId) {}
+
+export const contentWorkingGroupTypes = {
+  ChannelId: 'u64',
+  CuratorId: 'u64',
+  CuratorOpeningId: 'u64',
+  CuratorApplicationId: 'u64',
+  LeadId: 'u64',
+  PrincipalId: 'u64',
+  OptionalText,
+  Channel,
+  ChannelContentType,
+  ChannelCurationStatus,
+  ChannelPublicationStatus,
+  CurationActor,
+  Curator,
+  CuratorApplication,
+  CuratorOpening,
+  Lead,
+  OpeningPolicyCommitment,
+  Principal,
+  WorkingGroupUnstaker,
+  CuratorApplicationIdToCuratorIdMap,
+  CuratorApplicationIdSet,
+}
+
+export default contentWorkingGroupTypes

+ 72 - 166
types/src/council/index.ts

@@ -1,110 +1,72 @@
-import { Enum, Option } from '@polkadot/types/codec'
-import { getTypeRegistry, Struct, Vec } from '@polkadot/types'
-import { BlockNumber, AccountId, Balance, Hash } from '@polkadot/types/interfaces'
-import { u32 } from '@polkadot/types/primitive'
-import { MemberId } from '../members'
-
-export type TransferableStake = {
+import { Option, U8aFixed } from '@polkadot/types/codec'
+import { Vec } from '@polkadot/types'
+import { BlockNumber, Balance, Hash } from '@polkadot/types/interfaces'
+import { u32, u128 } from '@polkadot/types/primitive'
+import { RegistryTypes } from '@polkadot/types/types'
+import { JoyStructDecorated } from '../JoyStruct'
+import { JoyEnum } from '../JoyEnum'
+import AccountId from '@polkadot/types/generic/AccountId'
+
+export type ITransferableStake = {
   seat: Balance
   backing: Balance
 }
-
-export type ElectionStake = {
+export class TransferableStake
+  extends JoyStructDecorated({
+    seat: u128,
+    backing: u128,
+  })
+  implements ITransferableStake {}
+
+export type IElectionStake = {
   new: Balance
   transferred: Balance
 }
-
-export class Backer extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        member: 'AccountId',
-        stake: 'Balance',
-      },
-      value
-    )
-  }
-
-  get member(): MemberId {
-    return this.get('member') as MemberId
-  }
-
-  get stake(): Balance {
-    return this.get('stake') as Balance
-  }
-}
+export class ElectionStake
+  extends JoyStructDecorated({
+    new: u128,
+    transferred: u128,
+  })
+  implements IElectionStake {}
+
+export class Backer extends JoyStructDecorated({
+  member: AccountId,
+  stake: u128, // Balance
+}) {}
 
 export class Backers extends Vec.with(Backer) {}
-export class Seat extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        member: 'AccountId',
-        stake: 'Balance',
-        backers: Backers,
-      },
-      value
-    )
-  }
-
-  get member(): AccountId {
-    return this.get('member') as AccountId
-  }
-
-  get stake(): Balance {
-    return this.get('stake') as Balance
-  }
-
-  get backers(): Backers {
-    return this.get('backers') as Backers
-  }
-}
+export class Seat extends JoyStructDecorated({
+  member: AccountId,
+  stake: u128, // Balance
+  backers: Backers,
+}) {}
 
 export class Seats extends Vec.with(Seat) {}
 
-export type SealedVote = {
+export type ISealedVote = {
   voter: AccountId
   commitment: Hash
   stake: ElectionStake
   vote: Option<AccountId>
 }
+export class SealedVote
+  extends JoyStructDecorated({
+    voter: AccountId,
+    commitment: U8aFixed, // Hash
+    stake: ElectionStake,
+    vote: Option.with(AccountId),
+  })
+  implements ISealedVote {}
 
 export class Announcing extends u32 {}
 export class Voting extends u32 {}
 export class Revealing extends u32 {}
 
-export class ElectionStage extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Announcing,
-        Voting,
-        Revealing,
-      },
-      value,
-      index
-    )
-  }
-
-  /** Create a new Announcing stage. */
-  static Announcing(endsAt: BlockNumber | number): ElectionStage {
-    return this.newElectionStage('Announcing', endsAt)
-  }
-
-  /** Create a new Voting stage. */
-  static Voting(endsAt: BlockNumber | number): ElectionStage {
-    return this.newElectionStage('Voting', endsAt)
-  }
-
-  /** Create a new Revealing stage. */
-  static Revealing(endsAt: BlockNumber | number): ElectionStage {
-    return this.newElectionStage('Revealing', endsAt)
-  }
-
-  static newElectionStage(stageName: string, endsAt: BlockNumber | number) {
-    return new ElectionStage({ [stageName]: endsAt })
-  }
-}
+export class ElectionStage extends JoyEnum({
+  Announcing,
+  Voting,
+  Revealing,
+} as const) {}
 
 export type AnyElectionStage = Announcing | Voting | Revealing
 
@@ -119,85 +81,29 @@ export type IElectionParameters = {
   min_voting_stake: Balance
 }
 
-export class ElectionParameters extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        announcing_period: 'BlockNumber',
-        voting_period: 'BlockNumber',
-        revealing_period: 'BlockNumber',
-        council_size: 'u32',
-        candidacy_limit: 'u32',
-        new_term_duration: 'BlockNumber',
-        min_council_stake: 'Balance',
-        min_voting_stake: 'Balance',
-      },
-      value
-    )
-  }
-  get announcing_period() {
-    return this.get('announcing_period') as BlockNumber
-  }
-  get voting_period() {
-    return this.get('voting_period') as BlockNumber
-  }
-  get revealing_period() {
-    return this.get('revealing_period') as BlockNumber
-  }
-  get council_size() {
-    return this.get('council_size') as u32
-  }
-  get candidacy_limit() {
-    return this.get('candidacy_limit') as u32
-  }
-  get new_term_duration() {
-    return this.get('new_term_duration') as BlockNumber
-  }
-  get min_council_stake() {
-    return this.get('min_council_stake') as Balance
-  }
-  get min_voting_stake() {
-    return this.get('min_voting_stake') as Balance
-  }
+export class ElectionParameters
+  extends JoyStructDecorated({
+    announcing_period: u32, // BlockNumber
+    voting_period: u32, // BlockNumber
+    revealing_period: u32, // BlockNumber
+    council_size: u32,
+    candidacy_limit: u32,
+    new_term_duration: u32, // BlockNumber
+    min_council_stake: u128, // Balance
+    min_voting_stake: u128, // Balance
+  })
+  implements IElectionParameters {}
+
+export const councilTypes: RegistryTypes = {
+  ElectionStage,
+  ElectionStake,
+  SealedVote,
+  TransferableStake,
+  ElectionParameters,
+  Seat,
+  Seats,
+  Backer,
+  Backers,
 }
 
-// TODO Refactor: split this function and move to corresponding modules: election and proposals.
-export function registerCouncilAndElectionTypes() {
-  try {
-    const typeRegistry = getTypeRegistry()
-
-    typeRegistry.register({
-      ElectionStage,
-      ElectionStake: {
-        new: 'Balance',
-        transferred: 'Balance',
-      },
-      SealedVote: {
-        voter: 'AccountId',
-        commitment: 'Hash',
-        stake: 'ElectionStake',
-        vote: 'Option<AccountId>',
-      },
-      TransferableStake: {
-        seat: 'Balance',
-        backing: 'Balance',
-      },
-      ElectionParameters: {
-        announcing_period: 'BlockNumber',
-        voting_period: 'BlockNumber',
-        revealing_period: 'BlockNumber',
-        council_size: 'u32',
-        candidacy_limit: 'u32',
-        new_term_duration: 'BlockNumber',
-        min_council_stake: 'Balance',
-        min_voting_stake: 'Balance',
-      },
-      Seat,
-      Seats,
-      Backer,
-      Backers,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types for council and election modules', err)
-  }
-}
+export default councilTypes

File diff suppressed because it is too large
+ 26 - 0
types/src/definitions/augment-types.ts


+ 2 - 0
types/src/definitions/definitions.ts

@@ -0,0 +1,2 @@
+// We can put our types definitions here in the future (in order to use @polkadot/typegen)
+export {}

+ 12 - 32
types/src/discovery.ts

@@ -1,39 +1,19 @@
-import { Struct } from '@polkadot/types/codec'
-import { getTypeRegistry, Text, u32 } from '@polkadot/types'
-import { BlockNumber } from '@polkadot/types/interfaces'
+import { Text, u32 } from '@polkadot/types'
+import { RegistryTypes } from '@polkadot/types/types'
+import { JoyStructDecorated } from './common'
 
 export class IPNSIdentity extends Text {}
 export class Url extends Text {}
 
-export class AccountInfo extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        identity: IPNSIdentity,
-        expires_at: u32, // BlockNumber
-      },
-      value
-    )
-  }
+export class AccountInfo extends JoyStructDecorated({
+  identity: IPNSIdentity,
+  expires_at: u32, // BlockNumber
+}) {}
 
-  get identity(): IPNSIdentity {
-    return this.get('identity') as IPNSIdentity
-  }
-
-  get expires_at(): BlockNumber {
-    return this.get('expires_at') as BlockNumber
-  }
+export const discoveryTypes: RegistryTypes = {
+  Url,
+  IPNSIdentity,
+  // AccountInfo, FIXME: This overrides core Substrate type
 }
 
-export function registerDiscoveryTypes() {
-  try {
-    const typeRegistry = getTypeRegistry()
-    typeRegistry.register({
-      Url,
-      IPNSIdentity,
-      AccountInfo,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of discovery module', err)
-  }
-}
+export default discoveryTypes

+ 90 - 148
types/src/forum.ts

@@ -1,6 +1,7 @@
-import { getTypeRegistry, bool, u32, u64, Text, Option, Vec as Vector, GenericAccountId } from '@polkadot/types'
-import { AccountId } from '@polkadot/types/interfaces'
-import { BlockAndTime, JoyStruct, ThreadId, PostId } from './common'
+import { bool, u32, u64, Text, Option, Vec as Vector } from '@polkadot/types'
+import { BlockAndTime, ThreadId, PostId, JoyStructCustom, JoyStructDecorated } from './common'
+import { RegistryTypes } from '@polkadot/types/types'
+import AccountId from '@polkadot/types/generic/AccountId'
 
 export type ModerationActionType = {
   moderated_at: BlockAndTime
@@ -8,18 +9,13 @@ export type ModerationActionType = {
   rationale: Text
 }
 
-export class ModerationAction extends JoyStruct<ModerationActionType> {
-  constructor(value: ModerationActionType) {
-    super(
-      {
-        moderated_at: BlockAndTime,
-        moderator_id: GenericAccountId,
-        rationale: Text,
-      },
-      value
-    )
-  }
-
+export class ModerationAction extends JoyStructCustom({
+  moderated_at: BlockAndTime,
+  moderator_id: AccountId,
+  rationale: Text,
+})
+// FIXME: Make it JoyStructDecorated compatible
+{
   get moderated_at(): BlockAndTime {
     return this.getField('moderated_at')
   }
@@ -38,17 +34,12 @@ export type PostTextChangeType = {
   text: Text
 }
 
-export class PostTextChange extends JoyStruct<PostTextChangeType> {
-  constructor(value: PostTextChangeType) {
-    super(
-      {
-        expired_at: BlockAndTime,
-        text: Text,
-      },
-      value
-    )
-  }
-
+export class PostTextChange extends JoyStructCustom({
+  expired_at: BlockAndTime,
+  text: Text,
+})
+// FIXME: Make it JoyStructDecorated compatible
+{
   get expired_at(): BlockAndTime {
     return this.getField('expired_at')
   }
@@ -78,25 +69,12 @@ export type ChildPositionInParentCategoryType = {
   child_nr_in_parent_category: u32
 }
 
-export class ChildPositionInParentCategory extends JoyStruct<ChildPositionInParentCategoryType> {
-  constructor(value: ChildPositionInParentCategoryType) {
-    super(
-      {
-        parent_id: CategoryId,
-        child_nr_in_parent_category: u32,
-      },
-      value
-    )
-  }
-
-  get parent_id(): CategoryId {
-    return this.getField('parent_id')
-  }
-
-  get child_nr_in_parent_category(): u32 {
-    return this.getField('child_nr_in_parent_category')
-  }
-}
+export class ChildPositionInParentCategory
+  extends JoyStructDecorated({
+    parent_id: CategoryId,
+    child_nr_in_parent_category: u32,
+  })
+  implements ChildPositionInParentCategoryType {}
 
 export class OptionChildPositionInParentCategory extends Option.with(ChildPositionInParentCategory) {}
 
@@ -114,30 +92,21 @@ export type CategoryType = {
   moderator_id: AccountId
 }
 
-export class Category extends JoyStruct<CategoryType> {
-  constructor(value: CategoryType) {
-    super(
-      {
-        id: CategoryId,
-        title: Text,
-        description: Text,
-        created_at: BlockAndTime,
-        deleted: bool,
-        archived: bool,
-        num_direct_subcategories: u32,
-        num_direct_unmoderated_threads: u32,
-        num_direct_moderated_threads: u32,
-        position_in_parent_category: OptionChildPositionInParentCategory,
-        moderator_id: GenericAccountId,
-      },
-      value
-    )
-  }
-
-  static newEmpty(): Category {
-    return new Category({} as CategoryType)
-  }
-
+export class Category extends JoyStructCustom({
+  id: CategoryId,
+  title: Text,
+  description: Text,
+  created_at: BlockAndTime,
+  deleted: bool,
+  archived: bool,
+  num_direct_subcategories: u32,
+  num_direct_unmoderated_threads: u32,
+  num_direct_moderated_threads: u32,
+  position_in_parent_category: OptionChildPositionInParentCategory,
+  moderator_id: AccountId,
+})
+// FIXME: Make it JoyStructDecorated compatible
+{
   get id(): CategoryId {
     return this.getField('id')
   }
@@ -155,11 +124,11 @@ export class Category extends JoyStruct<CategoryType> {
   }
 
   get deleted(): boolean {
-    return this.getBoolean('deleted')
+    return this.getField('deleted').valueOf()
   }
 
   get archived(): boolean {
-    return this.getBoolean('archived')
+    return this.getField('archived').valueOf()
   }
 
   get num_direct_subcategories(): u32 {
@@ -175,7 +144,7 @@ export class Category extends JoyStruct<CategoryType> {
   }
 
   get num_threads_created(): u32 {
-    return new u32(this.num_direct_unmoderated_threads.add(this.num_direct_moderated_threads))
+    return new u32(this.registry, this.num_direct_unmoderated_threads.add(this.num_direct_moderated_threads))
   }
 
   get hasSubcategories(): boolean {
@@ -221,28 +190,19 @@ export type ThreadType = {
   author_id: AccountId
 }
 
-export class Thread extends JoyStruct<ThreadType> {
-  constructor(value: ThreadType) {
-    super(
-      {
-        id: ThreadId,
-        title: Text,
-        category_id: CategoryId,
-        nr_in_category: u32,
-        moderation: OptionModerationAction,
-        num_unmoderated_posts: u32,
-        num_moderated_posts: u32,
-        created_at: BlockAndTime,
-        author_id: GenericAccountId,
-      },
-      value
-    )
-  }
-
-  static newEmpty(): Thread {
-    return new Thread({} as ThreadType)
-  }
-
+export class Thread extends JoyStructCustom({
+  id: ThreadId,
+  title: Text,
+  category_id: CategoryId,
+  nr_in_category: u32,
+  moderation: OptionModerationAction,
+  num_unmoderated_posts: u32,
+  num_moderated_posts: u32,
+  created_at: BlockAndTime,
+  author_id: AccountId,
+})
+// FIXME: Make it JoyStructDecorated compatible
+{
   get id(): ThreadId {
     return this.getField('id')
   }
@@ -260,7 +220,7 @@ export class Thread extends JoyStruct<ThreadType> {
   }
 
   get moderation(): ModerationAction | undefined {
-    return this.unwrapOrUndefined('moderation')
+    return this.getField('moderation').unwrapOr(undefined)
   }
 
   get moderated(): boolean {
@@ -276,7 +236,7 @@ export class Thread extends JoyStruct<ThreadType> {
   }
 
   get num_posts_ever_created(): u32 {
-    return new u32(this.num_unmoderated_posts.add(this.num_moderated_posts))
+    return new u32(this.registry, this.num_unmoderated_posts.add(this.num_moderated_posts))
   }
 
   get created_at(): BlockAndTime {
@@ -300,27 +260,18 @@ export type PostType = {
 }
 
 // TODO deprectated: replaced w/ Post
-export class Post extends JoyStruct<PostType> {
-  constructor(value: PostType) {
-    super(
-      {
-        id: PostId,
-        thread_id: ThreadId,
-        nr_in_thread: u32,
-        current_text: Text,
-        moderation: OptionModerationAction,
-        text_change_history: VecPostTextChange,
-        created_at: BlockAndTime,
-        author_id: GenericAccountId,
-      },
-      value
-    )
-  }
-
-  static newEmpty(): Post {
-    return new Post({} as PostType)
-  }
-
+export class Post extends JoyStructCustom({
+  id: PostId,
+  thread_id: ThreadId,
+  nr_in_thread: u32,
+  current_text: Text,
+  moderation: OptionModerationAction,
+  text_change_history: VecPostTextChange,
+  created_at: BlockAndTime,
+  author_id: AccountId,
+})
+// FIXME: Make it JoyStructDecorated compatible
+{
   get id(): PostId {
     return this.getField('id')
   }
@@ -338,7 +289,7 @@ export class Post extends JoyStruct<PostType> {
   }
 
   get moderation(): ModerationAction | undefined {
-    return this.unwrapOrUndefined('moderation')
+    return this.getField('moderation').unwrapOr(undefined)
   }
 
   get moderated(): boolean {
@@ -366,19 +317,14 @@ export type ReplyType = {
 }
 
 // TODO deprectated: replaced w/ Post
-export class Reply extends JoyStruct<ReplyType> {
-  constructor(value: ReplyType) {
-    super(
-      {
-        owner: GenericAccountId,
-        thread_id: ThreadId,
-        text: Text,
-        moderation: OptionModerationAction,
-      },
-      value
-    )
-  }
-
+export class Reply extends JoyStructCustom({
+  owner: AccountId,
+  thread_id: ThreadId,
+  text: Text,
+  moderation: OptionModerationAction,
+})
+// FIXME: Make it JoyStructDecorated compatible
+{
   get owner(): AccountId {
     return this.getField('owner')
   }
@@ -392,7 +338,7 @@ export class Reply extends JoyStruct<ReplyType> {
   }
 
   get moderation(): ModerationAction | undefined {
-    return this.unwrapOrUndefined('moderation')
+    return this.getField('moderation').unwrapOr(undefined)
   }
 
   get moderated(): boolean {
@@ -400,20 +346,16 @@ export class Reply extends JoyStruct<ReplyType> {
   }
 }
 
-export function registerForumTypes() {
-  try {
-    getTypeRegistry().register({
-      PostTextChange,
-      ModerationAction,
-      ChildPositionInParentCategory,
-      CategoryId,
-      Category,
-      Thread,
-      Post,
-      ReplyId,
-      Reply,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of forum module', err)
-  }
+export const forumTypes: RegistryTypes = {
+  PostTextChange,
+  ModerationAction,
+  ChildPositionInParentCategory,
+  CategoryId,
+  Category,
+  Thread,
+  Post,
+  ReplyId,
+  Reply,
 }
+
+export default forumTypes

+ 132 - 316
types/src/hiring/index.ts

@@ -1,7 +1,7 @@
-import { getTypeRegistry, Null, u128, u64, u32, Vec, Option, Text } from '@polkadot/types'
-import { Enum } from '@polkadot/types/codec'
+import { Null, u128, u64, u32, Option, Text } from '@polkadot/types'
+import { BTreeSet } from '@polkadot/types/codec'
 import { BlockNumber, Balance } from '@polkadot/types/interfaces'
-import { JoyStruct, JoyEnum } from '../common'
+import { JoyEnum, JoyStructDecorated } from '../common'
 import { StakeId } from '../stake'
 
 import { GenericJoyStreamRoleSchema } from './schemas/role.schema.typings'
@@ -9,6 +9,7 @@ import { GenericJoyStreamRoleSchema } from './schemas/role.schema.typings'
 import ajv from 'ajv'
 
 import * as role_schema_json from './schemas/role.schema.json'
+import { RegistryTypes } from '@polkadot/types/types'
 
 export class ApplicationId extends u64 {}
 export class OpeningId extends u64 {}
@@ -25,9 +26,9 @@ export const ActivateOpeningAtKeys: { [k in keyof typeof ActivateOpeningAtDef]:
   ExactBlock: 'ExactBlock',
 } as const
 export type ActivateOpeningAtKey = keyof typeof ActivateOpeningAtDef
-// TODO: Replace with JoyEnum
-export class ActivateOpeningAt extends Enum.with(ActivateOpeningAtDef) {}
+export class ActivateOpeningAt extends JoyEnum(ActivateOpeningAtDef) {}
 
+// FIXME: Replace usages with isOfType, asType wherever possible
 export enum ApplicationDeactivationCauseKeys {
   External = 'External',
   Hired = 'Hired',
@@ -37,118 +38,74 @@ export enum ApplicationDeactivationCauseKeys {
   ReviewPeriodExpired = 'ReviewPeriodExpired',
   OpeningFilled = 'OpeningFilled',
 }
-
-export class ApplicationDeactivationCause extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      [
-        ApplicationDeactivationCauseKeys.External,
-        ApplicationDeactivationCauseKeys.Hired,
-        ApplicationDeactivationCauseKeys.NotHired,
-        ApplicationDeactivationCauseKeys.CrowdedOut,
-        ApplicationDeactivationCauseKeys.OpeningCancelled,
-        ApplicationDeactivationCauseKeys.ReviewPeriodExpired,
-        ApplicationDeactivationCauseKeys.OpeningFilled,
-      ],
-      value,
-      index
-    )
-  }
-}
+const ApplicationDeactivationCauseDef = {
+  External: Null,
+  Hired: Null,
+  NotHired: Null,
+  CrowdedOut: Null,
+  OpeningCancelled: Null,
+  ReviewPeriodExpired: Null,
+  OpeningFilled: Null,
+} as const
+export class ApplicationDeactivationCause extends JoyEnum(ApplicationDeactivationCauseDef) {}
 
 export type UnstakingApplicationStageType = {
   deactivation_initiated: BlockNumber
   cause: ApplicationDeactivationCause
 }
-export class UnstakingApplicationStage extends JoyStruct<UnstakingApplicationStageType> {
-  constructor(value?: UnstakingApplicationStageType) {
-    super(
-      {
-        deactivation_initiated: u32, // BlockNumber
-        cause: ApplicationDeactivationCause,
-      },
-      value
-    )
-  }
-
-  get cause(): ApplicationDeactivationCause {
-    return this.getField<ApplicationDeactivationCause>('cause')
-  }
-}
+export class UnstakingApplicationStage
+  extends JoyStructDecorated({
+    deactivation_initiated: u32, // BlockNumber
+    cause: ApplicationDeactivationCause,
+  })
+  implements UnstakingApplicationStageType {}
 
 export type InactiveApplicationStageType = {
   deactivation_initiated: BlockNumber
   deactivated: BlockNumber
   cause: ApplicationDeactivationCause
 }
-export class InactiveApplicationStage extends JoyStruct<InactiveApplicationStageType> {
-  constructor(value?: InactiveApplicationStageType) {
-    super(
-      {
-        deactivation_initiated: u32, // BlockNumber
-        deactivated: u32,
-        cause: ApplicationDeactivationCause,
-      },
-      value
-    )
-  }
-
-  get cause(): ApplicationDeactivationCause {
-    return this.getField<ApplicationDeactivationCause>('cause')
-  }
-}
+export class InactiveApplicationStage
+  extends JoyStructDecorated({
+    deactivation_initiated: u32, // BlockNumber
+    deactivated: u32,
+    cause: ApplicationDeactivationCause,
+  })
+  implements InactiveApplicationStageType {}
 
 export class ActiveApplicationStage extends Null {}
-
-// TODO: Find usages and replace with "JoyEnum-standard"
+// FIXME: Replace usages with isOfType, asType wherever possible
 export enum ApplicationStageKeys {
   Active = 'Active',
   Unstaking = 'Unstaking',
   Inactive = 'Inactive',
 }
-export class ApplicationStage extends JoyEnum({
+export const ApplicationStageDef = {
   Active: ActiveApplicationStage,
   Unstaking: UnstakingApplicationStage,
   Inactive: InactiveApplicationStage,
-} as const) {}
+} as const
+export class ApplicationStage extends JoyEnum(ApplicationStageDef) {}
 
 export type IApplicationRationingPolicy = {
   max_active_applicants: u32
 }
-export class ApplicationRationingPolicy extends JoyStruct<IApplicationRationingPolicy> {
-  constructor(value?: IApplicationRationingPolicy) {
-    super(
-      {
-        max_active_applicants: u32,
-      },
-      value
-    )
-  }
-
-  get max_active_applicants(): u32 {
-    return this.getField<u32>('max_active_applicants')
-  }
-}
+export class ApplicationRationingPolicy
+  extends JoyStructDecorated({
+    max_active_applicants: u32,
+  })
+  implements IApplicationRationingPolicy {}
 
 export type WaitingToBeingOpeningStageVariantType = {
   begins_at_block: BlockNumber
 }
-export class WaitingToBeingOpeningStageVariant extends JoyStruct<WaitingToBeingOpeningStageVariantType> {
-  constructor(value?: WaitingToBeingOpeningStageVariantType) {
-    super(
-      {
-        begins_at_block: u32,
-      },
-      value
-    )
-  }
-
-  get begins_at_block(): BlockNumber {
-    return this.getField<BlockNumber>('begins_at_block')
-  }
-}
+export class WaitingToBeingOpeningStageVariant
+  extends JoyStructDecorated({
+    begins_at_block: u32,
+  })
+  implements WaitingToBeingOpeningStageVariantType {}
 
-// TODO: Find usages and replace them with JoyEnum helpers
+// FIXME: Replace usages with isOfType, asType wherever possible
 export enum OpeningDeactivationCauseKeys {
   CancelledBeforeActivation = 'CancelledBeforeActivation',
   CancelledAcceptingApplications = 'CancelledAcceptingApplications',
@@ -156,62 +113,34 @@ export enum OpeningDeactivationCauseKeys {
   ReviewPeriodExpired = 'ReviewPeriodExpired',
   Filled = 'Filled',
 }
-
-class OpeningDeactivationCause_CancelledBeforeActivation extends Null {}
-class OpeningDeactivationCause_CancelledAcceptingApplications extends Null {}
-class OpeningDeactivationCause_CancelledInReviewPeriod extends Null {}
-class OpeningDeactivationCause_ReviewPeriodExpired extends Null {}
-class OpeningDeactivationCause_Filled extends Null {}
-
-export class OpeningDeactivationCause extends JoyEnum({
-  CancelledBeforeActivation: OpeningDeactivationCause_CancelledBeforeActivation,
-  CancelledAcceptingApplications: OpeningDeactivationCause_CancelledAcceptingApplications,
-  CancelledInReviewPeriod: OpeningDeactivationCause_CancelledInReviewPeriod,
-  ReviewPeriodExpired: OpeningDeactivationCause_ReviewPeriodExpired,
-  Filled: OpeningDeactivationCause_Filled,
-} as const) {}
+const OpeningDeactivationCauseDef = {
+  CancelledBeforeActivation: Null,
+  CancelledAcceptingApplications: Null,
+  CancelledInReviewPeriod: Null,
+  ReviewPeriodExpired: Null,
+  Filled: Null,
+} as const
+export class OpeningDeactivationCause extends JoyEnum(OpeningDeactivationCauseDef) {}
 
 export type IAcceptingApplications = {
   started_accepting_applicants_at_block: BlockNumber
 }
-export class AcceptingApplications extends JoyStruct<IAcceptingApplications> {
-  constructor(value?: IAcceptingApplications) {
-    super(
-      {
-        started_accepting_applicants_at_block: u32,
-      },
-      value
-    )
-  }
-
-  get started_accepting_applicants_at_block(): BlockNumber {
-    return this.getField<BlockNumber>('started_accepting_applicants_at_block')
-  }
-}
+export class AcceptingApplications
+  extends JoyStructDecorated({
+    started_accepting_applicants_at_block: u32,
+  })
+  implements IAcceptingApplications {}
 
 export type IReviewPeriod = {
   started_accepting_applicants_at_block: BlockNumber
   started_review_period_at_block: BlockNumber
 }
-export class ReviewPeriod extends JoyStruct<IReviewPeriod> {
-  constructor(value?: IReviewPeriod) {
-    super(
-      {
-        started_accepting_applicants_at_block: u32,
-        started_review_period_at_block: u32,
-      },
-      value
-    )
-  }
-
-  get started_accepting_applicants_at_block(): BlockNumber {
-    return this.getField<BlockNumber>('started_accepting_applicants_at_block')
-  }
-
-  get started_review_period_at_block(): BlockNumber {
-    return this.getField<BlockNumber>('started_review_period_at_block')
-  }
-}
+export class ReviewPeriod
+  extends JoyStructDecorated({
+    started_accepting_applicants_at_block: u32,
+    started_review_period_at_block: u32,
+  })
+  implements IReviewPeriod {}
 
 export type IDeactivated = {
   cause: OpeningDeactivationCause
@@ -219,35 +148,14 @@ export type IDeactivated = {
   started_accepting_applicants_at_block: BlockNumber
   started_review_period_at_block: Option<BlockNumber>
 }
-export class Deactivated extends JoyStruct<IDeactivated> {
-  constructor(value?: IDeactivated) {
-    super(
-      {
-        cause: OpeningDeactivationCause,
-        deactivated_at_block: u32,
-        started_accepting_applicants_at_block: u32,
-        started_review_period_at_block: Option.with(u32),
-      },
-      value
-    )
-  }
-
-  get cause(): OpeningDeactivationCause {
-    return this.getField<OpeningDeactivationCause>('cause')
-  }
-
-  get deactivated_at_block(): BlockNumber {
-    return this.getField<BlockNumber>('deactivated_at_block')
-  }
-
-  get started_accepting_applicants_at_block(): BlockNumber {
-    return this.getField<BlockNumber>('started_accepting_applicants_at_block')
-  }
-
-  get started_review_period_at_block(): BlockNumber {
-    return this.getField<BlockNumber>('started_review_period_at_block')
-  }
-}
+export class Deactivated
+  extends JoyStructDecorated({
+    cause: OpeningDeactivationCause,
+    deactivated_at_block: u32,
+    started_accepting_applicants_at_block: u32,
+    started_review_period_at_block: Option.with(u32),
+  })
+  implements IDeactivated {}
 
 export const ActiveOpeningStageDef = {
   AcceptingApplications: AcceptingApplications,
@@ -255,60 +163,48 @@ export const ActiveOpeningStageDef = {
   Deactivated: Deactivated,
 } as const
 export type ActiveOpeningStageKey = keyof typeof ActiveOpeningStageDef
-
 export class ActiveOpeningStage extends JoyEnum(ActiveOpeningStageDef) {}
 
 export type ActiveOpeningStageVariantType = {
   stage: ActiveOpeningStage
-  applications_added: Vec<ApplicationId> //BTreeSet<ApplicationId>,
+  applications_added: BTreeSet<ApplicationId>
   active_application_count: u32
   unstaking_application_count: u32
   deactivated_application_count: u32
 }
-export class ActiveOpeningStageVariant extends JoyStruct<ActiveOpeningStageVariantType> {
-  constructor(value?: ActiveOpeningStageVariantType) {
-    super(
-      {
-        stage: ActiveOpeningStage,
-        applications_added: Vec.with(ApplicationId), //BTreeSet<ApplicationId>,
-        active_application_count: u32,
-        unstaking_application_count: u32,
-        deactivated_application_count: u32,
-      },
-      value
-    )
-  }
-
-  get stage(): ActiveOpeningStage {
-    return this.getField<ActiveOpeningStage>('stage')
-  }
-
+export class ActiveOpeningStageVariant extends JoyStructDecorated({
+  stage: ActiveOpeningStage,
+  applications_added: BTreeSet.with(ApplicationId),
+  active_application_count: u32,
+  unstaking_application_count: u32,
+  deactivated_application_count: u32,
+}) {
   get is_active(): boolean {
     return this.stage.isOfType('AcceptingApplications')
   }
 }
 
-// TODO: Find usages and replace them with JoyEnum helpers
+// FIXME: Replace usages with isOfType, asType wherever possible
 export enum OpeningStageKeys {
   WaitingToBegin = 'WaitingToBegin',
   Active = 'Active',
 }
-
-export class OpeningStage extends JoyEnum({
+export const OpeningStageDef = {
   WaitingToBegin: WaitingToBeingOpeningStageVariant,
   Active: ActiveOpeningStageVariant,
-} as const) {}
+} as const
+export class OpeningStage extends JoyEnum(OpeningStageDef) {}
 
+// FIXME: Replace usages with isOfType, asType wherever possible
 export enum StakingAmountLimitModeKeys {
   AtLeast = 'AtLeast',
   Exact = 'Exact',
 }
-
-export class StakingAmountLimitMode extends Enum {
-  constructor(value?: any, index?: number) {
-    super([StakingAmountLimitModeKeys.AtLeast, StakingAmountLimitModeKeys.Exact], value, index)
-  }
-}
+export const StakingAmountLimitModeDef = {
+  AtLeast: Null,
+  Exact: Null,
+} as const
+export class StakingAmountLimitMode extends JoyEnum(StakingAmountLimitModeDef) {}
 
 export type IStakingPolicy = {
   amount: Balance
@@ -316,35 +212,14 @@ export type IStakingPolicy = {
   crowded_out_unstaking_period_length: Option<BlockNumber>
   review_period_expired_unstaking_period_length: Option<BlockNumber>
 }
-export class StakingPolicy extends JoyStruct<IStakingPolicy> {
-  constructor(value?: IStakingPolicy) {
-    super(
-      {
-        amount: u128,
-        amount_mode: StakingAmountLimitMode,
-        crowded_out_unstaking_period_length: Option.with(u32),
-        review_period_expired_unstaking_period_length: Option.with(u32),
-      },
-      value
-    )
-  }
-
-  get amount(): u128 {
-    return this.getField<u128>('amount')
-  }
-
-  get amount_mode(): StakingAmountLimitMode {
-    return this.getField<StakingAmountLimitMode>('amount_mode')
-  }
-
-  get crowded_out_unstaking_period_length(): Option<u32> {
-    return this.getField<Option<u32>>('crowded_out_unstaking_period_length')
-  }
-
-  get review_period_expired_unstaking_period_length(): Option<u32> {
-    return this.getField<Option<u32>>('review_period_expired_unstaking_period_length')
-  }
-}
+export class StakingPolicy
+  extends JoyStructDecorated({
+    amount: u128,
+    amount_mode: StakingAmountLimitMode,
+    crowded_out_unstaking_period_length: Option.with(u32),
+    review_period_expired_unstaking_period_length: Option.with(u32),
+  })
+  implements IStakingPolicy {}
 export const schemaValidator: ajv.ValidateFunction = new ajv({ allErrors: true }).compile(role_schema_json)
 
 const OpeningHRTFallback: GenericJoyStreamRoleSchema = {
@@ -373,24 +248,19 @@ export type IOpening = {
   human_readable_text: Text // Vec<u8>,
 }
 
-export class Opening extends JoyStruct<IOpening> {
-  constructor(value?: IOpening) {
-    super(
-      {
-        created: u32,
-        stage: OpeningStage,
-        max_review_period_length: u32,
-        application_rationing_policy: Option.with(ApplicationRationingPolicy),
-        application_staking_policy: Option.with(StakingPolicy),
-        role_staking_policy: Option.with(StakingPolicy),
-        human_readable_text: Text, // Vec.with(u8),
-      },
-      value
-    )
-  }
-
+export class Opening
+  extends JoyStructDecorated({
+    created: u32,
+    stage: OpeningStage,
+    max_review_period_length: u32,
+    application_rationing_policy: Option.with(ApplicationRationingPolicy),
+    application_staking_policy: Option.with(StakingPolicy),
+    role_staking_policy: Option.with(StakingPolicy),
+    human_readable_text: Text, // Vec.with(u8),
+  })
+  implements IOpening {
   parse_human_readable_text(): GenericJoyStreamRoleSchema | string | undefined {
-    const hrt = this.getField<Text>('human_readable_text')
+    const hrt = this.human_readable_text
 
     if (!hrt) {
       return undefined
@@ -421,34 +291,6 @@ export class Opening extends JoyStruct<IOpening> {
     return hrt
   }
 
-  get created(): BlockNumber {
-    return this.getField<BlockNumber>('created')
-  }
-
-  get stage(): OpeningStage {
-    return this.getField<OpeningStage>('stage')
-  }
-
-  get max_review_period_length(): BlockNumber {
-    return this.getField<BlockNumber>('max_review_period_length')
-  }
-
-  get application_rationing_policy(): Option<ApplicationRationingPolicy> {
-    return this.getField<Option<ApplicationRationingPolicy>>('application_rationing_policy')
-  }
-
-  get application_staking_policy(): Option<StakingPolicy> {
-    return this.getField<Option<StakingPolicy>>('application_staking_policy')
-  }
-
-  get role_staking_policy(): Option<StakingPolicy> {
-    return this.getField<Option<StakingPolicy>>('role_staking_policy')
-  }
-
-  get human_readable_text(): Text {
-    return this.getField<Text>('human_readable_text')
-  }
-
   get max_applicants(): number {
     const appPolicy = this.application_rationing_policy
     if (appPolicy.isNone) {
@@ -480,54 +322,28 @@ export type IApplication = {
   human_readable_text: Text
 }
 
-export class Application extends JoyStruct<IApplication> {
-  constructor(value?: IOpening) {
-    super(
-      {
-        opening_id: OpeningId,
-        application_index_in_opening: u32,
-        add_to_opening_in_block: u32,
-        active_role_staking_id: Option.with(StakeId),
-        active_application_staking_id: Option.with(StakeId),
-        stage: ApplicationStage,
-        human_readable_text: Text,
-      },
-      value
-    )
-  }
-
-  get stage(): ApplicationStage {
-    return this.getField<ApplicationStage>('stage')
-  }
-
-  get active_role_staking_id(): Option<StakeId> {
-    return this.getField<Option<StakeId>>('active_role_staking_id')
-  }
-
-  get active_application_staking_id(): Option<StakeId> {
-    return this.getField<Option<StakeId>>('active_application_staking_id')
-  }
-
-  get human_readable_text(): Text {
-    return this.getField<Text>('human_readable_text')
-  }
+export class Application
+  extends JoyStructDecorated({
+    opening_id: OpeningId,
+    application_index_in_opening: u32,
+    add_to_opening_in_block: u32,
+    active_role_staking_id: Option.with(StakeId),
+    active_application_staking_id: Option.with(StakeId),
+    stage: ApplicationStage,
+    human_readable_text: Text,
+  })
+  implements IApplication {}
+
+export const hiringTypes: RegistryTypes = {
+  ApplicationId: 'u64',
+  OpeningId: 'u64',
+  Application,
+  ApplicationStage,
+  ActivateOpeningAt,
+  ApplicationRationingPolicy,
+  OpeningStage,
+  StakingPolicy,
+  Opening,
 }
 
-export function registerHiringTypes() {
-  try {
-    getTypeRegistry().register({
-      ApplicationId: 'u64',
-      OpeningId: 'u64',
-      Application,
-      ApplicationStage,
-      // why the prefix? is there some other identically named type?
-      'hiring::ActivateOpeningAt': ActivateOpeningAt,
-      ApplicationRationingPolicy,
-      OpeningStage,
-      StakingPolicy,
-      Opening,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of hiring module', err)
-  }
-}
+export default hiringTypes

+ 35 - 41
types/src/index.ts

@@ -1,21 +1,20 @@
-import { getTypeRegistry } from '@polkadot/types'
-
-import * as common from './common'
-import * as members from './members'
-import * as council from './council'
-import * as roles from './roles'
-import * as forum from './forum'
-import * as stake from './stake'
-import * as mint from './mint'
-import * as recurringRewards from './recurring-rewards'
-import * as hiring from './hiring'
-import * as versionedStore from './versioned-store'
-import * as versionedStorePermissions from './versioned-store/permissions'
-import * as contentWorkingGroup from './content-working-group'
-import * as workingGroup from './working-group'
-import * as discovery from './discovery'
-import * as media from './media'
-import * as proposals from './proposals'
+import { RegistryTypes } from '@polkadot/types/types'
+import common from './common'
+import members from './members'
+import council from './council'
+import roles from './roles'
+import forum from './forum'
+import stake from './stake'
+import mint from './mint'
+import recurringRewards from './recurring-rewards'
+import hiring from './hiring'
+import versionedStore from './versioned-store'
+import versionedStorePermissions from './versioned-store/permissions'
+import contentWorkingGroup from './content-working-group'
+import workingGroup from './working-group'
+import discovery from './discovery'
+import media from './media'
+import proposals from './proposals'
 
 export {
   common,
@@ -36,27 +35,22 @@ export {
   proposals,
 }
 
-export function registerJoystreamTypes() {
-  const typeRegistry = getTypeRegistry()
-
-  typeRegistry.register({
-    MemoText: 'Text', // for the memo module
-  })
-
-  common.registerCommonTypes()
-  members.registerMembershipTypes()
-  council.registerCouncilAndElectionTypes()
-  roles.registerRolesTypes()
-  forum.registerForumTypes()
-  stake.registerStakeTypes()
-  mint.registerMintTypes()
-  recurringRewards.registerRecurringRewardsTypes()
-  hiring.registerHiringTypes()
-  versionedStore.registerVersionedStoreTypes()
-  versionedStorePermissions.registerVersionedStorePermissionsTypes()
-  contentWorkingGroup.registerContentWorkingGroupTypes()
-  workingGroup.registerWorkingGroupTypes()
-  discovery.registerDiscoveryTypes()
-  media.registerMediaTypes()
-  proposals.registerProposalTypes()
+export const types: RegistryTypes = {
+  MemoText: 'Text', // for the memo module
+  ...common,
+  ...members,
+  ...council,
+  ...roles,
+  ...forum,
+  ...stake,
+  ...mint,
+  ...recurringRewards,
+  ...hiring,
+  ...versionedStore,
+  ...versionedStorePermissions,
+  ...contentWorkingGroup,
+  ...workingGroup,
+  ...discovery,
+  ...media,
+  ...proposals,
 }

+ 47 - 114
types/src/media.ts

@@ -1,20 +1,21 @@
-import { Enum, Struct, Option, Vec as Vector, H256, BTreeMap, getTypeRegistry, u64, bool, Text } from '@polkadot/types'
-import { BlockAndTime } from './common'
+import { Option, Vec as Vector, BTreeMap, u64, bool, Text, Null } from '@polkadot/types'
+import { U8aFixed } from '@polkadot/types/codec'
+import { H256 } from '@polkadot/types/interfaces'
+import { BlockAndTime, JoyEnum, JoyStructDecorated } from './common'
 import { MemberId } from './members'
 import { StorageProviderId } from './working-group' // this should be in discovery really
-
 import { randomAsU8a } from '@polkadot/util-crypto'
 import { encodeAddress, decodeAddress } from '@polkadot/keyring'
-// import { u8aToString, stringToU8a } from '@polkadot/util';
+import { RegistryTypes, Registry } from '@polkadot/types/types'
 
-export class ContentId extends H256 {
-  static generate(): ContentId {
+export class ContentId extends U8aFixed implements H256 {
+  static generate(registry: Registry): ContentId {
     // randomAsU8a uses https://www.npmjs.com/package/tweetnacl#random-bytes-generation
-    return new ContentId(randomAsU8a())
+    return new ContentId(registry, randomAsU8a())
   }
 
-  static decode(contentId: string): ContentId {
-    return new ContentId(decodeAddress(contentId))
+  static decode(registry: Registry, contentId: string): ContentId {
+    return new ContentId(registry, decodeAddress(contentId))
   }
 
   static encode(contentId: Uint8Array): string {
@@ -32,120 +33,52 @@ export class DataObjectStorageRelationshipId extends u64 {}
 
 export class VecContentId extends Vector.with(ContentId) {}
 export class OptionVecContentId extends Option.with(VecContentId) {}
-export type LiaisonJudgementKey = 'Pending' | 'Accepted' | 'Rejected'
-
-export class LiaisonJudgement extends Enum {
-  constructor(value?: LiaisonJudgementKey) {
-    super(['Pending', 'Accepted', 'Rejected'], value)
-  }
-}
-
-export class DataObject extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        owner: MemberId,
-        added_at: BlockAndTime,
-        type_id: DataObjectTypeId,
-        size: u64,
-        liaison: StorageProviderId,
-        liaison_judgement: LiaisonJudgement,
-        ipfs_content_id: Text,
-      },
-      value
-    )
-  }
-
-  get owner(): MemberId {
-    return this.get('owner') as MemberId
-  }
-
-  get added_at(): BlockAndTime {
-    return this.get('added_at') as BlockAndTime
-  }
-
-  get type_id(): DataObjectTypeId {
-    return this.get('type_id') as DataObjectTypeId
-  }
 
+export const LiaisonJudgementDef = {
+  Pending: Null,
+  Accepted: Null,
+  Rejected: Null,
+} as const
+export type LiaisonJudgementKey = keyof typeof LiaisonJudgementDef
+export class LiaisonJudgement extends JoyEnum(LiaisonJudgementDef) {}
+
+export class DataObject extends JoyStructDecorated({
+  owner: MemberId,
+  added_at: BlockAndTime,
+  type_id: DataObjectTypeId,
+  size: u64,
+  liaison: StorageProviderId,
+  liaison_judgement: LiaisonJudgement,
+  ipfs_content_id: Text,
+}) {
   /** Actually it's 'size', but 'size' is already reserved by a parent class. */
   get size_in_bytes(): u64 {
     return this.get('size') as u64
   }
-
-  get liaison(): StorageProviderId {
-    return this.get('liaison') as StorageProviderId
-  }
-
-  get liaison_judgement(): LiaisonJudgement {
-    return this.get('liaison_judgement') as LiaisonJudgement
-  }
-
-  get ipfs_content_id(): Text {
-    return this.get('ipfs_content_id') as Text
-  }
 }
 
-export class DataObjectStorageRelationship extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        content_id: ContentId,
-        storage_provider: StorageProviderId,
-        ready: bool,
-      },
-      value
-    )
-  }
+export class DataObjectStorageRelationship extends JoyStructDecorated({
+  content_id: ContentId,
+  storage_provider: StorageProviderId,
+  ready: bool,
+}) {}
 
-  get content_id(): ContentId {
-    return this.get('content_id') as ContentId
-  }
-
-  get storage_provider(): StorageProviderId {
-    return this.get('storage_provider') as StorageProviderId
-  }
-
-  get ready(): bool {
-    return this.get('ready') as bool
-  }
-}
-
-export class DataObjectType extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        description: Text,
-        active: bool,
-      },
-      value
-    )
-  }
-
-  get description(): Text {
-    return this.get('description') as Text
-  }
-
-  get active(): bool {
-    return this.get('active') as bool
-  }
-}
+export class DataObjectType extends JoyStructDecorated({
+  description: Text,
+  active: bool,
+}) {}
 
 export class DataObjectsMap extends BTreeMap.with(ContentId, DataObject) {}
 
-export function registerMediaTypes() {
-  try {
-    getTypeRegistry().register({
-      ContentId,
-      LiaisonJudgement,
-      DataObject,
-      DataObjectStorageRelationshipId,
-      DataObjectStorageRelationship,
-      DataObjectTypeId,
-      DataObjectType,
-      DataObjectsMap,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of media module', err)
-  }
+export const mediaTypes: RegistryTypes = {
+  ContentId,
+  LiaisonJudgement,
+  DataObject,
+  DataObjectStorageRelationshipId,
+  DataObjectStorageRelationship,
+  DataObjectTypeId,
+  DataObjectType,
+  DataObjectsMap,
 }
+
+export default mediaTypes

+ 40 - 127
types/src/members.ts

@@ -1,19 +1,8 @@
-import {
-  Enum,
-  getTypeRegistry,
-  Option,
-  Struct,
-  Null,
-  bool,
-  u32,
-  u64,
-  u128,
-  Text,
-  GenericAccountId,
-} from '@polkadot/types'
-import { BlockNumber, Moment, BalanceOf } from '@polkadot/types/interfaces'
-import { JoyStruct } from './common'
-import AccountId from '@polkadot/types/primitive/Generic/AccountId'
+import { Option, Null, bool, u32, u64, u128, Text } from '@polkadot/types'
+import { BlockNumber, Moment } from '@polkadot/types/interfaces'
+import AccountId from '@polkadot/types/generic/AccountId'
+import { RegistryTypes } from '@polkadot/types/types'
+import { JoyEnum, JoyStructDecorated } from './common'
 
 export class MemberId extends u64 {}
 export class PaidTermId extends u64 {}
@@ -21,21 +10,13 @@ export class SubscriptionId extends u64 {}
 export class ActorId extends u64 {}
 
 export class Paid extends PaidTermId {}
-export class Screening extends GenericAccountId {}
+export class Screening extends AccountId {}
 export class Genesis extends Null {}
-export class EntryMethod extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Paid,
-        Screening,
-        Genesis,
-      },
-      value,
-      index
-    )
-  }
-}
+export class EntryMethod extends JoyEnum({
+  Paid,
+  Screening,
+  Genesis,
+}) {}
 
 export type IMembership = {
   handle: Text
@@ -49,102 +30,34 @@ export type IMembership = {
   root_account: AccountId
   controller_account: AccountId
 }
-export class Membership extends JoyStruct<IMembership> {
-  constructor(value?: IMembership) {
-    super(
-      {
-        handle: Text,
-        avatar_uri: Text,
-        about: Text,
-        registered_at_block: u32,
-        registered_at_time: u64,
-        entry: EntryMethod,
-        suspended: bool,
-        subscription: Option.with(SubscriptionId),
-        root_account: AccountId,
-        controller_account: AccountId,
-      },
-      value
-    )
-  }
-
-  get handle(): Text {
-    return this.get('handle') as Text
-  }
-
-  get avatar_uri(): Text {
-    return this.get('avatar_uri') as Text
-  }
-
-  get about(): Text {
-    return this.get('about') as Text
-  }
-
-  get registered_at_block(): u32 {
-    return this.get('registered_at_block') as u32
-  }
-
-  get registered_at_time(): u64 {
-    return this.get('registered_at_time') as u64
-  }
-
-  get entry(): EntryMethod {
-    return this.get('entry') as EntryMethod
-  }
-
-  get suspended(): bool {
-    return this.get('suspended') as bool
-  }
-
-  get subscription(): Option<SubscriptionId> {
-    return this.get('subscription') as Option<SubscriptionId>
-  }
-
-  get root_account(): AccountId {
-    return this.get('root_account') as AccountId
-  }
-
-  get controller_account(): AccountId {
-    return this.get('controller_account') as AccountId
-  }
-}
-
-export class PaidMembershipTerms extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        fee: u128, // BalanceOf
-        text: Text,
-      },
-      value
-    )
-  }
-
-  get fee(): BalanceOf {
-    return this.get('fee') as BalanceOf
-  }
-
-  get text(): Text {
-    return this.get('text') as Text
-  }
+export class Membership
+  extends JoyStructDecorated({
+    handle: Text,
+    avatar_uri: Text,
+    about: Text,
+    registered_at_block: u32,
+    registered_at_time: u64,
+    entry: EntryMethod,
+    suspended: bool,
+    subscription: Option.with(SubscriptionId),
+    root_account: AccountId,
+    controller_account: AccountId,
+  })
+  implements IMembership {}
+
+export class PaidMembershipTerms extends JoyStructDecorated({
+  fee: u128, // BalanceOf
+  text: Text,
+}) {}
+
+export const membersTypes: RegistryTypes = {
+  EntryMethod,
+  MemberId,
+  PaidTermId,
+  SubscriptionId,
+  Membership,
+  PaidMembershipTerms,
+  ActorId,
 }
 
-export function registerMembershipTypes() {
-  try {
-    const typeRegistry = getTypeRegistry()
-    typeRegistry.register({
-      EntryMethod,
-      MemberId,
-      PaidTermId,
-      SubscriptionId,
-      Membership,
-      PaidMembershipTerms: {
-        fee: 'BalanceOf',
-        text: 'Text',
-      },
-      ActorId,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of membership module', err)
-  }
-}
+export default membersTypes

+ 32 - 63
types/src/mint/index.ts

@@ -1,6 +1,7 @@
-import { getTypeRegistry, u32, u64, u128, Option, Enum } from '@polkadot/types'
+import { u32, u64, u128, Option } from '@polkadot/types'
 import { Balance, BlockNumber } from '@polkadot/types/interfaces'
-import { JoyStruct } from '../common'
+import { JoyEnum, JoyStructDecorated } from '../common'
+import { RegistryTypes } from '@polkadot/types/types'
 
 export class MintId extends u64 {}
 
@@ -8,51 +9,29 @@ export class Setting extends u128 {}
 export class Adding extends u128 {}
 export class Reducing extends u128 {}
 
-export class AdjustCapacityBy extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Setting,
-        Adding,
-        Reducing,
-      },
-      value,
-      index
-    )
-  }
-}
+export class AdjustCapacityBy extends JoyEnum({ Setting, Adding, Reducing } as const) {}
 
 export type IAdjustOnInterval = {
   block_interval: BlockNumber
   adjustment_type: AdjustCapacityBy
 }
-export class AdjustOnInterval extends JoyStruct<IAdjustOnInterval> {
-  constructor(value?: IAdjustOnInterval) {
-    super(
-      {
-        block_interval: u32,
-        adjustment_type: AdjustCapacityBy,
-      },
-      value
-    )
-  }
-}
+export class AdjustOnInterval
+  extends JoyStructDecorated({
+    block_interval: u32,
+    adjustment_type: AdjustCapacityBy,
+  })
+  implements IAdjustOnInterval {}
 
 export type INextAdjustment = {
   adjustment: AdjustOnInterval
   at_block: BlockNumber
 }
-export class NextAdjustment extends JoyStruct<INextAdjustment> {
-  constructor(value?: INextAdjustment) {
-    super(
-      {
-        adjustment: AdjustOnInterval,
-        at_block: u32,
-      },
-      value
-    )
-  }
-}
+export class NextAdjustment
+  extends JoyStructDecorated({
+    adjustment: AdjustOnInterval,
+    at_block: u32,
+  })
+  implements INextAdjustment {}
 
 export type IMint = {
   capacity: Balance
@@ -60,30 +39,20 @@ export type IMint = {
   created_at: BlockNumber
   total_minted: Balance
 }
-export class Mint extends JoyStruct<IMint> {
-  constructor(value?: IMint) {
-    super(
-      {
-        capacity: u128,
-        next_adjustment: Option.with(NextAdjustment),
-        created_at: u32,
-        total_minted: u128,
-      },
-      value
-    )
-  }
-}
+export class Mint
+  extends JoyStructDecorated({
+    capacity: u128,
+    next_adjustment: Option.with(NextAdjustment),
+    created_at: u32,
+    total_minted: u128,
+  })
+  implements IMint {}
 
-export function registerMintTypes() {
-  try {
-    getTypeRegistry().register({
-      MintId: 'u64',
-      Mint,
-      MintBalanceOf: 'Balance',
-      BalanceOfMint: 'Balance',
-      'minting::BalanceOf': 'Balance',
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of mint module', err)
-  }
-}
+export const mintTypes: RegistryTypes = {
+  MintId: 'u64',
+  Mint,
+  MintBalanceOf: 'Balance',
+  BalanceOfMint: 'Balance',
+  'minting::BalanceOf': 'Balance',
+}
+export default mintTypes

+ 172 - 485
types/src/proposals.ts

@@ -1,21 +1,8 @@
-import {
-  Text,
-  u32,
-  Enum,
-  getTypeRegistry,
-  Tuple,
-  GenericAccountId,
-  u8,
-  Vec,
-  Option,
-  Struct,
-  Null,
-  Bytes,
-} from '@polkadot/types'
-import { bool } from '@polkadot/types/primitive'
+import { Text, u32, Tuple, u8, Vec, Option, Null, Bytes } from '@polkadot/types'
+import { bool, u128 } from '@polkadot/types/primitive'
 import { BlockNumber, Balance } from '@polkadot/types/interfaces'
-import AccountId from '@polkadot/types/primitive/Generic/AccountId'
-import { ThreadId, JoyStruct, WorkingGroup } from './common'
+import AccountId from '@polkadot/types/generic/AccountId'
+import { ThreadId, WorkingGroup, JoyEnum, JoyStructDecorated } from './common'
 import { MemberId } from './members'
 import { RoleParameters } from './roles'
 import { StakeId } from './stake'
@@ -30,110 +17,42 @@ export type IVotingResults = {
   slashes: u32
 }
 
-export class VotingResults extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        abstensions: 'u32',
-        approvals: 'u32',
-        rejections: 'u32',
-        slashes: 'u32',
-      },
-      value
-    )
-  }
-}
+export class VotingResults extends JoyStructDecorated({
+  abstensions: u32,
+  approvals: u32,
+  rejections: u32,
+  slashes: u32,
+}) {}
 
 export type ProposalParametersType = {
   // During this period, votes can be accepted
   votingPeriod: BlockNumber
-
   /* A pause before execution of the approved proposal. Zero means approved proposal would be
      executed immediately. */
   gracePeriod: BlockNumber
-
   // Quorum percentage of approving voters required to pass the proposal.
   approvalQuorumPercentage: u32
-
   // Approval votes percentage threshold to pass the proposal.
   approvalThresholdPercentage: u32
-
   // Quorum percentage of voters required to slash the proposal.
   slashingQuorumPercentage: u32
-
   // Slashing votes percentage threshold to slash the proposal.
   slashingThresholdPercentage: u32
-
   // Proposal stake
-  requiredStake: Balance
+  requiredStake: Option<Balance>
 }
 
-class ProposalParameters extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        // During this period, votes can be accepted
-        votingPeriod: 'BlockNumber',
-
-        /* A pause before execution of the approved proposal. Zero means approved proposal would be
-     executed immediately. */
-        gracePeriod: 'BlockNumber',
-
-        // Quorum percentage of approving voters required to pass the proposal.
-        approvalQuorumPercentage: 'u32',
-
-        // Approval votes percentage threshold to pass the proposal.
-        approvalThresholdPercentage: 'u32',
-
-        // Quorum percentage of voters required to slash the proposal.
-        slashingQuorumPercentage: 'u32',
-
-        // Slashing votes percentage threshold to slash the proposal.
-        slashingThresholdPercentage: 'u32',
-
-        // Proposal stake
-        requiredStake: 'Option<Balance>',
-      },
-      value
-    )
-  }
-
-  // During this period, votes can be accepted
-  get votingPeriod(): BlockNumber {
-    return this.get('votingPeriod') as BlockNumber
-  }
-
-  /* A pause before execution of the approved proposal. Zero means approved proposal would be
-     executed immediately. */
-  get gracePeriod(): BlockNumber {
-    return this.get('gracePeriod') as BlockNumber
-  }
-
-  // Quorum percentage of approving voters required to pass the proposal.
-  get approvalQuorumPercentage(): u32 {
-    return this.get('approvalQuorumPercentage') as u32
-  }
-
-  // Approval votes percentage threshold to pass the proposal.
-  get approvalThresholdPercentage(): u32 {
-    return this.get('approvalThresholdPercentage') as u32
-  }
-
-  // Quorum percentage of voters required to slash the proposal.
-  get slashingQuorumPercentage(): u32 {
-    return this.get('slashingQuorumPercentage') as u32
-  }
-
-  // Slashing votes percentage threshold to slash the proposal.
-  get slashingThresholdPercentage(): u32 {
-    return this.get('slashingThresholdPercentage') as u32
-  }
-
-  // Proposal stake
-  get requiredStake(): Option<Balance> {
-    return this.get('requiredStake') as Option<Balance>
-  }
-}
+export class ProposalParameters
+  extends JoyStructDecorated({
+    votingPeriod: u32,
+    gracePeriod: u32,
+    approvalQuorumPercentage: u32,
+    approvalThresholdPercentage: u32,
+    slashingQuorumPercentage: u32,
+    slashingThresholdPercentage: u32,
+    requiredStake: Option.with(u128),
+  })
+  implements ProposalParametersType {}
 
 export type IProposal = {
   parameters: ProposalParameters
@@ -163,70 +82,35 @@ export type IActiveStake = {
   stake_id: StakeId
   source_account_id: AccountId
 }
-export class ActiveStake extends JoyStruct<IActiveStake> {
-  constructor(value?: IActiveStake) {
-    super(
-      {
-        stakeId: StakeId,
-        sourceAccountId: GenericAccountId,
-      },
-      value
-    )
-  }
-}
+export class ActiveStake extends JoyStructDecorated({ stake_id: StakeId, source_account_id: AccountId })
+  implements IActiveStake {}
 
-export class ExecutionFailedStatus extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        error: 'Vec<u8>',
-      },
-      value
-    )
-  }
-
-  get error() {
-    return this.get('error') as Vec<u8>
-  }
-}
+export class ExecutionFailedStatus extends JoyStructDecorated({
+  error: Vec.with(u8),
+}) {}
 
 class ExecutionFailed extends ExecutionFailedStatus {}
 
-export type ApprovedProposalStatuses = 'PendingExecution' | 'Executed' | 'ExecutionFailed'
-
-export class ApprovedProposalStatus extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        PendingExecution: Null,
-        Executed: Null,
-        ExecutionFailed,
-      },
-      value,
-      index
-    )
-  }
-}
+export const ApprovedProposalDef = {
+  PendingExecution: Null,
+  Executed: Null,
+  ExecutionFailed,
+} as const
+export type ApprovedProposalStatuses = keyof typeof ApprovedProposalDef
+export class ApprovedProposalStatus extends JoyEnum(ApprovedProposalDef) {}
+
 export class Approved extends ApprovedProposalStatus {}
 
-export type ProposalDecisionStatuses = 'Canceled' | 'Vetoed' | 'Rejected' | 'Slashed' | 'Expired' | 'Approved'
-
-export class ProposalDecisionStatus extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Canceled: Null,
-        Vetoed: Null,
-        Rejected: Null,
-        Slashed: Null,
-        Expired: Null,
-        Approved,
-      },
-      value,
-      index
-    )
-  }
-}
+export const ProposalDecisionStatusesDef = {
+  Canceled: Null,
+  Vetoed: Null,
+  Rejected: Null,
+  Slashed: Null,
+  Expired: Null,
+  Approved,
+} as const
+export type ProposalDecisionStatuses = keyof typeof ProposalDecisionStatusesDef
+export class ProposalDecisionStatus extends JoyEnum(ProposalDecisionStatusesDef) {}
 
 export type IFinalizationData = {
   proposalStatus: ProposalDecisionStatus
@@ -235,209 +119,87 @@ export type IFinalizationData = {
   stakeDataAfterUnstakingError: Option<ActiveStake>
 }
 
-export class FinalizationData extends JoyStruct<IFinalizationData> {
-  constructor(value?: IFinalizationData) {
-    super(
-      {
-        proposalStatus: ProposalDecisionStatus,
-        finalizedAt: u32,
-        encodedUnstakingErrorDueToBrokenRuntime: Option.with(Vec.with(u8)),
-        stakeDataAfterUnstakingError: Option.with(ActiveStake),
-      },
-      value
-    )
-  }
-}
+export class FinalizationData
+  // FIXME: Snake case for consistency?
+  extends JoyStructDecorated({
+    proposalStatus: ProposalDecisionStatus,
+    finalizedAt: u32,
+    encodedUnstakingErrorDueToBrokenRuntime: Option.with(Vec.with(u8)),
+    stakeDataAfterUnstakingError: Option.with(ActiveStake),
+  })
+  implements IFinalizationData {}
 
 export class Active extends Option.with(ActiveStake) {}
 export class Finalized extends FinalizationData {}
 
-export class ProposalStatus extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Active,
-        Finalized,
-      },
-      value,
-      index
-    )
-  }
-}
+export class ProposalStatus extends JoyEnum({
+  Active,
+  Finalized,
+} as const) {}
 
 export const VoteKinds = ['Approve', 'Reject', 'Slash', 'Abstain'] as const
-
-export class VoteKind extends Enum {
-  constructor(value?: any, index?: number) {
-    super(['Approve', 'Reject', 'Slash', 'Abstain'], value, index)
-  }
-}
+export type VoteKindKey = typeof VoteKinds[number]
+export const VoteKindDef = {
+  Approve: Null,
+  Reject: Null,
+  Slash: Null,
+  Abstain: Null,
+} as const
+export class VoteKind extends JoyEnum(VoteKindDef) {}
 
 export type ProposalVotes = [MemberId, VoteKind][]
 
 export class ProposalId extends u32 {}
 
-export class SpendingParams extends Tuple {
-  constructor(value?: any) {
-    super(['Balance', 'AccountId'], value)
-  }
-}
+export class SpendingParams extends Tuple.with(['Balance', 'AccountId']) {}
 
-class SetLeadParams extends Tuple {
-  constructor(value?: any) {
-    super([MemberId, AccountId], value)
-  }
-}
+class SetLeadParams extends Tuple.with([MemberId, AccountId]) {}
 
 export class SetLead extends Option.with(SetLeadParams) {}
 
-export class Proposal extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        // Proposals parameter, characterize different proposal types.
-        parameters: ProposalParameters,
-
-        // Identifier of member proposing.
-        proposerId: MemberId,
-
-        // Proposal description
-        title: Text,
-
-        // Proposal body
-        description: Text,
-
-        // When it was created.
-        createdAt: 'BlockNumber',
-
-        /// Current proposal status
-        status: ProposalStatus,
-
-        /// Curring voting result for the proposal
-        votingResults: VotingResults,
-      },
-      value
-    )
-  }
-
-  get parameters(): ProposalParameters {
-    return this.get('parameters') as ProposalParameters
-  }
-
-  get proposerId(): MemberId {
-    return this.get('proposerId') as MemberId
-  }
-
-  get title(): Text {
-    return this.get('description') as Text
-  }
-
-  get description(): Text {
-    return this.get('description') as Text
-  }
-
-  get createdAt(): BlockNumber {
-    return this.get('createdAt') as BlockNumber
-  }
-
-  get status(): ProposalStatus {
-    return this.get('status') as ProposalStatus
-  }
-
-  get votingResults(): VotingResults {
-    return this.get('votingResults') as VotingResults
-  }
-}
-
-export class ThreadCounter extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        author_id: MemberId,
-        counter: 'u32',
-      },
-      value
-    )
-  }
-
-  get author_id(): MemberId {
-    return this.get('author_id') as MemberId
-  }
-
-  get counter(): u32 {
-    return this.get('counter') as u32
-  }
-}
-
-export class DiscussionThread extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        title: Bytes,
-        created_at: 'BlockNumber',
-        author_id: MemberId,
-      },
-      value
-    )
-  }
-
-  get title(): Bytes {
-    return this.get('title') as Bytes
-  }
-
-  get created_at(): BlockNumber {
-    return this.get('created_ad') as BlockNumber
-  }
-
-  get author_id(): MemberId {
-    return this.get('author_id') as MemberId
-  }
-}
-
-export class DiscussionPost extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        text: Bytes,
-        /// When post was added.
-        created_at: 'BlockNumber',
-        /// When post was updated last time.
-        updated_at: 'BlockNumber',
-        /// Author of the post.
-        author_id: MemberId,
-        /// Parent thread id for this post
-        thread_id: ThreadId,
-        /// Defines how many times this post was edited. Zero on creation.
-        edition_number: u32,
-      },
-      value
-    )
-  }
-
-  get text(): Bytes {
-    return this.get('text') as Bytes
-  }
-
-  get created_at(): BlockNumber {
-    return this.get('created_at') as BlockNumber
-  }
-
-  get updated_at(): BlockNumber {
-    return this.get('updated_at') as BlockNumber
-  }
-
-  get author_id(): MemberId {
-    return this.get('author_id') as MemberId
-  }
-
-  get thread_id(): ThreadId {
-    return this.get('thread_id') as ThreadId
-  }
-
-  get edition_number(): u32 {
-    return this.get('edition_number') as u32
-  }
-}
+export class Proposal
+  // FIXME: Snake case for consistency?
+  extends JoyStructDecorated({
+    // Proposals parameter, characterize different proposal types.
+    parameters: ProposalParameters,
+    // Identifier of member proposing.
+    proposerId: MemberId,
+    // Proposal description
+    title: Text,
+    // Proposal body
+    description: Text,
+    // When it was created.
+    createdAt: u32, // BlockNumber
+    /// Current proposal status
+    status: ProposalStatus,
+    /// Curring voting result for the proposal
+    votingResults: VotingResults,
+  }) {}
+
+export class ThreadCounter extends JoyStructDecorated({
+  author_id: MemberId,
+  counter: u32,
+}) {}
+
+export class DiscussionThread extends JoyStructDecorated({
+  title: Bytes,
+  created_at: u32, // BlockNumber
+  author_id: MemberId,
+}) {}
+
+export class DiscussionPost extends JoyStructDecorated({
+  text: Bytes,
+  /// When post was added.
+  created_at: u32, // BlockNumber
+  /// When post was updated last time.
+  updated_at: u32, // BlockNumber
+  /// Author of the post.
+  author_id: MemberId,
+  /// Parent thread id for this post
+  thread_id: ThreadId,
+  /// Defines how many times this post was edited. Zero on creation.
+  edition_number: u32,
+}) {}
 
 export type IAddOpeningParameters = {
   activate_at: ActivateOpeningAt
@@ -446,35 +208,14 @@ export type IAddOpeningParameters = {
   working_group: WorkingGroup
 }
 
-export class AddOpeningParameters extends JoyStruct<IAddOpeningParameters> {
-  constructor(value?: IAddOpeningParameters) {
-    super(
-      {
-        activate_at: ActivateOpeningAt,
-        commitment: WorkingGroupOpeningPolicyCommitment,
-        human_readable_text: Bytes,
-        working_group: WorkingGroup,
-      },
-      value
-    )
-  }
-
-  get activate_at(): ActivateOpeningAt {
-    return this.getField<ActivateOpeningAt>('activate_at')
-  }
-
-  get commitment(): WorkingGroupOpeningPolicyCommitment {
-    return this.getField<WorkingGroupOpeningPolicyCommitment>('commitment')
-  }
-
-  get human_readable_text(): Bytes {
-    return this.getField<Bytes>('human_readable_text')
-  }
-
-  get working_group(): WorkingGroup {
-    return this.getField<WorkingGroup>('working_group')
-  }
-}
+export class AddOpeningParameters
+  extends JoyStructDecorated({
+    activate_at: ActivateOpeningAt,
+    commitment: WorkingGroupOpeningPolicyCommitment,
+    human_readable_text: Bytes,
+    working_group: WorkingGroup,
+  })
+  implements IAddOpeningParameters {}
 
 export type IFillOpeningParameters = {
   opening_id: OpeningId
@@ -483,35 +224,14 @@ export type IFillOpeningParameters = {
   working_group: WorkingGroup
 }
 
-export class FillOpeningParameters extends JoyStruct<IFillOpeningParameters> {
-  constructor(value?: IFillOpeningParameters) {
-    super(
-      {
-        opening_id: OpeningId,
-        successful_application_id: ApplicationId,
-        reward_policy: Option.with(RewardPolicy),
-        working_group: WorkingGroup,
-      },
-      value
-    )
-  }
-
-  get opening_id(): OpeningId {
-    return this.getField<OpeningId>('opening_id')
-  }
-
-  get successful_application_id(): ApplicationId {
-    return this.getField<ApplicationId>('successful_application_id')
-  }
-
-  get reward_policy(): Option<RewardPolicy> {
-    return this.getField<Option<RewardPolicy>>('reward_policy')
-  }
-
-  get working_group(): WorkingGroup {
-    return this.getField<WorkingGroup>('working_group')
-  }
-}
+export class FillOpeningParameters
+  extends JoyStructDecorated({
+    opening_id: OpeningId,
+    successful_application_id: ApplicationId,
+    reward_policy: Option.with(RewardPolicy),
+    working_group: WorkingGroup,
+  })
+  implements IFillOpeningParameters {}
 
 export type ITerminateRoleParameters = {
   worker_id: WorkerId
@@ -520,84 +240,51 @@ export type ITerminateRoleParameters = {
   working_group: WorkingGroup
 }
 
-export class TerminateRoleParameters extends JoyStruct<ITerminateRoleParameters> {
-  constructor(value?: ITerminateRoleParameters) {
-    super(
-      {
-        worker_id: WorkerId,
-        rationale: Bytes,
-        slash: bool,
-        working_group: WorkingGroup,
-      },
-      value
-    )
-  }
-
-  get worker_id(): WorkerId {
-    return this.getField<WorkerId>('worker_id')
-  }
-
-  get rationale(): Bytes {
-    return this.getField<Bytes>('rationale')
-  }
-
-  get slash(): bool {
-    return this.getField<bool>('slash')
-  }
-
-  get working_group(): WorkingGroup {
-    return this.getField<WorkingGroup>('working_group')
-  }
-}
-
-export class ProposalDetails extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Text: 'Text',
-        RuntimeUpgrade: 'Vec<u8>',
-        SetElectionParameters: ElectionParameters,
-        Spending: SpendingParams,
-        SetLead: SetLead,
-        SetContentWorkingGroupMintCapacity: 'Balance',
-        EvictStorageProvider: 'AccountId',
-        SetValidatorCount: 'u32',
-        SetStorageRoleParameters: RoleParameters,
-        AddWorkingGroupLeaderOpening: AddOpeningParameters,
-        BeginReviewWorkingGroupLeaderApplication: Tuple.with([OpeningId, WorkingGroup]),
-        FillWorkingGroupLeaderOpening: FillOpeningParameters,
-        SetWorkingGroupMintCapacity: Tuple.with(['Balance', WorkingGroup]),
-        DecreaseWorkingGroupLeaderStake: Tuple.with([WorkerId, 'Balance', WorkingGroup]),
-        SlashWorkingGroupLeaderStake: Tuple.with([WorkerId, 'Balance', WorkingGroup]),
-        SetWorkingGroupLeaderReward: Tuple.with([WorkerId, 'Balance', WorkingGroup]),
-        TerminateWorkingGroupLeaderRole: TerminateRoleParameters,
-      },
-      value,
-      index
-    )
-  }
-}
+export class TerminateRoleParameters
+  extends JoyStructDecorated({
+    worker_id: WorkerId,
+    rationale: Bytes,
+    slash: bool,
+    working_group: WorkingGroup,
+  })
+  implements ITerminateRoleParameters {}
+
+export class ProposalDetails extends JoyEnum({
+  Text: Text,
+  RuntimeUpgrade: Vec.with(u8),
+  SetElectionParameters: ElectionParameters,
+  Spending: SpendingParams,
+  SetLead: SetLead,
+  SetContentWorkingGroupMintCapacity: u128,
+  EvictStorageProvider: AccountId,
+  SetValidatorCount: u32,
+  SetStorageRoleParameters: RoleParameters,
+  AddWorkingGroupLeaderOpening: AddOpeningParameters,
+  BeginReviewWorkingGroupLeaderApplication: Tuple.with([OpeningId, WorkingGroup]),
+  FillWorkingGroupLeaderOpening: FillOpeningParameters,
+  SetWorkingGroupMintCapacity: Tuple.with(['Balance', WorkingGroup]),
+  DecreaseWorkingGroupLeaderStake: Tuple.with([WorkerId, 'Balance', WorkingGroup]),
+  SlashWorkingGroupLeaderStake: Tuple.with([WorkerId, 'Balance', WorkingGroup]),
+  SetWorkingGroupLeaderReward: Tuple.with([WorkerId, 'Balance', WorkingGroup]),
+  TerminateWorkingGroupLeaderRole: TerminateRoleParameters,
+} as const) {}
 
 // export default proposalTypes;
-export function registerProposalTypes() {
-  try {
-    getTypeRegistry().register({
-      ProposalId,
-      ProposalStatus,
-      ProposalOf: Proposal,
-      ProposalDetails,
-      ProposalDetailsOf: ProposalDetails, // Runtime alias
-      VotingResults,
-      ProposalParameters,
-      VoteKind,
-      ThreadCounter,
-      DiscussionThread,
-      DiscussionPost,
-      AddOpeningParameters,
-      FillOpeningParameters,
-      TerminateRoleParameters,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of proposals module', err)
-  }
+export const proposalsTypes = {
+  ProposalId,
+  ProposalStatus,
+  ProposalOf: Proposal,
+  ProposalDetails,
+  ProposalDetailsOf: ProposalDetails, // Runtime alias
+  VotingResults,
+  ProposalParameters,
+  VoteKind,
+  ThreadCounter,
+  DiscussionThread,
+  DiscussionPost,
+  AddOpeningParameters,
+  FillOpeningParameters,
+  TerminateRoleParameters,
 }
+
+export default proposalsTypes

+ 30 - 75
types/src/recurring-rewards/index.ts

@@ -1,7 +1,9 @@
-import { getTypeRegistry, u64, u128, Option } from '@polkadot/types'
-import { AccountId, Balance, BlockNumber } from '@polkadot/types/interfaces'
-import { JoyStruct } from '../common'
+import { u64, u128, Option, u32 } from '@polkadot/types'
+import { Balance, BlockNumber } from '@polkadot/types/interfaces'
 import { MintId } from '../mint'
+import { JoyStructDecorated } from '../common'
+import AccountId from '@polkadot/types/generic/AccountId'
+import { RegistryTypes } from '@polkadot/types/types'
 
 export class RecipientId extends u64 {}
 export class RewardRelationshipId extends u64 {}
@@ -10,25 +12,12 @@ export type IRecipient = {
   total_reward_received: Balance
   total_reward_missed: Balance
 }
-export class Recipient extends JoyStruct<IRecipient> {
-  constructor(value?: IRecipient) {
-    super(
-      {
-        total_reward_received: u128,
-        total_reward_missed: u128,
-      },
-      value
-    )
-  }
-
-  get total_reward_received(): u128 {
-    return this.getField<u128>('total_reward_received')
-  }
-
-  get total_reward_missed(): u128 {
-    return this.getField<u128>('total_reward_missed')
-  }
-}
+export class Recipient
+  extends JoyStructDecorated({
+    total_reward_received: u128,
+    total_reward_missed: u128,
+  })
+  implements IRecipient {}
 
 export type IRewardRelationship = {
   recipient: RecipientId
@@ -40,57 +29,23 @@ export type IRewardRelationship = {
   total_reward_received: Balance
   total_reward_missed: Balance
 }
-export class RewardRelationship extends JoyStruct<IRewardRelationship> {
-  constructor(value?: IRecipient) {
-    super(
-      {
-        recipient: RecipientId,
-        mint_id: MintId,
-        account: 'AccountId',
-        amount_per_payout: 'Balance',
-        next_payment_at_block: Option.with('BlockNumber'),
-        payout_interval: Option.with('BlockNumber'),
-        total_reward_received: 'Balance',
-        total_reward_missed: 'Balance',
-      },
-      value
-    )
-  }
-
-  get recipient(): RecipientId {
-    return this.getField<RecipientId>('recipient')
-  }
-
-  get total_reward_received(): Balance {
-    return this.getField<Balance>('total_reward_received')
-  }
-
-  get total_reward_missed(): Balance {
-    return this.getField<Balance>('total_reward_missed')
-  }
-
-  get amount_per_payout(): Balance {
-    return this.getField<Balance>('amount_per_payout')
-  }
-
-  get payout_interval(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('payout_interval')
-  }
-
-  get next_payment_at_block(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('next_payment_at_block')
-  }
-}
-
-export function registerRecurringRewardsTypes() {
-  try {
-    getTypeRegistry().register({
-      RecipientId: 'u64',
-      RewardRelationshipId: 'u64',
-      Recipient,
-      RewardRelationship,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of recurring rewards module', err)
-  }
+export class RewardRelationship
+  extends JoyStructDecorated({
+    recipient: RecipientId,
+    mint_id: MintId,
+    account: AccountId,
+    amount_per_payout: u128, // Balance
+    next_payment_at_block: Option.with(u32), // BlockNumber
+    payout_interval: Option.with(u32), // BlockNumber
+    total_reward_received: u128, // Balance
+    total_reward_missed: u128, // Balance
+  })
+  implements IRewardRelationship {}
+
+export const recurringRewardsTypes: RegistryTypes = {
+  RecipientId: 'u64',
+  RewardRelationshipId: 'u64',
+  Recipient,
+  RewardRelationship,
 }
+export default recurringRewardsTypes

+ 17 - 62
types/src/roles.ts

@@ -1,67 +1,22 @@
-import { Struct } from '@polkadot/types/codec'
-import { getTypeRegistry, u32, u128 } from '@polkadot/types'
-import { BlockNumber, Balance } from '@polkadot/types/interfaces'
+import { u32, u128 } from '@polkadot/types'
+import { JoyStructDecorated } from './common'
 
 // We only need this type for historic reasons to read old proposal state
 // that was related to the now defunct actors module
-export class RoleParameters extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        min_stake: u128, // Balance,
-        min_actors: u32,
-        max_actors: u32,
-        reward: u128, // Balance,
-        reward_period: u32, // BlockNumber,
-        bonding_period: u32, // BlockNumber,
-        unbonding_period: u32, // BlockNumber,
-        min_service_period: u32, // BlockNumber,
-        startup_grace_period: u32, // BlockNumber,
-        entry_request_fee: u128, // Balance
-      },
-      value
-    )
-  }
+export class RoleParameters extends JoyStructDecorated({
+  min_stake: u128, // Balance,
+  min_actors: u32,
+  max_actors: u32,
+  reward: u128, // Balance,
+  reward_period: u32, // BlockNumber,
+  bonding_period: u32, // BlockNumber,
+  unbonding_period: u32, // BlockNumber,
+  min_service_period: u32, // BlockNumber,
+  startup_grace_period: u32, // BlockNumber,
+  entry_request_fee: u128, // Balance
+}) {}
 
-  get min_stake(): Balance {
-    return this.get('min_stake') as Balance
-  }
-  get max_actors(): u32 {
-    return this.get('max_actors') as u32
-  }
-  get min_actors(): u32 {
-    return this.get('min_actors') as u32
-  }
-  get reward(): Balance {
-    return this.get('reward') as Balance
-  }
-  get reward_period(): BlockNumber {
-    return this.get('reward_period') as BlockNumber
-  }
-  get unbonding_period(): BlockNumber {
-    return this.get('unbonding_period') as BlockNumber
-  }
-  get bonding_period(): BlockNumber {
-    return this.get('bonding_period') as BlockNumber
-  }
-  get min_service_period(): BlockNumber {
-    return this.get('min_service_period') as BlockNumber
-  }
-  get startup_grace_period(): BlockNumber {
-    return this.get('startup_grace_period') as BlockNumber
-  }
-  get entry_request_fee(): Balance {
-    return this.get('entry_request_fee') as Balance
-  }
-}
-
-export function registerRolesTypes() {
-  try {
-    const typeRegistry = getTypeRegistry()
-    typeRegistry.register({
-      RoleParameters,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of roles module', err)
-  }
+export const rolesTypes = {
+  RoleParameters,
 }
+export default rolesTypes

+ 41 - 0
types/src/scripts/defsFromTypes.ts

@@ -0,0 +1,41 @@
+// Conversion of Joystream types into @polkadot/typegen compatible RegistryTypes object
+// (will require a few additonal tweaks to work, currently just logs the output in the console)
+
+import { types } from '../index'
+import { Constructor, Codec, RegistryTypes, Registry } from '@polkadot/types/types'
+import { TypeRegistry } from '@polkadot/types'
+
+function normalizeDef(registry: Registry, defOrConstructor: any, typeName: string) {
+  if (typeof defOrConstructor === 'string') {
+    return defOrConstructor
+  } else if (typeof defOrConstructor === 'function') {
+    const defString = new (defOrConstructor as Constructor<Codec>)(registry).toRawType().toString()
+    try {
+      const obj = JSON.parse(defString)
+      // def is an object:
+      return obj
+    } catch (e) {
+      // def if just a type name:
+      return defString
+    }
+  }
+
+  throw new Error(`Unkown type entry for ${typeName} found in registry!`)
+}
+
+async function defsFromTypes() {
+  const registry = new TypeRegistry()
+  registry.setKnownTypes({ types })
+  registry.register(types)
+  const defs: RegistryTypes = {}
+  Object.entries(registry.knownTypes.types as any).forEach(([typeName, defOrConstructor]) => {
+    const def = normalizeDef(registry, defOrConstructor, typeName)
+    defs[typeName] = def
+  })
+
+  return defs
+}
+
+defsFromTypes()
+  .then((defs) => console.log(defs))
+  .catch(console.error)

+ 108 - 0
types/src/scripts/updateAugmentTypes.ts

@@ -0,0 +1,108 @@
+// Adds Joystream types to /definitions/augment-types.ts allowing better api.createType TS support
+
+import common from '../common'
+import members from '../members'
+import council from '../council'
+import roles from '../roles'
+import forum from '../forum'
+import stake from '../stake'
+import mint from '../mint'
+import recurringRewards from '../recurring-rewards'
+import hiring from '../hiring'
+import versionedStore from '../versioned-store'
+import versionedStorePermissions from '../versioned-store/permissions'
+import contentWorkingGroup from '../content-working-group'
+import workingGroup from '../working-group'
+import discovery from '../discovery'
+import media from '../media'
+import proposals from '../proposals'
+import fs from 'fs'
+import path from 'path'
+
+const typesByModule = {
+  'common': common,
+  'members': members,
+  'council': council,
+  'roles': roles,
+  'forum': forum,
+  'stake': stake,
+  'mint': mint,
+  'recurring-rewards': recurringRewards,
+  'hiring': hiring,
+  'versioned-store': versionedStore,
+  'versioned-store/permissions': versionedStorePermissions,
+  'content-working-group': contentWorkingGroup,
+  'working-group': workingGroup,
+  'discovery': discovery,
+  'media': media,
+  'proposals': proposals,
+}
+
+type Imports = { [moduleName: string]: string[] }
+type AugmentTypes = { [typeName: string]: string }
+
+const imports: Imports = {}
+const augmentTypes: AugmentTypes = {}
+
+const populateFileByTemplateTag = (fileContent: string, tag: string, lines: string[]) => {
+  const fileLines = fileContent.split('\n')
+  const startIndex = fileLines.findIndex((line) => line.includes(`/** ${tag} **/`))
+  const endIndex = fileLines.findIndex((line) => line.includes(`/** /${tag} **/`))
+
+  if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
+    throw new Error(`populateFileByTemplateTag: Invalid tag (${tag})`)
+  }
+
+  const whitespaceMatch = fileLines[startIndex].match(/^(\s)+/)
+  const whitespace = whitespaceMatch ? whitespaceMatch[0] : ''
+
+  fileLines.splice(startIndex + 1, endIndex - (startIndex + 1), ...lines.map((line) => `${whitespace}${line}`))
+
+  return fileLines.join('\n')
+}
+
+const updateAugmentTypesFile = (filePath: string, imports: Imports, augmentTypes: AugmentTypes) => {
+  let fileContent = fs.readFileSync(filePath).toString()
+  fileContent = populateFileByTemplateTag(
+    fileContent,
+    'CUSTOMIMPORTS',
+    Object.entries(imports).map(
+      ([moduleName, importStatements]) =>
+        // import as to avoid namespace clashes
+        `import { ${importStatements.join(', ')} } from '../${moduleName}'`
+    )
+  )
+  fileContent = populateFileByTemplateTag(
+    fileContent,
+    'CUSTOMTYPES',
+    Object.entries(augmentTypes).map(([typeName, constructorName]) => `"${typeName}": ${constructorName};`)
+  )
+
+  fs.writeFileSync(filePath, fileContent)
+}
+
+const addAugmentTypes = (typeName: string, constructorName: string) => {
+  augmentTypes[typeName] = constructorName
+  augmentTypes[`Option<${typeName}>`] = `Option<${constructorName}>`
+  augmentTypes[`Vec<${typeName}>`] = `Vec<${constructorName}>`
+}
+
+Object.entries(typesByModule).forEach(([moduleName, types]) => {
+  Object.entries(types).forEach(([typeName, codecOrName]) => {
+    if (typeof codecOrName === 'function') {
+      const constructorName = codecOrName.name
+      if (!constructorName) {
+        throw new Error(`Codec constructor doesn't have a name: ${typeName}`)
+      }
+      const normalizedTypeName = typeName.replace(/[^A-Za-z0-9_]/g, '_')
+      // Add "as" to avoid namespace clashes
+      const importStatement = `${constructorName} as ${normalizedTypeName}`
+      !imports[moduleName] ? (imports[moduleName] = [importStatement]) : imports[moduleName].push(importStatement)
+      addAugmentTypes(typeName, normalizedTypeName)
+    } else if (typeof codecOrName === 'string') {
+      addAugmentTypes(typeName, codecOrName)
+    }
+  })
+})
+
+updateAugmentTypesFile(path.join(__dirname, '../definitions/augment-types.ts'), imports, augmentTypes)

+ 47 - 100
types/src/stake/index.ts

@@ -1,6 +1,7 @@
-import { getTypeRegistry, u32, u64, u128, Enum, Null, BTreeMap, bool } from '@polkadot/types'
-import { JoyStruct } from '../common'
+import { u32, u64, u128, Null, BTreeMap, bool } from '@polkadot/types'
 import { BlockNumber, Balance } from '@polkadot/types/interfaces'
+import { RegistryTypes } from '@polkadot/types/types'
+import { JoyEnum, JoyStructDecorated } from '../common'
 
 export class StakeId extends u64 {}
 export class SlashId extends u64 {}
@@ -11,52 +12,34 @@ export type ISlash = {
   blocks_remaining_in_active_period_for_slashing: BlockNumber
   slash_amount: Balance
 }
-export class Slash extends JoyStruct<ISlash> {
-  constructor(value?: ISlash) {
-    super(
-      {
-        started_at_block: u32,
-        is_active: bool,
-        blocks_remaining_in_active_period_for_slashing: u32,
-        slash_amount: u128,
-      },
-      value
-    )
-  }
-}
+export class Slash
+  extends JoyStructDecorated({
+    started_at_block: u32,
+    is_active: bool,
+    blocks_remaining_in_active_period_for_slashing: u32,
+    slash_amount: u128,
+  })
+  implements ISlash {}
 
 export type IUnstakingState = {
   started_at_block: BlockNumber
   is_active: bool
   blocks_remaining_in_active_period_for_unstaking: BlockNumber
 }
-export class UnstakingState extends JoyStruct<IUnstakingState> {
-  constructor(value?: IUnstakingState) {
-    super(
-      {
-        started_at_block: u32,
-        is_active: bool,
-        blocks_remaining_in_active_period_for_unstaking: u32,
-      },
-      value
-    )
-  }
-}
+export class UnstakingState
+  extends JoyStructDecorated({
+    started_at_block: u32,
+    is_active: bool,
+    blocks_remaining_in_active_period_for_unstaking: u32,
+  })
+  implements IUnstakingState {}
 
 export class Normal extends Null {}
 export class Unstaking extends UnstakingState {}
-export class StakedStatus extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Normal,
-        Unstaking,
-      },
-      value,
-      index
-    )
-  }
-}
+export class StakedStatus extends JoyEnum({
+  Normal,
+  Unstaking,
+} as const) {}
 
 export type IStakedState = {
   staked_amount: Balance
@@ -64,81 +47,45 @@ export type IStakedState = {
   next_slash_id: SlashId
   ongoing_slashes: BTreeMap<SlashId, Slash>
 }
-export class StakedState extends JoyStruct<IStakedState> {
-  constructor(value?: IStakedState) {
-    super(
-      {
-        staked_amount: u128,
-        staked_status: StakedStatus,
-        next_slash_id: SlashId,
-        ongoing_slashes: BTreeMap.with(SlashId, Slash),
-      },
-      value
-    )
-  }
-
-  get staked_amount(): u128 {
-    return this.getField<u128>('staked_amount')
-  }
-}
+export class StakedState
+  extends JoyStructDecorated({
+    staked_amount: u128,
+    staked_status: StakedStatus,
+    next_slash_id: SlashId,
+    ongoing_slashes: BTreeMap.with(SlashId, Slash),
+  })
+  implements IStakedState {}
 
 export class NotStaked extends Null {}
 export class Staked extends StakedState {}
 
-export class StakingStatus extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        NotStaked,
-        Staked,
-      },
-      value,
-      index
-    )
-  }
-}
+export class StakingStatus extends JoyEnum({
+  NotStaked,
+  Staked,
+} as const) {}
 
 export type IStake = {
   created: BlockNumber
   staking_status: StakingStatus
 }
 
-export class Stake extends JoyStruct<IStake> {
-  constructor(value?: IStake) {
-    super(
-      {
-        created: u32,
-        staking_status: StakingStatus,
-      },
-      value
-    )
-  }
-
-  get created(): u32 {
-    return this.getField<u32>('created')
-  }
-
-  get staking_status(): StakingStatus {
-    return this.getField<StakingStatus>('staking_status')
-  }
-
+export class Stake
+  extends JoyStructDecorated({
+    created: u32,
+    staking_status: StakingStatus,
+  })
+  implements IStake {
   get value(): Balance {
-    switch (this.staking_status.type) {
-      case 'Staked':
-        return (this.staking_status.value as Staked).staked_amount
+    if (this.staking_status.isOfType('Staked')) {
+      return this.staking_status.asType('Staked').staked_amount
     }
 
-    return new u128(0)
+    return new u128(this.registry, 0)
   }
 }
 
-export function registerStakeTypes() {
-  try {
-    getTypeRegistry().register({
-      StakeId: 'u64',
-      Stake,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of stake module', err)
-  }
+export const stakeTypes: RegistryTypes = {
+  StakeId: 'u64',
+  Stake,
 }
+export default stakeTypes

+ 36 - 34
types/src/versioned-store/EntityCodec.ts

@@ -1,10 +1,10 @@
 import BN from 'bn.js'
 import { Text, bool, Vec, u16 } from '@polkadot/types'
-import { Codec } from '@polkadot/types/types'
+import { Codec, Registry } from '@polkadot/types/types'
 import { Class, Entity, VecClassPropertyValue, ClassPropertyValue, EntityId, ClassId, unifyPropName } from '.'
 import * as PV from './PropertyValue'
 import { PropertyValue } from './PropertyValue'
-import { PropertyTypeName } from './PropertyTypeName'
+import { PropertyTypeKeys } from './PropertyType'
 import ChannelId from '../content-working-group/ChannelId'
 
 /**
@@ -40,9 +40,9 @@ function substrateToPlain<T>(x: Codec): T | undefined {
  *
  * @throws Error
  */
-function plainToSubstrate(propType: string, value: any): PropertyValue {
+function plainToSubstrate(registry: Registry, propType: string, value: any): PropertyValue {
   const ok = (typeEnum: PV.PropertyValueEnum) => {
-    return new PropertyValue({ [propType]: typeEnum })
+    return new PropertyValue(registry, { [propType]: typeEnum }) // FIXME: createType?
   }
 
   const valueAsBool = (): boolean => {
@@ -79,51 +79,48 @@ function plainToSubstrate(propType: string, value: any): PropertyValue {
     return valueAsArr() as string[]
   }
 
+  // FIXME: use createType?
   switch (propType) {
     // Primitives:
-
     case 'None':
-      return ok(new PV.None())
+      return ok(new PV.None(registry))
     case 'Bool':
-      return ok(new PV.Bool(valueAsBool()))
+      return ok(new PV.Bool(registry, valueAsBool()))
     case 'Uint16':
-      return ok(new PV.Uint16(value as string))
+      return ok(new PV.Uint16(registry, value as string))
     case 'Uint32':
-      return ok(new PV.Uint32(value as string))
+      return ok(new PV.Uint32(registry, value as string))
     case 'Uint64':
-      return ok(new PV.Uint64(value as string))
+      return ok(new PV.Uint64(registry, value as string))
     case 'Int16':
-      return ok(new PV.Int16(value as string))
+      return ok(new PV.Int16(registry, value as string))
     case 'Int32':
-      return ok(new PV.Int32(value as string))
+      return ok(new PV.Int32(registry, value as string))
     case 'Int64':
-      return ok(new PV.Int64(value as string))
+      return ok(new PV.Int64(registry, value as string))
     case 'Text':
-      return ok(new PV.Text(value as string))
+      return ok(new PV.Text(registry, value as string))
     case 'Internal':
-      return ok(new PV.Internal(value as string))
-
+      return ok(new PV.Internal(registry, value as string))
     // Vectors:
-
     case 'BoolVec':
-      return ok(new PV.BoolVec(valueAsBoolArr()))
+      return ok(new PV.BoolVec(registry, valueAsBoolArr()))
     case 'Uint16Vec':
-      return ok(new PV.Uint16Vec(valueAsStrArr()))
+      return ok(new PV.Uint16Vec(registry, valueAsStrArr()))
     case 'Uint32Vec':
-      return ok(new PV.Uint32Vec(valueAsStrArr()))
+      return ok(new PV.Uint32Vec(registry, valueAsStrArr()))
     case 'Uint64Vec':
-      return ok(new PV.Uint64Vec(valueAsStrArr()))
+      return ok(new PV.Uint64Vec(registry, valueAsStrArr()))
     case 'Int16Vec':
-      return ok(new PV.Int16Vec(valueAsStrArr()))
+      return ok(new PV.Int16Vec(registry, valueAsStrArr()))
     case 'Int32Vec':
-      return ok(new PV.Int32Vec(valueAsStrArr()))
+      return ok(new PV.Int32Vec(registry, valueAsStrArr()))
     case 'Int64Vec':
-      return ok(new PV.Int64Vec(valueAsStrArr()))
+      return ok(new PV.Int64Vec(registry, valueAsStrArr()))
     case 'TextVec':
-      return ok(new PV.TextVec(valueAsStrArr()))
+      return ok(new PV.TextVec(registry, valueAsStrArr()))
     case 'InternalVec':
-      return ok(new PV.InternalVec(valueAsArr()))
-
+      return ok(new PV.InternalVec(registry, valueAsArr()))
     default: {
       throw new Error(`Unknown property type name: ${propType}`)
     }
@@ -174,8 +171,10 @@ export interface ToPlainObjectProps {
 export abstract class EntityCodec<T extends PlainEntity> {
   private propNameToMetaMap: Map<string, PropMeta> = new Map()
   private propIndexToNameMap: Map<number, string> = new Map()
+  private registry: Registry
 
   public constructor(entityClass: Class) {
+    this.registry = entityClass.registry
     entityClass.properties.map((p, index) => {
       const propName = unifyPropName(p.name.toString())
       const propMeta = { index, type: p.prop_type.type.toString() }
@@ -244,26 +243,29 @@ export abstract class EntityCodec<T extends PlainEntity> {
     // console.log('propNameToMetaMap propNameToMetaMap', this.propNameToMetaMap)
     // console.log('toSubstrateUpdate updatedProps', updatedProps)
 
-    const res = new VecClassPropertyValue()
+    const res = new VecClassPropertyValue(this.registry) // FIXME: createType?
     Object.keys(updatedProps).map((propName) => {
       const meta = this.propNameToMetaMap.get(propName)
       if (meta) {
-        const propType = meta.type as PropertyTypeName
+        const propType = meta.type as PropertyTypeKeys
         const plainValue = (updatedProps as any)[propName]
 
         let codecValue: PropertyValue | undefined
         try {
-          codecValue = plainToSubstrate(propType, plainValue)
+          codecValue = plainToSubstrate(this.registry, propType, plainValue)
         } catch (err) {
           console.error(`Failed to convert plain value '${plainValue}' to Substrate codec. Error:`, err)
         }
 
         if (codecValue) {
           res.push(
-            new ClassPropertyValue({
-              in_class_index: new u16(meta.index),
-              value: codecValue,
-            })
+            new ClassPropertyValue(
+              this.registry, // FIXME: createType?
+              {
+                in_class_index: new u16(this.registry, meta.index),
+                value: codecValue,
+              }
+            )
           )
         }
       }

+ 27 - 76
types/src/versioned-store/PropertyType.ts

@@ -1,11 +1,11 @@
 import { u16, Null } from '@polkadot/types'
-import { Enum, Tuple } from '@polkadot/types/codec'
+import { Tuple } from '@polkadot/types/codec'
 import ClassId from './ClassId'
+import { JoyEnum } from '../common'
 
 export class None extends Null {}
 
 // Single values:
-
 export class Bool extends Null {}
 export class Uint16 extends Null {}
 export class Uint32 extends Null {}
@@ -15,9 +15,7 @@ export class Int32 extends Null {}
 export class Int64 extends Null {}
 export class Text extends u16 {}
 export class Internal extends ClassId {}
-
 // Vectors:
-
 export class BoolVec extends u16 {}
 export class Uint16Vec extends u16 {}
 export class Uint32Vec extends u16 {}
@@ -25,80 +23,33 @@ export class Uint64Vec extends u16 {}
 export class Int16Vec extends u16 {}
 export class Int32Vec extends u16 {}
 export class Int64Vec extends u16 {}
+export class TextVec extends Tuple.with([u16, u16]) {} // [maxItems, maxTextLength]
+export class InternalVec extends Tuple.with([u16, ClassId]) {} // [maxItems, classId]
 
-export class TextVec extends Tuple.with([u16, u16]) {
-  static newTypesafe(maxItems: u16 | number, maxTextLength: u16 | number) {
-    return new this([maxItems, maxTextLength])
-  }
-}
-
-export class InternalVec extends Tuple.with([u16, ClassId]) {
-  static newTypesafe(maxItems: u16 | number, classId: ClassId | number) {
-    return new this([maxItems, classId])
-  }
-}
-
-export type PropertyTypeEnum =
-  | None
-
+export const PropertyTypeDef = {
+  None,
   // Single values:
-  | Bool
-  | Uint16
-  | Uint32
-  | Uint64
-  | Int16
-  | Int32
-  | Int64
-  | Text
-  | Internal
-
+  Bool,
+  Uint16,
+  Uint32,
+  Uint64,
+  Int16,
+  Int32,
+  Int64,
+  Text,
+  Internal,
   // Vectors:
-  | BoolVec
-  | Uint16Vec
-  | Uint32Vec
-  | Uint64Vec
-  | Int16Vec
-  | Int32Vec
-  | Int64Vec
-  | TextVec
-  | InternalVec
-
-type PropertyTypeEnumValue = {
-  [typeName: string]: PropertyTypeEnum
-}
-
-export class PropertyType extends Enum {
-  constructor(value?: PropertyTypeEnumValue, index?: number) {
-    super(
-      {
-        None,
-
-        // Single values:
-        Bool,
-        Uint16,
-        Uint32,
-        Uint64,
-        Int16,
-        Int32,
-        Int64,
-        Text,
-        Internal,
-
-        // Vectors:
-        BoolVec,
-        Uint16Vec,
-        Uint32Vec,
-        Uint64Vec,
-        Int16Vec,
-        Int32Vec,
-        Int64Vec,
-        TextVec,
-        InternalVec,
-      },
-      value,
-      index
-    )
-  }
-}
+  BoolVec,
+  Uint16Vec,
+  Uint32Vec,
+  Uint64Vec,
+  Int16Vec,
+  Int32Vec,
+  Int64Vec,
+  TextVec,
+  InternalVec,
+} as const
+export type PropertyTypeKeys = keyof typeof PropertyTypeDef
+export class PropertyType extends JoyEnum(PropertyTypeDef) {}
 
 export default PropertyType

+ 0 - 22
types/src/versioned-store/PropertyTypeName.ts

@@ -1,22 +0,0 @@
-export type PropertyTypeName =
-  | 'None'
-  | 'Bool'
-  | 'Uint16'
-  | 'Uint32'
-  | 'Uint64'
-  | 'Int16'
-  | 'Int32'
-  | 'Int64'
-  | 'Text'
-  | 'Internal'
-
-  // Vectors:
-  | 'BoolVec'
-  | 'Uint16Vec'
-  | 'Uint32Vec'
-  | 'Uint64Vec'
-  | 'Int16Vec'
-  | 'Int32Vec'
-  | 'Int64Vec'
-  | 'TextVec'
-  | 'InternalVec'

+ 25 - 56
types/src/versioned-store/PropertyValue.ts

@@ -10,8 +10,8 @@ import {
   i32,
   i64,
 } from '@polkadot/types'
-import { Enum } from '@polkadot/types/codec'
 import EntityId from './EntityId'
+import { JoyEnum } from '../common'
 
 export class None extends Null {}
 
@@ -40,67 +40,36 @@ export class Int64Vec extends Vector.with(i64) {}
 export class TextVec extends Vector.with(PolkaText) {}
 export class InternalVec extends Vector.with(EntityId) {}
 
-export type PropertyValueEnum =
-  | None
-
+export const PropertyValueDef = {
+  None,
   // Single values:
-  | Bool
-  | Uint16
-  | Uint32
-  | Uint64
-  | Int16
-  | Int32
-  | Int64
-  | Text
-  | Internal
-
+  Bool,
+  Uint16,
+  Uint32,
+  Uint64,
+  Int16,
+  Int32,
+  Int64,
+  Text,
+  Internal,
   // Vectors:
-  | BoolVec
-  | Uint16Vec
-  | Uint32Vec
-  | Uint64Vec
-  | Int16Vec
-  | Int32Vec
-  | Int64Vec
-  | TextVec
-  | InternalVec
+  BoolVec,
+  Uint16Vec,
+  Uint32Vec,
+  Uint64Vec,
+  Int16Vec,
+  Int32Vec,
+  Int64Vec,
+  TextVec,
+  InternalVec,
+} as const
 
+// FIXME: Fix naming conventions, or remove those later?
+export type PropertyValueEnum = InstanceType<typeof PropertyValueDef[keyof typeof PropertyValueDef]>
 export type PropertyValueEnumValue = {
   [typeName: string]: PropertyValueEnum
 }
 
-export class PropertyValue extends Enum {
-  constructor(value?: PropertyValueEnumValue, index?: number) {
-    super(
-      {
-        None,
-
-        // Single values:
-        Bool,
-        Uint16,
-        Uint32,
-        Uint64,
-        Int16,
-        Int32,
-        Int64,
-        Text,
-        Internal,
-
-        // Vectors:
-        BoolVec,
-        Uint16Vec,
-        Uint32Vec,
-        Uint64Vec,
-        Int16Vec,
-        Int32Vec,
-        Int64Vec,
-        TextVec,
-        InternalVec,
-      },
-      value,
-      index
-    )
-  }
-}
+export class PropertyValue extends JoyEnum(PropertyValueDef) {}
 
 export default PropertyValue

+ 51 - 105
types/src/versioned-store/index.ts

@@ -1,11 +1,12 @@
-import { getTypeRegistry, u16, Text, bool as Bool } from '@polkadot/types'
+import { u16, Text, bool as Bool } from '@polkadot/types'
 import { Vec as Vector } from '@polkadot/types/codec'
-import { JoyStruct } from '../common'
 import EntityId from './EntityId'
 import ClassId from './ClassId'
 import PropertyType from './PropertyType'
 import PropertyValue from './PropertyValue'
 import { camelCase, upperFirst } from 'lodash'
+import { RegistryTypes } from '@polkadot/types/types'
+import { JoyStructDecorated, JoyStructCustom } from '../common'
 
 export { ClassId, EntityId, PropertyType, PropertyValue }
 
@@ -16,25 +17,20 @@ export type PropertyTsType = {
   description: Text
 }
 
-export class Property extends JoyStruct<PropertyTsType> {
-  constructor(value: PropertyTsType) {
-    super(
-      {
-        prop_type: PropertyType,
-        required: Bool,
-        name: Text,
-        description: Text,
-      },
-      value
-    )
-  }
-
+export class Property extends JoyStructCustom({
+  prop_type: PropertyType,
+  required: Bool,
+  name: Text,
+  description: Text,
+})
+// FIXME: Make it JoyStructDecorated compatible
+{
   get prop_type(): PropertyType {
     return this.getField('prop_type')
   }
 
   get required(): boolean {
-    return this.getBoolean('required')
+    return this.getField('required').valueOf()
   }
 
   get name(): string {
@@ -54,20 +50,11 @@ export type ClassSchemaType = {
   properties: VecU16
 }
 
-export class ClassSchema extends JoyStruct<ClassSchemaType> {
-  constructor(value: ClassSchemaType) {
-    super(
-      {
-        properties: VecU16,
-      },
-      value
-    )
-  }
-
-  get properties(): VecU16 {
-    return this.getField('properties')
-  }
-}
+export class ClassSchema
+  extends JoyStructDecorated({
+    properties: VecU16,
+  })
+  implements ClassSchemaType {}
 
 export class VecClassSchema extends Vector.with(ClassSchema) {}
 
@@ -76,25 +63,12 @@ export type ClassPropertyValueType = {
   value: PropertyValue
 }
 
-export class ClassPropertyValue extends JoyStruct<ClassPropertyValueType> {
-  constructor(value: ClassPropertyValueType) {
-    super(
-      {
-        in_class_index: u16,
-        value: PropertyValue,
-      },
-      value
-    )
-  }
-
-  get in_class_index(): u16 {
-    return this.getField('in_class_index')
-  }
-
-  get value(): PropertyValue {
-    return this.getField('value')
-  }
-}
+export class ClassPropertyValue
+  extends JoyStructDecorated({
+    in_class_index: u16,
+    value: PropertyValue,
+  })
+  implements ClassPropertyValueType {}
 
 export class VecClassPropertyValue extends Vector.with(ClassPropertyValue) {}
 
@@ -106,20 +80,15 @@ export type ClassType = {
   description: Text
 }
 
-export class Class extends JoyStruct<ClassType> {
-  constructor(value: ClassType) {
-    super(
-      {
-        id: ClassId,
-        properties: VecProperty,
-        schemas: VecClassSchema,
-        name: Text,
-        description: Text,
-      },
-      value
-    )
-  }
-
+export class Class extends JoyStructCustom({
+  id: ClassId,
+  properties: VecProperty,
+  schemas: VecClassSchema,
+  name: Text,
+  description: Text,
+})
+// FIXME: Make it JoyStructDecorated compatible
+{
   get id(): ClassId {
     return this.getField('id')
   }
@@ -148,32 +117,13 @@ export type EntityType = {
   values: VecClassPropertyValue
 }
 
-export class Entity extends JoyStruct<EntityType> {
-  constructor(value: EntityType) {
-    super(
-      {
-        id: EntityId,
-        class_id: ClassId,
-        in_class_schema_indexes: VecU16,
-        values: VecClassPropertyValue,
-      },
-      value
-    )
-  }
-
-  get id(): EntityId {
-    return this.getField('id')
-  }
-
-  get class_id(): ClassId {
-    return this.getField('class_id')
-  }
-
-  get in_class_schema_indexes(): VecU16 {
-    return this.getField('in_class_schema_indexes')
-  }
-
-  /** NOTE: Renamed to `entity_values` because `values` is already in use. */
+export class Entity extends JoyStructDecorated({
+  id: EntityId,
+  class_id: ClassId,
+  in_class_schema_indexes: VecU16,
+  values: VecClassPropertyValue,
+}) {
+  /** NOTE: Renamed to `entity_values` because `values` is already in use (Map's original method). */
   get entity_values(): VecClassPropertyValue {
     return this.getField('values')
   }
@@ -205,20 +155,16 @@ export function unifyPropName(propName: string): string {
   return camelCase(propName)
 }
 
-export function registerVersionedStoreTypes() {
-  try {
-    getTypeRegistry().register({
-      ClassId: 'u64',
-      EntityId: 'u64',
-      Class,
-      Entity,
-      ClassSchema,
-      Property,
-      PropertyType,
-      PropertyValue,
-      ClassPropertyValue,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of Versioned Store module', err)
-  }
+export const versionedStoreTypes: RegistryTypes = {
+  ClassId: 'u64',
+  EntityId: 'u64',
+  Class,
+  Entity,
+  ClassSchema,
+  Property,
+  PropertyType,
+  PropertyValue,
+  ClassPropertyValue,
 }
+
+export default versionedStoreTypes

+ 12 - 45
types/src/versioned-store/permissions/ClassPermissions.ts

@@ -1,6 +1,6 @@
 import { u32, bool } from '@polkadot/types'
 import { BlockNumber } from '@polkadot/types/interfaces'
-import { JoyStruct, CredentialSet } from '../../common'
+import { CredentialSet, JoyStructDecorated } from '../../common'
 import EntityPermissions from './EntityPermissions'
 import { ReferenceConstraint } from './reference-constraint'
 
@@ -14,47 +14,14 @@ type IClassPermissions = {
   last_permissions_update: BlockNumber
 }
 
-export default class ClassPermissionsType extends JoyStruct<IClassPermissions> {
-  constructor(value: IClassPermissions) {
-    super(
-      {
-        entity_permissions: EntityPermissions,
-        entities_can_be_created: bool,
-        add_schemas: CredentialSet,
-        create_entities: CredentialSet,
-        reference_constraint: ReferenceConstraint,
-        admins: CredentialSet,
-        last_permissions_update: u32, // BlockNumber,
-      },
-      value
-    )
-  }
-
-  get entity_permissions(): EntityPermissions {
-    return this.getField('entity_permissions')
-  }
-
-  get entities_can_be_created(): bool {
-    return this.getField('entities_can_be_created')
-  }
-
-  get add_schemas(): CredentialSet {
-    return this.getField('add_schemas')
-  }
-
-  get create_entities(): CredentialSet {
-    return this.getField('create_entities')
-  }
-
-  get reference_constraint(): ReferenceConstraint {
-    return this.getField('reference_constraint')
-  }
-
-  get admins(): CredentialSet {
-    return this.getField('admins')
-  }
-
-  get last_permissions_update(): u32 {
-    return this.getField('last_permissions_update')
-  }
-}
+export default class ClassPermissionsType
+  extends JoyStructDecorated({
+    entity_permissions: EntityPermissions,
+    entities_can_be_created: bool,
+    add_schemas: CredentialSet,
+    create_entities: CredentialSet,
+    reference_constraint: ReferenceConstraint,
+    admins: CredentialSet,
+    last_permissions_update: u32, // BlockNumber,
+  })
+  implements IClassPermissions {}

+ 7 - 20
types/src/versioned-store/permissions/EntityPermissions.ts

@@ -1,4 +1,4 @@
-import { JoyStruct } from '../../JoyStruct'
+import { JoyStructDecorated } from '../../JoyStruct'
 import { bool } from '@polkadot/types'
 import { CredentialSet } from '../../common'
 
@@ -7,22 +7,9 @@ type IEntityPermissions = {
   maintainer_has_all_permissions: bool
 }
 
-export default class EntityPermissions extends JoyStruct<IEntityPermissions> {
-  constructor(value: IEntityPermissions) {
-    super(
-      {
-        update: CredentialSet,
-        maintainer_has_all_permissions: bool,
-      },
-      value
-    )
-  }
-
-  get update(): CredentialSet {
-    return this.getField('update')
-  }
-
-  get maintainer_has_all_permissions(): bool {
-    return this.getField('maintainer_has_all_permissions')
-  }
-}
+export default class EntityPermissions
+  extends JoyStructDecorated({
+    update: CredentialSet,
+    maintainer_has_all_permissions: bool,
+  })
+  implements IEntityPermissions {}

+ 7 - 20
types/src/versioned-store/permissions/PropertyOfClass.ts

@@ -1,28 +1,15 @@
 import { u16 } from '@polkadot/types'
-import { JoyStruct } from '../../common'
 import ClassId from '../ClassId'
+import { JoyStructDecorated } from '../../common'
 
 type IPropertyOfClass = {
   class_id: ClassId
   property_index: u16
 }
 
-export default class PropertyOfClass extends JoyStruct<IPropertyOfClass> {
-  constructor(value: IPropertyOfClass) {
-    super(
-      {
-        class_id: ClassId,
-        property_index: u16,
-      },
-      value
-    )
-  }
-
-  get class_id(): ClassId {
-    return this.getField('class_id')
-  }
-
-  get property_index(): u16 {
-    return this.getField('property_index')
-  }
-}
+export default class PropertyOfClass
+  extends JoyStructDecorated({
+    class_id: ClassId,
+    property_index: u16,
+  })
+  implements IPropertyOfClass {}

+ 7 - 20
types/src/versioned-store/permissions/batching/ParametrizedClassPropertyValue.ts

@@ -1,28 +1,15 @@
 import { ParametrizedPropertyValue } from './parametrized-property-value'
-import { JoyStruct } from '../../../common'
 import { u16 } from '@polkadot/types'
+import { JoyStructDecorated } from '../../../common'
 
 type IParametrizedClassPropertyValue = {
   in_class_index: u16
   value: ParametrizedPropertyValue
 }
 
-export default class ParametrizedClassPropertyValue extends JoyStruct<IParametrizedClassPropertyValue> {
-  constructor(value: IParametrizedClassPropertyValue) {
-    super(
-      {
-        in_class_index: u16,
-        value: ParametrizedPropertyValue,
-      },
-      value
-    )
-  }
-
-  get in_class_index(): u16 {
-    return this.getField('in_class_index')
-  }
-
-  get value(): ParametrizedPropertyValue {
-    return this.getField('value')
-  }
-}
+export default class ParametrizedClassPropertyValue
+  extends JoyStructDecorated({
+    in_class_index: u16,
+    value: ParametrizedPropertyValue,
+  })
+  implements IParametrizedClassPropertyValue {}

+ 8 - 25
types/src/versioned-store/permissions/batching/index.ts

@@ -1,4 +1,4 @@
-import { JoyStruct, Credential } from '../../../common'
+import { Credential, JoyStructDecorated } from '../../../common'
 import { OperationType } from './operation-types'
 import { bool, Option } from '@polkadot/types'
 
@@ -8,27 +8,10 @@ type IOperation = {
   operation_type: OperationType
 }
 
-export class Operation extends JoyStruct<IOperation> {
-  constructor(value: IOperation) {
-    super(
-      {
-        with_credential: Option.with(Credential),
-        as_entity_maintainer: bool,
-        operation_type: OperationType,
-      },
-      value
-    )
-  }
-
-  get with_credential(): Option<Credential> {
-    return this.getField('with_credential')
-  }
-
-  get as_entity_maintainer(): bool {
-    return this.getField('as_entity_maintainer')
-  }
-
-  get operation_type(): OperationType {
-    return this.getField('operation_type')
-  }
-}
+export class Operation
+  extends JoyStructDecorated({
+    with_credential: Option.with(Credential),
+    as_entity_maintainer: bool,
+    operation_type: OperationType,
+  })
+  implements IOperation {}

+ 19 - 26
types/src/versioned-store/permissions/batching/operation-types.ts

@@ -1,4 +1,4 @@
-import { Enum, u16 } from '@polkadot/types'
+import { u16 } from '@polkadot/types'
 import {
   CreateEntityOperation,
   UpdatePropertyValuesOperation,
@@ -7,56 +7,49 @@ import {
 } from './operations'
 import ClassId from '../../ClassId'
 import { ParametrizedEntity } from './parametrized-entity'
+import { JoyEnum } from '../../../common'
+import { Registry } from '@polkadot/types/types'
 
 export class CreateEntity extends CreateEntityOperation {}
 export class UpdatePropertyValues extends UpdatePropertyValuesOperation {}
 export class AddSchemaSupportToEntity extends AddSchemaSupportToEntityOperation {}
 
-export type OperationTypeVariant = CreateEntity | UpdatePropertyValues | AddSchemaSupportToEntity
+export const OperationTypeDef = {
+  CreateEntity,
+  UpdatePropertyValues,
+  AddSchemaSupportToEntity,
+} as const
 
-type OperationTypeVariantValue = {
-  [typeName: string]: OperationTypeVariant
-}
-
-export class OperationType extends Enum {
-  constructor(value?: OperationTypeVariantValue, index?: number) {
-    super(
-      {
-        CreateEntity,
-        UpdatePropertyValues,
-        AddSchemaSupportToEntity,
-      },
-      value,
-      index
-    )
-  }
-
-  static CreateEntity(class_id: ClassId): OperationType {
-    const value = new CreateEntity({ class_id })
-    return new OperationType({ CreateEntity: value })
+export class OperationType extends JoyEnum(OperationTypeDef) {
+  // TODO: Are those are worth preserving?
+  static CreateEntity(registry: Registry, class_id: ClassId): OperationType {
+    const value = new CreateEntity(registry, { class_id })
+    return new OperationType(registry, { CreateEntity: value })
   }
 
   static UpdatePropertyValues(
+    registry: Registry,
     entity_id: ParametrizedEntity,
     parametrized_property_values: ParameterizedClassPropertyValues
   ): OperationType {
-    const value = new UpdatePropertyValues({
+    const value = new UpdatePropertyValues(registry, {
       entity_id,
       parametrized_property_values,
     })
-    return new OperationType({ UpdatePropertyValues: value })
+    return new OperationType(registry, { UpdatePropertyValues: value })
   }
 
   static AddSchemaSupportToEntity(
+    registry: Registry,
     entity_id: ParametrizedEntity,
     schema_id: u16,
     parametrized_property_values: ParameterizedClassPropertyValues
   ): OperationType {
-    const value = new AddSchemaSupportToEntity({
+    const value = new AddSchemaSupportToEntity(registry, {
       entity_id,
       schema_id,
       parametrized_property_values,
     })
-    return new OperationType({ AddSchemaSupportToEntity: value })
+    return new OperationType(registry, { AddSchemaSupportToEntity: value })
   }
 }

+ 23 - 57
types/src/versioned-store/permissions/batching/operations.ts

@@ -1,8 +1,8 @@
 import ClassId from '../../ClassId'
-import { JoyStruct } from '../../../common'
 import { ParametrizedEntity } from './parametrized-entity'
 import { Vec, u16 } from '@polkadot/types'
 import ParametrizedClassPropertyValue from './ParametrizedClassPropertyValue'
+import { JoyStructDecorated } from '../../../common'
 
 // TODO Rename to ParametrizedClassPropertyValue
 export class ParameterizedClassPropertyValues extends Vec.with(ParametrizedClassPropertyValue) {}
@@ -22,62 +22,28 @@ export type IAddSchemaSupportToEntityOperation = {
   parametrized_property_values: ParameterizedClassPropertyValues
 }
 
-export class CreateEntityOperation extends JoyStruct<ICreateEntityOperation> {
-  constructor(value: ICreateEntityOperation) {
-    super(
-      {
-        class_id: ClassId,
-      },
-      value
-    )
-  }
-
-  get class_id(): ClassId {
-    return this.getField('class_id')
-  }
-}
-
-export class UpdatePropertyValuesOperation extends JoyStruct<IUpdatePropertyValuesOperation> {
-  constructor(value: IUpdatePropertyValuesOperation) {
-    super(
-      {
-        entity_id: ParametrizedEntity,
-        parametrized_property_values: ParameterizedClassPropertyValues,
-      },
-      value
-    )
-  }
-
-  get entity_id(): ParametrizedEntity {
-    return this.getField('entity_id')
-  }
-
+export class CreateEntityOperation
+  extends JoyStructDecorated({
+    class_id: ClassId,
+  })
+  implements ICreateEntityOperation {}
+
+export class UpdatePropertyValuesOperation
+  extends JoyStructDecorated({
+    entity_id: ParametrizedEntity,
+    parametrized_property_values: ParameterizedClassPropertyValues,
+  })
+  implements IUpdatePropertyValuesOperation {}
+
+export class AddSchemaSupportToEntityOperation
+  extends JoyStructDecorated({
+    entity_id: ParametrizedEntity,
+    schema_id: u16,
+    parametrized_property_values: ParameterizedClassPropertyValues,
+  })
+  implements IAddSchemaSupportToEntityOperation {
+  // Additional helper
   get property_values(): ParameterizedClassPropertyValues {
-    return this.getField('parametrized_property_values')
-  }
-}
-
-export class AddSchemaSupportToEntityOperation extends JoyStruct<IAddSchemaSupportToEntityOperation> {
-  constructor(value: IAddSchemaSupportToEntityOperation) {
-    super(
-      {
-        entity_id: ParametrizedEntity,
-        schema_id: u16,
-        parametrized_property_values: ParameterizedClassPropertyValues,
-      },
-      value
-    )
-  }
-
-  get entity_id(): ParametrizedEntity {
-    return this.getField('entity_id')
-  }
-
-  get property_values(): ParameterizedClassPropertyValues {
-    return this.getField('parametrized_property_values')
-  }
-
-  get schema_id(): u16 {
-    return this.getField('schema_id')
+    return this.parametrized_property_values
   }
 }

+ 13 - 22
types/src/versioned-store/permissions/batching/parametrized-entity.ts

@@ -1,32 +1,23 @@
-import { Enum, u32 } from '@polkadot/types'
+import { u32 } from '@polkadot/types'
 import EntityId from '../../EntityId'
+import { Registry } from '@polkadot/types/types'
+import { JoyEnum } from '../../../common'
 
 export class InternalEntityJustAdded extends u32 {}
 export class ExistingEntity extends EntityId {}
 
-export type ParametrizedEntityVariant = InternalEntityJustAdded | ExistingEntity
+export const ParametrizedEntityDef = {
+  InternalEntityJustAdded,
+  ExistingEntity,
+} as const
 
-type ParametrizedEntityValue = {
-  [typeName: string]: ParametrizedEntityVariant
-}
-
-export class ParametrizedEntity extends Enum {
-  constructor(value?: ParametrizedEntityValue, index?: number) {
-    super(
-      {
-        InternalEntityJustAdded,
-        ExistingEntity,
-      },
-      value,
-      index
-    )
-  }
-
-  static InternalEntityJustAdded(index: u32): ParametrizedEntity {
-    return new ParametrizedEntity({ InternalEntityJustAdded: new InternalEntityJustAdded(index) })
+export class ParametrizedEntity extends JoyEnum(ParametrizedEntityDef) {
+  // TODO: Are those worth preserving?
+  static InternalEntityJustAdded(registry: Registry, index: u32): ParametrizedEntity {
+    return new ParametrizedEntity(registry, { InternalEntityJustAdded: new InternalEntityJustAdded(registry, index) })
   }
 
-  static ExistingEntity(entity_id: EntityId): ParametrizedEntity {
-    return new ParametrizedEntity({ ExistingEntity: new ExistingEntity(entity_id) })
+  static ExistingEntity(registry: Registry, entity_id: EntityId): ParametrizedEntity {
+    return new ParametrizedEntity(registry, { ExistingEntity: new ExistingEntity(registry, entity_id) })
   }
 }

+ 21 - 26
types/src/versioned-store/permissions/batching/parametrized-property-value.ts

@@ -1,39 +1,34 @@
-import { Enum, u32, Vec } from '@polkadot/types'
+import { u32, Vec } from '@polkadot/types'
 import { PropertyValue as VersionedStorePropertyValue, PropertyValueEnumValue } from '../../PropertyValue'
 import { ParametrizedEntity } from './parametrized-entity'
+import { Registry } from '@polkadot/types/types'
+import { JoyEnum } from '../../../common'
 
 export class PropertyValue extends VersionedStorePropertyValue {}
 export class InternalEntityJustAdded extends u32 {}
 export class InternalEntityVec extends Vec.with(ParametrizedEntity) {}
 
-export type ParametrizedPropertyValueVariant = PropertyValue | InternalEntityJustAdded | InternalEntityVec
-
-type ParametrizedPropertyValueType = {
-  [typeName: string]: ParametrizedPropertyValueVariant
-}
-
-export class ParametrizedPropertyValue extends Enum {
-  constructor(value?: ParametrizedPropertyValueType, index?: number) {
-    super(
-      {
-        PropertyValue,
-        InternalEntityJustAdded,
-        InternalEntityVec,
-      },
-      value,
-      index
-    )
-  }
-
-  static PropertyValue(value: PropertyValueEnumValue): ParametrizedPropertyValue {
-    return new ParametrizedPropertyValue({ PropertyValue: new VersionedStorePropertyValue(value) })
+export const ParametrizedPropertyValueDef = {
+  PropertyValue,
+  InternalEntityJustAdded,
+  InternalEntityVec,
+} as const
+export class ParametrizedPropertyValue extends JoyEnum(ParametrizedPropertyValueDef) {
+  // TODO: Are those worth preserving?
+  static PropertyValue(registry: Registry, value: PropertyValueEnumValue): ParametrizedPropertyValue {
+    return new ParametrizedPropertyValue(registry, { PropertyValue: new VersionedStorePropertyValue(registry, value) })
   }
 
-  static InternalEntityJustAdded(index: number | u32): ParametrizedPropertyValue {
-    return new ParametrizedPropertyValue({ InternalEntityJustAdded: new InternalEntityJustAdded(index) })
+  static InternalEntityJustAdded(registry: Registry, index: number | u32): ParametrizedPropertyValue {
+    return new ParametrizedPropertyValue(registry, {
+      InternalEntityJustAdded: new InternalEntityJustAdded(registry, index),
+    })
   }
 
-  static InternalEntityVec(entities: ParametrizedEntity[] | Vec<ParametrizedEntity>): ParametrizedPropertyValue {
-    return new ParametrizedPropertyValue({ InternalEntityVec: new InternalEntityVec(entities) })
+  static InternalEntityVec(
+    registry: Registry,
+    entities: ParametrizedEntity[] | Vec<ParametrizedEntity>
+  ): ParametrizedPropertyValue {
+    return new ParametrizedPropertyValue(registry, { InternalEntityVec: new InternalEntityVec(registry, entities) })
   }
 }

+ 8 - 13
types/src/versioned-store/permissions/index.ts

@@ -1,21 +1,16 @@
-import { getTypeRegistry } from '@polkadot/types'
-
 import EntityPermissions from './EntityPermissions'
 import { ReferenceConstraint } from './reference-constraint'
 import ClassPermissionsType from './ClassPermissions'
 import { Operation } from './batching/'
+import { RegistryTypes } from '@polkadot/types/types'
 
 export { EntityPermissions, ReferenceConstraint, ClassPermissionsType, Operation }
 
-export function registerVersionedStorePermissionsTypes() {
-  try {
-    getTypeRegistry().register({
-      EntityPermissions,
-      ReferenceConstraint,
-      ClassPermissionsType,
-      Operation,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of versioned store module', err)
-  }
+export const versionedStorePermissionsTypes: RegistryTypes = {
+  EntityPermissions,
+  ReferenceConstraint,
+  ClassPermissionsType,
+  Operation,
 }
+
+export default versionedStorePermissionsTypes

+ 9 - 32
types/src/versioned-store/permissions/reference-constraint.ts

@@ -1,38 +1,15 @@
-import { Enum, Null, Vec } from '@polkadot/types'
+import { Null, BTreeSet } from '@polkadot/types'
 import PropertyOfClass from './PropertyOfClass'
+import { JoyEnum } from '../../common'
 
 export class NoReferencingAllowed extends Null {}
 export class NoConstraint extends Null {}
-export class Restricted extends Vec.with(PropertyOfClass) {} // BtreeSet ?
+export class Restricted extends BTreeSet.with(PropertyOfClass) {}
 
-export type ReferenceConstraintVariant = NoReferencingAllowed | NoConstraint | Restricted
+export const ReferenceConstraintDef = {
+  NoReferencingAllowed,
+  NoConstraint,
+  Restricted,
+} as const
 
-export type ReferenceConstraintValue = {
-  [typeName: string]: ReferenceConstraintVariant
-}
-
-export class ReferenceConstraint extends Enum {
-  constructor(value?: ReferenceConstraintValue, index?: number) {
-    super(
-      {
-        NoReferencingAllowed,
-        NoConstraint,
-        Restricted,
-      },
-      value,
-      index
-    )
-  }
-
-  static NoReferencingAllowed(): ReferenceConstraint {
-    return new ReferenceConstraint({ NoReferencingAllowed: new NoReferencingAllowed() })
-  }
-
-  static NoConstraint(): ReferenceConstraint {
-    return new ReferenceConstraint({ NoConstraint: new NoConstraint() })
-  }
-
-  static Restricted(restrictions: Vec<PropertyOfClass>): ReferenceConstraint {
-    return new ReferenceConstraint({ Restricted: new Restricted(restrictions) })
-  }
-}
+export class ReferenceConstraint extends JoyEnum(ReferenceConstraintDef) {}

+ 87 - 238
types/src/working-group/index.ts

@@ -1,12 +1,13 @@
-import { getTypeRegistry, Bytes, BTreeMap, Option } from '@polkadot/types'
-import { u16, Null } from '@polkadot/types/primitive'
-import { AccountId, BlockNumber, Balance } from '@polkadot/types/interfaces'
-import { BTreeSet, JoyStruct } from '../common'
+import { Bytes, BTreeMap, BTreeSet, Option } from '@polkadot/types'
+import { u16, Null, u32, u128 } from '@polkadot/types/primitive'
+import AccountId from '@polkadot/types/generic/AccountId'
+import { BlockNumber, Balance } from '@polkadot/types/interfaces'
 import { MemberId, ActorId } from '../members'
 import { RewardRelationshipId } from '../recurring-rewards'
 import { StakeId } from '../stake'
 import { ApplicationId, OpeningId, ApplicationRationingPolicy, StakingPolicy } from '../hiring'
-import { JoyEnum } from '../JoyEnum'
+import { JoyEnum, JoyStructDecorated } from '../common'
+import { RegistryTypes } from '@polkadot/types/types'
 
 export class RationaleText extends Bytes {}
 
@@ -20,35 +21,14 @@ export type IApplication = {
 // This type is also defined in /hiring (and those are incosistent), but here
 // it is beeing registered as "ApplicationOf" (which is an alias used by the runtime working-group module),
 // so it shouldn't cause any conflicts
-export class Application extends JoyStruct<IApplication> {
-  constructor(value?: IApplication) {
-    super(
-      {
-        role_account_id: 'AccountId',
-        opening_id: OpeningId,
-        member_id: MemberId,
-        application_id: ApplicationId,
-      },
-      value
-    )
-  }
-
-  get role_account_id(): AccountId {
-    return this.getField<AccountId>('role_account_id')
-  }
-
-  get opening_id(): OpeningId {
-    return this.getField<OpeningId>('opening_id')
-  }
-
-  get member_id(): MemberId {
-    return this.getField<MemberId>('member_id')
-  }
-
-  get application_id(): ApplicationId {
-    return this.getField<ApplicationId>('application_id')
-  }
-}
+export class Application
+  extends JoyStructDecorated({
+    role_account_id: AccountId,
+    opening_id: OpeningId,
+    member_id: MemberId,
+    application_id: ApplicationId,
+  })
+  implements IApplication {}
 
 export class WorkerId extends ActorId {}
 
@@ -64,30 +44,13 @@ export type IRoleStakeProfile = {
   exit_unstaking_period: Option<BlockNumber>
 }
 
-export class RoleStakeProfile extends JoyStruct<IRoleStakeProfile> {
-  constructor(value?: IRoleStakeProfile) {
-    super(
-      {
-        stake_id: StakeId,
-        termination_unstaking_period: 'Option<BlockNumber>',
-        exit_unstaking_period: 'Option<BlockNumber>',
-      },
-      value
-    )
-  }
-
-  get stake_id(): StakeId {
-    return this.getField<StakeId>('stake_id')
-  }
-
-  get termination_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('termination_unstaking_period')
-  }
-
-  get exit_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('exit_unstaking_period')
-  }
-}
+export class RoleStakeProfile
+  extends JoyStructDecorated({
+    stake_id: StakeId,
+    termination_unstaking_period: Option.with(u32), // Option<BlockNumber>
+    exit_unstaking_period: Option.with(u32), // Option<BlockNumber>
+  })
+  implements IRoleStakeProfile {}
 
 export type IWorker = {
   member_id: MemberId
@@ -96,35 +59,15 @@ export type IWorker = {
   role_stake_profile: Option<RoleStakeProfile>
 }
 
-export class Worker extends JoyStruct<IWorker> {
-  constructor(value?: IWorker) {
-    super(
-      {
-        member_id: MemberId,
-        role_account_id: 'AccountId',
-        reward_relationship: Option.with(RewardRelationshipId),
-        role_stake_profile: Option.with(RoleStakeProfile),
-      },
-      value
-    )
-  }
-
-  get member_id(): MemberId {
-    return this.getField<MemberId>('member_id')
-  }
-
-  get role_account_id(): AccountId {
-    return this.getField<AccountId>('role_account_id')
-  }
-
-  get reward_relationship(): Option<RewardRelationshipId> {
-    return this.getField<Option<RewardRelationshipId>>('reward_relationship')
-  }
-
-  get role_stake_profile(): Option<RoleStakeProfile> {
-    return this.getField<Option<RoleStakeProfile>>('role_stake_profile')
-  }
-
+export class Worker
+  extends JoyStructDecorated({
+    member_id: MemberId,
+    role_account_id: AccountId,
+    reward_relationship: Option.with(RewardRelationshipId),
+    role_stake_profile: Option.with(RoleStakeProfile),
+  })
+  implements IWorker {
+  // FIXME: Won't be needed soon?
   get is_active(): boolean {
     return !this.isEmpty
   }
@@ -138,17 +81,12 @@ export type ISlashableTerms = {
 // This type is also defined in /content-working-group, but currently both those definitions are identical
 // (I added this defininition here too, because techinicaly those are 2 different types in the runtime.
 // Later the definition in /content-working-group will be removed and we can just register this type here)
-export class SlashableTerms extends JoyStruct<ISlashableTerms> {
-  constructor(value?: ISlashableTerms) {
-    super(
-      {
-        max_count: u16,
-        max_percent_pts_per_time: u16,
-      },
-      value
-    )
-  }
-}
+export class SlashableTerms
+  extends JoyStructDecorated({
+    max_count: u16,
+    max_percent_pts_per_time: u16,
+  })
+  implements ISlashableTerms {}
 
 export class UnslashableTerms extends Null {}
 
@@ -184,75 +122,22 @@ export type IWorkingGroupOpeningPolicyCommitment = {
 // Since both those types are basically the same structs (only filed names are different) nothing seems to break, but it's
 // very fragile atm and any change to this type in working-group module could result in "unsolvable" inconsistencies
 // (this won't be an issue after CWG gets refactored to use the working-grpup module too)
-export class WorkingGroupOpeningPolicyCommitment extends JoyStruct<IWorkingGroupOpeningPolicyCommitment> {
-  constructor(value?: IWorkingGroupOpeningPolicyCommitment) {
-    super(
-      {
-        application_rationing_policy: Option.with(ApplicationRationingPolicy),
-        max_review_period_length: 'BlockNumber',
-        application_staking_policy: Option.with(StakingPolicy),
-        role_staking_policy: Option.with(StakingPolicy),
-        role_slashing_terms: SlashingTerms,
-        fill_opening_successful_applicant_application_stake_unstaking_period: 'Option<BlockNumber>',
-        fill_opening_failed_applicant_application_stake_unstaking_period: 'Option<BlockNumber>',
-        fill_opening_failed_applicant_role_stake_unstaking_period: 'Option<BlockNumber>',
-        terminate_application_stake_unstaking_period: 'Option<BlockNumber>',
-        terminate_role_stake_unstaking_period: 'Option<BlockNumber>',
-        exit_role_application_stake_unstaking_period: 'Option<BlockNumber>',
-        exit_role_stake_unstaking_period: 'Option<BlockNumber>',
-      },
-      value
-    )
-  }
-
-  get application_rationing_policy(): Option<ApplicationRationingPolicy> {
-    return this.getField<Option<ApplicationRationingPolicy>>('application_rationing_policy')
-  }
-
-  get max_review_period_length(): BlockNumber {
-    return this.getField<BlockNumber>('max_review_period_length')
-  }
-
-  get application_staking_policy(): Option<StakingPolicy> {
-    return this.getField<Option<StakingPolicy>>('application_staking_policy')
-  }
-
-  get role_staking_policy(): Option<StakingPolicy> {
-    return this.getField<Option<StakingPolicy>>('role_staking_policy')
-  }
-
-  get role_slashing_terms(): SlashingTerms {
-    return this.getField<SlashingTerms>('role_slashing_terms')
-  }
-
-  get fill_opening_successful_applicant_application_stake_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('fill_opening_successful_applicant_application_stake_unstaking_period')
-  }
-
-  get fill_opening_failed_applicant_application_stake_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('fill_opening_failed_applicant_application_stake_unstaking_period')
-  }
-
-  get fill_opening_failed_applicant_role_stake_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('fill_opening_failed_applicant_role_stake_unstaking_period')
-  }
-
-  get terminate_application_stake_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('terminate_application_stake_unstaking_period')
-  }
-
-  get terminate_role_stake_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('terminate_role_stake_unstaking_period')
-  }
-
-  get exit_role_application_stake_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('exit_role_application_stake_unstaking_period')
-  }
-
-  get exit_role_stake_unstaking_period(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('exit_role_stake_unstaking_period')
-  }
-}
+export class WorkingGroupOpeningPolicyCommitment
+  extends JoyStructDecorated({
+    application_rationing_policy: Option.with(ApplicationRationingPolicy),
+    max_review_period_length: u32, // BlockNumber
+    application_staking_policy: Option.with(StakingPolicy),
+    role_staking_policy: Option.with(StakingPolicy),
+    role_slashing_terms: SlashingTerms,
+    fill_opening_successful_applicant_application_stake_unstaking_period: Option.with(u32),
+    fill_opening_failed_applicant_application_stake_unstaking_period: Option.with(u32),
+    fill_opening_failed_applicant_role_stake_unstaking_period: Option.with(u32),
+    terminate_application_stake_unstaking_period: Option.with(u32),
+    terminate_role_stake_unstaking_period: Option.with(u32),
+    exit_role_application_stake_unstaking_period: Option.with(u32),
+    exit_role_stake_unstaking_period: Option.with(u32),
+  })
+  implements IWorkingGroupOpeningPolicyCommitment {}
 
 export class OpeningType_Leader extends Null {}
 export class OpeningType_Worker extends Null {}
@@ -273,35 +158,14 @@ export type IOpening = {
 // This type is also defined in /hiring (and those are incosistent), but here
 // it is beeing registered as "OpeningOf" (which is an alias used by the runtime working-group module),
 // so it shouldn't cause any conflicts
-export class Opening extends JoyStruct<IOpening> {
-  constructor(value?: IWorker) {
-    super(
-      {
-        hiring_opening_id: OpeningId,
-        applications: BTreeSet.with(ApplicationId),
-        policy_commitment: WorkingGroupOpeningPolicyCommitment,
-        opening_type: OpeningType,
-      },
-      value
-    )
-  }
-
-  get hiring_opening_id(): OpeningId {
-    return this.getField<OpeningId>('hiring_opening_id')
-  }
-
-  get applications(): BTreeSet<ApplicationId> {
-    return this.getField<BTreeSet<ApplicationId>>('applications')
-  }
-
-  get policy_commitment(): WorkingGroupOpeningPolicyCommitment {
-    return this.getField<WorkingGroupOpeningPolicyCommitment>('policy_commitment')
-  }
-
-  get opening_type(): OpeningType {
-    return this.getField<OpeningType>('opening_type')
-  }
-}
+export class Opening
+  extends JoyStructDecorated({
+    hiring_opening_id: OpeningId,
+    applications: BTreeSet.with(ApplicationId),
+    policy_commitment: WorkingGroupOpeningPolicyCommitment,
+    opening_type: OpeningType,
+  })
+  implements IOpening {}
 
 // Also defined in "content-working-group" runtime module, but those definitions are the consistent
 export type IRewardPolicy = {
@@ -310,47 +174,32 @@ export type IRewardPolicy = {
   payout_interval: Option<BlockNumber>
 }
 
-export class RewardPolicy extends JoyStruct<IRewardPolicy> {
-  constructor(value?: IRewardPolicy) {
-    super(
-      {
-        amount_per_payout: 'Balance',
-        next_payment_at_block: 'BlockNumber',
-        payout_interval: 'Option<BlockNumber>',
-      },
-      value
-    )
-  }
-  get amount_per_payout(): Balance {
-    return this.getField<Balance>('amount_per_payout')
-  }
-  get next_payment_at_block(): BlockNumber {
-    return this.getField<BlockNumber>('next_payment_at_block')
-  }
-  get payout_interval(): Option<BlockNumber> {
-    return this.getField<Option<BlockNumber>>('payout_interval')
-  }
+export class RewardPolicy
+  extends JoyStructDecorated({
+    amount_per_payout: u128, // Balance
+    next_payment_at_block: u32, // BlockNumber
+    payout_interval: Option.with(u32), // Option<BlockNumber>
+  })
+  implements IRewardPolicy {}
+
+// Needed for types augment tool
+export { OpeningId, ApplicationId }
+
+export const workingGroupTypes: RegistryTypes = {
+  RationaleText,
+  ApplicationOf: Application,
+  ApplicationIdSet,
+  ApplicationIdToWorkerIdMap,
+  WorkerId,
+  WorkerOf: Worker,
+  OpeningOf: Opening,
+  StorageProviderId,
+  OpeningType,
+  /// Alias used by the runtime working-group module
+  HiringApplicationId: ApplicationId,
+  RewardPolicy,
+  'working_group::OpeningId': OpeningId,
+  'working_group::WorkerId': WorkerId,
 }
 
-export function registerWorkingGroupTypes() {
-  try {
-    getTypeRegistry().register({
-      RationaleText,
-      ApplicationOf: Application,
-      ApplicationIdSet,
-      ApplicationIdToWorkerIdMap,
-      WorkerId,
-      WorkerOf: Worker,
-      OpeningOf: Opening,
-      StorageProviderId,
-      OpeningType,
-      /// Alias used by the runtime working-group module
-      HiringApplicationId: ApplicationId,
-      RewardPolicy,
-      'working_group::OpeningId': OpeningId,
-      'working_group::WorkerId': WorkerId,
-    })
-  } catch (err) {
-    console.error('Failed to register custom types of working-group module', err)
-  }
-}
+export default workingGroupTypes

+ 29 - 0
types/tsconfig-base.json

@@ -0,0 +1,29 @@
+{
+  "compilerOptions": {
+    "target": "esnext",
+    "module": "commonjs",
+    "strict": true,
+    "noImplicitAny": true,
+    "noUnusedLocals": true,
+    "noImplicitReturns": true,
+    "moduleResolution": "node",
+    "allowSyntheticDefaultImports": true,     /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+    "experimentalDecorators": true,           /* Enables experimental support for ES7 decorators. */
+    "declaration": true,
+    "resolveJsonModule": true,
+    "types" : [
+      "node"
+    ],
+    "forceConsistentCasingInFileNames": true,
+    "baseUrl": ".",
+    "paths": {
+      "@polkadot/types/augment": ["src/definitions/augment-types.ts"]
+    }
+  },
+  "exclude": [
+    "node_modules",
+    "**/*.spec.ts",
+    "**/*.d.ts"
+  ]
+}

+ 6 - 0
types/tsconfig-scripts.json

@@ -0,0 +1,6 @@
+{
+  "extends": "./tsconfig-base.json",
+  "include": [
+    "src/scripts/*.ts"
+  ]
+}

+ 3 - 20
types/tsconfig.json

@@ -1,29 +1,12 @@
 {
+  "extends": "./tsconfig-base.json",
   "compilerOptions": {
-    "target": "esnext",
-    "module": "commonjs",
-    "strict": true,
-    "noImplicitAny": true,
-    "noUnusedLocals": true,
-    "noImplicitReturns": true,
-    "moduleResolution": "node",
-    "allowSyntheticDefaultImports": true,     /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
-    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
-    "experimentalDecorators": true,           /* Enables experimental support for ES7 decorators. */
-    "declaration": true,
-    "outDir": "./",
-    "resolveJsonModule": true,
-    "types" : [
-      "node"
-    ],
-    "forceConsistentCasingInFileNames": true
+    "outDir": "./"
   },
   "include": [
     "src/**/*.ts"
   ],
   "exclude": [
-    "node_modules",
-    "**/*.spec.ts",
-    "**/*.d.ts"
+    "src/scripts"
   ]
 }

+ 428 - 204
yarn.lock

@@ -83,6 +83,28 @@
     semver "^5.4.1"
     source-map "^0.5.0"
 
+"@babel/core@^7.11.0":
+  version "7.11.1"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643"
+  integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==
+  dependencies:
+    "@babel/code-frame" "^7.10.4"
+    "@babel/generator" "^7.11.0"
+    "@babel/helper-module-transforms" "^7.11.0"
+    "@babel/helpers" "^7.10.4"
+    "@babel/parser" "^7.11.1"
+    "@babel/template" "^7.10.4"
+    "@babel/traverse" "^7.11.0"
+    "@babel/types" "^7.11.0"
+    convert-source-map "^1.7.0"
+    debug "^4.1.0"
+    gensync "^1.0.0-beta.1"
+    json5 "^2.1.2"
+    lodash "^4.17.19"
+    resolve "^1.3.2"
+    semver "^5.4.1"
+    source-map "^0.5.0"
+
 "@babel/core@^7.5.5":
   version "7.10.1"
   resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.1.tgz#2a0ad0ea693601820defebad2140206503d89af3"
@@ -125,6 +147,15 @@
     lodash "^4.17.13"
     source-map "^0.5.0"
 
+"@babel/generator@^7.11.0":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c"
+  integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==
+  dependencies:
+    "@babel/types" "^7.11.0"
+    jsesc "^2.5.1"
+    source-map "^0.5.0"
+
 "@babel/generator@^7.4.0", "@babel/generator@^7.6.0", "@babel/generator@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369"
@@ -290,6 +321,13 @@
   dependencies:
     "@babel/types" "^7.10.1"
 
+"@babel/helper-member-expression-to-functions@^7.10.4":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df"
+  integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==
+  dependencies:
+    "@babel/types" "^7.11.0"
+
 "@babel/helper-member-expression-to-functions@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74"
@@ -311,6 +349,13 @@
   dependencies:
     "@babel/types" "^7.10.1"
 
+"@babel/helper-module-imports@^7.10.4":
+  version "7.10.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620"
+  integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==
+  dependencies:
+    "@babel/types" "^7.10.4"
+
 "@babel/helper-module-transforms@^7.10.1":
   version "7.10.1"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622"
@@ -324,6 +369,19 @@
     "@babel/types" "^7.10.1"
     lodash "^4.17.13"
 
+"@babel/helper-module-transforms@^7.11.0":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359"
+  integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==
+  dependencies:
+    "@babel/helper-module-imports" "^7.10.4"
+    "@babel/helper-replace-supers" "^7.10.4"
+    "@babel/helper-simple-access" "^7.10.4"
+    "@babel/helper-split-export-declaration" "^7.11.0"
+    "@babel/template" "^7.10.4"
+    "@babel/types" "^7.11.0"
+    lodash "^4.17.19"
+
 "@babel/helper-module-transforms@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.4.tgz#8d7cdb1e1f8ea3d8c38b067345924ac4f8e0879a"
@@ -343,6 +401,13 @@
   dependencies:
     "@babel/types" "^7.10.1"
 
+"@babel/helper-optimise-call-expression@^7.10.4":
+  version "7.10.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673"
+  integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==
+  dependencies:
+    "@babel/types" "^7.10.4"
+
 "@babel/helper-optimise-call-expression@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2"
@@ -388,6 +453,16 @@
     "@babel/traverse" "^7.10.1"
     "@babel/types" "^7.10.1"
 
+"@babel/helper-replace-supers@^7.10.4":
+  version "7.10.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf"
+  integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==
+  dependencies:
+    "@babel/helper-member-expression-to-functions" "^7.10.4"
+    "@babel/helper-optimise-call-expression" "^7.10.4"
+    "@babel/traverse" "^7.10.4"
+    "@babel/types" "^7.10.4"
+
 "@babel/helper-replace-supers@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2"
@@ -406,6 +481,14 @@
     "@babel/template" "^7.10.1"
     "@babel/types" "^7.10.1"
 
+"@babel/helper-simple-access@^7.10.4":
+  version "7.10.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461"
+  integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==
+  dependencies:
+    "@babel/template" "^7.10.4"
+    "@babel/types" "^7.10.4"
+
 "@babel/helper-simple-access@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294"
@@ -428,6 +511,13 @@
   dependencies:
     "@babel/types" "^7.10.4"
 
+"@babel/helper-split-export-declaration@^7.11.0":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f"
+  integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==
+  dependencies:
+    "@babel/types" "^7.11.0"
+
 "@babel/helper-split-export-declaration@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
@@ -464,6 +554,15 @@
     "@babel/traverse" "^7.10.1"
     "@babel/types" "^7.10.1"
 
+"@babel/helpers@^7.10.4":
+  version "7.10.4"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044"
+  integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==
+  dependencies:
+    "@babel/template" "^7.10.4"
+    "@babel/traverse" "^7.10.4"
+    "@babel/types" "^7.10.4"
+
 "@babel/helpers@^7.6.0", "@babel/helpers@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302"
@@ -515,6 +614,11 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64"
   integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==
 
+"@babel/parser@^7.11.0", "@babel/parser@^7.11.1":
+  version "7.11.1"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.1.tgz#d91a387990b21e5d20047b336bb19b0553f02ff5"
+  integrity sha512-u9QMIRdKVF7hfEkb3nu2LgZDIzCQPv+yHD9Eg6ruoJLjkrQ9fFz4IBSlF/9XwoNri9+2F1IY+dYuOfZrXq8t3w==
+
 "@babel/plugin-proposal-async-generator-functions@^7.2.0", "@babel/plugin-proposal-async-generator-functions@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d"
@@ -1296,6 +1400,17 @@
     "@babel/helper-plugin-utils" "^7.0.0"
     "@babel/plugin-transform-typescript" "^7.7.4"
 
+"@babel/register@^7.10.5":
+  version "7.10.5"
+  resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.10.5.tgz#354f3574895f1307f79efe37a51525e52fd38d89"
+  integrity sha512-eYHdLv43nyvmPn9bfNfrcC4+iYNwdQ8Pxk1MFJuU/U5LpSYl/PH4dFMazCYZDFVi8ueG3shvO+AQfLrxpYulQw==
+  dependencies:
+    find-cache-dir "^2.0.0"
+    lodash "^4.17.19"
+    make-dir "^2.1.0"
+    pirates "^4.0.0"
+    source-map-support "^0.5.16"
+
 "@babel/register@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.7.4.tgz#45a4956471a9df3b012b747f5781cc084ee8f128"
@@ -1344,6 +1459,13 @@
   dependencies:
     regenerator-runtime "^0.13.2"
 
+"@babel/runtime@^7.10.5", "@babel/runtime@^7.11.0":
+  version "7.11.1"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.1.tgz#087afc57e7bf1073e792fe54f8fb3cfa752f9230"
+  integrity sha512-nH5y8fLvVl3HAb+ezbgcgwrH8QbClWo8xzkOu7+oyqngo3EVorwpWJQaqXPjGRpfj7mQvsJCl/S8knkfkPWqrw==
+  dependencies:
+    regenerator-runtime "^0.13.4"
+
 "@babel/template@^7.10.1":
   version "7.10.1"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811"
@@ -1401,6 +1523,21 @@
     globals "^11.1.0"
     lodash "^4.17.13"
 
+"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24"
+  integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==
+  dependencies:
+    "@babel/code-frame" "^7.10.4"
+    "@babel/generator" "^7.11.0"
+    "@babel/helper-function-name" "^7.10.4"
+    "@babel/helper-split-export-declaration" "^7.11.0"
+    "@babel/parser" "^7.11.0"
+    "@babel/types" "^7.11.0"
+    debug "^4.1.0"
+    globals "^11.1.0"
+    lodash "^4.17.19"
+
 "@babel/traverse@^7.7.0":
   version "7.10.4"
   resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.4.tgz#e642e5395a3b09cc95c8e74a27432b484b697818"
@@ -1443,6 +1580,15 @@
     lodash "^4.17.13"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.11.0":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d"
+  integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.10.4"
+    lodash "^4.17.19"
+    to-fast-properties "^2.0.0"
+
 "@cnakazawa/watch@^1.0.3":
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef"
@@ -1833,6 +1979,7 @@
     "@types/yargs" "^13.0.0"
 
 "@joystream/types@^0.12.0", "@nicaea/types@npm:@joystream/types@^0.12.0":
+  name "@nicaea/types"
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/@joystream/types/-/types-0.12.0.tgz#4033967ae2ac111f894fb4100e414f7cdbe95611"
   integrity sha512-pHHYTbIa6V1C4k9aj+M6Fkwa2I2Br+4x7cuvREmrVh21GHjGuzoIwB74MfqFajdSTDQDZbjdixcYDES6uo3sUg==
@@ -1848,8 +1995,9 @@
 "@joystream/types@link:types":
   version "0.13.0"
   dependencies:
-    "@polkadot/keyring" "^1.7.0-beta.5"
-    "@polkadot/types" "^0.96.1"
+    "@polkadot/api" "^1.26.1"
+    "@polkadot/keyring" "^3.0.1"
+    "@polkadot/types" "^1.26.1"
     "@types/lodash" "^4.14.157"
     "@types/vfile" "^4.0.0"
     ajv "^6.11.0"
@@ -2881,46 +3029,53 @@
   dependencies:
     "@types/node" ">= 8"
 
-"@polkadot/api-contract@^0.96.1":
-  version "0.96.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-0.96.1.tgz#d43c80059caaf0014c353d0c6544d39a1b6926a3"
-  integrity sha512-nvIY70YiIbsBBP/48NeFJTc6DCGp9H5Rw+c9hR8J3hZYzbe8qMwpuTS+gHePxwJt/wMFdW8yMP7QS/1tN0JDsA==
-  dependencies:
-    "@babel/runtime" "^7.7.1"
-    "@polkadot/types" "^0.96.1"
-
-"@polkadot/api-derive@^0.96.1":
-  version "0.96.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-0.96.1.tgz#dc49db7293b585c4bde5e334c134127821a0ebed"
-  integrity sha512-PGWdUvlD2acUKOgaJcYWuMTfSuQKUpwgwjer5SomHLFn4ZPOz8iDa7mYtrgmxQctRv1zsuck2X01uhxdEdtJZw==
-  dependencies:
-    "@babel/runtime" "^7.7.1"
-    "@polkadot/api" "^0.96.1"
-    "@polkadot/types" "^0.96.1"
-
-"@polkadot/api-metadata@^0.96.1":
-  version "0.96.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-metadata/-/api-metadata-0.96.1.tgz#5aaf7b78a72049cca9cbde5b078f26a330ab515c"
-  integrity sha512-I9F3twpSCgx4ny25a3moGrhf2vHKFnjooO3W9NaAxIj/us4q4Gqo4+czQajqt8vaJqrNMq/PE7lzVz1NhYDrZQ==
-  dependencies:
-    "@babel/runtime" "^7.7.1"
-    "@polkadot/types" "^0.96.1"
-    "@polkadot/util" "^1.7.0-beta.5"
-    "@polkadot/util-crypto" "^1.7.0-beta.5"
-
-"@polkadot/api@^0.96.1":
-  version "0.96.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-0.96.1.tgz#708b7f487091e6ffafac16c71074d1366f8f122f"
-  integrity sha512-FeYyMfJL0NACJBIuG7C7mp7f9J/WOGUERF/hUP3RlIz4Ld2X0vRjEoOgiG0VIS89I4K31XaNmSjIchH244WtHg==
-  dependencies:
-    "@babel/runtime" "^7.7.1"
-    "@polkadot/api-derive" "^0.96.1"
-    "@polkadot/api-metadata" "^0.96.1"
-    "@polkadot/keyring" "^1.7.0-beta.5"
-    "@polkadot/rpc-core" "^0.96.1"
-    "@polkadot/rpc-provider" "^0.96.1"
-    "@polkadot/types" "^0.96.1"
-    "@polkadot/util-crypto" "^1.7.0-beta.5"
+"@polkadot/api-contract@^0.96.1", "@polkadot/api-contract@^1.26.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-1.27.1.tgz#52b45b7de8ce35b0d278f4c37eafdcd0b0b7b8c7"
+  integrity sha512-4Md0LXysEctONz38u7TG9EEFHL2rd9s25nzskGOuFm3FoLomFrvUHGsheIr0zM6wDg8yScRh9zvdkc8EvG4sWQ==
+  dependencies:
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/api" "1.27.1"
+    "@polkadot/rpc-core" "1.27.1"
+    "@polkadot/types" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    bn.js "^5.1.2"
+    rxjs "^6.6.2"
+
+"@polkadot/api-derive@1.27.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-1.27.1.tgz#5001f19cb29ea4d7924412950b41e46fcca45d81"
+  integrity sha512-WPZEZ9THeYOkkGzDDsCGSTrWJuWu6qegmWLo52pqD7enmP3dADDoKqPzszHVbEAfc+wYtc5Ye4EogUAiK30iMg==
+  dependencies:
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/api" "1.27.1"
+    "@polkadot/rpc-core" "1.27.1"
+    "@polkadot/rpc-provider" "1.27.1"
+    "@polkadot/types" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    "@polkadot/util-crypto" "^3.0.1"
+    bn.js "^5.1.2"
+    memoizee "^0.4.14"
+    rxjs "^6.6.2"
+
+"@polkadot/api@1.27.1", "@polkadot/api@^0.96.1", "@polkadot/api@^1.26.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-1.27.1.tgz#dcd3ae5d8699ea5555369b9594888eb1008dd7fe"
+  integrity sha512-ANMLmNR1PfXLoQ7Ysep9sM/2U3oh3fjFI+9P4Yy9Pv+XMvCROaGAcvxoG+hHfWFz6OAT7ABwyiocV93PuOpAww==
+  dependencies:
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/api-derive" "1.27.1"
+    "@polkadot/keyring" "^3.0.1"
+    "@polkadot/metadata" "1.27.1"
+    "@polkadot/rpc-core" "1.27.1"
+    "@polkadot/rpc-provider" "1.27.1"
+    "@polkadot/types" "1.27.1"
+    "@polkadot/types-known" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    "@polkadot/util-crypto" "^3.0.1"
+    bn.js "^5.1.2"
+    eventemitter3 "^4.0.4"
+    rxjs "^6.6.2"
 
 "@polkadot/dev-react@^0.32.0-beta.13":
   version "0.32.0-beta.15"
@@ -3023,21 +3178,26 @@
   dependencies:
     "@babel/runtime" "^7.7.4"
 
-"@polkadot/jsonrpc@^0.96.1":
-  version "0.96.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/jsonrpc/-/jsonrpc-0.96.1.tgz#78ae3565169d2bd3cb46abbcb67d4768fb0f6154"
-  integrity sha512-UHpcUGIvkG4dJ5gUhDyfJ1xfr/VcBlJ5lIlGamGsnNacMuIVmmEsftgxtPlJLWHuoA1EBEHY4cbPSv9CUJ0IFw==
+"@polkadot/keyring@^1.7.0-beta.5", "@polkadot/keyring@^3.0.1":
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-3.0.1.tgz#3944079697c15b2af81e1f57b1c4aeab703a4fef"
+  integrity sha512-vAHSBnisiDYHsBbEzAgIpuwQp3vIDN2uWQ/1wAE2BrKzXCBQM7RrF3LRcLFySk0xzQoDs7AP1TlPoakxJ/C/Qw==
   dependencies:
-    "@babel/runtime" "^7.7.1"
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/util" "3.0.1"
+    "@polkadot/util-crypto" "3.0.1"
 
-"@polkadot/keyring@^1.7.0-beta.5":
-  version "1.7.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-1.7.1.tgz#53a3dd87e547aaee0a877e4fc5fdfc4757e60a0d"
-  integrity sha512-CWCnU0zsaot0QvEiasKfhCiVlZCIVKOQGPzXiVE9JSjoqTQQJ0BEdaEfM4x0/bFFvvsn/8RcjLPpxBPSfe2eOg==
+"@polkadot/metadata@1.27.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/metadata/-/metadata-1.27.1.tgz#40b8e26f9eee30df5b6790aaab406dae1e6d3152"
+  integrity sha512-jOsWvpGNFkV3NGSGVTzyir0PKinxoa97CYEQj8tJTU7iHDPnSs5R/BEmI0+1hg4ZM/47n+YU8d0lLktD6wbMOA==
   dependencies:
-    "@babel/runtime" "^7.7.4"
-    "@polkadot/util" "^1.7.1"
-    "@polkadot/util-crypto" "^1.7.1"
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/types" "1.27.1"
+    "@polkadot/types-known" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    "@polkadot/util-crypto" "^3.0.1"
+    bn.js "^5.1.2"
 
 "@polkadot/react-identicon@^0.47.0-beta.3":
   version "0.47.1"
@@ -3064,30 +3224,33 @@
     qrcode-generator "^1.4.4"
     react-qr-reader "^2.2.1"
 
-"@polkadot/rpc-core@^0.96.1":
-  version "0.96.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-0.96.1.tgz#8da81d3a690fc4e9b2ccc65761166b4830c5d1a3"
-  integrity sha512-ygSaJpz/QPEq1p35wYRzONuP2PCtkAJ9eS8swQqUIezTo2ZPUOyBhmnJ3nxj11R8YnQClq4Id0QdsJmH1ClYgw==
-  dependencies:
-    "@babel/runtime" "^7.7.1"
-    "@polkadot/jsonrpc" "^0.96.1"
-    "@polkadot/rpc-provider" "^0.96.1"
-    "@polkadot/types" "^0.96.1"
-    "@polkadot/util" "^1.7.0-beta.5"
-    rxjs "^6.5.3"
-
-"@polkadot/rpc-provider@^0.96.1":
-  version "0.96.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-0.96.1.tgz#4936f1876484e3388b6d4b31ee51a7f8946638ad"
-  integrity sha512-cUhp8FMCYHrXrBTbxZrok/hPIgtOXEUhIXn5/zrffg1Qpbzju/y/bXx7c1Kxl1JF7Bg0vSBRZEGJTn/x0irWRQ==
+"@polkadot/rpc-core@1.27.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-1.27.1.tgz#afe7d1890c779eaf2bec9bb1336b5ba2ff1ba15b"
+  integrity sha512-HxLHHdV3bDqTltsEedCRGiZeTGmeahnk6OEGyysFOW3PFIrygwwuYa0Mo10lS93dwy9xZw4oE3h9qZqox2mGmQ==
   dependencies:
-    "@babel/runtime" "^7.7.1"
-    "@polkadot/api-metadata" "^0.96.1"
-    "@polkadot/util" "^1.7.0-beta.5"
-    "@polkadot/util-crypto" "^1.7.0-beta.5"
-    eventemitter3 "^4.0.0"
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/metadata" "1.27.1"
+    "@polkadot/rpc-provider" "1.27.1"
+    "@polkadot/types" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    memoizee "^0.4.14"
+    rxjs "^6.6.2"
+
+"@polkadot/rpc-provider@1.27.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-1.27.1.tgz#c0307a9e9c658f4072ad94ac6e98e2bd78bb1ee6"
+  integrity sha512-12lpsmHNYLZ3p0X0h643U+sw+WE/kzVB9Q0Y0RA9Recq794cBGiEgK/nmVjT5hrTEk+2+qdtu+CqficWt2FeQw==
+  dependencies:
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/metadata" "1.27.1"
+    "@polkadot/types" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    "@polkadot/util-crypto" "^3.0.1"
+    bn.js "^5.1.2"
+    eventemitter3 "^4.0.4"
     isomorphic-fetch "^2.2.1"
-    websocket "^1.0.30"
+    websocket "^1.0.31"
 
 "@polkadot/ts@^0.1.56":
   version "0.1.91"
@@ -3110,16 +3273,46 @@
   dependencies:
     "@types/chrome" "^0.0.114"
 
-"@polkadot/types@^0.96.1":
-  version "0.96.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-0.96.1.tgz#84a7123db0ae2922217a0b830a59acb9d83f176f"
-  integrity sha512-b8AZBNmMjB0+34Oxue3AYc0gIjDHYCdVGtDpel0omHkLMcEquSvrCniLm+p7g4cfArICiZPFmS9In/OWWdRUVA==
-  dependencies:
-    "@babel/runtime" "^7.7.1"
-    "@polkadot/util" "^1.7.0-beta.5"
-    "@polkadot/util-crypto" "^1.7.0-beta.5"
-    "@types/memoizee" "^0.4.3"
+"@polkadot/typegen@^1.26.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/typegen/-/typegen-1.27.1.tgz#e092f54f686d16af11a9e1bde7b9f4bb70413eb8"
+  integrity sha512-Yhj8suhErKV/E5WRaQ9iAIzu3ihHSMk3Ncm/viyA7dMCmtvlEpiSqLeWuA/yrSQ/wHwwyiwnNyjZ7VbptGx1yw==
+  dependencies:
+    "@babel/core" "^7.11.0"
+    "@babel/register" "^7.10.5"
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/api" "1.27.1"
+    "@polkadot/metadata" "1.27.1"
+    "@polkadot/rpc-provider" "1.27.1"
+    "@polkadot/types" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    handlebars "^4.7.6"
+    websocket "^1.0.31"
+    yargs "^15.4.1"
+
+"@polkadot/types-known@1.27.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-1.27.1.tgz#d6c48c7b075cd0a9772fcc5df8d98f77b0da35f3"
+  integrity sha512-9HzHJXznuuG0EQPR3XN931smIzA5usOP2D4Te/uyjiqHgXGUv1EU/vPYaacYYRrjLNdytNcF3HbW97fxu+fC6w==
+  dependencies:
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/types" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    bn.js "^5.1.2"
+
+"@polkadot/types@1.27.1", "@polkadot/types@^0.96.1", "@polkadot/types@^1.26.1":
+  version "1.27.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-1.27.1.tgz#243f796178f9308a8e58f13fa13d0f3ed1fd2bc8"
+  integrity sha512-6sX+0/cBUEd/Pt6Y4JSjUI44nqH6qyuRcs6bte2OsEsm06XTEMoIqICPHoOS36Sd/ux7IA/gTZgEj39C9mJWBQ==
+  dependencies:
+    "@babel/runtime" "^7.11.0"
+    "@polkadot/metadata" "1.27.1"
+    "@polkadot/util" "^3.0.1"
+    "@polkadot/util-crypto" "^3.0.1"
+    "@types/bn.js" "^4.11.6"
+    bn.js "^5.1.2"
     memoizee "^0.4.14"
+    rxjs "^6.6.2"
 
 "@polkadot/ui-assets@^0.47.0-beta.3":
   version "0.47.1"
@@ -3165,45 +3358,41 @@
     "@types/color" "^3.0.0"
     color "^3.1.2"
 
-"@polkadot/util-crypto@^1.7.0-beta.5", "@polkadot/util-crypto@^1.7.1":
-  version "1.7.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-1.7.1.tgz#6cb1ed1f7ecbea3b41100231830817e7fd116dc6"
-  integrity sha512-g0JCciJLJXbkc/Q+2QuJgCgS0Xfl7tO97ALdsI00bgSDA7zlh2zhjpx03Ve47hMndmn7K8ClIGrj4nxHx/95Tw==
+"@polkadot/util-crypto@3.0.1", "@polkadot/util-crypto@^3.0.1":
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-3.0.1.tgz#800746a39a00e5aa7dc7b901bbde0f5e3e0be60b"
+  integrity sha512-4G5kzNfqa/nQGuTtoFsy3DESApc8BTgTHbAvLwSkxzM3j8YsvC5ayJ3AFYvM2UT2PDwXmrFx4cwRnYsYZvhC9A==
   dependencies:
-    "@babel/runtime" "^7.7.4"
-    "@polkadot/util" "^1.7.1"
-    "@polkadot/wasm-crypto" "^0.14.1"
-    "@types/bip39" "^2.4.2"
-    "@types/bs58" "^4.0.0"
-    "@types/pbkdf2" "^3.0.0"
-    "@types/secp256k1" "^3.5.0"
-    "@types/xxhashjs" "^0.2.1"
-    base-x "3.0.5"
-    bip39 "^2.5.0"
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/util" "3.0.1"
+    "@polkadot/wasm-crypto" "^1.2.1"
+    base-x "^3.0.8"
+    bip39 "^3.0.2"
     blakejs "^1.1.0"
-    bs58 "^4.0.1"
+    bn.js "^5.1.2"
+    elliptic "^6.5.3"
     js-sha3 "^0.8.0"
-    secp256k1 "^3.7.0"
-    tweetnacl "^1.0.1"
+    pbkdf2 "^3.1.1"
+    scryptsy "^2.1.0"
+    tweetnacl "^1.0.3"
     xxhashjs "^0.2.2"
 
-"@polkadot/util@^1.7.0-beta.5", "@polkadot/util@^1.7.1":
-  version "1.7.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-1.7.1.tgz#cb262fa5a441097c0c093532f70d0b7e0503fbb1"
-  integrity sha512-tWvh+vYDIiXDIWgAGd9zyJWlDKxQ5KYTKZ9uTlLxfuy1qXEdVOjlX9Qz5+FACU2742e8tTvtvM9KfK05VK5X/A==
+"@polkadot/util@3.0.1", "@polkadot/util@^3.0.1":
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-3.0.1.tgz#f7ed9d81d745136aa6d6ad57277ee05c88f32784"
+  integrity sha512-WvH+seT03YQ+6dWJqo285uYHsDvMEGzgYQILEclzQo8xExeCYLIX6GptpW0vGycVxdZmmCdDmUFbcQSRsFawYA==
   dependencies:
-    "@babel/runtime" "^7.7.4"
-    "@types/bn.js" "^4.11.5"
-    bn.js "^4.11.8"
+    "@babel/runtime" "^7.10.5"
+    "@types/bn.js" "^4.11.6"
+    bn.js "^5.1.2"
     camelcase "^5.3.1"
-    chalk "^3.0.0"
+    chalk "^4.1.0"
     ip-regex "^4.1.0"
-    moment "^2.24.0"
 
-"@polkadot/wasm-crypto@^0.14.1":
-  version "0.14.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-0.14.1.tgz#f4923bba22d7c68a4be3575ba27790947b212633"
-  integrity sha512-Xng7L2Z8TNZa/5g6pot4O06Jf0ohQRZdvfl8eQL+E/L2mcqJYC1IjkMxJBSBuQEV7hisWzh9mHOy5WCcgPk29Q==
+"@polkadot/wasm-crypto@^1.2.1":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-1.2.1.tgz#2189702447acd28d763886359576c87562241767"
+  integrity sha512-nckIoZBV4nBZdeKwFwH5t7skS7L7GO5EFUl5B1F6uCjUfdNpDz3DtqbYQHcLdCZNmG4TDLg6w/1J+rkl2SiUZw==
 
 "@reach/router@^1.2.1":
   version "1.2.1"
@@ -3799,13 +3988,6 @@
   dependencies:
     "@babel/types" "^7.3.0"
 
-"@types/bip39@^2.4.2":
-  version "2.4.2"
-  resolved "https://registry.yarnpkg.com/@types/bip39/-/bip39-2.4.2.tgz#f5d6617212be496bb998d3969f657f77a10c5287"
-  integrity sha512-Vo9lqOIRq8uoIzEVrV87ZvcIM0PN9t0K3oYZ/CS61fIYKCBdOIM7mlWzXuRvSXrDtVa1uUO2w1cdfufxTC0bzg==
-  dependencies:
-    "@types/node" "*"
-
 "@types/bn.js@^4.11.5":
   version "4.11.5"
   resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.5.tgz#40e36197433f78f807524ec623afcf0169ac81dc"
@@ -3813,12 +3995,12 @@
   dependencies:
     "@types/node" "*"
 
-"@types/bs58@^4.0.0":
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/@types/bs58/-/bs58-4.0.1.tgz#3d51222aab067786d3bc3740a84a7f5a0effaa37"
-  integrity sha512-yfAgiWgVLjFCmRv8zAcOIHywYATEwiTVccTLnRp6UxTNavT55M9d/uhK3T03St/+8/z/wW+CRjGKUNmEqoHHCA==
+"@types/bn.js@^4.11.6":
+  version "4.11.6"
+  resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
+  integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==
   dependencies:
-    base-x "^3.0.6"
+    "@types/node" "*"
 
 "@types/chai@*", "@types/chai@^4.2.11":
   version "4.2.11"
@@ -4023,11 +4205,6 @@
   resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.7.2.tgz#1393f076773b55cc7078c0fbeb86a497c69db97e"
   integrity sha512-A3EDyNaq6OCcpaOia2HQ/tu2QYt8DKuj4ExP21VU3cU3HTo2FLslvbqa2T1vux910RHvuSVqpwKnnykSFcRWOA==
 
-"@types/memoizee@^0.4.3":
-  version "0.4.3"
-  resolved "https://registry.yarnpkg.com/@types/memoizee/-/memoizee-0.4.3.tgz#f48270d19327c1709620132cf54d598650f98492"
-  integrity sha512-N6QT0c9ZbEKl33n1wyoTxZs4cpN+YXjs0Aqy5Qim8ipd9PBNIPqOh/p5Pixc4601tqr5GErsdxUbfqviDfubNw==
-
 "@types/mime-types@^2.1.0":
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73"
@@ -4072,6 +4249,11 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2"
   integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==
 
+"@types/node@11.11.6":
+  version "11.11.6"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a"
+  integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
+
 "@types/node@^10.17.18":
   version "10.17.24"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.24.tgz#c57511e3a19c4b5e9692bb2995c40a3a52167944"
@@ -4087,13 +4269,6 @@
   resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
   integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
 
-"@types/pbkdf2@^3.0.0":
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.0.0.tgz#5d9ca5f12a78a08cc89ad72883ad4a30af359229"
-  integrity sha512-6J6MHaAlBJC/eVMy9jOwj9oHaprfutukfW/Dyt0NEnpQ/6HN6YQrpvLwzWdWDeWZIdenjGHlbYDzyEODO5Z+2Q==
-  dependencies:
-    "@types/node" "*"
-
 "@types/prettier@^1.16.1":
   version "1.19.0"
   resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.0.tgz#a2502fb7ce9b6626fdbfc2e2a496f472de1bdd05"
@@ -4247,13 +4422,6 @@
   resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
   integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
 
-"@types/secp256k1@^3.5.0":
-  version "3.5.0"
-  resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-3.5.0.tgz#0f3baf16b07488c6da2633a63b4160bcf8d0fd5b"
-  integrity sha512-ZE39QhkIaNK6xbKIp1VLN5O36r97LuslLmRnjAcT0sVDxcfvrk3zqp/VnIfmGza7J6jDxR8dIai3hsCxPYglPA==
-  dependencies:
-    "@types/node" "*"
-
 "@types/sinon@*":
   version "9.0.4"
   resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-9.0.4.tgz#e934f904606632287a6e7f7ab0ce3f08a0dad4b1"
@@ -4357,13 +4525,6 @@
   resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.14.1.tgz#0d8a53f308f017c53a5ddc3d07f4d6fa76b790d7"
   integrity sha512-0Ki9jAAhKDSuLDXOIMADg54Hu60SuBTEsWaJGGy5cV+SSUQ63J2a+RrYYGrErzz39fXzTibhKrAQJAb8M7PNcA==
 
-"@types/xxhashjs@^0.2.1":
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/@types/xxhashjs/-/xxhashjs-0.2.1.tgz#6cd06b2eca5228765ff45960cf2c2a557ddf109a"
-  integrity sha512-Akm13wkwsQylVnBokl/aiKLtSxndSjfgTjdvmSxXNehYy4NymwdfdJHwGhpV54wcYfmOByOp3ak8AGdUlvp0sA==
-  dependencies:
-    "@types/node" "*"
-
 "@types/yargs-parser@*":
   version "13.1.0"
   resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228"
@@ -6147,14 +6308,7 @@ base-x@3.0.4:
   dependencies:
     safe-buffer "^5.0.1"
 
-base-x@3.0.5:
-  version "3.0.5"
-  resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.5.tgz#d3ada59afed05b921ab581ec3112e6444ba0795a"
-  integrity sha512-C3picSgzPSLE+jW3tcBzJoGwitOtazb5B+5YmAxZm2ybmTi9LNgAtDO/jjVEBZwHoXmDBZ9m/IELj3elJVRBcA==
-  dependencies:
-    safe-buffer "^5.0.1"
-
-base-x@^3.0.2, base-x@^3.0.6:
+base-x@^3.0.2:
   version "3.0.7"
   resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.7.tgz#1c5a7fafe8f66b4114063e8da102799d4e7c408f"
   integrity sha512-zAKJGuQPihXW22fkrfOclUUZXM2g92z5GzlSMHxhO6r6Qj+Nm0ccaGNBzDZojzwOMkpjAv4J0fOv1U4go+a4iw==
@@ -6260,16 +6414,15 @@ bindings@^1.2.1, bindings@^1.4.0, bindings@^1.5.0:
   dependencies:
     file-uri-to-path "1.0.0"
 
-bip39@^2.5.0:
-  version "2.6.0"
-  resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.6.0.tgz#9e3a720b42ec8b3fbe4038f1e445317b6a99321c"
-  integrity sha512-RrnQRG2EgEoqO24ea+Q/fftuPUZLmrEM3qNhhGsA3PbaXaCW791LTzPuVyx/VprXQcTbPJ3K3UeTna8ZnVl2sg==
+bip39@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.2.tgz#2baf42ff3071fc9ddd5103de92e8f80d9257ee32"
+  integrity sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==
   dependencies:
+    "@types/node" "11.11.6"
     create-hash "^1.1.0"
     pbkdf2 "^3.0.9"
     randombytes "^2.0.1"
-    safe-buffer "^5.0.1"
-    unorm "^1.3.3"
 
 bip66@^1.1.5:
   version "1.1.5"
@@ -6324,6 +6477,11 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.8, bn.js@^4.4.0:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
   integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
 
+bn.js@^5.1.2:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0"
+  integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==
+
 body-parser@1.19.0, body-parser@^1.19.0:
   version "1.19.0"
   resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
@@ -6968,6 +7126,14 @@ chalk@^4.0.0:
     ansi-styles "^4.1.0"
     supports-color "^7.1.0"
 
+chalk@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
+  integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
+  dependencies:
+    ansi-styles "^4.1.0"
+    supports-color "^7.1.0"
+
 character-entities-html4@^1.0.0:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.3.tgz#5ce6e01618e47048ac22f34f7f39db5c6fd679ef"
@@ -7373,6 +7539,15 @@ cliui@^5.0.0:
     strip-ansi "^5.2.0"
     wrap-ansi "^5.1.0"
 
+cliui@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
+  integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
+  dependencies:
+    string-width "^4.2.0"
+    strip-ansi "^6.0.0"
+    wrap-ansi "^6.2.0"
+
 clone-buffer@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
@@ -9266,7 +9441,7 @@ element-resize-detector@^1.1.15:
   dependencies:
     batch-processor "^1.0.0"
 
-elliptic@^6.0.0, elliptic@^6.4.1:
+elliptic@^6.0.0:
   version "6.5.2"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762"
   integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==
@@ -9279,7 +9454,7 @@ elliptic@^6.0.0, elliptic@^6.4.1:
     minimalistic-assert "^1.0.0"
     minimalistic-crypto-utils "^1.0.0"
 
-elliptic@^6.5.2:
+elliptic@^6.5.2, elliptic@^6.5.3:
   version "6.5.3"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
   integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==
@@ -10214,6 +10389,11 @@ eventemitter3@^4.0.0:
   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
   integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
 
+eventemitter3@^4.0.4:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384"
+  integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==
+
 events-to-array@^1.0.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/events-to-array/-/events-to-array-1.1.2.tgz#2d41f563e1fe400ed4962fe1a4d5c6a7539df7f6"
@@ -11834,6 +12014,18 @@ handlebars@^4.1.2, handlebars@^4.4.0, handlebars@^4.5.3:
   optionalDependencies:
     uglify-js "^3.1.4"
 
+handlebars@^4.7.6:
+  version "4.7.6"
+  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e"
+  integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==
+  dependencies:
+    minimist "^1.2.5"
+    neo-async "^2.6.0"
+    source-map "^0.6.1"
+    wordwrap "^1.0.0"
+  optionalDependencies:
+    uglify-js "^3.1.4"
+
 har-schema@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@@ -15133,6 +15325,11 @@ lodash@^4.0.0, lodash@^4.0.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11,
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
 
+lodash@^4.17.19:
+  version "4.17.19"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
+  integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
+
 log-driver@^1.2.7:
   version "1.2.7"
   resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8"
@@ -17680,6 +17877,17 @@ pbkdf2@^3.0.3, pbkdf2@^3.0.9:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
+pbkdf2@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94"
+  integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==
+  dependencies:
+    create-hash "^1.1.2"
+    create-hmac "^1.1.4"
+    ripemd160 "^2.0.1"
+    safe-buffer "^5.0.1"
+    sha.js "^2.4.8"
+
 peer-id@~0.12.2:
   version "0.12.5"
   resolved "https://registry.yarnpkg.com/peer-id/-/peer-id-0.12.5.tgz#b22a1edc5b4aaaa2bb830b265ba69429823e5179"
@@ -20093,6 +20301,11 @@ regenerator-runtime@^0.13.2:
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
   integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
 
+regenerator-runtime@^0.13.4:
+  version "0.13.7"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
+  integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
+
 regenerator-transform@^0.14.0:
   version "0.14.1"
   resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
@@ -20627,6 +20840,13 @@ rxjs@^6.4.0, rxjs@^6.5.3:
   dependencies:
     tslib "^1.9.0"
 
+rxjs@^6.6.2:
+  version "6.6.2"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2"
+  integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==
+  dependencies:
+    tslib "^1.9.0"
+
 safe-buffer@5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
@@ -20735,6 +20955,11 @@ schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.1.0, schema-utils@^2.5
     ajv "^6.10.2"
     ajv-keywords "^3.4.1"
 
+scryptsy@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790"
+  integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==
+
 scss-tokenizer@^0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
@@ -20762,20 +20987,6 @@ secp256k1@^3.6.2:
     nan "^2.14.0"
     safe-buffer "^5.1.2"
 
-secp256k1@^3.7.0:
-  version "3.7.1"
-  resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.7.1.tgz#12e473e0e9a7c2f2d4d4818e722ad0e14cc1e2f1"
-  integrity sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==
-  dependencies:
-    bindings "^1.5.0"
-    bip66 "^1.1.5"
-    bn.js "^4.11.8"
-    create-hash "^1.2.0"
-    drbg.js "^1.0.1"
-    elliptic "^6.4.1"
-    nan "^2.14.0"
-    safe-buffer "^5.1.2"
-
 section-matter@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167"
@@ -22769,7 +22980,7 @@ ts-log@^2.1.4:
   resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.1.4.tgz#063c5ad1cbab5d49d258d18015963489fb6fb59a"
   integrity sha512-P1EJSoyV+N3bR/IWFeAqXzKPZwHpnLY6j7j58mAvewHRipo+BQM2Y1f9Y9BjEQznKwgqqZm7H8iuixmssU7tYQ==
 
-ts-node@^8.5.2:
+ts-node@^8.5.2, ts-node@^8.6.2:
   version "8.10.2"
   resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d"
   integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==
@@ -22854,16 +23065,11 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
   integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
 
-tweetnacl@^1.0.0:
+tweetnacl@^1.0.0, tweetnacl@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
   integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
 
-tweetnacl@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.1.tgz#2594d42da73cd036bd0d2a54683dd35a6b55ca17"
-  integrity sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A==
-
 type-check@~0.3.2:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@@ -22988,10 +23194,10 @@ typescript-formatter@^7.2.2:
     commandpost "^1.0.0"
     editorconfig "^0.15.0"
 
-typescript@3.7.2, typescript@3.7.x, typescript@^3.0.3, typescript@^3.6.4, typescript@^3.7.2, typescript@^3.8.3, typescript@^3.9.6:
-  version "3.7.2"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
-  integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
+typescript@3.7.2, typescript@3.7.x, typescript@^3.0.3, typescript@^3.6.4, typescript@^3.7.2, typescript@^3.8.3, typescript@^3.9.6, typescript@^3.9.7:
+  version "3.9.7"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
+  integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
 
 u2f-api@0.2.7:
   version "0.2.7"
@@ -23240,11 +23446,6 @@ universalify@^1.0.0:
   resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
   integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
 
-unorm@^1.3.3:
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af"
-  integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==
-
 unpipe@1.0.0, unpipe@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@@ -24004,12 +24205,13 @@ websocket-extensions@>=0.1.1:
   resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
   integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==
 
-websocket@^1.0.30:
-  version "1.0.30"
-  resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.30.tgz#91d3bd00c3d43e916f0cf962f8f8c451bb0b2373"
-  integrity sha512-aO6klgaTdSMkhfl5VVJzD5fm+Srhh5jLYbS15+OiI1sN6h/RU/XW6WN9J1uVIpUKNmsTvT3Hs35XAFjn9NMfOw==
+websocket@^1.0.31:
+  version "1.0.31"
+  resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.31.tgz#e5d0f16c3340ed87670e489ecae6144c79358730"
+  integrity sha512-VAouplvGKPiKFDTeCCO65vYHsyay8DqoBSlzIO3fayrfOgU94lQN5a1uWVnFrMLceTJw/+fQXR5PGbUVRaHshQ==
   dependencies:
     debug "^2.2.0"
+    es5-ext "^0.10.50"
     nan "^2.14.0"
     typedarray-to-buffer "^3.1.5"
     yaeti "^0.0.6"
@@ -24116,6 +24318,11 @@ word-wrap@~1.2.3:
   resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
   integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
 
+wordwrap@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+  integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
+
 wordwrap@~0.0.2:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
@@ -24434,7 +24641,7 @@ yargs-parser@^15.0.0:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
-yargs-parser@^18.1.3:
+yargs-parser@^18.1.2, yargs-parser@^18.1.3:
   version "18.1.3"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
   integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
@@ -24583,6 +24790,23 @@ yargs@^14.2.0, yargs@^14.2.2:
     y18n "^4.0.0"
     yargs-parser "^15.0.0"
 
+yargs@^15.4.1:
+  version "15.4.1"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
+  integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
+  dependencies:
+    cliui "^6.0.0"
+    decamelize "^1.2.0"
+    find-up "^4.1.0"
+    get-caller-file "^2.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^2.0.0"
+    set-blocking "^2.0.0"
+    string-width "^4.2.0"
+    which-module "^2.0.0"
+    y18n "^4.0.0"
+    yargs-parser "^18.1.2"
+
 yargs@^7.0.0:
   version "7.1.0"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"

Some files were not shown because too many files changed in this diff