Forráskód Böngészése

Merge pull request #1071 from Lezek123/memberships-refactor-adjustments

Pioneer, types, CLI: Changes following membership module refactorization
Mokhtar Naamani 4 éve
szülő
commit
b92f94911d
64 módosított fájl, 329 hozzáadás és 514 törlés
  1. 8 10
      .github/workflows/joystream-cli.yml
  2. 3 3
      cli/README.md
  3. 1 1
      cli/package.json
  4. 7 6
      cli/src/Api.ts
  5. 3 3
      cli/src/Types.ts
  6. 3 3
      cli/src/commands/api/inspect.ts
  7. 1 1
      pioneer/packages/apps-routing/src/joy-members.ts
  8. 3 3
      pioneer/packages/joy-members/src/Dashboard.tsx
  9. 12 14
      pioneer/packages/joy-members/src/Details.tsx
  10. 3 3
      pioneer/packages/joy-members/src/DetailsByHandle.tsx
  11. 30 30
      pioneer/packages/joy-members/src/EditForm.tsx
  12. 9 9
      pioneer/packages/joy-members/src/MemberPreview.tsx
  13. 6 6
      pioneer/packages/joy-members/src/index.tsx
  14. 7 9
      pioneer/packages/joy-proposals/src/Proposal/Body.tsx
  15. 4 4
      pioneer/packages/joy-proposals/src/forms/AddWorkingGroupOpeningForm.tsx
  16. 4 4
      pioneer/packages/joy-proposals/src/forms/SetContentWorkingGroupLeadForm.tsx
  17. 0 1
      pioneer/packages/joy-proposals/src/stories/data/ProposalDetails.mock.ts
  18. 4 4
      pioneer/packages/joy-roles/src/elements.tsx
  19. 3 4
      pioneer/packages/joy-roles/src/mocks.ts
  20. 9 5
      pioneer/packages/joy-roles/src/tabs/Admin.controller.tsx
  21. 1 9
      pioneer/packages/joy-roles/src/transport.mock.ts
  22. 17 39
      pioneer/packages/joy-roles/src/transport.substrate.ts
  23. 0 3
      pioneer/packages/joy-roles/src/transport.ts
  24. 2 2
      pioneer/packages/joy-utils/src/MemberProfilePreview.tsx
  25. 2 2
      pioneer/packages/joy-utils/src/MembersDropdown.tsx
  26. 58 122
      pioneer/packages/joy-utils/src/MyAccount.tsx
  27. 5 5
      pioneer/packages/joy-utils/src/accounts.ts
  28. 12 10
      pioneer/packages/joy-utils/src/transport/contentWorkingGroup.ts
  29. 6 6
      pioneer/packages/joy-utils/src/transport/council.ts
  30. 0 3
      pioneer/packages/joy-utils/src/transport/index.ts
  31. 14 8
      pioneer/packages/joy-utils/src/transport/members.ts
  32. 4 4
      pioneer/packages/joy-utils/src/transport/proposals.ts
  33. 0 19
      pioneer/packages/joy-utils/src/transport/storageProviders.ts
  34. 2 2
      pioneer/packages/joy-utils/src/transport/workingGroups.ts
  35. 0 1
      pioneer/packages/joy-utils/src/types/members.ts
  36. 2 2
      pioneer/packages/joy-utils/src/types/proposals.ts
  37. 3 3
      pioneer/packages/joy-utils/src/types/workingGroups.ts
  38. 2 1
      tests/network-tests/package.json
  39. 1 1
      tests/network-tests/src/iznik/tests/council/electingCouncilTest.ts
  40. 1 1
      tests/network-tests/src/iznik/tests/fixtures/councilElectionModule.ts
  41. 4 4
      tests/network-tests/src/iznik/tests/fixtures/proposalsModule.ts
  42. 3 3
      tests/network-tests/src/iznik/tests/fixtures/workingGroupModule.ts
  43. 1 1
      tests/network-tests/src/iznik/tests/membership/membershipCreationTest.ts
  44. 1 1
      tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts
  45. 1 1
      tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts
  46. 1 1
      tests/network-tests/src/iznik/tests/proposals/manageLeaderRoleTest.ts
  47. 1 1
      tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts
  48. 1 1
      tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts
  49. 1 1
      tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts
  50. 1 1
      tests/network-tests/src/iznik/tests/proposals/updateRuntime.ts
  51. 1 1
      tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts
  52. 1 1
      tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts
  53. 1 1
      tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts
  54. 1 1
      tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts
  55. 1 1
      tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts
  56. 1 1
      tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts
  57. 1 1
      tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts
  58. 1 1
      tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts
  59. 13 13
      tests/network-tests/src/iznik/utils/apiWrapper.ts
  60. 1 1
      tests/network-tests/src/iznik/utils/utils.ts
  61. 2 2
      types/package.json
  62. 15 24
      types/src/content-working-group/index.ts
  63. 5 80
      types/src/members.ts
  64. 18 5
      yarn.lock

+ 8 - 10
.github/workflows/joystream-cli.yml

@@ -18,12 +18,11 @@ jobs:
       run: |
         yarn install --frozen-lockfile
         yarn workspace @joystream/cli checks
-    - name: npm pack test
+    - name: yarn pack test
       run: |
-        cd cli
-        npm pack | tail -1 | xargs tar xzf
-        cd package && npm link
-        joystream-cli help
+        yarn workspace @joystream/cli pack --filename cli-pack-test.tgz
+        tar zxvf ./cli/cli-pack-test.tgz -C cli
+        cd ./cli/package && yarn link
 
   cli_build_osx:
     name: MacOS Checks
@@ -41,9 +40,8 @@ jobs:
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
         yarn workspace @joystream/cli checks
-    - name: npm pack test
+    - name: yarn pack test
       run: |
-        cd cli
-        npm pack | tail -1 | xargs tar xzf
-        cd package && npm link
-        joystream-cli help
+        yarn workspace @joystream/cli pack --filename cli-pack-test.tgz
+        tar zxvf ./cli/cli-pack-test.tgz -C cli
+        cd ./cli/package && yarn link

+ 3 - 3
cli/README.md

@@ -244,9 +244,9 @@ EXAMPLES
   $ api:inspect
   $ api:inspect -t=query
   $ api:inspect -t=query -M=members
-  $ api:inspect -t=query -M=members -m=memberProfile
-  $ api:inspect -t=query -M=members -m=memberProfile -e
-  $ api:inspect -t=query -M=members -m=memberProfile -e -a=1
+  $ api:inspect -t=query -M=members -m=membershipById
+  $ api:inspect -t=query -M=members -m=membershipById -e
+  $ api:inspect -t=query -M=members -m=membershipById -e -a=1
 ```
 
 _See code: [src/commands/api/inspect.ts](https://github.com/Joystream/substrate-runtime-joystream/blob/master/cli/src/commands/api/inspect.ts)_

+ 1 - 1
cli/package.json

@@ -8,7 +8,7 @@
   },
   "bugs": "https://github.com/Joystream/joystream/issues",
   "dependencies": {
-    "@joystream/types": "^0.12.0",
+    "@joystream/types": "^0.13.0",
     "@oclif/command": "^1.5.19",
     "@oclif/config": "^1.14.0",
     "@oclif/plugin-autocomplete": "^0.2.0",

+ 7 - 6
cli/src/Api.ts

@@ -43,7 +43,7 @@ import {
   OpeningId,
   StakingPolicy,
 } from '@joystream/types/hiring'
-import { MemberId, Profile } from '@joystream/types/members'
+import { MemberId, Membership } from '@joystream/types/members'
 import { RewardRelationship, RewardRelationshipId } from '@joystream/types/recurring-rewards'
 import { Stake, StakeId } from '@joystream/types/stake'
 import { LinkageResult } from '@polkadot/types/codec/Linkage'
@@ -193,10 +193,11 @@ export default class Api {
     return this._api.query[module]
   }
 
-  protected async memberProfileById(memberId: MemberId): Promise<Profile | null> {
-    const profile = (await this._api.query.members.memberProfile(memberId)) as Option<Profile>
+  protected async membershipById(memberId: MemberId): Promise<Membership | null> {
+    const profile = (await this._api.query.members.membershipById(memberId)) as Membership
 
-    return profile.unwrapOr(null)
+    // Can't just use profile.isEmpty because profile.suspended is Bool (which isEmpty method always returns false)
+    return profile.handle.isEmpty ? null : profile
   }
 
   async groupLead(group: WorkingGroups): Promise<GroupMember | null> {
@@ -238,7 +239,7 @@ export default class Api {
     const roleAccount = worker.role_account_id
     const memberId = worker.member_id
 
-    const profile = await this.memberProfileById(memberId)
+    const profile = await this.membershipById(memberId)
 
     if (!profile) {
       throw new Error(`Group member profile not found! (member id: ${memberId.toNumber()})`)
@@ -358,7 +359,7 @@ export default class Api {
       wgApplicationId,
       applicationId: appId.toNumber(),
       wgOpeningId: wgApplication.opening_id.toNumber(),
-      member: await this.memberProfileById(wgApplication.member_id),
+      member: await this.membershipById(wgApplication.member_id),
       roleAccout: wgApplication.role_account_id,
       stakes: {
         application: appStakingId.isSome ? (await this.stakeValue(appStakingId.unwrap())).toNumber() : 0,

+ 3 - 3
cli/src/Types.ts

@@ -8,7 +8,7 @@ import { BlockNumber, Balance, AccountId } from '@polkadot/types/interfaces'
 import { DerivedBalances } from '@polkadot/api-derive/types'
 import { KeyringPair } from '@polkadot/keyring/types'
 import { WorkerId, OpeningType } from '@joystream/types/working-group'
-import { Profile, MemberId } from '@joystream/types/members'
+import { Membership, MemberId } from '@joystream/types/members'
 import {
   GenericJoyStreamRoleSchema,
   JobSpecifics,
@@ -103,7 +103,7 @@ export type GroupMember = {
   workerId: WorkerId
   memberId: MemberId
   roleAccount: AccountId
-  profile: Profile
+  profile: Membership
   stake?: Balance
   reward?: Reward
 }
@@ -112,7 +112,7 @@ export type GroupApplication = {
   wgApplicationId: number
   applicationId: number
   wgOpeningId: number
-  member: Profile | null
+  member: Membership | null
   roleAccout: AccountId
   stakes: {
     application: number

+ 3 - 3
cli/src/commands/api/inspect.ts

@@ -35,9 +35,9 @@ export default class ApiInspect extends ApiCommandBase {
     '$ api:inspect',
     '$ api:inspect -t=query',
     '$ api:inspect -t=query -M=members',
-    '$ api:inspect -t=query -M=members -m=memberProfile',
-    '$ api:inspect -t=query -M=members -m=memberProfile -e',
-    '$ api:inspect -t=query -M=members -m=memberProfile -e -a=1',
+    '$ api:inspect -t=query -M=members -m=membershipById',
+    '$ api:inspect -t=query -M=members -m=membershipById -e',
+    '$ api:inspect -t=query -M=members -m=membershipById -e -a=1',
   ]
 
   static flags = {

+ 1 - 1
pioneer/packages/apps-routing/src/joy-members.ts

@@ -6,7 +6,7 @@ export default [
   {
     Component: Members,
     display: {
-      needsApi: ['query.members.membersCreated']
+      needsApi: ['query.members.nextMemberId']
     },
     i18n: {
       defaultValue: 'Membership'

+ 3 - 3
pioneer/packages/joy-members/src/Dashboard.tsx

@@ -16,7 +16,7 @@ import { FIRST_MEMBER_ID } from './constants';
 
 type Props = ApiProps & I18nProps & {
   newMembershipsAllowed?: Bool;
-  membersCreated?: BN;
+  nextMemberId?: BN;
   minHandleLength?: BN;
   maxHandleLength?: BN;
   maxAvatarUriLength?: BN;
@@ -36,7 +36,7 @@ class Dashboard extends React.PureComponent<Props> {
         {isAllowed && (isAllowed.eq(true) ? 'Yes' : 'No')}
       </Bubble>
       <Bubble label='Next member ID'>
-        {formatNumber(p.membersCreated)}
+        {formatNumber(p.nextMemberId)}
       </Bubble>
       <Bubble label='First member ID'>
         {formatNumber(FIRST_MEMBER_ID)}
@@ -75,7 +75,7 @@ class Dashboard extends React.PureComponent<Props> {
 export default translate(
   withCalls<Props>(
     queryMembershipToProp('newMembershipsAllowed'),
-    queryMembershipToProp('membersCreated'),
+    queryMembershipToProp('nextMemberId'),
     queryMembershipToProp('minHandleLength'),
     queryMembershipToProp('maxHandleLength'),
     queryMembershipToProp('maxAvatarUriLength'),

+ 12 - 14
pioneer/packages/joy-members/src/Details.tsx

@@ -12,7 +12,7 @@ import AddressMini from '@polkadot/react-components/AddressMiniJoy';
 import { formatNumber } from '@polkadot/util';
 
 import translate from './translate';
-import { MemberId, Profile, EntryMethod, Paid, Screening, Genesis, SubscriptionId } from '@joystream/types/members';
+import { MemberId, Membership, EntryMethod, Paid, Screening, Genesis, SubscriptionId } from '@joystream/types/members';
 import { queryMembershipToProp } from './utils';
 import { Seat } from '@joystream/types/council';
 import { nonEmptyStr, queryToProp } from '@polkadot/joy-utils/index';
@@ -21,17 +21,15 @@ import { MyAccountProps, withMyAccount } from '@polkadot/joy-utils/MyAccount';
 type Props = ApiProps & I18nProps & MyAccountProps & {
   preview?: boolean;
   memberId: MemberId;
-  // This cannot be named just "memberProfile", since it will conflict with "withAccount's" memberProfile
-  // (which holds  member profile associated with currently selected account)
-  detailsMemberProfile?: Option<any>; // TODO refactor to Option<Profile>
+  membership?: Membership;
   activeCouncil?: Seat[];
 };
 
 class Component extends React.PureComponent<Props> {
   render () {
-    const { detailsMemberProfile } = this.props;
-    return detailsMemberProfile
-      ? this.renderProfile(detailsMemberProfile.unwrap() as Profile)
+    const { membership } = this.props;
+    return membership && !membership.handle.isEmpty
+      ? this.renderProfile(membership)
       : (
         <div className={'item ProfileDetails'}>
           <Loader active inline/>
@@ -39,7 +37,7 @@ class Component extends React.PureComponent<Props> {
       );
   }
 
-  private renderProfile (memberProfile: Profile) {
+  private renderProfile (membership: Membership) {
     const {
       preview = false,
       myAddress,
@@ -51,7 +49,7 @@ class Component extends React.PureComponent<Props> {
       avatar_uri,
       root_account,
       controller_account
-    } = memberProfile;
+    } = membership;
 
     const hasAvatar = avatar_uri && nonEmptyStr(avatar_uri.toString());
     const isMyProfile = myAddress && (myAddress === root_account.toString() || myAddress === controller_account.toString());
@@ -83,12 +81,12 @@ class Component extends React.PureComponent<Props> {
           </div>
         </div>
       </div>
-      {!preview && this.renderDetails(memberProfile, isCouncilor)}
+      {!preview && this.renderDetails(membership, isCouncilor)}
       </>
     );
   }
 
-  private renderDetails (memberProfile: Profile, isCouncilor: boolean) {
+  private renderDetails (membership: Membership, isCouncilor: boolean) {
     const {
       about,
       registered_at_block,
@@ -99,7 +97,7 @@ class Component extends React.PureComponent<Props> {
       root_account,
       controller_account
 
-    } = memberProfile;
+    } = membership;
 
     const { memberId } = this.props;
 
@@ -173,8 +171,8 @@ export default translate(withMyAccount(
   withCalls<Props>(
     queryToProp('query.council.activeCouncil'),
     queryMembershipToProp(
-      'memberProfile',
-      { paramName: 'memberId', propName: 'detailsMemberProfile' }
+      'membershipById',
+      { paramName: 'memberId', propName: 'membership' }
     )
   )(Component)
 ));

+ 3 - 3
pioneer/packages/joy-members/src/DetailsByHandle.tsx

@@ -11,11 +11,11 @@ import { queryMembershipToProp } from './utils';
 
 type DetailsByHandleProps = {
   handle: string;
-  handles?: MemberId;
+  memberIdByHandle?: MemberId;
 };
 
 function DetailsByHandleInner (p: DetailsByHandleProps) {
-  const { handles: memberId } = p;
+  const { memberIdByHandle: memberId } = p;
   return memberId !== undefined // here we can't make distinction value existing and loading
     ? <div className='ui massive relaxed middle aligned list FullProfile'>
       <Details memberId={memberId} />
@@ -24,7 +24,7 @@ function DetailsByHandleInner (p: DetailsByHandleProps) {
 }
 
 const DetailsByHandle = withCalls<DetailsByHandleProps>(
-  queryMembershipToProp('handles', 'handle')
+  queryMembershipToProp('memberIdByHandle', 'handle')
 )(DetailsByHandleInner);
 
 type Props = I18nProps & {

+ 30 - 30
pioneer/packages/joy-members/src/EditForm.tsx

@@ -4,12 +4,12 @@ import { Link } from 'react-router-dom';
 import { Form, Field, withFormik, FormikProps } from 'formik';
 import * as Yup from 'yup';
 
-import { Option, Vec } from '@polkadot/types';
+import { Vec } from '@polkadot/types';
 import Section from '@polkadot/joy-utils/Section';
 import TxButton from '@polkadot/joy-utils/TxButton';
 import * as JoyForms from '@polkadot/joy-utils/forms';
 import { SubmittableResult } from '@polkadot/api';
-import { MemberId, UserInfo, Profile, PaidTermId, PaidMembershipTerms } from '@joystream/types/members';
+import { MemberId, Membership, PaidTermId, PaidMembershipTerms } from '@joystream/types/members';
 import { OptionText } from '@joystream/types/common';
 import { MyAccountProps, withMyAccount } from '@polkadot/joy-utils/MyAccount';
 import { queryMembershipToProp } from './utils';
@@ -43,7 +43,7 @@ type ValidationProps = {
 };
 
 type OuterProps = ValidationProps & {
-  profile?: Profile;
+  profile?: Membership;
   paidTerms: PaidMembershipTerms;
   paidTermId: PaidTermId;
   memberId?: MemberId;
@@ -108,18 +108,18 @@ const InnerForm = (props: FormProps) => {
   const buildTxParams = () => {
     if (!isValid) return [];
 
-    const userInfo = new UserInfo({
-      handle: fieldToTextOption('handle'),
-      avatar_uri: fieldToTextOption('avatar'),
-      about: fieldToTextOption('about')
-    });
+    const userInfo = [
+      fieldToTextOption('handle'),
+      fieldToTextOption('avatar'),
+      fieldToTextOption('about')
+    ];
 
     if (profile) {
       // update profile
-      return [memberId, userInfo];
+      return [memberId, ...userInfo];
     } else {
       // register as new member
-      return [paidTermId, userInfo];
+      return [paidTermId, ...userInfo];
     }
   };
 
@@ -171,7 +171,7 @@ const InnerForm = (props: FormProps) => {
             label={profile ? 'Update my profile' : 'Register'}
             isDisabled={!dirty || isSubmitting}
             params={buildTxParams()}
-            tx={profile ? 'members.updateProfile' : 'members.buyMembership'}
+            tx={profile ? 'members.updateMembership' : 'members.buyMembership'}
             onClick={onSubmit}
             txFailedCb={onTxFailed}
             txSuccessCb={onTxSuccess}
@@ -207,19 +207,19 @@ const EditForm = withFormik<OuterProps, FormValues>({
   }
 })(InnerForm);
 
-type WithMyProfileProps = {
+type WithMembershipDataProps = {
   memberId?: MemberId;
-  memberProfile?: Option<any>; // TODO refactor to Option<Profile>
+  membership?: Membership;
   paidTermsId: PaidTermId;
-  paidTerms?: Option<PaidMembershipTerms>;
+  paidTerms?: PaidMembershipTerms;
   minHandleLength?: BN;
   maxHandleLength?: BN;
   maxAvatarUriLength?: BN;
   maxAboutTextLength?: BN;
 };
 
-function WithMyProfileInner (p: WithMyProfileProps) {
-  const triedToFindProfile = !p.memberId || p.memberProfile;
+function WithMembershipDataInner (p: WithMembershipDataProps) {
+  const triedToFindProfile = !p.memberId || p.membership;
   if (
     triedToFindProfile &&
     p.paidTerms &&
@@ -228,9 +228,9 @@ function WithMyProfileInner (p: WithMyProfileProps) {
     p.maxAvatarUriLength &&
     p.maxAboutTextLength
   ) {
-    const profile = p.memberProfile ? p.memberProfile.unwrapOr(undefined) : undefined;
+    const membership = p.membership && !p.membership.handle.isEmpty ? p.membership : undefined;
 
-    if (!profile && p.paidTerms.isNone) {
+    if (!membership && p.paidTerms.isEmpty) {
       console.error('Could not find active paid membership terms');
     }
 
@@ -240,8 +240,8 @@ function WithMyProfileInner (p: WithMyProfileProps) {
         maxHandleLength={p.maxHandleLength.toNumber()}
         maxAvatarUriLength={p.maxAvatarUriLength.toNumber()}
         maxAboutTextLength={p.maxAboutTextLength.toNumber()}
-        profile={profile as Profile}
-        paidTerms={p.paidTerms.unwrap()}
+        profile={membership}
+        paidTerms={p.paidTerms}
         paidTermId={p.paidTermsId}
         memberId={p.memberId}
       />
@@ -249,22 +249,22 @@ function WithMyProfileInner (p: WithMyProfileProps) {
   } else return <em>Loading...</em>;
 }
 
-const WithMyProfile = withCalls<WithMyProfileProps>(
+const WithMembershipData = withCalls<WithMembershipDataProps>(
   queryMembershipToProp('minHandleLength'),
   queryMembershipToProp('maxHandleLength'),
   queryMembershipToProp('maxAvatarUriLength'),
   queryMembershipToProp('maxAboutTextLength'),
-  queryMembershipToProp('memberProfile', 'memberId'),
+  queryMembershipToProp('membershipById', { paramName: 'memberId', propName: 'membership' }),
   queryMembershipToProp('paidMembershipTermsById', { paramName: 'paidTermsId', propName: 'paidTerms' })
-)(WithMyProfileInner);
+)(WithMembershipDataInner);
 
-type WithMyMemberIdProps = MyAccountProps & {
+type WithMembershipDataWrapperProps = MyAccountProps & {
   memberIdsByRootAccountId?: Vec<MemberId>;
   memberIdsByControllerAccountId?: Vec<MemberId>;
   paidTermsIds?: Vec<PaidTermId>;
 };
 
-function WithMyMemberIdInner (p: WithMyMemberIdProps) {
+function WithMembershipDataWrapperInner (p: WithMembershipDataWrapperProps) {
   if (p.allAccounts && !Object.keys(p.allAccounts).length) {
     return (
       <Message warning className="JoyMainStatus">
@@ -284,7 +284,7 @@ function WithMyMemberIdInner (p: WithMyMemberIdProps) {
       p.memberIdsByRootAccountId.concat(p.memberIdsByControllerAccountId);
       const memberId = p.memberIdsByRootAccountId.length ? p.memberIdsByRootAccountId[0] : undefined;
 
-      return <WithMyProfile memberId={memberId} paidTermsId={p.paidTermsIds[0]} />;
+      return <WithMembershipData memberId={memberId} paidTermsId={p.paidTermsIds[0]} />;
     } else {
       console.error('Active paid membership terms is empty');
     }
@@ -293,12 +293,12 @@ function WithMyMemberIdInner (p: WithMyMemberIdProps) {
   return <em>Loading...</em>;
 }
 
-const WithMyMemberId = withMyAccount(
-  withCalls<WithMyMemberIdProps>(
+const WithMembershipDataWrapper = withMyAccount(
+  withCalls<WithMembershipDataWrapperProps>(
     queryMembershipToProp('memberIdsByRootAccountId', 'myAddress'),
     queryMembershipToProp('memberIdsByControllerAccountId', 'myAddress'),
     queryMembershipToProp('activePaidMembershipTerms', { propName: 'paidTermsIds' })
-  )(WithMyMemberIdInner)
+  )(WithMembershipDataWrapperInner)
 );
 
-export default WithMyMemberId;
+export default WithMembershipDataWrapper;

+ 9 - 9
pioneer/packages/joy-members/src/MemberPreview.tsx

@@ -4,12 +4,12 @@ import { Link } from 'react-router-dom';
 import { ApiProps } from '@polkadot/react-api/types';
 import { I18nProps } from '@polkadot/react-components/types';
 import { withCalls, withMulti } from '@polkadot/react-api/with';
-import { Option, Vec } from '@polkadot/types';
+import { Vec } from '@polkadot/types';
 import { AccountId } from '@polkadot/types/interfaces';
 import IdentityIcon from '@polkadot/react-components/IdentityIcon';
 
 import translate from './translate';
-import { MemberId, Profile } from '@joystream/types/members';
+import { MemberId, Membership } from '@joystream/types/members';
 import { queryMembershipToProp } from './utils';
 import { Seat } from '@joystream/types/council';
 import { nonEmptyStr, queryToProp } from '@polkadot/joy-utils/index';
@@ -22,7 +22,7 @@ const InlineAvatarSizePx = 24;
 type MemberPreviewProps = ApiProps & I18nProps & {
   accountId: AccountId;
   memberId?: MemberId;
-  memberProfile?: Option<any>; // TODO refactor to Option<Profile>
+  membership?: Membership;
   activeCouncil?: Seat[];
   prefixLabel?: string;
   inline?: boolean;
@@ -32,15 +32,15 @@ type MemberPreviewProps = ApiProps & I18nProps & {
 
 class InnerMemberPreview extends React.PureComponent<MemberPreviewProps> {
   render () {
-    const { memberProfile } = this.props;
-    return memberProfile
-      ? this.renderProfile(memberProfile.unwrap() as Profile)
+    const { membership } = this.props;
+    return membership && !membership.handle.isEmpty
+      ? this.renderProfile(membership)
       : null;
   }
 
-  private renderProfile (memberProfile: Profile) {
+  private renderProfile (membership: Membership) {
     const { activeCouncil = [], accountId, prefixLabel, inline, className, style } = this.props;
-    const { handle, avatar_uri } = memberProfile;
+    const { handle, avatar_uri } = membership;
 
     const hasAvatar = avatar_uri && nonEmptyStr(avatar_uri.toString());
     const isCouncilor: boolean = accountId !== undefined && activeCouncil.find(x => accountId.eq(x.member)) !== undefined;
@@ -113,6 +113,6 @@ export const MemberPreview = withMulti(
   setMemberIdByAccountId,
   withCalls<MemberPreviewProps>(
     queryToProp('query.council.activeCouncil'), // TODO Refactor: extract ActiveCouncilContext
-    queryMembershipToProp('memberProfile', 'memberId')
+    queryMembershipToProp('membershipById', { paramName: 'memberId', propName: 'membership' })
   )
 );

+ 6 - 6
pioneer/packages/joy-members/src/index.tsx

@@ -22,12 +22,12 @@ import { RouteComponentProps } from 'react-router-dom';
 
 // define out internal types
 type Props = AppProps & ApiProps & I18nProps & MyAccountProps & {
-  membersCreated?: BN;
+  nextMemberId?: BN;
 };
 
 class App extends React.PureComponent<Props> {
   private buildTabs (): TabItem[] {
-    const { t, membersCreated: memberCount, iAmMember } = this.props;
+    const { t, nextMemberId: memberCount, iAmMember } = this.props;
 
     return [
       {
@@ -47,9 +47,9 @@ class App extends React.PureComponent<Props> {
   }
 
   private renderList (routeProps: RouteComponentProps) {
-    const { membersCreated, ...otherProps } = this.props;
-    return membersCreated
-      ? <List firstMemberId={FIRST_MEMBER_ID} membersCreated={membersCreated} {...otherProps} {...routeProps}/>
+    const { nextMemberId, ...otherProps } = this.props;
+    return nextMemberId
+      ? <List firstMemberId={FIRST_MEMBER_ID} membersCreated={nextMemberId} {...otherProps} {...routeProps}/>
       : <em>Loading...</em>;
   }
 
@@ -79,6 +79,6 @@ export default withMulti(
   translate,
   withMyAccount,
   withCalls<Props>(
-    queryMembershipToProp('membersCreated')
+    queryMembershipToProp('nextMemberId')
   )
 );

+ 7 - 9
pioneer/packages/joy-proposals/src/Proposal/Body.tsx

@@ -7,7 +7,7 @@ import styled from 'styled-components';
 import AddressMini from '@polkadot/react-components/AddressMiniJoy';
 import TxButton from '@polkadot/joy-utils/TxButton';
 import { ProposalId, TerminateRoleParameters } from '@joystream/types/proposals';
-import { MemberId, Profile } from '@joystream/types/members';
+import { MemberId, Membership } from '@joystream/types/members';
 import ProfilePreview from '@polkadot/joy-utils/MemberProfilePreview';
 import { useTransport, usePromise } from '@polkadot/joy-utils/react/hooks';
 import { Option, Bytes } from '@polkadot/types/';
@@ -55,20 +55,18 @@ function ProposedMember (props: { memberId?: MemberId | number | null }) {
   const memberId: MemberId | number = props.memberId;
 
   const transport = useTransport();
-  const [member, error, loading] = usePromise<Option<Profile> | null>(
-    () => transport.members.memberProfile(memberId),
+  const [member, error, loading] = usePromise<Membership | null>(
+    () => transport.members.membershipById(memberId),
     null
   );
 
-  const profile = member && member.unwrapOr(null);
-
   return (
     <PromiseComponent error={error} loading={loading} message="Fetching profile...">
-      { profile ? (
+      { (member && !member.handle.isEmpty) ? (
         <ProfilePreview
-          avatar_uri={ profile.avatar_uri.toString() }
-          root_account={ profile.root_account.toString() }
-          handle={ profile.handle.toString() }
+          avatar_uri={ member.avatar_uri.toString() }
+          root_account={ member.root_account.toString() }
+          handle={ member.handle.toString() }
           link={ true }
         />
       ) : 'Profile not found' }

+ 4 - 4
pioneer/packages/joy-proposals/src/forms/AddWorkingGroupOpeningForm.tsx

@@ -188,15 +188,15 @@ const valuesToAddOpeningParams = (values: FormValues): SimplifiedTypeInterface<I
 };
 
 const AddWorkingGroupOpeningForm: React.FunctionComponent<FormInnerProps> = props => {
-  const { handleChange, errors, touched, values, setFieldValue, myMemberId, memberProfile } = props;
+  const { handleChange, errors, touched, values, setFieldValue, myMemberId, myMembership } = props;
   useEffect(() => {
-    if (memberProfile?.isSome && !touched.humanReadableText) {
+    if (myMembership && !touched.humanReadableText) {
       setFieldValue(
         'humanReadableText',
-        JSON.stringify(HRTDefault(memberProfile.unwrap().handle.toString(), values.workingGroup), undefined, 4)
+        JSON.stringify(HRTDefault(myMembership.handle.toString(), values.workingGroup), undefined, 4)
       );
     }
-  }, [values.workingGroup, memberProfile]);
+  }, [values.workingGroup, myMembership]);
   const errorLabelsProps = getFormErrorLabelsProps<FormValues>(errors, touched);
 
   return (

+ 4 - 4
pioneer/packages/joy-proposals/src/forms/SetContentWorkingGroupLeadForm.tsx

@@ -16,7 +16,7 @@ import Validation from '../validationSchema';
 import { FormField } from './FormFields';
 import { withFormContainer } from './FormContainer';
 import { useTransport, usePromise } from '@polkadot/joy-utils/react/hooks';
-import { Profile } from '@joystream/types/members';
+import { Membership } from '@joystream/types/members';
 import { PromiseComponent } from '@polkadot/joy-utils/react/components';
 import _ from 'lodash';
 import './forms.css';
@@ -35,7 +35,7 @@ type ExportComponentProps = ProposalFormExportProps<FormAdditionalProps, FormVal
 type FormContainerProps = ProposalFormContainerProps<ExportComponentProps>;
 type FormInnerProps = ProposalFormInnerProps<FormContainerProps, FormValues>;
 
-function memberOptionKey (id: number, profile: Profile) {
+function memberOptionKey (id: number, profile: Membership) {
   return `${id}:${profile.root_account.toString()}`;
 }
 
@@ -46,7 +46,7 @@ const MEMBERS_NONE_OPTION: DropdownItemProps = {
   value: 'none'
 };
 
-function membersToOptions (members: { id: number; profile: Profile }[]) {
+function membersToOptions (members: { id: number; profile: Membership }[]) {
   return [MEMBERS_NONE_OPTION].concat(
     members
       .map(({ id, profile }) => ({
@@ -66,7 +66,7 @@ function filterMembers (options: DropdownItemProps[], query: string) {
   return options.filter((opt) => regexp.test((opt.text || '').toString()));
 }
 
-type MemberWithId = { id: number; profile: Profile };
+type MemberWithId = { id: number; profile: Membership };
 
 const SetContentWorkingGroupsLeadForm: React.FunctionComponent<FormInnerProps> = props => {
   const { handleChange, errors, touched, values } = props;

+ 0 - 1
pioneer/packages/joy-proposals/src/stories/data/ProposalDetails.mock.ts

@@ -31,7 +31,6 @@ const mockedProposal: ParsedProposal = {
     handle: 'bob55',
     registered_at_block: 18,
     registered_at_time: 1588087314000,
-    roles: [],
     entry: {
       Paid: 0
     },

+ 4 - 4
pioneer/packages/joy-roles/src/elements.tsx

@@ -6,7 +6,7 @@ import { Link } from 'react-router-dom';
 import { Balance } from '@polkadot/types/interfaces';
 import { formatBalance } from '@polkadot/util';
 import Identicon from '@polkadot/react-identicon';
-import { IProfile, MemberId } from '@joystream/types/members';
+import { IMembership, MemberId } from '@joystream/types/members';
 import { GenericAccountId } from '@polkadot/types';
 import { LeadRoleState } from '@joystream/types/content-working-group';
 import { WorkerId } from '@joystream/types/working-group';
@@ -28,7 +28,7 @@ export function BalanceView (props: BalanceProps) {
 }
 
 type ProfileProps = {
-  profile: IProfile;
+  profile: IMembership;
 }
 
 export function HandleView (props: ProfileProps) {
@@ -46,7 +46,7 @@ export type GroupMember = {
   group: WorkingGroups;
   workerId: number;
   roleAccount: GenericAccountId;
-  profile: IProfile;
+  profile: IMembership;
   title: string;
   stake?: Balance;
   rewardRelationship?: RewardRelationship;
@@ -56,7 +56,7 @@ export type GroupLead = {
   memberId: MemberId;
   workerId?: WorkerId; // In case of "working-group" module
   roleAccount: GenericAccountId;
-  profile: IProfile;
+  profile: IMembership;
   title: string;
   stage?: LeadRoleState;
   stake?: Balance;

+ 3 - 4
pioneer/packages/joy-roles/src/mocks.ts

@@ -1,7 +1,7 @@
 import { bool, Option, Text, u32, u64, Vec } from '@polkadot/types';
 import AccountId from '@polkadot/types/primitive/Generic/AccountId';
 
-import { ActorInRole, IProfile, EntryMethod } from '@joystream/types/members';
+import { IMembership, EntryMethod } from '@joystream/types/members';
 
 import {
   AcceptingApplications,
@@ -11,7 +11,7 @@ import {
   ApplicationId
 } from '@joystream/types/hiring';
 
-export function mockProfile (name: string, avatar_uri = ''): IProfile {
+export function mockProfile (name: string, avatar_uri = ''): IMembership {
   return {
     handle: new Text(name),
     avatar_uri: new Text(avatar_uri),
@@ -22,8 +22,7 @@ export function mockProfile (name: string, avatar_uri = ''): IProfile {
     suspended: new bool(false),
     subscription: new Option(u64),
     root_account: new AccountId('5HZ6GtaeyxagLynPryM7ZnmLzoWFePKuDrkb4AT8rT4pU1fp'),
-    controller_account: new AccountId('5HZ6GtaeyxagLynPryM7ZnmLzoWFePKuDrkb4AT8rT4pU1fp'),
-    roles: new Vec<ActorInRole>(ActorInRole)
+    controller_account: new AccountId('5HZ6GtaeyxagLynPryM7ZnmLzoWFePKuDrkb4AT8rT4pU1fp')
   };
 }
 

+ 9 - 5
pioneer/packages/joy-roles/src/tabs/Admin.controller.tsx

@@ -45,7 +45,7 @@ import {
 } from '@joystream/types/hiring';
 
 import {
-  Profile,
+  Membership,
   MemberId
 } from '@joystream/types/members';
 
@@ -77,7 +77,7 @@ type ids = {
 type application = ids & {
   account: string;
   memberId: number;
-  profile: Profile;
+  profile: Membership;
   stage: ApplicationStage;
   applicationStake: Balance;
   roleStake: Balance;
@@ -430,8 +430,12 @@ export class AdminController extends Controller<State, ITransport> {
     this.queueExtrinsic({ extrinsic: tx, txSuccessCb: this.onTxSuccess, accountId });
   }
 
-  protected async profile (id: MemberId): Promise<Option<Profile>> {
-    return (await this.api.query.members.memberProfile(id)) as Option<Profile>;
+  protected async profile (id: MemberId): Promise<Membership> {
+    const member = (await this.api.query.members.membershipById(id)) as Membership;
+    if (member.handle.isEmpty) {
+      throw new Error(`Expected member profile not found! (id: ${id.toString()}`);
+    }
+    return member;
   }
 
   protected async stakeValue (stakeId: StakeId): Promise<Balance> {
@@ -517,7 +521,7 @@ export class AdminController extends Controller<State, ITransport> {
         stage: baseApplications.value.stage,
         account: cApplication.value.role_account_id.toString(),
         memberId: cApplication.value.member_id.toNumber(),
-        profile: (await this.profile(cApplication.value.member_id)).unwrap(),
+        profile: (await this.profile(cApplication.value.member_id)),
         applicationStake: await this.applicationStake(baseApplications.value),
         roleStake: await this.roleStake(baseApplications.value),
         application: baseApplications.value

+ 1 - 9
pioneer/packages/joy-roles/src/transport.mock.ts

@@ -6,7 +6,7 @@ import { Subscribable, Transport as TransportBase } from '@polkadot/joy-utils/in
 
 import { ITransport } from './transport';
 
-import { Role, MemberId } from '@joystream/types/members';
+import { MemberId } from '@joystream/types/members';
 import {
   Opening,
   ApplicationRationingPolicy,
@@ -36,14 +36,6 @@ export class Transport extends TransportBase implements ITransport {
     return Math.random() * (max - min) + min;
   }
 
-  roles (): Promise<Array<Role>> {
-    return this.promise<Array<Role>>(
-      [
-        new Role('StorageProvider')
-      ]
-    );
-  }
-
   groupLeadStatus (group: WorkingGroups = WorkingGroups.ContentCurators): Promise<GroupLeadStatus> {
     return this.simulateApiResponse<GroupLeadStatus>({
       loaded: true

+ 17 - 39
pioneer/packages/joy-roles/src/transport.substrate.ts

@@ -32,7 +32,7 @@ import {
 import { Application, Opening, OpeningId, ApplicationId, ActiveApplicationStage } from '@joystream/types/hiring';
 import { Stake, StakeId } from '@joystream/types/stake';
 import { RewardRelationship, RewardRelationshipId } from '@joystream/types/recurring-rewards';
-import { ActorInRole, Profile, MemberId, Role, RoleKeys, ActorId } from '@joystream/types/members';
+import { Membership, MemberId, ActorId } from '@joystream/types/members';
 import { createAccount, generateSeed } from '@polkadot/joy-utils/accounts';
 
 import { WorkingGroupMembership, GroupLeadStatus } from './tabs/WorkingGroup';
@@ -176,11 +176,6 @@ export class Transport extends TransportBase implements ITransport {
     this.cachedApi.unsubscribe();
   }
 
-  async roles (): Promise<Array<Role>> {
-    const roles: any = await this.cachedApi.query.actors.availableRoles();
-    return this.promise<Array<Role>>(roles.map((role: Role) => role));
-  }
-
   protected async stakeValue (stakeId: StakeId): Promise<Balance> {
     const stake = new SingleLinkedMapEntry<Stake>(
       Stake,
@@ -209,31 +204,14 @@ export class Transport extends TransportBase implements ITransport {
     return relationship?.total_reward_received || new u128(0);
   }
 
-  protected async memberIdFromRoleAndActorId (role: Role, id: ActorId): Promise<MemberId> {
-    const memberId = (
-      await this.cachedApi.query.members.membershipIdByActorInRole(
-        new ActorInRole({
-          role: role,
-          actor_id: id
-        })
-      )
-    ) as MemberId;
-
-    return memberId;
-  }
-
-  protected memberIdFromCuratorId (curatorId: CuratorId): Promise<MemberId> {
-    return this.memberIdFromRoleAndActorId(
-      new Role(RoleKeys.Curator),
-      curatorId
-    );
-  }
+  protected async curatorMemberId (curator: Curator): Promise<MemberId> {
+    const curatorApplicationId = curator.induction.curator_application_id;
+    const curatorApplication = new SingleLinkedMapEntry<CuratorApplication>(
+      CuratorApplication,
+      await this.cachedApi.query.contentWorkingGroup.curatorApplicationById(curatorApplicationId)
+    ).value;
 
-  protected memberIdFromLeadId (leadId: LeadId): Promise<MemberId> {
-    return this.memberIdFromRoleAndActorId(
-      new Role(RoleKeys.CuratorLead),
-      leadId
-    );
+    return curatorApplication.member_id;
   }
 
   protected async workerRewardRelationship (worker: GroupWorker): Promise<RewardRelationship | undefined> {
@@ -250,12 +228,12 @@ export class Transport extends TransportBase implements ITransport {
   ): Promise<GroupMember> {
     const roleAccount = worker.role_account_id;
     const memberId = group === WorkingGroups.ContentCurators
-      ? await this.memberIdFromCuratorId(id)
+      ? await this.curatorMemberId(worker as Curator)
       : (worker as Worker).member_id;
 
-    const profile = await this.cachedApi.query.members.memberProfile(memberId) as Option<Profile>;
-    if (profile.isNone) {
-      throw new Error('no profile found');
+    const profile = await this.cachedApi.query.members.membershipById(memberId) as Membership;
+    if (profile.handle.isEmpty) {
+      throw new Error('No group member profile found!');
     }
 
     let stakeValue: Balance = new u128(0);
@@ -270,7 +248,7 @@ export class Transport extends TransportBase implements ITransport {
       group,
       memberId,
       workerId: id.toNumber(),
-      profile: profile.unwrap(),
+      profile,
       title: workerRoleNameByGroup[group],
       stake: stakeValue,
       rewardRelationship
@@ -321,7 +299,7 @@ export class Transport extends TransportBase implements ITransport {
       await this.cachedApi.query.contentWorkingGroup.leadById(leadId)
     );
 
-    const memberId = await this.memberIdFromLeadId(leadId);
+    const memberId = lead.value.member_id;
 
     return {
       lead: lead.value,
@@ -360,9 +338,9 @@ export class Transport extends TransportBase implements ITransport {
       : await this.currentStorageLead();
 
     if (currentLead !== null) {
-      const profile = await this.cachedApi.query.members.memberProfile(currentLead.memberId) as Option<Profile>;
+      const profile = await this.cachedApi.query.members.membershipById(currentLead.memberId) as Membership;
 
-      if (profile.isNone) {
+      if (profile.handle.isEmpty) {
         throw new Error(`${group} lead profile not found!`);
       }
 
@@ -379,7 +357,7 @@ export class Transport extends TransportBase implements ITransport {
           memberId: currentLead.memberId,
           workerId: currentLead.workerId,
           roleAccount: currentLead.lead.role_account_id,
-          profile: profile.unwrap(),
+          profile,
           title: _.startCase(group) + ' Lead',
           stage: group === WorkingGroups.ContentCurators ? (currentLead.lead as Lead).stage : undefined,
           stake,

+ 0 - 3
pioneer/packages/joy-roles/src/transport.ts

@@ -1,8 +1,6 @@
 import { Subscribable } from '@polkadot/joy-utils/index';
 import { Balance } from '@polkadot/types/interfaces';
 
-import { Role } from '@joystream/types/members';
-
 import { WorkingGroupMembership, GroupLeadStatus } from './tabs/WorkingGroup';
 import { WorkingGroupOpening } from './tabs/Opportunities';
 import { keyPairDetails } from './flows/apply';
@@ -10,7 +8,6 @@ import { ActiveRole, OpeningApplication } from './tabs/MyRoles';
 import { WorkingGroups } from './working_groups';
 
 export interface ITransport {
-  roles: () => Promise<Array<Role>>;
   groupLeadStatus: (group: WorkingGroups) => Promise<GroupLeadStatus>;
   curationGroup: () => Promise<WorkingGroupMembership>;
   storageGroup: () => Promise<WorkingGroupMembership>;

+ 2 - 2
pioneer/packages/joy-utils/src/MemberProfilePreview.tsx

@@ -4,7 +4,7 @@ import { IdentityIcon } from '@polkadot/react-components';
 import { Link } from 'react-router-dom';
 import { Text } from '@polkadot/types';
 import { AccountId } from '@polkadot/types/interfaces';
-import { MemberId, Profile } from '@joystream/types/members';
+import { MemberId, Membership } from '@joystream/types/members';
 import styled from 'styled-components';
 
 type ProfileItemProps = {
@@ -68,7 +68,7 @@ export default function ProfilePreview (
 }
 
 type ProfilePreviewFromStructProps = {
-  profile: Profile;
+  profile: Membership;
   link?: boolean;
   id?: number | MemberId;
 };

+ 2 - 2
pioneer/packages/joy-utils/src/MembersDropdown.tsx

@@ -1,6 +1,6 @@
 import React, { useEffect, useState, useContext } from 'react';
 import { Dropdown, DropdownItemProps, DropdownProps } from 'semantic-ui-react';
-import { Profile } from '@joystream/types/members';
+import { Membership } from '@joystream/types/members';
 import { memberFromAccount, MemberFromAccount } from './accounts';
 import { AccountId } from '@polkadot/types/interfaces';
 import { ApiContext } from '@polkadot/react-api';
@@ -14,7 +14,7 @@ const StyledMembersDropdown = styled(Dropdown)`
 `;
 
 function membersToOptions (members: MemberFromAccount[]) {
-  const validMembers = members.filter(m => m.profile !== undefined) as (MemberFromAccount & { profile: Profile })[];
+  const validMembers = members.filter(m => m.profile !== undefined) as (MemberFromAccount & { profile: Membership })[];
   return validMembers
     .map(({ id, profile, account }) => ({
       key: profile.handle,

+ 58 - 122
pioneer/packages/joy-utils/src/MyAccount.tsx

@@ -8,7 +8,7 @@ import accountObservable from '@polkadot/ui-keyring/observable/accounts';
 import { withCalls, withMulti, withObservable } from '@polkadot/react-api/index';
 import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
 
-import { MemberId, Profile } from '@joystream/types/members';
+import { MemberId, Membership } from '@joystream/types/members';
 import { CuratorId, LeadId, Lead, CurationActor, Curator } from '@joystream/types/content-working-group';
 
 import { queryMembershipToProp } from '@polkadot/joy-members/utils';
@@ -29,7 +29,7 @@ export type MyAccountProps = MyAddressProps & {
   memberIdsByControllerAccountId?: Vec<MemberId>;
   myMemberIdChecked?: boolean;
   iAmMember?: boolean;
-  memberProfile?: Option<Profile>;
+  myMembership?: Membership | null;
 
   // Content Working Group
   curatorEntries?: any; // entire linked_map: CuratorId => Curator
@@ -37,12 +37,6 @@ export type MyAccountProps = MyAddressProps & {
   contentLeadId?: LeadId;
   contentLeadEntry?: any; // linked_map value
 
-  // From member's roles
-  myContentLeadId?: LeadId;
-  myCuratorIds?: CuratorId[];
-  memberIsCurator?: boolean;
-  memberIsContentLead?: boolean;
-
   curationActor?: any;
   allAccounts?: SubjectInfo;
 };
@@ -92,7 +86,23 @@ function withMyMembership<P extends MyAccountProps> (Component: React.ComponentT
   return ResultComponent;
 }
 
-const withMyProfile = withCalls<MyAccountProps>(queryMembershipToProp('memberProfile', 'myMemberId'));
+function resolveMyProfile<P extends { myMembership?: Membership | null }> (Component: React.ComponentType<P>) {
+  const ResultComponent: React.FunctionComponent<P> = (props: P) => {
+    let { myMembership } = props;
+    myMembership = (!myMembership || myMembership.handle.isEmpty) ? null : myMembership;
+    return <Component {...props} myMembership={ myMembership } />;
+  };
+  ResultComponent.displayName = `resolveMyProfile(${componentName(Component)})`;
+  return ResultComponent;
+}
+
+const withMyProfileCall = withCalls<MyAccountProps>(queryMembershipToProp('membershipById', {
+  paramName: 'myMemberId',
+  propName: 'myMembership'
+}));
+
+const withMyProfile = <P extends MyAccountProps>(Component: React.ComponentType<P>) =>
+  withMulti(Component, withMyProfileCall, resolveMyProfile);
 
 const withContentWorkingGroupDetails = withCalls<MyAccountProps>(
   queryToProp('query.contentWorkingGroup.currentLeadId', { propName: 'isLeadSet' }),
@@ -126,146 +136,73 @@ const resolveLeadEntry = withCalls<MyAccountProps>(
 const withContentWorkingGroup = <P extends MyAccountProps>(Component: React.ComponentType<P>) =>
   withMulti(Component, withContentWorkingGroupDetails, resolveLead, resolveLeadEntry);
 
-function withMyRoles<P extends MyAccountProps> (Component: React.ComponentType<P>) {
-  const ResultComponent: React.FunctionComponent<P> = (props: P) => {
-    const { iAmMember, memberProfile } = props;
-
-    let myContentLeadId;
-    const myCuratorIds: Array<CuratorId> = [];
-
-    if (iAmMember && memberProfile && memberProfile.isSome) {
-      const profile = memberProfile.unwrap();
-      profile.roles.forEach(role => {
-        if (role.isContentLead) {
-          myContentLeadId = role.actor_id;
-        } else if (role.isCurator) {
-          myCuratorIds.push(role.actor_id);
-        }
-      });
-    }
-
-    const memberIsContentLead = myContentLeadId !== undefined;
-    const memberIsCurator = myCuratorIds.length > 0;
-
-    const newProps = {
-      memberIsContentLead,
-      memberIsCurator,
-      myContentLeadId,
-      myCuratorIds
-    };
-
-    return <Component {...props} {...newProps} />;
-  };
-  ResultComponent.displayName = `withMyRoles(${componentName(Component)})`;
-  return ResultComponent;
-}
-
-const canUseAccount = (account: AccountId, allAccounts: SubjectInfo | undefined) => {
-  if (!allAccounts || !Object.keys(allAccounts).length) {
-    return false;
-  }
-
-  const ix = Object.keys(allAccounts).findIndex(key => {
-    return account.eq(allAccounts[key].json.address);
-  });
-
-  return ix !== -1;
-};
-
 function withCurationActor<P extends MyAccountProps> (Component: React.ComponentType<P>) {
   const ResultComponent: React.FunctionComponent<P> = (props: P) => {
     const {
       myAccountId,
       isLeadSet,
       contentLeadEntry,
-      myCuratorIds,
       curatorEntries,
-      allAccounts,
-      memberIsContentLead,
-      memberIsCurator
+      allAccounts
     } = props;
 
     if (!myAccountId || !isLeadSet || !contentLeadEntry || !curatorEntries || !allAccounts) {
       return <Component {...props} />;
     }
 
-    const leadRoleAccount = isLeadSet.isSome
-      ? new SingleLinkedMapEntry<Lead>(Lead, contentLeadEntry).value.role_account
+    let lead = isLeadSet.isSome
+      ? new SingleLinkedMapEntry<Lead>(Lead, contentLeadEntry).value
       : null;
 
-    // Is current key the content lead key?
-    if (leadRoleAccount && leadRoleAccount.eq(myAccountId)) {
-      return <Component {...props} curationActor={[new CurationActor('Lead'), myAccountId]} />;
+    // Ignore lead if he's not active
+    // TODO: Does if ever happen if we query currentLeadById?
+    if (!(lead?.stage.isOfType('Active'))) {
+      lead = null;
     }
 
-    const curators = new MultipleLinkedMapEntry<CuratorId, Curator>(CuratorId, Curator, curatorEntries);
+    const curators = new MultipleLinkedMapEntry(CuratorId, Curator, curatorEntries);
+
+    const curationActorByAccount = (accountId: AccountId | string) => {
+      if (lead && lead.role_account.toString() === accountId.toString()) {
+        return new CurationActor({ Lead: null });
+      }
 
-    const correspondingCurationActor = (accountId: AccountId, curators: MultipleLinkedMapEntry<CuratorId, Curator>) => {
-      const ix = curators.linked_values.findIndex(curator => myAccountId.eq(curator.role_account) && curator.is_active);
+      const matchingCuratorIndex = curators.linked_values.findIndex(curator =>
+        curator.is_active && accountId.toString() === curator.role_account.toString()
+      );
 
-      return ix >= 0
+      return matchingCuratorIndex >= 0
         ? new CurationActor({
-          Curator: curators.linked_keys[ix]
+          Curator: curators.linked_keys[matchingCuratorIndex]
         })
         : null;
     };
 
-    const firstMatchingCurationActor = correspondingCurationActor(myAccountId, curators);
-
-    // Is the current key corresponding to an active curator role key?
-    if (firstMatchingCurationActor) {
-      return <Component {...props} curationActor={[firstMatchingCurationActor, myAccountId]} />;
-    }
-
-    // See if we have the member's lead role account
-    if (leadRoleAccount && memberIsContentLead && canUseAccount(leadRoleAccount, allAccounts)) {
-      return <Component {...props} curationActor={[new CurationActor('Lead'), leadRoleAccount]} />;
-    }
-
-    // See if we have one of the member's curator role accounts
-    if (memberIsCurator && myCuratorIds && curators.linked_keys.length) {
-      for (let i = 0; i < myCuratorIds.length; i++) {
-        const curator_id = myCuratorIds[i];
-        const ix = curators.linked_keys.findIndex(id => id.eq(curator_id));
-
-        if (ix >= 0) {
-          const curator = curators.linked_values[ix];
-          if (curator.is_active && canUseAccount(curator.role_account, allAccounts)) {
-            return (
-              <Component
-                {...props}
-                curationActor={[new CurationActor({ Curator: curator_id }), curator.role_account]}
-              />
-            );
-          }
-        }
+    // First priority - currently selected account
+    let actor = curationActorByAccount(myAccountId);
+    let actorKey: AccountId | null = myAccountId;
+    // Second priority - check other keys and find best role
+    // TODO: Prioritize current member?
+    // TODO: Perhaps just don't do that at all and force the user to select the correct key to avoid confision?
+    if (!actor) {
+      const allActorsWithKeys = Object.keys(allAccounts).map(accKey => ({
+        actor: curationActorByAccount(allAccounts[accKey].json.address),
+        key: new GenericAccountId(allAccounts[accKey].json.address)
+      }));
+      let actorWithKey = allActorsWithKeys.find(({ actor }) => actor?.isOfType('Lead'));
+      if (!actorWithKey) {
+        actorWithKey = allActorsWithKeys.find(({ actor }) => actor?.isOfType('Curator'));
       }
+      actor = actorWithKey?.actor || null;
+      actorKey = actorWithKey?.key || null;
     }
 
-    // selected key doesn't have any special role, check other available keys..
-
-    // Use lead role key if available
-    if (leadRoleAccount && canUseAccount(leadRoleAccount, allAccounts)) {
-      return <Component {...props} curationActor={[new CurationActor('Lead'), leadRoleAccount]} />;
-    }
-
-    // Use first available active curator role key if available
-    if (curators.linked_keys.length) {
-      for (let i = 0; i < curators.linked_keys.length; i++) {
-        const curator = curators.linked_values[i];
-        if (curator.is_active && canUseAccount(curator.role_account, allAccounts)) {
-          return (
-            <Component
-              {...props}
-              curationActor={[new CurationActor({ Curator: curators.linked_keys[i] }), curator.role_account]}
-            />
-          );
-        }
-      }
+    if (actor && actorKey) {
+      return <Component {...props} curationActor={[actor, actorKey]} />;
+    } else {
+      // we don't have any key that can fulfill a curation action
+      return <Component {...props} />;
     }
-
-    // we don't have any key that can fulfill a curation action
-    return <Component {...props} />;
   };
   ResultComponent.displayName = `withCurationActor(${componentName(Component)})`;
   return ResultComponent;
@@ -280,7 +217,6 @@ export const withMyAccount = <P extends MyAccountProps>(Component: React.Compone
     withMyMembership,
     withMyProfile,
     withContentWorkingGroup,
-    withMyRoles,
     withCurationActor
   );
 

+ 5 - 5
pioneer/packages/joy-utils/src/accounts.ts

@@ -10,8 +10,7 @@ import { isHex, u8aToHex } from '@polkadot/util';
 import { keyExtractSuri, mnemonicGenerate, mnemonicValidate, randomAsU8a } from '@polkadot/util-crypto';
 
 import { ApiPromise } from '@polkadot/api';
-import { MemberId, Profile } from '@joystream/types/members';
-import { Option } from '@polkadot/types';
+import { MemberId, Membership } from '@joystream/types/members';
 import { AccountId } from '@polkadot/types/interfaces';
 import { Vec } from '@polkadot/types/codec';
 
@@ -142,17 +141,18 @@ export function isPasswordValid (password: string): boolean {
   return password.length === 0 || keyring.isPassValid(password);
 }
 
-export type MemberFromAccount = { account: string; id: number; profile?: Profile };
+export type MemberFromAccount = { account: string; id: number; profile?: Membership };
 
+// TODO: Use transport instead (now that it's available in joy-utils)
 export async function memberFromAccount (api: ApiPromise, accountId: AccountId | string): Promise<MemberFromAccount> {
   const [memberId] =
     ((await api.query.members.memberIdsByRootAccountId(accountId)) as Vec<MemberId>)
       .concat((await api.query.members.memberIdsByControllerAccountId(accountId)) as Vec<MemberId>);
-  const member = (await api.query.members.memberProfile(memberId)) as Option<Profile>;
+  const member = (await api.query.members.membershipById(memberId)) as Membership;
 
   return {
     account: accountId.toString(),
     id: memberId.toNumber(),
-    profile: member.unwrapOr(undefined)
+    profile: member.handle.isEmpty ? undefined : member
   };
 }

+ 12 - 10
pioneer/packages/joy-utils/src/transport/contentWorkingGroup.ts

@@ -1,11 +1,12 @@
-import { MemberId, Profile, ActorInRole, RoleKeys, Role } from '@joystream/types/members';
+import { Membership } from '@joystream/types/members';
 import { u128, Vec, Option } from '@polkadot/types/';
 import BaseTransport from './base';
 import { MintId, Mint } from '@joystream/types/mint';
-import { LeadId } from '@joystream/types/content-working-group';
+import { LeadId, Lead } from '@joystream/types/content-working-group';
 import { ApiPromise } from '@polkadot/api';
 import MembersTransport from './members';
 import { APIQueryCache } from '../APIQueryCache';
+import { SingleLinkedMapEntry } from '..';
 
 export default class ContentWorkingGroupTransport extends BaseTransport {
   private membersT: MembersTransport;
@@ -21,19 +22,20 @@ export default class ContentWorkingGroupTransport extends BaseTransport {
     return (WGMint[0].get('capacity') as u128).toNumber();
   }
 
-  async currentLead (): Promise<{ id: number; profile: Profile } | null> {
+  async currentLead (): Promise<{ id: number; profile: Membership } | null> {
     const optLeadId = (await this.contentWorkingGroup.currentLeadId()) as Option<LeadId>;
     const leadId = optLeadId.unwrapOr(null);
 
     if (!leadId) return null;
 
-    const actorInRole = new ActorInRole({
-      role: new Role(RoleKeys.CuratorLead),
-      actor_id: leadId
-    });
-    const memberId = (await this.members.membershipIdByActorInRole(actorInRole)) as MemberId;
-    const profile = (await this.membersT.memberProfile(memberId)).unwrapOr(null);
+    const lead = new SingleLinkedMapEntry(Lead, await this.contentWorkingGroup.leadById(leadId)).value;
 
-    return profile && { id: memberId.toNumber(), profile };
+    if (!lead.stage.isOfType('Active')) {
+      return null;
+    }
+
+    const profile = await this.membersT.expectedMembership(lead.member_id);
+
+    return profile && { id: lead.member_id.toNumber(), profile };
   }
 }

+ 6 - 6
pioneer/packages/joy-utils/src/transport/council.ts

@@ -1,7 +1,7 @@
 import { ParsedMember } from '../types/members';
 import BaseTransport from './base';
 import { Seats, ElectionParameters } from '@joystream/types/council';
-import { MemberId, Profile } from '@joystream/types/members';
+import { MemberId, Membership } from '@joystream/types/members';
 import { u32, Vec } from '@polkadot/types/';
 import { Balance, BlockNumber } from '@polkadot/types/interfaces';
 import { FIRST_MEMBER_ID } from '../consts/members';
@@ -34,7 +34,7 @@ export default class CouncilTransport extends BaseTransport {
     return Promise.all(
       council.map(async seat => {
         const memberIds = (await this.members.memberIdsByControllerAccountId(seat.member)) as Vec<MemberId>;
-        const member = (await this.membersT.memberProfile(memberIds[0])).toJSON() as ParsedMember;
+        const member = (await this.membersT.expectedMembership(memberIds[0])).toJSON() as ParsedMember;
         return {
           ...member,
           memberId: memberIds[0]
@@ -43,13 +43,13 @@ export default class CouncilTransport extends BaseTransport {
     );
   }
 
-  async membersExceptCouncil (): Promise<{ id: number; profile: Profile }[]> {
+  async membersExceptCouncil (): Promise<{ id: number; profile: Membership }[]> {
     // Council members to filter out
     const activeCouncil = (await this.council.activeCouncil()) as Seats;
-    const membersCount = ((await this.members.membersCreated()) as MemberId).toNumber();
-    const profiles: { id: number; profile: Profile }[] = [];
+    const membersCount = ((await this.members.nextMemberId()) as MemberId).toNumber();
+    const profiles: { id: number; profile: Membership }[] = [];
     for (let id = FIRST_MEMBER_ID.toNumber(); id < membersCount; ++id) {
-      const profile = (await this.membersT.memberProfile(new MemberId(id))).unwrapOr(null);
+      const profile = (await this.membersT.membershipById(new MemberId(id)));
       if (
         !profile ||
         // Filter out council members

+ 0 - 3
pioneer/packages/joy-utils/src/transport/index.ts

@@ -4,7 +4,6 @@ import ContentWorkingGroupTransport from './contentWorkingGroup';
 import ProposalsTransport from './proposals';
 import MembersTransport from './members';
 import CouncilTransport from './council';
-import StorageProvidersTransport from './storageProviders';
 import ValidatorsTransport from './validators';
 import WorkingGroupsTransport from './workingGroups';
 import { APIQueryCache } from '../APIQueryCache';
@@ -18,7 +17,6 @@ export default class Transport {
   public council: CouncilTransport;
   public proposals: ProposalsTransport;
   public contentWorkingGroup: ContentWorkingGroupTransport;
-  public storageProviders: StorageProvidersTransport;
   public validators: ValidatorsTransport;
   public workingGroups: WorkingGroupsTransport;
 
@@ -27,7 +25,6 @@ export default class Transport {
     this.cacheApi = new APIQueryCache(api);
     this.chain = new ChainTransport(api, this.cacheApi);
     this.members = new MembersTransport(api, this.cacheApi);
-    this.storageProviders = new StorageProvidersTransport(api, this.cacheApi);
     this.validators = new ValidatorsTransport(api, this.cacheApi);
     this.council = new CouncilTransport(api, this.cacheApi, this.members, this.chain);
     this.contentWorkingGroup = new ContentWorkingGroupTransport(api, this.cacheApi, this.members);

+ 14 - 8
pioneer/packages/joy-utils/src/transport/members.ts

@@ -1,18 +1,24 @@
 import BaseTransport from './base';
-import { MemberId, Profile } from '@joystream/types/members';
-import { Option } from '@polkadot/types/';
+import { MemberId, Membership } from '@joystream/types/members';
 
 export default class MembersTransport extends BaseTransport {
-  memberProfile (id: MemberId | number): Promise<Option<Profile>> {
-    return this.members.memberProfile(id) as Promise<Option<Profile>>;
+  async membershipById (id: MemberId | number): Promise<Membership | null> {
+    const member = (await this.members.membershipById(id)) as Membership;
+    // Can't just use member.isEmpty because member.suspended is Bool (which isEmpty method always returns false)
+    return member.handle.isEmpty ? null : member;
   }
 
   // Throws if profile not found
-  async expectedMemberProfile (id: MemberId | number): Promise<Profile> {
-    return (await this.memberProfile(id)).unwrap();
+  async expectedMembership (id: MemberId | number): Promise<Membership> {
+    const member = await this.membershipById(id);
+    if (!member) {
+      throw new Error(`Expected member profile not found! ID: ${id.toString()}`);
+    }
+
+    return member;
   }
 
-  async membersCreated (): Promise<number> {
-    return (await this.members.membersCreated() as MemberId).toNumber();
+  async nextMemberId (): Promise<number> {
+    return (await this.members.nextMemberId() as MemberId).toNumber();
   }
 }

+ 4 - 4
pioneer/packages/joy-utils/src/transport/proposals.ts

@@ -108,7 +108,7 @@ export default class ProposalsTransport extends BaseTransport {
     if (!rawProposal) {
       rawProposal = await this.rawProposalById(id);
     }
-    const proposer = (await this.membersT.memberProfile(rawProposal.proposerId)).toJSON() as ParsedMember;
+    const proposer = (await this.membersT.expectedMembership(rawProposal.proposerId)).toJSON() as ParsedMember;
     const proposal = rawProposal.toJSON() as {
       title: string;
       description: string;
@@ -193,7 +193,7 @@ export default class ProposalsTransport extends BaseTransport {
       'proposalsEngine.voteExistsByProposalByVoter', // Double map of intrest
       proposalId, // First double-map key value
       (v) => new VoteKind(v), // Converter from hex
-      async () => (await this.membersT.membersCreated()), // A function that returns the number of iterations to go through when chekcing possible values for the second double-map key (memberId)
+      async () => (await this.membersT.nextMemberId()), // A function that returns the number of iterations to go through when chekcing possible values for the second double-map key (memberId)
       FIRST_MEMBER_ID.toNumber() // Min. possible value for second double-map key (memberId)
     );
 
@@ -201,7 +201,7 @@ export default class ProposalsTransport extends BaseTransport {
     for (const voteEntry of voteEntries) {
       const memberId = voteEntry.secondKey;
       const vote = voteEntry.value;
-      const parsedMember = (await this.membersT.memberProfile(memberId)).toJSON() as ParsedMember;
+      const parsedMember = (await this.membersT.expectedMembership(memberId)).toJSON() as ParsedMember;
       votesWithMembers.push({
         vote,
         member: {
@@ -270,7 +270,7 @@ export default class ProposalsTransport extends BaseTransport {
         updatedAt: await this.chainT.blockTimestamp(post.updated_at.toNumber()),
         updatedAtBlock: post.updated_at.toNumber(),
         authorId: post.author_id,
-        author: (await this.membersT.memberProfile(post.author_id)).unwrapOr(null),
+        author: (await this.membersT.expectedMembership(post.author_id)),
         editsCount: post.edition_number.toNumber()
       });
     }

+ 0 - 19
pioneer/packages/joy-utils/src/transport/storageProviders.ts

@@ -1,19 +0,0 @@
-import BaseTransport from './base';
-import { IStorageRoleParameters } from '../types/storageProviders';
-import { RoleKeys } from '@joystream/types/members';
-import { Vec } from '@polkadot/types/';
-import { AccountId } from '@polkadot/types/interfaces';
-
-export default class StorageProvidersTransport extends BaseTransport {
-  async roleParameters (): Promise<IStorageRoleParameters> {
-    const params = (
-      await this.api.query.actors.parameters(RoleKeys.StorageProvider)
-    ).toJSON() as IStorageRoleParameters;
-    return params;
-  }
-
-  async providers (): Promise<AccountId[]> {
-    const providers = (await this.actors.accountIdsByRole(RoleKeys.StorageProvider)) as Vec<AccountId>;
-    return providers.toArray();
-  }
-}

+ 2 - 2
pioneer/packages/joy-utils/src/transport/workingGroups.ts

@@ -46,7 +46,7 @@ export default class WorkingGroupsTransport extends BaseTransport {
       ? (await this.rewardRelationship(worker.reward_relationship.unwrap()))
       : undefined;
 
-    const profile = await this.membersT.expectedMemberProfile(worker.member_id);
+    const profile = await this.membersT.expectedMembership(worker.member_id);
 
     return { group, workerId, worker, profile, stake, reward };
   }
@@ -135,7 +135,7 @@ export default class WorkingGroupsTransport extends BaseTransport {
     return {
       wgApplicationId,
       applicationId: appId.toNumber(),
-      member: await this.membersT.expectedMemberProfile(wgApplication.member_id),
+      member: await this.membersT.expectedMembership(wgApplication.member_id),
       roleAccout: wgApplication.role_account_id,
       stakes: {
         application: appStakingId.isSome ? (await this.stakeValue(appStakingId.unwrap())).toNumber() : 0,

+ 0 - 1
pioneer/packages/joy-utils/src/types/members.ts

@@ -4,7 +4,6 @@ export type ParsedMember = {
   handle: string;
   registered_at_block: number;
   registered_at_time: number;
-  roles: any[];
   entry: { [k: string]: any };
   root_account: string;
   controller_account: string;

+ 2 - 2
pioneer/packages/joy-utils/src/types/proposals.ts

@@ -1,5 +1,5 @@
 import { ProposalId, VoteKind } from '@joystream/types/proposals';
-import { MemberId, Profile } from '@joystream/types/members';
+import { MemberId, Membership } from '@joystream/types/members';
 import { ThreadId, PostId } from '@joystream/types/common';
 import { ParsedMember } from './members';
 
@@ -98,7 +98,7 @@ export type ParsedPost = {
   createdAtBlock: number;
   updatedAt: Date;
   updatedAtBlock: number;
-  author: Profile | null;
+  author: Membership | null;
   authorId: MemberId;
   editsCount: number;
 };

+ 3 - 3
pioneer/packages/joy-utils/src/types/workingGroups.ts

@@ -1,5 +1,5 @@
 import { Worker, Opening as WGOpening } from '@joystream/types/working-group';
-import { Profile } from '@joystream/types/members';
+import { Membership } from '@joystream/types/members';
 import { OpeningId, Opening, ApplicationStage } from '@joystream/types/hiring';
 import { AccountId } from '@polkadot/types/interfaces';
 import { WorkingGroupKey } from '@joystream/types/common';
@@ -8,7 +8,7 @@ import { RewardRelationship } from '@joystream/types/recurring-rewards';
 export type WorkerData = {
   workerId: number;
   worker: Worker;
-  profile: Profile;
+  profile: Membership;
   stake?: number;
   reward?: RewardRelationship;
   group: WorkingGroupKey;
@@ -23,7 +23,7 @@ export type OpeningData = {
 export type ParsedApplication = {
   wgApplicationId: number;
   applicationId: number;
-  member: Profile;
+  member: Membership;
   roleAccout: AccountId;
   stakes: {
     application: number;

+ 2 - 1
tests/network-tests/package.json

@@ -14,7 +14,8 @@
   },
   "dependencies": {
     "@constantinople/types@npm:@joystream/types": "^0.10.0",
-    "@nicaea/types": "link:../../types",
+    "@nicaea/types@npm:@joystream/types": "^0.12.0",
+    "@alexandria/types": "link:../../types",
     "@polkadot/api": "^0.96.1",
     "@polkadot/keyring": "^1.7.0-beta.5",
     "@rome/types@npm:@joystream/types": "^0.7.0",

+ 1 - 1
tests/network-tests/src/iznik/tests/council/electingCouncilTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import BN from 'bn.js'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { closeApi } from '../../utils/closeApi'
 import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule'

+ 1 - 1
tests/network-tests/src/iznik/tests/fixtures/councilElectionModule.ts

@@ -2,7 +2,7 @@ import { ApiWrapper } from '../../utils/apiWrapper'
 import { KeyringPair } from '@polkadot/keyring/types'
 import BN from 'bn.js'
 import { assert } from 'chai'
-import { Seat } from '@nicaea/types/council'
+import { Seat } from '@alexandria/types/council'
 import { v4 as uuid } from 'uuid'
 import { Utils } from '../../utils/utils'
 import { Fixture } from './interfaces/fixture'

+ 4 - 4
tests/network-tests/src/iznik/tests/fixtures/proposalsModule.ts

@@ -2,7 +2,7 @@ import { KeyringPair } from '@polkadot/keyring/types'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { v4 as uuid } from 'uuid'
 import BN from 'bn.js'
-import { FillOpeningParameters } from '@nicaea/types/proposals'
+import { FillOpeningParameters } from '@alexandria/types/proposals'
 import { Fixture } from './interfaces/fixture'
 import { Bytes, Option, u32 } from '@polkadot/types'
 import { Balance, BlockNumber } from '@polkadot/types/interfaces'
@@ -13,9 +13,9 @@ import {
   ApplicationRationingPolicy,
   OpeningId,
   StakingPolicy,
-} from '@nicaea/types/hiring'
-import { RewardPolicy, SlashingTerms, WorkingGroupOpeningPolicyCommitment } from '@nicaea/types/working-group'
-import { WorkingGroup } from '@nicaea/types/common'
+} from '@alexandria/types/hiring'
+import { RewardPolicy, SlashingTerms, WorkingGroupOpeningPolicyCommitment } from '@alexandria/types/working-group'
+import { WorkingGroup } from '@alexandria/types/common'
 
 export class CreateWorkingGroupLeaderOpeningFixture implements Fixture {
   private apiWrapper: ApiWrapper

+ 3 - 3
tests/network-tests/src/iznik/tests/fixtures/workingGroupModule.ts

@@ -6,21 +6,21 @@ import { Balance, BlockNumber, Event } from '@polkadot/types/interfaces'
 import { Keyring } from '@polkadot/api'
 import { Option, u32 } from '@polkadot/types'
 import { v4 as uuid } from 'uuid'
-import { RewardRelationship } from '@nicaea/types/recurring-rewards'
+import { RewardRelationship } from '@alexandria/types/recurring-rewards'
 import {
   Application,
   ApplicationIdToWorkerIdMap,
   SlashingTerms,
   Worker,
   WorkingGroupOpeningPolicyCommitment,
-} from '@nicaea/types/working-group'
+} from '@alexandria/types/working-group'
 import { Utils } from '../../utils/utils'
 import {
   ActivateOpeningAt,
   ApplicationRationingPolicy,
   Opening as HiringOpening,
   StakingPolicy,
-} from '@nicaea/types/hiring'
+} from '@alexandria/types/hiring'
 import { Fixture } from './interfaces/fixture'
 
 export class AddWorkerOpeningFixture implements Fixture {

+ 1 - 1
tests/network-tests/src/iznik/tests/membership/membershipCreationTest.ts

@@ -3,7 +3,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import { initConfig } from '../../utils/config'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { closeApi } from '../../utils/closeApi'
 import { BuyMembershipHappyCaseFixture, BuyMembershipWithInsufficienFundsFixture } from '../fixtures/membershipModule'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { ContentWorkingGroupMintCapacityProposalFixture } from '../fixtures/proposalsModule'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/manageLeaderRoleTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { Utils } from '../../utils/utils'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { Utils } from '../../utils/utils'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { Utils } from '../../utils/utils'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/updateRuntime.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { Utils } from '../../utils/utils'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper } from '../../utils/apiWrapper'
 import { Utils } from '../../utils/utils'

+ 1 - 1
tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts

@@ -4,7 +4,7 @@ import { Keyring, WsProvider } from '@polkadot/api'
 import BN from 'bn.js'
 import { setTestTimeout } from '../../utils/setTestTimeout'
 import tap from 'tap'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { Utils } from '../../utils/utils'

+ 1 - 1
tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts

@@ -1,5 +1,5 @@
 import { initConfig } from '../../utils/config'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { WsProvider, Keyring } from '@polkadot/api'

+ 1 - 1
tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts

@@ -1,5 +1,5 @@
 import { initConfig } from '../../utils/config'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { WsProvider, Keyring } from '@polkadot/api'

+ 1 - 1
tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts

@@ -1,5 +1,5 @@
 import { initConfig } from '../../utils/config'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { WsProvider, Keyring } from '@polkadot/api'

+ 1 - 1
tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts

@@ -1,5 +1,5 @@
 import { initConfig } from '../../utils/config'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { WsProvider, Keyring } from '@polkadot/api'

+ 1 - 1
tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts

@@ -1,5 +1,5 @@
 import { initConfig } from '../../utils/config'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { WsProvider, Keyring } from '@polkadot/api'

+ 1 - 1
tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts

@@ -1,5 +1,5 @@
 import { initConfig } from '../../utils/config'
-import { registerJoystreamTypes } from '@nicaea/types'
+import { registerJoystreamTypes } from '@alexandria/types'
 import { closeApi } from '../../utils/closeApi'
 import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper'
 import { WsProvider, Keyring } from '@polkadot/api'

+ 13 - 13
tests/network-tests/src/iznik/utils/apiWrapper.ts

@@ -2,9 +2,9 @@ import { ApiPromise, WsProvider } from '@polkadot/api'
 import { Bytes, Option, u32, Vec } from '@polkadot/types'
 import { Codec } from '@polkadot/types/types'
 import { KeyringPair } from '@polkadot/keyring/types'
-import { MemberId, PaidMembershipTerms, UserInfo } from '@nicaea/types/members'
-import { Mint, MintId } from '@nicaea/types/mint'
-import { Lead, LeadId } from '@nicaea/types/content-working-group'
+import { MemberId, PaidMembershipTerms } from '@alexandria/types/members'
+import { Mint, MintId } from '@alexandria/types/mint'
+import { Lead, LeadId } from '@alexandria/types/content-working-group'
 import {
   Application,
   ApplicationIdToWorkerIdMap,
@@ -14,16 +14,16 @@ import {
   Worker,
   WorkerId,
   WorkingGroupOpeningPolicyCommitment,
-} from '@nicaea/types/working-group'
-import { RoleParameters } from '@nicaea/types/roles'
-import { Seat } from '@nicaea/types/council'
+} from '@alexandria/types/working-group'
+import { RoleParameters } from '@alexandria/types/roles'
+import { Seat } from '@alexandria/types/council'
 import { AccountId, Balance, BalanceOf, BlockNumber, Event, EventRecord } from '@polkadot/types/interfaces'
 import BN from 'bn.js'
 import { SubmittableExtrinsic } from '@polkadot/api/types'
 import { Sender } from './sender'
 import { Utils } from './utils'
-import { Stake, StakedState } from '@nicaea/types/stake'
-import { RewardRelationship } from '@nicaea/types/recurring-rewards'
+import { Stake, StakedState } from '@alexandria/types/stake'
+import { RewardRelationship } from '@alexandria/types/recurring-rewards'
 import {
   ActivateOpeningAt,
   Application as HiringApplication,
@@ -32,9 +32,9 @@ import {
   Opening as HiringOpening,
   OpeningId,
   StakingPolicy,
-} from '@nicaea/types/hiring'
-import { FillOpeningParameters } from '@nicaea/types/proposals'
-import { WorkingGroup } from '@nicaea/types/common'
+} from '@alexandria/types/hiring'
+import { FillOpeningParameters } from '@alexandria/types/proposals'
+import { WorkingGroup } from '@alexandria/types/common'
 
 export enum WorkingGroups {
   StorageWorkingGroup = 'storageWorkingGroup',
@@ -74,7 +74,7 @@ export class ApiWrapper {
     expectFailure = false
   ): Promise<void> {
     return this.sender.signAndSend(
-      this.api.tx.members.buyMembership(paidTermsId, new UserInfo({ 'handle': name, 'avatar_uri': '', 'about': '' })),
+      this.api.tx.members.buyMembership(paidTermsId, /* Handle: */ name, /* Avatar uri: */ '', /* About: */ ''),
       account,
       expectFailure
     )
@@ -120,7 +120,7 @@ export class ApiWrapper {
 
   public estimateBuyMembershipFee(account: KeyringPair, paidTermsId: number, name: string): BN {
     return this.estimateTxFee(
-      this.api.tx.members.buyMembership(paidTermsId, new UserInfo({ 'handle': name, 'avatar_uri': '', 'about': '' }))
+      this.api.tx.members.buyMembership(paidTermsId, /* Handle: */ name, /* Avatar uri: */ '', /* About: */ '')
     )
   }
 

+ 1 - 1
tests/network-tests/src/iznik/utils/utils.ts

@@ -4,7 +4,7 @@ import { blake2AsHex } from '@polkadot/util-crypto'
 import BN from 'bn.js'
 import fs from 'fs'
 import Keyring, { decodeAddress } from '@polkadot/keyring'
-import { Seat } from '@nicaea/types/council'
+import { Seat } from '@alexandria/types/council'
 import { KeyringPair } from '@polkadot/keyring/types'
 import { v4 as uuid } from 'uuid'
 

+ 2 - 2
types/package.json

@@ -1,7 +1,7 @@
 {
   "name": "@joystream/types",
-  "version": "0.12.0",
-  "description": "Types for Joystream Substrate Runtime - nicaea release",
+  "version": "0.13.0",
+  "description": "Types for Joystream Substrate Runtime - Alexandria release",
   "main": "index.js",
   "types": "index.d.ts",
   "scripts": {

+ 15 - 24
types/src/content-working-group/index.ts

@@ -20,6 +20,7 @@ import { OpeningId, ApplicationId, ApplicationRationingPolicy, StakingPolicy } f
 import { RewardRelationshipId } from '../recurring-rewards'
 
 import ChannelId from './ChannelId'
+import { JoyEnum } from '../JoyEnum'
 export { ChannelId }
 export class CuratorId extends ActorId {}
 export class CuratorOpeningId extends OpeningId {}
@@ -97,18 +98,10 @@ export class Channel extends JoyStruct<IChannel> {
   }
 }
 
-export class CurationActor extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Lead: Null,
-        Curator: CuratorId,
-      },
-      value,
-      index
-    )
-  }
-}
+export class CurationActor extends JoyEnum({
+  Lead: Null,
+  Curator: CuratorId,
+}) {}
 
 export class Principal extends Enum {
   constructor(value?: any, index?: number) {
@@ -489,20 +482,13 @@ export class ExitedLeadRole extends JoyStruct<IExitedLeadRole> {
   }
 }
 
-export class LeadRoleState extends Enum {
-  constructor(value?: any, index?: number) {
-    super(
-      {
-        Active: Null,
-        Exited: ExitedLeadRole,
-      },
-      value,
-      index
-    )
-  }
-}
+export class LeadRoleState extends JoyEnum({
+  Active: Null,
+  Exited: ExitedLeadRole,
+} as const) {}
 
 export type ILead = {
+  member_id: MemberId
   role_account: AccountId
   reward_relationship: Option<RewardRelationshipId>
   inducted: BlockNumber
@@ -512,6 +498,7 @@ export class Lead extends JoyStruct<ILead> {
   constructor(value?: ILead) {
     super(
       {
+        member_id: MemberId,
         role_account: GenericAccountId,
         reward_relationship: Option.with(RewardRelationshipId),
         inducted: u32,
@@ -521,6 +508,10 @@ export class Lead extends JoyStruct<ILead> {
     )
   }
 
+  get member_id(): MemberId {
+    return this.getField<MemberId>('member_id')
+  }
+
   get role_account(): GenericAccountId {
     return this.getField<GenericAccountId>('role_account')
   }

+ 5 - 80
types/src/members.ts

@@ -10,10 +10,9 @@ import {
   u128,
   Text,
   GenericAccountId,
-  Vec,
 } from '@polkadot/types'
 import { BlockNumber, Moment, BalanceOf } from '@polkadot/types/interfaces'
-import { OptionText, JoyStruct } from './common'
+import { JoyStruct } from './common'
 import AccountId from '@polkadot/types/primitive/Generic/AccountId'
 
 export class MemberId extends u64 {}
@@ -38,48 +37,7 @@ export class EntryMethod extends Enum {
   }
 }
 
-export enum RoleKeys {
-  StorageProvider = 'StorageProvider',
-  ChannelOwner = 'ChannelOwner',
-  CuratorLead = 'CuratorLead',
-  Curator = 'Curator',
-}
-
-export class Role extends Enum {
-  constructor(value?: any, index?: number) {
-    super([RoleKeys.StorageProvider, RoleKeys.ChannelOwner, RoleKeys.CuratorLead, RoleKeys.Curator], value, index)
-  }
-}
-
-export class ActorInRole extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        role: Role,
-        actor_id: ActorId,
-      },
-      value
-    )
-  }
-
-  get role(): Role {
-    return this.get('role') as Role
-  }
-
-  get actor_id(): ActorId {
-    return this.get('actor_id') as ActorId
-  }
-
-  get isContentLead(): boolean {
-    return this.role.eq(RoleKeys.CuratorLead)
-  }
-
-  get isCurator(): boolean {
-    return this.role.eq(RoleKeys.Curator)
-  }
-}
-
-export type IProfile = {
+export type IMembership = {
   handle: Text
   avatar_uri: Text
   about: Text
@@ -90,10 +48,9 @@ export type IProfile = {
   subscription: Option<SubscriptionId>
   root_account: AccountId
   controller_account: AccountId
-  roles: Vec<ActorInRole>
 }
-export class Profile extends JoyStruct<IProfile> {
-  constructor(value?: IProfile) {
+export class Membership extends JoyStruct<IMembership> {
+  constructor(value?: IMembership) {
     super(
       {
         handle: Text,
@@ -106,7 +63,6 @@ export class Profile extends JoyStruct<IProfile> {
         subscription: Option.with(SubscriptionId),
         root_account: AccountId,
         controller_account: AccountId,
-        roles: Vec.with(ActorInRole),
       },
       value
     )
@@ -151,29 +107,6 @@ export class Profile extends JoyStruct<IProfile> {
   get controller_account(): AccountId {
     return this.get('controller_account') as AccountId
   }
-
-  get roles(): Vec<ActorInRole> {
-    return this.get('roles') as Vec<ActorInRole>
-  }
-}
-
-export class UserInfo extends Struct {
-  constructor(value?: any) {
-    super(
-      {
-        handle: OptionText,
-        avatar_uri: OptionText,
-        about: OptionText,
-      },
-      value
-    )
-  }
-}
-
-export type CheckedUserInfo = {
-  handle: Text
-  avatar_uri: Text
-  about: Text
 }
 
 export class PaidMembershipTerms extends Struct {
@@ -204,20 +137,12 @@ export function registerMembershipTypes() {
       MemberId,
       PaidTermId,
       SubscriptionId,
-      Profile,
-      UserInfo,
-      CheckedUserInfo: {
-        handle: 'Text',
-        avatar_uri: 'Text',
-        about: 'Text',
-      },
+      Membership,
       PaidMembershipTerms: {
         fee: 'BalanceOf',
         text: 'Text',
       },
-      Role,
       ActorId,
-      ActorInRole,
     })
   } catch (err) {
     console.error('Failed to register custom types of membership module', err)

+ 18 - 5
yarn.lock

@@ -2,6 +2,10 @@
 # yarn lockfile v1
 
 
+"@alexandria/types@link:types":
+  version "0.0.0"
+  uid ""
+
 "@babel/cli@^7.7.4":
   version "7.7.4"
   resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.7.4.tgz#38804334c8db40209f88c69a5c90998e60cca18b"
@@ -1828,8 +1832,21 @@
     "@types/istanbul-reports" "^1.1.1"
     "@types/yargs" "^13.0.0"
 
-"@joystream/types@link:types":
+"@joystream/types@^0.12.0", "@nicaea/types@npm:@joystream/types@^0.12.0":
   version "0.12.0"
+  resolved "https://registry.yarnpkg.com/@joystream/types/-/types-0.12.0.tgz#4033967ae2ac111f894fb4100e414f7cdbe95611"
+  integrity sha512-pHHYTbIa6V1C4k9aj+M6Fkwa2I2Br+4x7cuvREmrVh21GHjGuzoIwB74MfqFajdSTDQDZbjdixcYDES6uo3sUg==
+  dependencies:
+    "@polkadot/keyring" "^1.7.0-beta.5"
+    "@polkadot/types" "^0.96.1"
+    "@types/lodash" "^4.14.157"
+    "@types/vfile" "^4.0.0"
+    ajv "^6.11.0"
+    lodash "^4.17.15"
+    moment "^2.24.0"
+
+"@joystream/types@link:types":
+  version "0.13.0"
   dependencies:
     "@polkadot/keyring" "^1.7.0-beta.5"
     "@polkadot/types" "^0.96.1"
@@ -2584,10 +2601,6 @@
     call-me-maybe "^1.0.1"
     glob-to-regexp "^0.3.0"
 
-"@nicaea/types@link:types":
-  version "0.0.0"
-  uid ""
-
 "@nodelib/fs.scandir@2.1.3":
   version "2.1.3"
   resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"