Переглянути джерело

Merge pull request #2435 from ondratra/query_node_sudo_calls

query node - mappings support for sudo calls
Mokhtar Naamani 3 роки тому
батько
коміт
7b777bcdcb

+ 53 - 0
query-node/mappings/src/common.ts

@@ -1,6 +1,7 @@
 import { SubstrateEvent } from '@dzlzv/hydra-common'
 import { DatabaseManager } from '@dzlzv/hydra-db-utils'
 import { u64 } from '@polkadot/types/primitive';
+import { SubstrateExtrinsic, ExtrinsicArg } from '@dzlzv/hydra-common'
 
 // Asset
 import {
@@ -67,6 +68,58 @@ export async function prepareDataObject(
   return dataObject
 }
 
+/////////////////// Sudo extrinsic calls ///////////////////////////////////////
+
+// soft-peg interface for typegen-generated `*Call` types
+export interface IGenericExtrinsicObject<T> {
+  readonly extrinsic: SubstrateExtrinsic
+  readonly expectedArgTypes: string[]
+  args: T
+}
+
+// arguments for calling extrinsic as sudo
+export interface ISudoCallArgs<T> extends ExtrinsicArg {
+  args: T
+  callIndex: string
+}
+
+/*
+  Extracts extrinsic arguments from the Substrate event. Supports both direct extrinsic calls and sudo calls.
+*/
+export function extractExtrinsicArgs<DataParams, EventObject extends IGenericExtrinsicObject<DataParams>>(
+  rawEvent: SubstrateEvent,
+  callFactory: new (event: SubstrateEvent) => EventObject
+): DataParams {
+  // escape when extrinsic info is not available
+  if (!rawEvent.extrinsic) {
+    throw 'Invalid event - no extrinsic set' // this should never happen
+  }
+
+  // regural extrinsic call?
+  if (rawEvent.extrinsic.section != 'sudo') {
+    return (new callFactory(rawEvent)).args
+  }
+
+  // sudo extrinsic call
+
+  // see Substrate's sudo frame for more info about sudo extrinsics and `call` argument index
+  const argIndex = false
+    || (rawEvent.extrinsic.method == 'sudoAs' && 1) // who, *call*
+    || (rawEvent.extrinsic.method == 'sudo' && 0) // *call*
+    || (rawEvent.extrinsic.method == 'sudoUncheckedWeight' && 0) // *call*, _weight
+
+  // ensure `call` argument was found
+  if (argIndex === false) {
+    // this could possibly happen in sometime in future if new sudo options are introduced in Substrate
+    throw 'Not implemented situation with sudo'
+  }
+
+  // typecast call arguments
+  const callArgs = rawEvent.extrinsic.args[argIndex].value as unknown as ISudoCallArgs<DataParams>
+
+  return callArgs.args
+}
+
 /////////////////// Logger /////////////////////////////////////////////////////
 
 /*

+ 0 - 2
query-node/mappings/src/content/channel.ts

@@ -197,7 +197,6 @@ export async function content_ChannelCategoryCreated(
 ) {
   // read event data
   const {channelCategoryCreationParameters, channelCategoryId} = new Content.ChannelCategoryCreatedEvent(event).data
-  const {actor: contentActor} = new Content.CreateChannelCategoryCall(event).args
 
   // read metadata
   const protobufContent = await readProtobuf(
@@ -240,7 +239,6 @@ export async function content_ChannelCategoryUpdated(
   const {
     channelCategoryId,
     channelCategoryUpdateParameters,
-    contentActor,
   } = new Content.ChannelCategoryUpdatedEvent(event).data
 
   // load channel category

+ 7 - 6
query-node/mappings/src/membership.ts

@@ -9,6 +9,7 @@ import { FindConditions } from 'typeorm'
 import {
   inconsistentState,
   logger,
+  extractExtrinsicArgs,
 } from './common'
 import { Members } from '../../generated/types'
 import { MembershipEntryMethod, Membership } from 'query-node'
@@ -18,7 +19,7 @@ import { EntryMethod } from '@joystream/types/augment'
 export async function members_MemberRegistered(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
   const { accountId, memberId, entryMethod } = new Members.MemberRegisteredEvent(event).data
-  const { avatarUri, about, handle } = new Members.BuyMembershipCall(event).args
+  const { avatarUri, about, handle } = extractExtrinsicArgs(event, Members.BuyMembershipCall)
 
   // create new membership
   const member = new Membership({
@@ -47,7 +48,7 @@ export async function members_MemberRegistered(db: DatabaseManager, event: Subst
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function members_MemberUpdatedAboutText(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const { text, memberId } = new Members.ChangeMemberAboutTextCall(event).args
+  const { text, memberId } = extractExtrinsicArgs(event, Members.ChangeMemberAboutTextCall)
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -73,7 +74,7 @@ export async function members_MemberUpdatedAboutText(db: DatabaseManager, event:
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function members_MemberUpdatedAvatar(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const { uri, memberId } = new Members.ChangeMemberAvatarCall(event).args
+  const { uri, memberId } = extractExtrinsicArgs(event, Members.ChangeMemberAvatarCall)
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -99,7 +100,7 @@ export async function members_MemberUpdatedAvatar(db: DatabaseManager, event: Su
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function members_MemberUpdatedHandle(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const { handle, memberId } = new Members.ChangeMemberHandleCall(event).args
+  const { handle, memberId } = extractExtrinsicArgs(event, Members.ChangeMemberHandleCall)
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -125,7 +126,7 @@ export async function members_MemberUpdatedHandle(db: DatabaseManager, event: Su
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function members_MemberSetRootAccount(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const { newRootAccount, memberId } = new Members.SetRootAccountCall(event).args
+  const { newRootAccount, memberId } = extractExtrinsicArgs(event, Members.SetRootAccountCall)
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -151,7 +152,7 @@ export async function members_MemberSetRootAccount(db: DatabaseManager, event: S
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function members_MemberSetControllerAccount(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const { newControllerAccount, memberId } = new Members.SetControllerAccountCall(event).args
+  const { newControllerAccount, memberId } = extractExtrinsicArgs(event, Members.SetControllerAccountCall)
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })