index.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. import { Null, u128, u64, u32, Option, Text, BTreeSet } from '@polkadot/types'
  2. import { BlockNumber, Balance } from '@polkadot/types/interfaces'
  3. import { JoyBTreeSet, JoyEnum, JoyStructDecorated } from '../common'
  4. import { StakeId } from '../stake'
  5. import { GenericJoyStreamRoleSchema } from './schemas/role.schema.typings'
  6. import Ajv from 'ajv'
  7. import * as role_schema_json from './schemas/role.schema.json'
  8. import { RegistryTypes } from '@polkadot/types/types'
  9. export class ApplicationId extends u64 {}
  10. export class OpeningId extends u64 {}
  11. export class CurrentBlock extends Null {}
  12. export class ExactBlock extends u32 {} // BlockNumber
  13. export const ActivateOpeningAtDef = {
  14. CurrentBlock,
  15. ExactBlock,
  16. } as const
  17. export const ActivateOpeningAtKeys: { [k in keyof typeof ActivateOpeningAtDef]: k } = {
  18. CurrentBlock: 'CurrentBlock',
  19. ExactBlock: 'ExactBlock',
  20. } as const
  21. export type ActivateOpeningAtKey = keyof typeof ActivateOpeningAtDef
  22. export class ActivateOpeningAt extends JoyEnum(ActivateOpeningAtDef) {}
  23. // FIXME: Replace usages with isOfType, asType wherever possible
  24. export enum ApplicationDeactivationCauseKeys {
  25. External = 'External',
  26. Hired = 'Hired',
  27. NotHired = 'NotHired',
  28. CrowdedOut = 'CrowdedOut',
  29. OpeningCancelled = 'OpeningCancelled',
  30. ReviewPeriodExpired = 'ReviewPeriodExpired',
  31. OpeningFilled = 'OpeningFilled',
  32. }
  33. const ApplicationDeactivationCauseDef = {
  34. External: Null,
  35. Hired: Null,
  36. NotHired: Null,
  37. CrowdedOut: Null,
  38. OpeningCancelled: Null,
  39. ReviewPeriodExpired: Null,
  40. OpeningFilled: Null,
  41. } as const
  42. export class ApplicationDeactivationCause extends JoyEnum(ApplicationDeactivationCauseDef) {}
  43. export type UnstakingApplicationStageType = {
  44. deactivation_initiated: BlockNumber
  45. cause: ApplicationDeactivationCause
  46. }
  47. export class UnstakingApplicationStage
  48. extends JoyStructDecorated({
  49. deactivation_initiated: u32, // BlockNumber
  50. cause: ApplicationDeactivationCause,
  51. })
  52. implements UnstakingApplicationStageType {}
  53. export type InactiveApplicationStageType = {
  54. deactivation_initiated: BlockNumber
  55. deactivated: BlockNumber
  56. cause: ApplicationDeactivationCause
  57. }
  58. export class InactiveApplicationStage
  59. extends JoyStructDecorated({
  60. deactivation_initiated: u32, // BlockNumber
  61. deactivated: u32,
  62. cause: ApplicationDeactivationCause,
  63. })
  64. implements InactiveApplicationStageType {}
  65. export class ActiveApplicationStage extends Null {}
  66. // FIXME: Replace usages with isOfType, asType wherever possible
  67. export enum ApplicationStageKeys {
  68. Active = 'Active',
  69. Unstaking = 'Unstaking',
  70. Inactive = 'Inactive',
  71. }
  72. export const ApplicationStageDef = {
  73. Active: ActiveApplicationStage,
  74. Unstaking: UnstakingApplicationStage,
  75. Inactive: InactiveApplicationStage,
  76. } as const
  77. export class ApplicationStage extends JoyEnum(ApplicationStageDef) {}
  78. export type IApplicationRationingPolicy = {
  79. max_active_applicants: u32
  80. }
  81. export class ApplicationRationingPolicy
  82. extends JoyStructDecorated({
  83. max_active_applicants: u32,
  84. })
  85. implements IApplicationRationingPolicy {}
  86. export type WaitingToBeingOpeningStageVariantType = {
  87. begins_at_block: BlockNumber
  88. }
  89. export class WaitingToBeingOpeningStageVariant
  90. extends JoyStructDecorated({
  91. begins_at_block: u32,
  92. })
  93. implements WaitingToBeingOpeningStageVariantType {}
  94. // FIXME: Replace usages with isOfType, asType wherever possible
  95. export enum OpeningDeactivationCauseKeys {
  96. CancelledBeforeActivation = 'CancelledBeforeActivation',
  97. CancelledAcceptingApplications = 'CancelledAcceptingApplications',
  98. CancelledInReviewPeriod = 'CancelledInReviewPeriod',
  99. ReviewPeriodExpired = 'ReviewPeriodExpired',
  100. Filled = 'Filled',
  101. }
  102. const OpeningDeactivationCauseDef = {
  103. CancelledBeforeActivation: Null,
  104. CancelledAcceptingApplications: Null,
  105. CancelledInReviewPeriod: Null,
  106. ReviewPeriodExpired: Null,
  107. Filled: Null,
  108. } as const
  109. export class OpeningDeactivationCause extends JoyEnum(OpeningDeactivationCauseDef) {}
  110. export type IAcceptingApplications = {
  111. started_accepting_applicants_at_block: BlockNumber
  112. }
  113. export class AcceptingApplications
  114. extends JoyStructDecorated({
  115. started_accepting_applicants_at_block: u32,
  116. })
  117. implements IAcceptingApplications {}
  118. export type IReviewPeriod = {
  119. started_accepting_applicants_at_block: BlockNumber
  120. started_review_period_at_block: BlockNumber
  121. }
  122. export class ReviewPeriod
  123. extends JoyStructDecorated({
  124. started_accepting_applicants_at_block: u32,
  125. started_review_period_at_block: u32,
  126. })
  127. implements IReviewPeriod {}
  128. export type IDeactivated = {
  129. cause: OpeningDeactivationCause
  130. deactivated_at_block: BlockNumber
  131. started_accepting_applicants_at_block: BlockNumber
  132. started_review_period_at_block: Option<BlockNumber>
  133. }
  134. export class Deactivated
  135. extends JoyStructDecorated({
  136. cause: OpeningDeactivationCause,
  137. deactivated_at_block: u32,
  138. started_accepting_applicants_at_block: u32,
  139. started_review_period_at_block: Option.with(u32),
  140. })
  141. implements IDeactivated {}
  142. export const ActiveOpeningStageDef = {
  143. AcceptingApplications: AcceptingApplications,
  144. ReviewPeriod: ReviewPeriod,
  145. Deactivated: Deactivated,
  146. } as const
  147. export type ActiveOpeningStageKey = keyof typeof ActiveOpeningStageDef
  148. export class ActiveOpeningStage extends JoyEnum(ActiveOpeningStageDef) {}
  149. export type ActiveOpeningStageVariantType = {
  150. stage: ActiveOpeningStage
  151. applications_added: BTreeSet<ApplicationId>
  152. active_application_count: u32
  153. unstaking_application_count: u32
  154. deactivated_application_count: u32
  155. }
  156. export class ActiveOpeningStageVariant extends JoyStructDecorated({
  157. stage: ActiveOpeningStage,
  158. applications_added: JoyBTreeSet(ApplicationId),
  159. active_application_count: u32,
  160. unstaking_application_count: u32,
  161. deactivated_application_count: u32,
  162. }) {
  163. get is_active(): boolean {
  164. return this.stage.isOfType('AcceptingApplications')
  165. }
  166. }
  167. // FIXME: Replace usages with isOfType, asType wherever possible
  168. export enum OpeningStageKeys {
  169. WaitingToBegin = 'WaitingToBegin',
  170. Active = 'Active',
  171. }
  172. export const OpeningStageDef = {
  173. WaitingToBegin: WaitingToBeingOpeningStageVariant,
  174. Active: ActiveOpeningStageVariant,
  175. } as const
  176. export class OpeningStage extends JoyEnum(OpeningStageDef) {}
  177. // FIXME: Replace usages with isOfType, asType wherever possible
  178. export enum StakingAmountLimitModeKeys {
  179. AtLeast = 'AtLeast',
  180. Exact = 'Exact',
  181. }
  182. export const StakingAmountLimitModeDef = {
  183. AtLeast: Null,
  184. Exact: Null,
  185. } as const
  186. export class StakingAmountLimitMode extends JoyEnum(StakingAmountLimitModeDef) {}
  187. export type IStakingPolicy = {
  188. amount: Balance
  189. amount_mode: StakingAmountLimitMode
  190. crowded_out_unstaking_period_length: Option<BlockNumber>
  191. review_period_expired_unstaking_period_length: Option<BlockNumber>
  192. }
  193. export class StakingPolicy
  194. extends JoyStructDecorated({
  195. amount: u128,
  196. amount_mode: StakingAmountLimitMode,
  197. crowded_out_unstaking_period_length: Option.with(u32),
  198. review_period_expired_unstaking_period_length: Option.with(u32),
  199. })
  200. implements IStakingPolicy {}
  201. export const schemaValidator: Ajv.ValidateFunction = new Ajv({ allErrors: true }).compile(role_schema_json)
  202. const OpeningHRTFallback: GenericJoyStreamRoleSchema = {
  203. version: 1,
  204. headline: 'Unknown',
  205. job: {
  206. title: 'Unknown',
  207. description: 'Unknown',
  208. },
  209. application: {},
  210. reward: 'Unknown',
  211. creator: {
  212. membership: {
  213. handle: 'Unknown',
  214. },
  215. },
  216. }
  217. export type IOpening = {
  218. created: BlockNumber
  219. stage: OpeningStage
  220. max_review_period_length: BlockNumber
  221. application_rationing_policy: Option<ApplicationRationingPolicy>
  222. application_staking_policy: Option<StakingPolicy>
  223. role_staking_policy: Option<StakingPolicy>
  224. human_readable_text: Text // Vec<u8>,
  225. }
  226. export class Opening
  227. extends JoyStructDecorated({
  228. created: u32,
  229. stage: OpeningStage,
  230. max_review_period_length: u32,
  231. application_rationing_policy: Option.with(ApplicationRationingPolicy),
  232. application_staking_policy: Option.with(StakingPolicy),
  233. role_staking_policy: Option.with(StakingPolicy),
  234. human_readable_text: Text, // Vec.with(u8),
  235. })
  236. implements IOpening {
  237. parse_human_readable_text(): GenericJoyStreamRoleSchema | string | undefined {
  238. const hrt = this.human_readable_text
  239. if (!hrt) {
  240. return undefined
  241. }
  242. const str = hrt.toString()
  243. try {
  244. const obj = JSON.parse(str)
  245. if (schemaValidator(obj) === true) {
  246. return (obj as unknown) as GenericJoyStreamRoleSchema
  247. }
  248. console.log('parse_human_readable_text JSON schema validation failed:', schemaValidator.errors)
  249. } catch (e) {
  250. console.log('parse_human_readable_text JSON schema validation failed:', e.toString())
  251. }
  252. return str
  253. }
  254. parse_human_readable_text_with_fallback(): GenericJoyStreamRoleSchema {
  255. const hrt = this.parse_human_readable_text()
  256. if (typeof hrt !== 'object') {
  257. return OpeningHRTFallback
  258. }
  259. return hrt
  260. }
  261. get max_applicants(): number {
  262. const appPolicy = this.application_rationing_policy
  263. if (appPolicy.isNone) {
  264. return 0
  265. }
  266. return appPolicy.unwrap().max_active_applicants.toNumber()
  267. }
  268. get is_active(): boolean {
  269. switch (this.stage.type) {
  270. case OpeningStageKeys.WaitingToBegin:
  271. return true
  272. case OpeningStageKeys.Active:
  273. return (this.stage.value as ActiveOpeningStageVariant).is_active
  274. }
  275. return false
  276. }
  277. }
  278. export type IApplication = {
  279. opening_id: OpeningId
  280. application_index_in_opening: u32
  281. add_to_opening_in_block: BlockNumber
  282. active_role_staking_id: Option<StakeId>
  283. active_application_staking_id: Option<StakeId>
  284. stage: ApplicationStage
  285. human_readable_text: Text
  286. }
  287. export class Application
  288. extends JoyStructDecorated({
  289. opening_id: OpeningId,
  290. application_index_in_opening: u32,
  291. add_to_opening_in_block: u32,
  292. active_role_staking_id: Option.with(StakeId),
  293. active_application_staking_id: Option.with(StakeId),
  294. stage: ApplicationStage,
  295. human_readable_text: Text,
  296. })
  297. implements IApplication {}
  298. export const hiringTypes: RegistryTypes = {
  299. ApplicationId: 'u64',
  300. OpeningId: 'u64',
  301. Application,
  302. ApplicationStage,
  303. ActivateOpeningAt,
  304. ApplicationRationingPolicy,
  305. OpeningStage,
  306. StakingPolicy,
  307. Opening,
  308. // Expose in registry for api.createType purposes:
  309. WaitingToBeingOpeningStageVariant,
  310. ActiveOpeningStageVariant,
  311. ActiveOpeningStage,
  312. AcceptingApplications,
  313. ReviewPeriod,
  314. Deactivated,
  315. OpeningDeactivationCause,
  316. InactiveApplicationStage,
  317. UnstakingApplicationStage,
  318. ApplicationDeactivationCause,
  319. StakingAmountLimitMode,
  320. }
  321. export default hiringTypes