Types.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. import BN from 'bn.js'
  2. import { ElectionStage, Seat } from '@joystream/types/council'
  3. import { Option, Text } from '@polkadot/types'
  4. import { Constructor, Codec } from '@polkadot/types/types'
  5. import { Struct, Vec } from '@polkadot/types/codec'
  6. import { u32 } from '@polkadot/types/primitive'
  7. import { BlockNumber, Balance, AccountId } from '@polkadot/types/interfaces'
  8. import { DeriveBalancesAll } from '@polkadot/api-derive/types'
  9. import { KeyringPair } from '@polkadot/keyring/types'
  10. import { WorkerId, OpeningType } from '@joystream/types/working-group'
  11. import { Membership, MemberId } from '@joystream/types/members'
  12. import {
  13. GenericJoyStreamRoleSchema,
  14. JobSpecifics,
  15. ApplicationDetails,
  16. QuestionSections,
  17. QuestionSection,
  18. QuestionsFields,
  19. QuestionField,
  20. EntryInMembershipModuke,
  21. HiringProcess,
  22. AdditionalRolehiringProcessDetails,
  23. CreatorDetails,
  24. } from '@joystream/types/hiring/schemas/role.schema.typings'
  25. import ajv from 'ajv'
  26. import { Opening, StakingPolicy, ApplicationStageKeys } from '@joystream/types/hiring'
  27. import { Validator } from 'inquirer'
  28. import { JoyStructCustom } from '@joystream/types/common'
  29. // KeyringPair type extended with mandatory "meta.name"
  30. // It's used for accounts/keys management within CLI.
  31. // If not provided in the account json file, the meta.name value is set to "Unnamed Account"
  32. export type NamedKeyringPair = KeyringPair & {
  33. meta: {
  34. name: string
  35. }
  36. }
  37. // Summary of the account information fetched from the api for "account:current" purposes (currently just balances)
  38. export type AccountSummary = {
  39. balances: DeriveBalancesAll
  40. }
  41. // This function allows us to easily transform the tuple into the object
  42. // and simplifies the creation of consitent Object and Tuple types (seen below).
  43. export function createCouncilInfoObj(
  44. activeCouncil: Seat[],
  45. termEndsAt: BlockNumber,
  46. autoStart: boolean,
  47. newTermDuration: BN,
  48. candidacyLimit: BN,
  49. councilSize: BN,
  50. minCouncilStake: Balance,
  51. minVotingStake: Balance,
  52. announcingPeriod: BlockNumber,
  53. votingPeriod: BlockNumber,
  54. revealingPeriod: BlockNumber,
  55. round: BN,
  56. stage: Option<ElectionStage>
  57. ) {
  58. return {
  59. activeCouncil,
  60. termEndsAt,
  61. autoStart,
  62. newTermDuration,
  63. candidacyLimit,
  64. councilSize,
  65. minCouncilStake,
  66. minVotingStake,
  67. announcingPeriod,
  68. votingPeriod,
  69. revealingPeriod,
  70. round,
  71. stage,
  72. }
  73. }
  74. // Object/Tuple containing council/councilElection information (council:info).
  75. // The tuple is useful, because that's how api.queryMulti returns the results.
  76. export type CouncilInfoTuple = Parameters<typeof createCouncilInfoObj>
  77. export type CouncilInfoObj = ReturnType<typeof createCouncilInfoObj>
  78. // Object with "name" and "value" properties, used for rendering simple CLI tables like:
  79. // Total balance: 100 JOY
  80. // Free calance: 50 JOY
  81. export type NameValueObj = { name: string; value: string }
  82. // Working groups related types
  83. export enum WorkingGroups {
  84. StorageProviders = 'storageProviders',
  85. }
  86. // In contrast to Pioneer, currently only StorageProviders group is available in CLI
  87. export const AvailableGroups: readonly WorkingGroups[] = [WorkingGroups.StorageProviders] as const
  88. export type Reward = {
  89. totalRecieved: Balance
  90. value: Balance
  91. interval?: number
  92. nextPaymentBlock: number // 0 = no incoming payment
  93. }
  94. // Compound working group types
  95. export type GroupMember = {
  96. workerId: WorkerId
  97. memberId: MemberId
  98. roleAccount: AccountId
  99. profile: Membership
  100. stake?: Balance
  101. reward?: Reward
  102. }
  103. export type GroupApplication = {
  104. wgApplicationId: number
  105. applicationId: number
  106. wgOpeningId: number
  107. member: Membership | null
  108. roleAccout: AccountId
  109. stakes: {
  110. application: number
  111. role: number
  112. }
  113. humanReadableText: string
  114. stage: ApplicationStageKeys
  115. }
  116. export enum OpeningStatus {
  117. WaitingToBegin = 'WaitingToBegin',
  118. AcceptingApplications = 'AcceptingApplications',
  119. InReview = 'InReview',
  120. Complete = 'Complete',
  121. Cancelled = 'Cancelled',
  122. Unknown = 'Unknown',
  123. }
  124. export type GroupOpeningStage = {
  125. status: OpeningStatus
  126. block?: number
  127. date?: Date
  128. }
  129. export type GroupOpeningStakes = {
  130. application?: StakingPolicy
  131. role?: StakingPolicy
  132. }
  133. export const stakingPolicyUnstakingPeriodKeys = [
  134. 'crowded_out_unstaking_period_length',
  135. 'review_period_expired_unstaking_period_length',
  136. ] as const
  137. export type StakingPolicyUnstakingPeriodKey = typeof stakingPolicyUnstakingPeriodKeys[number]
  138. export const openingPolicyUnstakingPeriodsKeys = [
  139. 'fill_opening_failed_applicant_application_stake_unstaking_period',
  140. 'fill_opening_failed_applicant_role_stake_unstaking_period',
  141. 'fill_opening_successful_applicant_application_stake_unstaking_period',
  142. 'terminate_application_stake_unstaking_period',
  143. 'terminate_role_stake_unstaking_period',
  144. 'exit_role_application_stake_unstaking_period',
  145. 'exit_role_stake_unstaking_period',
  146. ] as const
  147. export type OpeningPolicyUnstakingPeriodsKey = typeof openingPolicyUnstakingPeriodsKeys[number]
  148. export type UnstakingPeriodsKey =
  149. | OpeningPolicyUnstakingPeriodsKey
  150. | 'crowded_out_application_stake_unstaking_period_length'
  151. | 'crowded_out_role_stake_unstaking_period_length'
  152. | 'review_period_expired_application_stake_unstaking_period_length'
  153. | 'review_period_expired_role_stake_unstaking_period_length'
  154. export type UnstakingPeriods = {
  155. [k in UnstakingPeriodsKey]: number
  156. }
  157. export type GroupOpening = {
  158. wgOpeningId: number
  159. openingId: number
  160. stage: GroupOpeningStage
  161. opening: Opening
  162. stakes: GroupOpeningStakes
  163. applications: GroupApplication[]
  164. type: OpeningType
  165. unstakingPeriods: UnstakingPeriods
  166. }
  167. // Some helper structs for generating human_readable_text in working group opening extrinsic
  168. // Note those types are not part of the runtime etc., we just use them to simplify prompting for values
  169. // (since there exists functionality that handles that for substrate types like: Struct, Vec etc.)
  170. interface WithJSONable<T> {
  171. toJSONObj: () => T
  172. }
  173. export class HRTJobSpecificsStruct
  174. extends JoyStructCustom({
  175. title: Text,
  176. description: Text,
  177. })
  178. implements WithJSONable<JobSpecifics> {
  179. get title(): string {
  180. return this.getField('title').toString()
  181. }
  182. get description(): string {
  183. return this.getField('description').toString()
  184. }
  185. toJSONObj(): JobSpecifics {
  186. const { title, description } = this
  187. return { title, description }
  188. }
  189. }
  190. export class HRTEntryInMembershipModukeStruct
  191. extends JoyStructCustom({
  192. handle: Text,
  193. })
  194. implements WithJSONable<EntryInMembershipModuke> {
  195. get handle(): string {
  196. return this.getField('handle').toString()
  197. }
  198. toJSONObj(): EntryInMembershipModuke {
  199. const { handle } = this
  200. return { handle }
  201. }
  202. }
  203. export class HRTCreatorDetailsStruct
  204. extends JoyStructCustom({
  205. membership: HRTEntryInMembershipModukeStruct,
  206. })
  207. implements WithJSONable<CreatorDetails> {
  208. get membership(): EntryInMembershipModuke {
  209. return this.getField('membership').toJSONObj()
  210. }
  211. toJSONObj(): CreatorDetails {
  212. const { membership } = this
  213. return { membership }
  214. }
  215. }
  216. export class HRTHiringProcessStruct
  217. extends JoyStructCustom({
  218. details: Vec.with(Text),
  219. })
  220. implements WithJSONable<HiringProcess> {
  221. get details(): AdditionalRolehiringProcessDetails {
  222. return this.getField('details')
  223. .toArray()
  224. .map((v) => v.toString())
  225. }
  226. toJSONObj(): HiringProcess {
  227. const { details } = this
  228. return { details }
  229. }
  230. }
  231. export class HRTQuestionFieldStruct
  232. extends JoyStructCustom({
  233. title: Text,
  234. type: Text,
  235. })
  236. implements WithJSONable<QuestionField> {
  237. get title(): string {
  238. return this.getField('title').toString()
  239. }
  240. get type(): string {
  241. return this.getField('type').toString()
  242. }
  243. toJSONObj(): QuestionField {
  244. const { title, type } = this
  245. return { title, type }
  246. }
  247. }
  248. class HRTQuestionsFieldsVec extends Vec.with(HRTQuestionFieldStruct) implements WithJSONable<QuestionsFields> {
  249. toJSONObj(): QuestionsFields {
  250. return this.toArray().map((v) => v.toJSONObj())
  251. }
  252. }
  253. export class HRTQuestionSectionStruct
  254. extends JoyStructCustom({
  255. title: Text,
  256. questions: HRTQuestionsFieldsVec,
  257. })
  258. implements WithJSONable<QuestionSection> {
  259. get title(): string {
  260. return this.getField('title').toString()
  261. }
  262. get questions(): QuestionsFields {
  263. return this.getField('questions').toJSONObj()
  264. }
  265. toJSONObj(): QuestionSection {
  266. const { title, questions } = this
  267. return { title, questions }
  268. }
  269. }
  270. export class HRTQuestionSectionsVec extends Vec.with(HRTQuestionSectionStruct)
  271. implements WithJSONable<QuestionSections> {
  272. toJSONObj(): QuestionSections {
  273. return this.toArray().map((v) => v.toJSONObj())
  274. }
  275. }
  276. export class HRTApplicationDetailsStruct
  277. extends JoyStructCustom({
  278. sections: HRTQuestionSectionsVec,
  279. })
  280. implements WithJSONable<ApplicationDetails> {
  281. get sections(): QuestionSections {
  282. return this.getField('sections').toJSONObj()
  283. }
  284. toJSONObj(): ApplicationDetails {
  285. const { sections } = this
  286. return { sections }
  287. }
  288. }
  289. export class HRTStruct
  290. extends JoyStructCustom({
  291. version: u32,
  292. headline: Text,
  293. job: HRTJobSpecificsStruct,
  294. application: HRTApplicationDetailsStruct,
  295. reward: Text,
  296. creator: HRTCreatorDetailsStruct,
  297. process: HRTHiringProcessStruct,
  298. })
  299. implements WithJSONable<GenericJoyStreamRoleSchema> {
  300. get version(): number {
  301. return this.getField('version').toNumber()
  302. }
  303. get headline(): string {
  304. return this.getField('headline').toString()
  305. }
  306. get job(): JobSpecifics {
  307. return this.getField('job').toJSONObj()
  308. }
  309. get application(): ApplicationDetails {
  310. return this.getField('application').toJSONObj()
  311. }
  312. get reward(): string {
  313. return this.getField('reward').toString()
  314. }
  315. get creator(): CreatorDetails {
  316. return this.getField('creator').toJSONObj()
  317. }
  318. get process(): HiringProcess {
  319. return this.getField('process').toJSONObj()
  320. }
  321. toJSONObj(): GenericJoyStreamRoleSchema {
  322. const { version, headline, job, application, reward, creator, process } = this
  323. return { version, headline, job, application, reward, creator, process }
  324. }
  325. }
  326. // Api-related
  327. // Additional options that can be passed to ApiCommandBase.promptForParam in order to override
  328. // its default behaviour, change param name, add validation etc.
  329. export type ApiParamOptions<ParamType = Codec> = {
  330. forcedName?: string
  331. value?: {
  332. default: ParamType
  333. locked?: boolean
  334. }
  335. jsonSchema?: {
  336. struct: Constructor<Struct>
  337. schemaValidator: ajv.ValidateFunction
  338. }
  339. validator?: Validator
  340. nestedOptions?: ApiParamsOptions // For more complex params, like structs
  341. }
  342. export type ApiParamsOptions = {
  343. [paramName: string]: ApiParamOptions
  344. }
  345. export type ApiMethodArg = Codec
  346. export type ApiMethodNamedArg = {
  347. name: string
  348. value: ApiMethodArg
  349. }
  350. export type ApiMethodNamedArgs = ApiMethodNamedArg[]