diff --git a/runner/src/indexer/indexer.ts b/runner/src/indexer/indexer.ts index fd69a3898..6a8c43267 100644 --- a/runner/src/indexer/indexer.ts +++ b/runner/src/indexer/indexer.ts @@ -13,12 +13,28 @@ interface Dependencies { parser: Parser }; +// '@near-lake/primitives/receipt' FunctionCall but with base64 decoded args +declare class DecodedFunctionCall { + readonly methodName: string; + readonly args: string; + readonly gas: number; + readonly deposit: string; + constructor (methodName: string, args: string, gas: number, deposit: string); +} + interface Context { graphql: (operation: string, variables?: Record) => Promise set: (key: string, value: any) => Promise log: (...log: any[]) => Promise fetchFromSocialApi: (path: string, options?: any) => Promise db: Record any>> + base64Decode: (base64EncodedString: string) => string + getFunctionCalls: ( + block: Block, + contract: string, + method: string, + ) => DecodedFunctionCall[] + getSocialOperations: (block: Block, operation: string) => Array> } interface IndexerFunction { @@ -140,6 +156,26 @@ export default class Indexer { const functionNameWithoutAccount = functionName.split('/')[1].replace(/[.-]/g, '_'); const schemaName = functionName.replace(/[^a-zA-Z0-9]/g, '_'); + const base64DecodeFunction = (base64EncodedString: string): string => { + const buff = Buffer.from(base64EncodedString, 'base64'); + return JSON.parse(buff.toString('utf-8')); + }; + const getFunctionCallsFunction = (block: Block, contract: string, method: string): any[] => { + return block + .actions() + .filter((action) => action.receiverId === contract) + .flatMap((action) => + action.operations + // @ts-expect-error block data is an object keyed by type + .map(({ FunctionCall }) => FunctionCall) + .filter((operation) => operation?.methodName === method) + .map((functionCallOperation) => ({ + ...functionCallOperation, + args: base64DecodeFunction(functionCallOperation.args), + })), + ); + }; + return { graphql: async (operation, variables) => { console.log(`${functionName}: Running context graphql`, operation); @@ -164,7 +200,25 @@ export default class Indexer { fetchFromSocialApi: async (path, options) => { return await this.deps.fetch(`https://api.near.social${path}`, options); }, - db: this.buildDatabaseContext(account, schemaName, schema, blockHeight) + db: this.buildDatabaseContext(account, schemaName, schema, blockHeight), + base64Decode: base64DecodeFunction, + getFunctionCalls: getFunctionCallsFunction, + getSocialOperations: (block, operation) => { + const contract = 'social.near'; + const method = 'set'; + return getFunctionCallsFunction(block, contract, method) + .filter((functionCall) => { + const accountId = Object.keys(functionCall.args.data)[0]; + return functionCall.args.data[accountId][operation]; + }) + .map((functionCall) => { + const accountId = Object.keys(functionCall.args.data)[0]; + return { + accountId, + data: functionCall.args.data[accountId][operation], + }; + }); + }, }; }