瀏覽代碼

Merge branch 'joystream-types-upgrade' into pioneer-new-apps

Leszek Wiesner 4 年之前
父節點
當前提交
685c7fc32e
共有 45 個文件被更改,包括 11859 次插入3384 次删除
  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. 1663 0
      types/yarn.lock
  45. 8579 228
      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"
@@ -21,14 +21,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",
     "madge": "^3.9.2"
   },

+ 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

文件差異過大導致無法顯示
+ 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?: WorkingGroupOpeningPolicyCommitment) {
-    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"
   ]
 }

+ 1663 - 0
types/yarn.lock

@@ -0,0 +1,1663 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/parser@^7.0.0":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d"
+  integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw==
+
+"@babel/runtime@^7.10.5":
+  version "7.11.0"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.0.tgz#f10245877042a815e07f7e693faff0ae9d3a2aac"
+  integrity sha512-qArkXsjJq7H+T86WrIFV0Fnu/tNOkZ4cgXmjkzAu3b/58D5mFIO8JH/y77t7C9q0OdDRdh9s7Ue5GasYssxtXw==
+  dependencies:
+    regenerator-runtime "^0.13.4"
+
+"@polkadot/api-derive@1.26.1":
+  version "1.26.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-1.26.1.tgz#e9f135b1f2ee0f572392758dcf4a0beb9c9d54a1"
+  integrity sha512-09SCFtf6RibjyFm8aSDUD+opQTPIKqEP8fX8Gs+ZvXlyHSkVbR4ffjaTILgZJQNAPOrLeVSOGmR9dD+xKaKSBQ==
+  dependencies:
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/api" "1.26.1"
+    "@polkadot/rpc-core" "1.26.1"
+    "@polkadot/rpc-provider" "1.26.1"
+    "@polkadot/types" "1.26.1"
+    "@polkadot/util" "^3.0.1"
+    "@polkadot/util-crypto" "^3.0.1"
+    bn.js "^5.1.2"
+    memoizee "^0.4.14"
+    rxjs "^6.6.0"
+
+"@polkadot/api@1.26.1", "@polkadot/api@^1.26.1":
+  version "1.26.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-1.26.1.tgz#215268489c10b1a65429c6ce451c8d65bd3ad843"
+  integrity sha512-al8nmLgIU1EKo0oROEgw1mqUvrHJu4gKYBwnFONaEOxHSxBgBSSgNy1MWKNntAQYDKA4ETCj4pz7ZpMXTx2SDA==
+  dependencies:
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/api-derive" "1.26.1"
+    "@polkadot/keyring" "^3.0.1"
+    "@polkadot/metadata" "1.26.1"
+    "@polkadot/rpc-core" "1.26.1"
+    "@polkadot/rpc-provider" "1.26.1"
+    "@polkadot/types" "1.26.1"
+    "@polkadot/types-known" "1.26.1"
+    "@polkadot/util" "^3.0.1"
+    "@polkadot/util-crypto" "^3.0.1"
+    bn.js "^5.1.2"
+    eventemitter3 "^4.0.4"
+    rxjs "^6.6.0"
+
+"@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.10.5"
+    "@polkadot/util" "3.0.1"
+    "@polkadot/util-crypto" "3.0.1"
+
+"@polkadot/metadata@1.26.1":
+  version "1.26.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/metadata/-/metadata-1.26.1.tgz#64b959415dab6f61ba415b0a337a3ec06e3cad3e"
+  integrity sha512-SyfIIFRx6Oatr1W5KtrmBlxoyJ338tuiuYRMmHuWTGs5jnYQlKf/yd3UiUkibaA372fFEx6/qGWHwutyS0STCA==
+  dependencies:
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/types" "1.26.1"
+    "@polkadot/types-known" "1.26.1"
+    "@polkadot/util" "^3.0.1"
+    "@polkadot/util-crypto" "^3.0.1"
+    bn.js "^5.1.2"
+
+"@polkadot/rpc-core@1.26.1":
+  version "1.26.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-1.26.1.tgz#bd1574f149a13d458c9fb626123a126daa91266e"
+  integrity sha512-sxZgc4/pbZS9rKgtwnjZzg6BsVY2PZd46yFLLFCF+QYlnM8nhYWD4hSDiEvN0N3/SNNAFJydnwE8qYV0n4dEJw==
+  dependencies:
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/metadata" "1.26.1"
+    "@polkadot/rpc-provider" "1.26.1"
+    "@polkadot/types" "1.26.1"
+    "@polkadot/util" "^3.0.1"
+    memoizee "^0.4.14"
+    rxjs "^6.6.0"
+
+"@polkadot/rpc-provider@1.26.1":
+  version "1.26.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-1.26.1.tgz#85adef601ab7e65925761ac6e7081019de4de1c7"
+  integrity sha512-Cbwk9ydRqbri9peag8tUcmlmhUdK1MYhDcU7UgOJ9BzptnHM5BdstzC3L1lYpfFzxgyCBaDYRhnAKAIqEcQHDw==
+  dependencies:
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/metadata" "1.26.1"
+    "@polkadot/types" "1.26.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.31"
+
+"@polkadot/types-known@1.26.1":
+  version "1.26.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-1.26.1.tgz#0e377b23d4e1dc69d282c7a96ee88926f6edacaf"
+  integrity sha512-zxdwuLTtHqmhKJCMM/tMEM+/SV6W6zI8J1QxeCw09YT6MKWx13M+uw6C66Owdm9gXyNYyq2XkGHqBH67Zpq5zg==
+  dependencies:
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/types" "1.26.1"
+    "@polkadot/util" "^3.0.1"
+    bn.js "^5.1.2"
+
+"@polkadot/types@1.26.1", "@polkadot/types@^1.26.1":
+  version "1.26.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-1.26.1.tgz#e58a823da22bd526b298f7d42384bf59b8994fad"
+  integrity sha512-mrA3+qYyDvfOIOMkY8lg2ziCYpwOl3N1LUxKdiyBDtKM7Dl8ZWQ0nLUCDW5MhbzDlThmYjE4feBRA+2eBShfyA==
+  dependencies:
+    "@babel/runtime" "^7.10.5"
+    "@polkadot/metadata" "1.26.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.0"
+
+"@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.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"
+    bn.js "^5.1.2"
+    elliptic "^6.5.3"
+    js-sha3 "^0.8.0"
+    pbkdf2 "^3.1.1"
+    scryptsy "^2.1.0"
+    tweetnacl "^1.0.3"
+    xxhashjs "^0.2.2"
+
+"@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.10.5"
+    "@types/bn.js" "^4.11.6"
+    bn.js "^5.1.2"
+    camelcase "^5.3.1"
+    chalk "^4.1.0"
+    ip-regex "^4.1.0"
+
+"@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==
+
+"@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:
+    "@types/node" "*"
+
+"@types/color-name@^1.1.1":
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
+  integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
+
+"@types/lodash@^4.14.157":
+  version "4.14.158"
+  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.158.tgz#b38ea8b6fe799acd076d7a8d7ab71c26ef77f785"
+  integrity sha512-InCEXJNTv/59yO4VSfuvNrZHt7eeNtWQEgnieIA+mIC+MOWM9arOWG2eQ8Vhk6NbOre6/BidiXhkZYeDY9U35w==
+
+"@types/node@*":
+  version "14.0.27"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1"
+  integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==
+
+"@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/unist@^2.0.0", "@types/unist@^2.0.2":
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
+  integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
+
+"@types/vfile@^4.0.0":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-4.0.0.tgz#c32d13cbda319bc9f4ab3cacc0263b4ba1dd1ea3"
+  integrity sha512-eleP0/Cz8uVWxARDLi3Axq2+fDdN4ibAXoC6Pv8p6s7znXaUL7XvhgeIhjCiNMnvlLNP+tmCLd+RuCryGgmtEg==
+  dependencies:
+    vfile "*"
+
+"@typescript-eslint/typescript-estree@^2.29.0":
+  version "2.34.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5"
+  integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==
+  dependencies:
+    debug "^4.1.1"
+    eslint-visitor-keys "^1.1.0"
+    glob "^7.1.6"
+    is-glob "^4.0.1"
+    lodash "^4.17.15"
+    semver "^7.3.2"
+    tsutils "^3.17.1"
+
+ajv@^6.11.0:
+  version "6.12.3"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706"
+  integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==
+  dependencies:
+    fast-deep-equal "^3.1.1"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.4.1"
+    uri-js "^4.2.2"
+
+ansi-regex@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
+  integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
+
+ansi-styles@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+  dependencies:
+    color-convert "^1.9.0"
+
+ansi-styles@^4.1.0:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
+  integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
+  dependencies:
+    "@types/color-name" "^1.1.1"
+    color-convert "^2.0.1"
+
+app-module-path@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5"
+  integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU=
+
+ast-module-types@^2.3.1, ast-module-types@^2.3.2, ast-module-types@^2.4.0, ast-module-types@^2.6.0:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-2.6.0.tgz#f9f367fd273bbe01e52f2c51b5f46b65801d5d7f"
+  integrity sha512-zXSoVaMrf2R+r+ISid5/9a8SXm1LLdkhHzh6pSRhj9jklzruOOl1hva1YmFT33wAstg/f9ZndJAlq1BSrFLSGA==
+
+balanced-match@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+  integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+
+base-x@^3.0.8:
+  version "3.0.8"
+  resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d"
+  integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==
+  dependencies:
+    safe-buffer "^5.0.1"
+
+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"
+
+blakejs@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.0.tgz#69df92ef953aa88ca51a32df6ab1c54a155fc7a5"
+  integrity sha1-ad+S75U6qIylGjLfarHFShVfx6U=
+
+bn.js@^4.4.0:
+  version "4.11.9"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
+  integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
+
+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==
+
+brace-expansion@^1.1.7:
+  version "1.1.11"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+  integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+  dependencies:
+    balanced-match "^1.0.0"
+    concat-map "0.0.1"
+
+brorand@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+  integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
+
+camelcase@^5.3.1:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+  integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+chalk@^2.4.2:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+  dependencies:
+    ansi-styles "^3.2.1"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.3.0"
+
+chalk@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
+  integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
+  dependencies:
+    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"
+
+cipher-base@^1.0.1, cipher-base@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+  integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+cli-cursor@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
+  integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
+  dependencies:
+    restore-cursor "^3.1.0"
+
+cli-spinners@^2.2.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f"
+  integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA==
+
+clone@^1.0.2:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+  integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
+
+color-convert@^1.9.0:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+  integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+  dependencies:
+    color-name "1.1.3"
+
+color-convert@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+  dependencies:
+    color-name "~1.1.4"
+
+color-name@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+  integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+color-name@~1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+  integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+commander@^2.13.0, commander@^2.16.0, commander@^2.19.0, commander@^2.20.3, commander@^2.8.1:
+  version "2.20.3"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+  integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+commander@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
+  integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
+
+commondir@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+  integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
+
+concat-map@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+  integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+core-util-is@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+  integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+
+create-hash@^1.1.0, create-hash@^1.1.2:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
+  integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
+  dependencies:
+    cipher-base "^1.0.1"
+    inherits "^2.0.1"
+    md5.js "^1.3.4"
+    ripemd160 "^2.0.1"
+    sha.js "^2.4.0"
+
+create-hmac@^1.1.4:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
+  integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
+  dependencies:
+    cipher-base "^1.0.3"
+    create-hash "^1.1.0"
+    inherits "^2.0.1"
+    ripemd160 "^2.0.0"
+    safe-buffer "^5.0.1"
+    sha.js "^2.4.8"
+
+cuint@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b"
+  integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=
+
+d@1, d@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
+  integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
+  dependencies:
+    es5-ext "^0.10.50"
+    type "^1.0.1"
+
+debug@^2.2.0:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+  dependencies:
+    ms "2.0.0"
+
+debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+  integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+  dependencies:
+    ms "^2.1.1"
+
+decomment@^0.9.2:
+  version "0.9.3"
+  resolved "https://registry.yarnpkg.com/decomment/-/decomment-0.9.3.tgz#b913f32e5fe1113848f516caa5c7afefa9544d38"
+  integrity sha512-5skH5BfUL3n09RDmMVaHS1QGCiZRnl2nArUwmsE9JRY93Ueh3tihYl5wIrDdAuXnoFhxVis/DmRWREO2c6DG3w==
+  dependencies:
+    esprima "4.0.1"
+
+deep-extend@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+  integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
+
+deep-is@~0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+  integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+
+defaults@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
+  integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
+  dependencies:
+    clone "^1.0.2"
+
+dependency-tree@^7.2.1:
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/dependency-tree/-/dependency-tree-7.2.1.tgz#41c8f6feb54a2ae32475c0158e8d2c2696bb7f54"
+  integrity sha512-nBxnjkqDW4LqAzBazy60V4lE0mAtIQ+oers/GIIvVvGYVdCD9+RNNd4G9jjstyz7ZFVg/j/OiYCvK5MjoVqA2w==
+  dependencies:
+    commander "^2.19.0"
+    debug "^4.1.1"
+    filing-cabinet "^2.5.1"
+    precinct "^6.2.0"
+    typescript "^3.7.5"
+
+detective-amd@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/detective-amd/-/detective-amd-3.0.0.tgz#40c8e21e229df8bca1ee2d4b952a7b67b01e2a5a"
+  integrity sha512-kOpKHyabdSKF9kj7PqYHLeHPw+TJT8q2u48tZYMkIcas28el1CYeLEJ42Nm+563/Fq060T5WknfwDhdX9+kkBQ==
+  dependencies:
+    ast-module-types "^2.3.1"
+    escodegen "^1.8.0"
+    get-amd-module-type "^3.0.0"
+    node-source-walk "^4.0.0"
+
+detective-cjs@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/detective-cjs/-/detective-cjs-3.1.1.tgz#18da3e39a002d2098a1123d45ce1de1b0d9045a0"
+  integrity sha512-JQtNTBgFY6h8uT6pgph5QpV3IyxDv+z3qPk/FZRDT9TlFfm5dnRtpH39WtQEr1khqsUxVqXzKjZHpdoQvQbllg==
+  dependencies:
+    ast-module-types "^2.4.0"
+    node-source-walk "^4.0.0"
+
+detective-es6@^2.1.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/detective-es6/-/detective-es6-2.2.0.tgz#8f2baba3f8cd90a5cfd748f5ac436f0158ed2585"
+  integrity sha512-fSpNY0SLER7/sVgQZ1NxJPwmc9uCTzNgdkQDhAaj8NPYwr7Qji9QBcmbNvtMCnuuOGMuKn3O7jv0An+/WRWJZQ==
+  dependencies:
+    node-source-walk "^4.0.0"
+
+detective-less@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/detective-less/-/detective-less-1.0.2.tgz#a68af9ca5f69d74b7d0aa190218b211d83b4f7e3"
+  integrity sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==
+  dependencies:
+    debug "^4.0.0"
+    gonzales-pe "^4.2.3"
+    node-source-walk "^4.0.0"
+
+detective-postcss@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/detective-postcss/-/detective-postcss-3.0.1.tgz#511921951f66135e17d0ece2e7604c6e4966c9c6"
+  integrity sha512-tfTS2GdpUal5NY0aCqI4dpEy8Xfr88AehYKB0iBIZvo8y2g3UsrcDnrp9PR2FbzoW7xD5Rip3NJW7eCSvtqdUw==
+  dependencies:
+    debug "^4.1.1"
+    is-url "^1.2.4"
+    postcss "^7.0.2"
+    postcss-values-parser "^1.5.0"
+
+detective-sass@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/detective-sass/-/detective-sass-3.0.1.tgz#496b819efd1f5c4dd3f0e19b43a8634bdd6927c4"
+  integrity sha512-oSbrBozRjJ+QFF4WJFbjPQKeakoaY1GiR380NPqwdbWYd5wfl5cLWv0l6LsJVqrgWfFN1bjFqSeo32Nxza8Lbw==
+  dependencies:
+    debug "^4.1.1"
+    gonzales-pe "^4.2.3"
+    node-source-walk "^4.0.0"
+
+detective-scss@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/detective-scss/-/detective-scss-2.0.1.tgz#06f8c21ae6dedad1fccc26d544892d968083eaf8"
+  integrity sha512-VveyXW4WQE04s05KlJ8K0bG34jtHQVgTc9InspqoQxvnelj/rdgSAy7i2DXAazyQNFKlWSWbS+Ro2DWKFOKTPQ==
+  dependencies:
+    debug "^4.1.1"
+    gonzales-pe "^4.2.3"
+    node-source-walk "^4.0.0"
+
+detective-stylus@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/detective-stylus/-/detective-stylus-1.0.0.tgz#50aee7db8babb990381f010c63fabba5b58e54cd"
+  integrity sha1-UK7n24uruZA4HwEMY/q7pbWOVM0=
+
+detective-typescript@^5.8.0:
+  version "5.8.0"
+  resolved "https://registry.yarnpkg.com/detective-typescript/-/detective-typescript-5.8.0.tgz#c46776571e26bad6c9ada020cb3cb4e5625d1311"
+  integrity sha512-SrsUCfCaDTF64QVMHMidRal+kmkbIc5zP8cxxZPsomWx9vuEUjBlSJNhf7/ypE5cLdJJDI4qzKDmyzqQ+iz/xg==
+  dependencies:
+    "@typescript-eslint/typescript-estree" "^2.29.0"
+    ast-module-types "^2.6.0"
+    node-source-walk "^4.2.0"
+    typescript "^3.8.3"
+
+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==
+  dependencies:
+    bn.js "^4.4.0"
+    brorand "^1.0.1"
+    hash.js "^1.0.0"
+    hmac-drbg "^1.0.0"
+    inherits "^2.0.1"
+    minimalistic-assert "^1.0.0"
+    minimalistic-crypto-utils "^1.0.0"
+
+encoding@^0.1.11:
+  version "0.1.13"
+  resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
+  integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
+  dependencies:
+    iconv-lite "^0.6.2"
+
+enhanced-resolve@^4.1.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126"
+  integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==
+  dependencies:
+    graceful-fs "^4.1.2"
+    memory-fs "^0.5.0"
+    tapable "^1.0.0"
+
+errno@^0.1.3:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
+  integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==
+  dependencies:
+    prr "~1.0.1"
+
+es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
+  version "0.10.53"
+  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
+  integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
+  dependencies:
+    es6-iterator "~2.0.3"
+    es6-symbol "~3.1.3"
+    next-tick "~1.0.0"
+
+es6-iterator@^2.0.3, es6-iterator@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
+  integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
+  dependencies:
+    d "1"
+    es5-ext "^0.10.35"
+    es6-symbol "^3.1.1"
+
+es6-symbol@^3.1.1, es6-symbol@~3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
+  integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
+  dependencies:
+    d "^1.0.1"
+    ext "^1.1.2"
+
+es6-weak-map@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53"
+  integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==
+  dependencies:
+    d "1"
+    es5-ext "^0.10.46"
+    es6-iterator "^2.0.3"
+    es6-symbol "^3.1.1"
+
+escape-string-regexp@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+  integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+
+escodegen@^1.8.0:
+  version "1.14.3"
+  resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
+  integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
+  dependencies:
+    esprima "^4.0.1"
+    estraverse "^4.2.0"
+    esutils "^2.0.2"
+    optionator "^0.8.1"
+  optionalDependencies:
+    source-map "~0.6.1"
+
+eslint-visitor-keys@^1.1.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
+  integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
+
+esprima@4.0.1, esprima@^4.0.0, esprima@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+  integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+estraverse@^4.2.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+  integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+esutils@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+  integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+event-emitter@^0.3.5:
+  version "0.3.5"
+  resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
+  integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+
+eventemitter3@^4.0.4:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384"
+  integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==
+
+ext@^1.1.2:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244"
+  integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==
+  dependencies:
+    type "^2.0.0"
+
+fast-deep-equal@^3.1.1:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+  integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-json-stable-stringify@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+  integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@~2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+  integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
+
+file-exists-dazinatorfork@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/file-exists-dazinatorfork/-/file-exists-dazinatorfork-1.0.2.tgz#cd8d0d85f63e39dc81eceb0b687c44a2cca95c47"
+  integrity sha512-r70c72ln2YHzQINNfxDp02hAhbGkt1HffZ+Du8oetWDLjDtFja/Lm10lUaSh9e+wD+7VDvPee0b0C9SAy8pWZg==
+
+filing-cabinet@^2.5.1:
+  version "2.5.1"
+  resolved "https://registry.yarnpkg.com/filing-cabinet/-/filing-cabinet-2.5.1.tgz#f920976d46310710595ed995f033a301570ef6ab"
+  integrity sha512-GWOdObzou2L0HrJUk8MpJa01q0ZOwuTwTssM2+P+ABJWEGlVWd6ueEatANFdin94/3rdkVSdqpH14VqCNqp3RA==
+  dependencies:
+    app-module-path "^2.2.0"
+    commander "^2.13.0"
+    debug "^4.1.1"
+    decomment "^0.9.2"
+    enhanced-resolve "^4.1.0"
+    is-relative-path "^1.0.2"
+    module-definition "^3.0.0"
+    module-lookup-amd "^6.1.0"
+    resolve "^1.11.1"
+    resolve-dependency-path "^2.0.0"
+    sass-lookup "^3.0.0"
+    stylus-lookup "^3.0.1"
+    typescript "^3.0.3"
+
+find@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/find/-/find-0.3.0.tgz#4082e8fc8d8320f1a382b5e4f521b9bc50775cb8"
+  integrity sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==
+  dependencies:
+    traverse-chain "~0.1.0"
+
+flatten@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
+  integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
+
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+  integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+
+get-amd-module-type@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/get-amd-module-type/-/get-amd-module-type-3.0.0.tgz#bb334662fa04427018c937774570de495845c288"
+  integrity sha512-99Q7COuACPfVt18zH9N4VAMyb81S6TUgJm2NgV6ERtkh9VIkAaByZkW530wl3lLN5KTtSrK9jVLxYsoP5hQKsw==
+  dependencies:
+    ast-module-types "^2.3.2"
+    node-source-walk "^4.0.0"
+
+get-own-enumerable-property-symbols@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
+  integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
+
+glob@^7.1.6:
+  version "7.1.6"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
+  integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+gonzales-pe@^4.2.3:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3"
+  integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==
+  dependencies:
+    minimist "^1.2.5"
+
+graceful-fs@^4.1.2:
+  version "4.2.4"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
+  integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
+
+graphviz@0.0.9:
+  version "0.0.9"
+  resolved "https://registry.yarnpkg.com/graphviz/-/graphviz-0.0.9.tgz#0bbf1df588c6a92259282da35323622528c4bbc4"
+  integrity sha512-SmoY2pOtcikmMCqCSy2NO1YsRfu9OO0wpTlOYW++giGjfX1a6gax/m1Fo8IdUd0/3H15cTOfR1SMKwohj4LKsg==
+  dependencies:
+    temp "~0.4.0"
+
+has-flag@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+  integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+
+has-flag@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+  integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+hash-base@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
+  integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
+  dependencies:
+    inherits "^2.0.4"
+    readable-stream "^3.6.0"
+    safe-buffer "^5.2.0"
+
+hash.js@^1.0.0, hash.js@^1.0.3:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
+  integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
+  dependencies:
+    inherits "^2.0.3"
+    minimalistic-assert "^1.0.1"
+
+hmac-drbg@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+  integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
+  dependencies:
+    hash.js "^1.0.3"
+    minimalistic-assert "^1.0.0"
+    minimalistic-crypto-utils "^1.0.1"
+
+iconv-lite@^0.6.2:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01"
+  integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3.0.0"
+
+indexes-of@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
+  integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
+
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+ini@~1.3.0:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
+  integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
+
+ip-regex@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.1.0.tgz#5ad62f685a14edb421abebc2fff8db94df67b455"
+  integrity sha512-pKnZpbgCTfH/1NLIlOduP/V+WRXzC2MOz3Qo8xmxk8C5GudJLgK5QyLVXOSWy3ParAH7Eemurl3xjv/WXYFvMA==
+
+is-buffer@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623"
+  integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==
+
+is-extglob@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+  integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
+
+is-glob@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
+  integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
+  dependencies:
+    is-extglob "^2.1.1"
+
+is-interactive@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
+  integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
+
+is-obj@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+  integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
+
+is-promise@^2.1:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
+  integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
+
+is-regexp@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+  integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
+
+is-relative-path@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-relative-path/-/is-relative-path-1.0.2.tgz#091b46a0d67c1ed0fe85f1f8cfdde006bb251d46"
+  integrity sha1-CRtGoNZ8HtD+hfH4z93gBrslHUY=
+
+is-stream@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+  integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
+
+is-typedarray@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+  integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+
+is-url@^1.2.4:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
+  integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
+
+isarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+  integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+
+isomorphic-fetch@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
+  integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
+  dependencies:
+    node-fetch "^1.0.1"
+    whatwg-fetch ">=0.10.0"
+
+js-sha3@^0.8.0:
+  version "0.8.0"
+  resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
+  integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
+
+json-schema-traverse@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+  integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+levn@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+  integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
+  dependencies:
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+
+lodash@^4.17.15:
+  version "4.17.19"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
+  integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
+
+log-symbols@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4"
+  integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==
+  dependencies:
+    chalk "^2.4.2"
+
+lru-queue@0.1:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3"
+  integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=
+  dependencies:
+    es5-ext "~0.10.2"
+
+madge@^3.9.2:
+  version "3.9.2"
+  resolved "https://registry.yarnpkg.com/madge/-/madge-3.9.2.tgz#a432de2c858092d379c2910a21a622ad2b1b24c7"
+  integrity sha512-6ZvyKinAOOzcRpvpm1iyOuds+LvWIq3o3GmUYAHMJdIpDAgVY3mphxVzeWNo3agIOv0X0T/zbLycXQm9Rn19nA==
+  dependencies:
+    chalk "^4.1.0"
+    commander "^5.1.0"
+    commondir "^1.0.1"
+    debug "^4.0.1"
+    dependency-tree "^7.2.1"
+    detective-amd "^3.0.0"
+    detective-cjs "^3.1.1"
+    detective-es6 "^2.1.0"
+    detective-less "^1.0.2"
+    detective-postcss "^3.0.1"
+    detective-sass "^3.0.1"
+    detective-scss "^2.0.1"
+    detective-stylus "^1.0.0"
+    detective-typescript "^5.8.0"
+    graphviz "0.0.9"
+    ora "^4.0.4"
+    pify "^5.0.0"
+    pluralize "^8.0.0"
+    precinct "^6.3.1"
+    pretty-ms "^7.0.0"
+    rc "^1.2.7"
+    typescript "^3.9.5"
+    walkdir "^0.4.1"
+
+make-dir@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+  integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+  dependencies:
+    pify "^4.0.1"
+    semver "^5.6.0"
+
+md5.js@^1.3.4:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
+  integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
+  dependencies:
+    hash-base "^3.0.0"
+    inherits "^2.0.1"
+    safe-buffer "^5.1.2"
+
+memoizee@^0.4.14:
+  version "0.4.14"
+  resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57"
+  integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==
+  dependencies:
+    d "1"
+    es5-ext "^0.10.45"
+    es6-weak-map "^2.0.2"
+    event-emitter "^0.3.5"
+    is-promise "^2.1"
+    lru-queue "0.1"
+    next-tick "1"
+    timers-ext "^0.1.5"
+
+memory-fs@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c"
+  integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==
+  dependencies:
+    errno "^0.1.3"
+    readable-stream "^2.0.1"
+
+mimic-fn@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+  integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+  integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+  integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
+
+minimatch@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+  integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+  dependencies:
+    brace-expansion "^1.1.7"
+
+minimist@^1.2.0, minimist@^1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+  integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+
+module-definition@^3.0.0, module-definition@^3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/module-definition/-/module-definition-3.3.0.tgz#aae06d68c99c5f93841e59b8a4469b974956d4d4"
+  integrity sha512-HTplA9xwDzH67XJFC1YvZMUElWJD28DV0dUq7lhTs+JKJamUOWA/CcYWSlhW5amJO66uWtY7XdltT+LfX0wIVg==
+  dependencies:
+    ast-module-types "^2.6.0"
+    node-source-walk "^4.0.0"
+
+module-lookup-amd@^6.1.0:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/module-lookup-amd/-/module-lookup-amd-6.2.0.tgz#70600008b3f26630fde9ef9ae6165ac69de6ecbb"
+  integrity sha512-uxHCj5Pw9psZiC1znjU2qPsubt6haCSsN9m7xmIdoTciEgfxUkE1vhtDvjHPuOXEZrVJhjKgkmkP+w73rRuelQ==
+  dependencies:
+    commander "^2.8.1"
+    debug "^4.1.0"
+    file-exists-dazinatorfork "^1.0.2"
+    find "^0.3.0"
+    requirejs "^2.3.5"
+    requirejs-config-file "^3.1.1"
+
+moment@^2.24.0:
+  version "2.27.0"
+  resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d"
+  integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==
+
+ms@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+  integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+ms@^2.1.1:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+  integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+mute-stream@0.0.8:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
+  integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
+
+nan@^2.14.0:
+  version "2.14.1"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
+  integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
+
+next-tick@1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
+  integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
+
+next-tick@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
+  integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
+
+node-fetch@^1.0.1:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
+  integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
+  dependencies:
+    encoding "^0.1.11"
+    is-stream "^1.0.1"
+
+node-source-walk@^4.0.0, node-source-walk@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-4.2.0.tgz#c2efe731ea8ba9c03c562aa0a9d984e54f27bc2c"
+  integrity sha512-hPs/QMe6zS94f5+jG3kk9E7TNm4P2SulrKiLWMzKszBfNZvL/V6wseHlTd7IvfW0NZWqPtK3+9yYNr+3USGteA==
+  dependencies:
+    "@babel/parser" "^7.0.0"
+
+once@^1.3.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+  integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+  dependencies:
+    wrappy "1"
+
+onetime@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5"
+  integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==
+  dependencies:
+    mimic-fn "^2.1.0"
+
+optionator@^0.8.1:
+  version "0.8.3"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
+  integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+  dependencies:
+    deep-is "~0.1.3"
+    fast-levenshtein "~2.0.6"
+    levn "~0.3.0"
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+    word-wrap "~1.2.3"
+
+ora@^4.0.4:
+  version "4.0.5"
+  resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.5.tgz#7410b5cc2d99fa637fd5099bbb9f02bfbb5a361e"
+  integrity sha512-jCDgm9DqvRcNIAEv2wZPrh7E5PcQiDUnbnWbAfu4NGAE2ZNqPFbDixmWldy1YG2QfLeQhuiu6/h5VRrk6cG50w==
+  dependencies:
+    chalk "^3.0.0"
+    cli-cursor "^3.1.0"
+    cli-spinners "^2.2.0"
+    is-interactive "^1.0.0"
+    log-symbols "^3.0.0"
+    mute-stream "0.0.8"
+    strip-ansi "^6.0.0"
+    wcwidth "^1.0.1"
+
+parse-ms@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d"
+  integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==
+
+path-is-absolute@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+  integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
+path-parse@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+  integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+
+pbkdf2@^3.0.9, 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"
+
+pify@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+  integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+pify@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
+  integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
+
+pluralize@^8.0.0:
+  version "8.0.0"
+  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
+  integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
+
+postcss-values-parser@^1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz#5d9fa63e2bcb0179ce48f3235303765eb89f3047"
+  integrity sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ==
+  dependencies:
+    flatten "^1.0.2"
+    indexes-of "^1.0.1"
+    uniq "^1.0.1"
+
+postcss@^7.0.2:
+  version "7.0.32"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"
+  integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==
+  dependencies:
+    chalk "^2.4.2"
+    source-map "^0.6.1"
+    supports-color "^6.1.0"
+
+precinct@^6.2.0, precinct@^6.3.1:
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/precinct/-/precinct-6.3.1.tgz#8ad735a8afdfc48b56ed39c9ad3bf999b6b928dc"
+  integrity sha512-JAwyLCgTylWminoD7V0VJwMElWmwrVSR6r9HaPWCoswkB4iFzX7aNtO7VBfAVPy+NhmjKb8IF8UmlWJXzUkOIQ==
+  dependencies:
+    commander "^2.20.3"
+    debug "^4.1.1"
+    detective-amd "^3.0.0"
+    detective-cjs "^3.1.1"
+    detective-es6 "^2.1.0"
+    detective-less "^1.0.2"
+    detective-postcss "^3.0.1"
+    detective-sass "^3.0.1"
+    detective-scss "^2.0.1"
+    detective-stylus "^1.0.0"
+    detective-typescript "^5.8.0"
+    module-definition "^3.3.0"
+    node-source-walk "^4.2.0"
+
+prelude-ls@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+  integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
+
+pretty-ms@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-7.0.0.tgz#45781273110caf35f55cab21a8a9bd403a233dc0"
+  integrity sha512-J3aPWiC5e9ZeZFuSeBraGxSkGMOvulSWsxDByOcbD1Pr75YL3LSNIKIb52WXbCLE1sS5s4inBBbryjF4Y05Ceg==
+  dependencies:
+    parse-ms "^2.1.0"
+
+process-nextick-args@~2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+  integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
+prr@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+  integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
+
+punycode@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+  integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+
+randombytes@^2.0.1:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+  integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+  dependencies:
+    safe-buffer "^5.1.0"
+
+rc@^1.2.7:
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+  integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
+  dependencies:
+    deep-extend "^0.6.0"
+    ini "~1.3.0"
+    minimist "^1.2.0"
+    strip-json-comments "~2.0.1"
+
+readable-stream@^2.0.1:
+  version "2.3.7"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
+  integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.1.1"
+    util-deprecate "~1.0.1"
+
+readable-stream@^3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
+  integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
+  dependencies:
+    inherits "^2.0.3"
+    string_decoder "^1.1.1"
+    util-deprecate "^1.0.1"
+
+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==
+
+replace-ext@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
+  integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
+
+requirejs-config-file@^3.1.1:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/requirejs-config-file/-/requirejs-config-file-3.1.2.tgz#de8c0b3eebdf243511c994a8a24b006f8b825997"
+  integrity sha512-sdLWywcDuNz7EIOhenSbRfT4YF84nItDv90coN2htbokjmU2QeyQuSBZILQUKNksepl8UPVU+hgYySFaDxbJPQ==
+  dependencies:
+    esprima "^4.0.0"
+    make-dir "^2.1.0"
+    stringify-object "^3.2.1"
+
+requirejs@^2.3.5:
+  version "2.3.6"
+  resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
+  integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
+
+resolve-dependency-path@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-dependency-path/-/resolve-dependency-path-2.0.0.tgz#11700e340717b865d216c66cabeb4a2a3c696736"
+  integrity sha512-DIgu+0Dv+6v2XwRaNWnumKu7GPufBBOr5I1gRPJHkvghrfCGOooJODFvgFimX/KRxk9j0whD2MnKHzM1jYvk9w==
+
+resolve@^1.11.1:
+  version "1.17.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
+  integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
+  dependencies:
+    path-parse "^1.0.6"
+
+restore-cursor@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
+  integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
+  dependencies:
+    onetime "^5.1.0"
+    signal-exit "^3.0.2"
+
+ripemd160@^2.0.0, ripemd160@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
+  integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
+  dependencies:
+    hash-base "^3.0.0"
+    inherits "^2.0.1"
+
+rxjs@^6.6.0:
+  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.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+  integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+  integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+"safer-buffer@>= 2.1.2 < 3.0.0":
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+sass-lookup@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-3.0.0.tgz#3b395fa40569738ce857bc258e04df2617c48cac"
+  integrity sha512-TTsus8CfFRn1N44bvdEai1no6PqdmDiQUiqW5DlpmtT+tYnIt1tXtDIph5KA1efC+LmioJXSnCtUVpcK9gaKIg==
+  dependencies:
+    commander "^2.16.0"
+
+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==
+
+semver@^5.6.0:
+  version "5.7.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+  integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+semver@^7.3.2:
+  version "7.3.2"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
+  integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
+
+sha.js@^2.4.0, sha.js@^2.4.8:
+  version "2.4.11"
+  resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
+  integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+signal-exit@^3.0.2:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
+  integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
+
+source-map@^0.6.1, source-map@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+string_decoder@^1.1.1:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+  integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+  dependencies:
+    safe-buffer "~5.2.0"
+
+string_decoder@~1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+  integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+  dependencies:
+    safe-buffer "~5.1.0"
+
+stringify-object@^3.2.1:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629"
+  integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==
+  dependencies:
+    get-own-enumerable-property-symbols "^3.0.0"
+    is-obj "^1.0.1"
+    is-regexp "^1.0.0"
+
+strip-ansi@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
+  integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
+  dependencies:
+    ansi-regex "^5.0.0"
+
+strip-json-comments@~2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+  integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
+
+stylus-lookup@^3.0.1:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd"
+  integrity sha512-oEQGHSjg/AMaWlKe7gqsnYzan8DLcGIHe0dUaFkucZZ14z4zjENRlQMCHT4FNsiWnJf17YN9OvrCfCoi7VvOyg==
+  dependencies:
+    commander "^2.8.1"
+    debug "^4.1.0"
+
+supports-color@^5.3.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+  integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+  dependencies:
+    has-flag "^3.0.0"
+
+supports-color@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
+  integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+  dependencies:
+    has-flag "^3.0.0"
+
+supports-color@^7.1.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
+  integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
+  dependencies:
+    has-flag "^4.0.0"
+
+tapable@^1.0.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
+  integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
+
+temp@~0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/temp/-/temp-0.4.0.tgz#671ad63d57be0fe9d7294664b3fc400636678a60"
+  integrity sha1-ZxrWPVe+D+nXKUZks/xABjZnimA=
+
+timers-ext@^0.1.5:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6"
+  integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==
+  dependencies:
+    es5-ext "~0.10.46"
+    next-tick "1"
+
+traverse-chain@~0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1"
+  integrity sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=
+
+tslib@^1.8.1, tslib@^1.9.0:
+  version "1.13.0"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
+  integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
+
+tsutils@^3.17.1:
+  version "3.17.1"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
+  integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==
+  dependencies:
+    tslib "^1.8.1"
+
+tweetnacl@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
+  integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
+
+type-check@~0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+  integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
+  dependencies:
+    prelude-ls "~1.1.2"
+
+type@^1.0.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
+  integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
+
+type@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3"
+  integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==
+
+typedarray-to-buffer@^3.1.5:
+  version "3.1.5"
+  resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
+  integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
+  dependencies:
+    is-typedarray "^1.0.0"
+
+typescript@^3.0.3, typescript@^3.7.2, typescript@^3.7.5, typescript@^3.8.3, typescript@^3.9.5:
+  version "3.9.7"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
+  integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
+
+uniq@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
+  integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=
+
+unist-util-stringify-position@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da"
+  integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==
+  dependencies:
+    "@types/unist" "^2.0.2"
+
+uri-js@^4.2.2:
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
+  integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
+  dependencies:
+    punycode "^2.1.0"
+
+util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+  integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+
+vfile-message@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a"
+  integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==
+  dependencies:
+    "@types/unist" "^2.0.0"
+    unist-util-stringify-position "^2.0.0"
+
+vfile@*:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.0.tgz#26c78ac92eb70816b01d4565e003b7e65a2a0e01"
+  integrity sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw==
+  dependencies:
+    "@types/unist" "^2.0.0"
+    is-buffer "^2.0.0"
+    replace-ext "1.0.0"
+    unist-util-stringify-position "^2.0.0"
+    vfile-message "^2.0.0"
+
+walkdir@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39"
+  integrity sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==
+
+wcwidth@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
+  integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
+  dependencies:
+    defaults "^1.0.3"
+
+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"
+
+whatwg-fetch@>=0.10.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.2.0.tgz#8e134f701f0a4ab5fda82626f113e2b647fd16dc"
+  integrity sha512-SdGPoQMMnzVYThUbSrEvqTlkvC1Ux27NehaJ/GUHBfNrh5Mjg+1/uRyFMwVnxO2MrikMWvWAqUGgQOfVU4hT7w==
+
+word-wrap@~1.2.3:
+  version "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==
+
+wrappy@1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+  integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
+xxhashjs@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/xxhashjs/-/xxhashjs-0.2.2.tgz#8a6251567621a1c46a5ae204da0249c7f8caa9d8"
+  integrity sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==
+  dependencies:
+    cuint "^0.2.2"
+
+yaeti@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577"
+  integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=

文件差異過大導致無法顯示
+ 8579 - 228
yarn.lock


部分文件因文件數量過多而無法顯示