Integrate generated watcher to invoke handlers in graph-node (#33)

* Invoke handlers based on watcher-ts events

* Read subgraph yaml and listen to events from watcher-ts

* Create GraphWatcher class to use in generated example contract watcher

* Call graph-node event handler from generated watcher
This commit is contained in:
2021-12-28 16:08:05 +05:30
committed by nabarun
parent 1c15c1eedb
commit 6cca55a1ab
51 changed files with 2533 additions and 384 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
import path from 'path';
import { instantiate } from './index';
import { instantiate } from './loader';
import { createEvent } from './utils';
describe('call handler in mapping code', () => {
+1 -1
View File
@@ -6,7 +6,7 @@ import assert from 'assert';
import { ethers } from 'ethers';
import path from 'path';
import { instantiate } from './index';
import { instantiate } from './loader';
import { createEvent } from './utils';
import edenNetworkAbi from '../test/subgraph/eden/EdenNetwork/abis/EdenNetwork.json';
import merkleDistributorAbi from '../test/subgraph/eden/EdenNetworkDistribution/abis/MerkleDistributor.json';
+1 -1
View File
@@ -5,7 +5,7 @@
import assert from 'assert';
import path from 'path';
import { instantiate } from './index';
import { instantiate } from './loader';
import exampleAbi from '../test/subgraph/example1/build/Example1/abis/Example1.json';
describe('eth-call wasm tests', () => {
+1 -363
View File
@@ -1,363 +1 @@
//
// Copyright 2021 Vulcanize, Inc.
//
import assert from 'assert';
import fs from 'fs/promises';
import loader from '@vulcanize/assemblyscript/lib/loader';
import {
utils,
BigNumber,
getDefaultProvider,
Contract,
ContractInterface
} from 'ethers';
import { TypeId } from './types';
import { fromEthereumValue, toEthereumValue } from './utils';
const NETWORK_URL = 'http://127.0.0.1:8081';
type idOfType = (TypeId: number) => number
interface DataSource {
address: string
}
interface GraphData {
abis?: {[key: string]: ContractInterface};
dataSource?: DataSource;
}
export const instantiate = async (filePath: string, data: GraphData = {}): Promise<loader.ResultObject & { exports: any }> => {
const { abis = {}, dataSource } = data;
const buffer = await fs.readFile(filePath);
const provider = getDefaultProvider(NETWORK_URL);
const imports: WebAssembly.Imports = {
index: {
'store.get': async (entity: number, id: number) => {
console.log('store.get');
const entityString = __getString(entity);
console.log('entity:', entityString);
const idString = __getString(id);
console.log('id:', idString);
// TODO: Implement store get to fetch from DB using entity and id.
// TODO: Fill entity with field values.
// return Entity.__new()
return null;
},
'store.set': async (entity: number, id: number, data: number) => {
console.log('store.set');
const entityString = __getString(entity);
console.log('entity:', entityString);
const idString = __getString(id);
console.log('id:', idString);
const entityInstance = await Entity.wrap(data);
const entityInstanceId = __getString(await entityInstance.getString(await __newString('id')));
console.log('entity instance id:', entityInstanceId);
// TODO: Implement store set to save entity in db with values from entityInstance.
},
'typeConversion.stringToH160': () => {
console.log('index typeConversion.stringToH160');
},
'typeConversion.bytesToHex': () => {
console.log('index typeConversion.bytesToHex');
},
// 'typeConversion.bytesToString': () => {
// console.log('typeConversion.bytesToString');
// },
'typeConversion.bigIntToString': () => {
console.log('index typeConversion.bigIntToString');
},
// 'bigDecimal.fromString': () => {
// console.log('bigDecimal.fromString');
// },
// 'bigDecimal.times': () => {
// console.log('bigDecimal.times');
// },
'bigDecimal.dividedBy': () => {
console.log('bigDecimal.dividedBy');
},
// 'bigDecimal.plus': () => {
// console.log('bigDecimal.plus');
// },
// 'bigDecimal.minus': () => {
// console.log('bigDecimal.minus');
// },
'bigInt.plus': () => {
console.log('bigInt.plus');
},
'bigInt.minus': () => {
console.log('bigInt.minus');
},
'bigInt.times': () => {
console.log('bigInt.times');
},
'bigInt.dividedBy': () => {
console.log('bigInt.dividedBy');
},
// 'bigInt.mod': () => {
// console.log('bigInt.mod');
// },
'bigInt.fromString': () => {
console.log('bigInt.fromString');
},
'log.log': (_: number, msg: number) => {
console.log('log.log', __getString(msg));
},
// 'dataSource.create': () => {
// console.log('dataSource.create');
// },
'dataSource.address': () => {
console.log('dataSource.address');
},
'test.asyncMethod': async () => {
console.log('before timer start');
await new Promise(resolve => {
setTimeout(() => {
resolve(1);
}, 3000);
});
console.log('after timer complete');
return 123;
}
},
ethereum: {
'ethereum.call': async (call: number) => {
const smartContractCall = await ethereum.SmartContractCall.wrap(call);
const contractAddress = await Address.wrap(await smartContractCall.contractAddress);
const contractName = __getString(await smartContractCall.contractName);
const functionName = __getString(await smartContractCall.functionName);
const functionSignature = __getString(await smartContractCall.functionSignature);
let functionParams = __getArray(await smartContractCall.functionParams);
console.log('ethereum.call params');
console.log('functionSignature:', functionSignature);
const abi = abis[contractName];
const contract = new Contract(__getString(await contractAddress.toHexString()), abi, provider);
try {
const functionParamsPromise = functionParams.map(async param => {
const ethereumValue = await ethereum.Value.wrap(param);
return fromEthereumValue(exports, ethereumValue);
});
functionParams = await Promise.all(functionParamsPromise);
// TODO: Check for function overloading.
let result = await contract[functionName](...functionParams);
if (!Array.isArray(result)) {
result = [result];
}
// TODO: Check for function overloading.
// Using function signature does not work.
const outputs = contract.interface.getFunction(functionName).outputs;
const resultPtrArrayPromise = result.map(async (value: any, index: number) => {
assert(outputs);
return toEthereumValue(exports, value, outputs[index].type);
});
const resultPtrArray: any[] = await Promise.all(resultPtrArrayPromise);
const res = await __newArray(await getIdOfType(TypeId.ArrayEthereumValue), resultPtrArray);
return res;
} catch (err) {
console.log('eth_call error', err);
return null;
}
}
},
conversion: {
'typeConversion.stringToH160': async (s: number) => {
const string = __getString(s);
const address = utils.getAddress(string);
const byteArray = utils.arrayify(address);
const uint8ArrayId = await getIdOfType(TypeId.Uint8Array);
const ptr = __newArray(uint8ArrayId, byteArray);
return ptr;
},
'typeConversion.bigIntToString': (bigInt: number) => {
const bigIntByteArray = __getArray(bigInt);
const bigNumber = BigNumber.from(bigIntByteArray);
const ptr = __newString(bigNumber.toString());
return ptr;
},
'typeConversion.bigIntToHex': () => {
console.log('index typeConversion.bigIntToHex');
},
'typeConversion.bytesToHex': async (bytes: number) => {
const byteArray = __getArray(bytes);
const hexString = utils.hexlify(byteArray);
const ptr = await __newString(hexString);
return ptr;
},
'typeConversion.bytesToString': () => {
console.log('index typeConversion.bytesToString');
},
'typeConversion.bytesToBase58': () => {
console.log('index typeConversion.bytesToBase58');
}
},
numbers: {
'bigDecimal.dividedBy': async (x: number, y: number) => {
console.log('numbers bigDecimal.dividedBy');
const bigDecimaly = BigDecimal.wrap(y);
const yDigitsBigIntArray = __getArray(await bigDecimaly.digits);
const yDigits = BigNumber.from(yDigitsBigIntArray);
const yExpBigIntArray = __getArray(await bigDecimaly.exp);
const yExp = BigNumber.from(yExpBigIntArray);
console.log('y digits and exp', yDigits, yExp);
},
'bigDecimal.toString': () => {
console.log('numbers bigDecimal.toString');
},
'bigDecimal.fromString': () => {
console.log('numbers bigDecimal.toString');
},
'bigDecimal.plus': () => {
console.log('bigDecimal.plus');
},
'bigDecimal.minus': () => {
console.log('bigDecimal.minus');
},
'bigDecimal.times': () => {
console.log('bigDecimal.times');
},
'bigInt.fromString': async (s: number) => {
const string = __getString(s);
const bigNumber = BigNumber.from(string);
const hex = bigNumber.toHexString();
const bytes = utils.arrayify(hex);
const uint8ArrayId = await getIdOfType(TypeId.Uint8Array);
const ptr = await __newArray(uint8ArrayId, bytes);
const bigInt = await BigInt.fromSignedBytes(ptr);
return bigInt;
},
'bigInt.plus': async (x: number, y: number) => {
const xBigInt = await BigInt.wrap(x);
const xBigNumber = BigNumber.from(__getString(await xBigInt.toString()));
const yBigInt = await BigInt.wrap(y);
const yBigNumber = BigNumber.from(__getString(await yBigInt.toString()));
const sum = xBigNumber.add(yBigNumber);
const ptr = await __newString(sum.toString());
const sumBigInt = await BigInt.fromString(ptr);
return sumBigInt;
},
'bigInt.minus': async (x: number, y: number) => {
const xBigInt = await BigInt.wrap(x);
const xBigNumber = BigNumber.from(__getString(await xBigInt.toString()));
const yBigInt = await BigInt.wrap(y);
const yBigNumber = BigNumber.from(__getString(await yBigInt.toString()));
const diff = xBigNumber.sub(yBigNumber);
const ptr = await __newString(diff.toString());
const diffBigInt = BigInt.fromString(ptr);
return diffBigInt;
},
'bigInt.times': async (x: number, y: number) => {
const xBigInt = await BigInt.wrap(x);
const xBigNumber = BigNumber.from(__getString(await xBigInt.toString()));
const yBigInt = await BigInt.wrap(y);
const yBigNumber = BigNumber.from(__getString(await yBigInt.toString()));
const product = xBigNumber.mul(yBigNumber);
const ptr = await __newString(product.toString());
const productBigInt = BigInt.fromString(ptr);
return productBigInt;
},
'bigInt.dividedBy': async (x: number, y: number) => {
const xBigInt = await BigInt.wrap(x);
const xBigNumber = BigNumber.from(__getString(await xBigInt.toString()));
const yBigInt = await BigInt.wrap(y);
const yBigNumber = BigNumber.from(__getString(await yBigInt.toString()));
const quotient = xBigNumber.div(yBigNumber);
const ptr = await __newString(quotient.toString());
const quotientBigInt = BigInt.fromString(ptr);
return quotientBigInt;
},
'bigInt.dividedByDecimal': () => {
console.log('bigInt.dividedByDecimal');
},
'bigInt.mod': () => {
console.log('bigInt.mod');
},
'bigInt.bitOr': () => {
console.log('bigInt.bitOr');
},
'bigInt.bitAnd': () => {
console.log('bigInt.bitAnd');
},
'bigInt.leftShift': () => {
console.log('bigInt.leftShift');
},
'bigInt.rightShift': () => {
console.log('bigInt.rightShift');
},
'bigInt.pow': () => {
console.log('bigInt.pow');
}
},
datasource: {
'dataSource.address': async () => {
assert(dataSource);
return Address.fromString(await __newString(dataSource.address));
}
}
};
const instance = await loader.instantiate(buffer, imports);
const { exports } = instance;
const { __getString, __newString, __getArray, __newArray } = exports;
// TODO: Assign from types file generated by graph-cli
const getIdOfType: idOfType = exports.id_of_type as idOfType;
const BigDecimal: any = exports.BigDecimal as any;
const BigInt: any = exports.BigInt as any;
const Address: any = exports.Address as any;
const ethereum: any = exports.ethereum as any;
const Entity: any = exports.Entity as any;
return instance;
};
export * from './watcher';
@@ -5,7 +5,7 @@
import path from 'path';
import { expect } from 'chai';
import { instantiate } from './index';
import { instantiate } from './loader';
const WASM_FILE_PATH = '../build/debug.wasm';
+363
View File
@@ -0,0 +1,363 @@
//
// Copyright 2021 Vulcanize, Inc.
//
import assert from 'assert';
import fs from 'fs/promises';
import loader from '@vulcanize/assemblyscript/lib/loader';
import {
utils,
BigNumber,
getDefaultProvider,
Contract,
ContractInterface
} from 'ethers';
import { TypeId } from './types';
import { fromEthereumValue, toEthereumValue } from './utils';
const NETWORK_URL = 'http://127.0.0.1:8081';
type idOfType = (TypeId: number) => number
interface DataSource {
address: string
}
interface GraphData {
abis?: {[key: string]: ContractInterface};
dataSource?: DataSource;
}
export const instantiate = async (filePath: string, data: GraphData = {}): Promise<loader.ResultObject & { exports: any }> => {
const { abis = {}, dataSource } = data;
const buffer = await fs.readFile(filePath);
const provider = getDefaultProvider(NETWORK_URL);
const imports: WebAssembly.Imports = {
index: {
'store.get': async (entity: number, id: number) => {
console.log('store.get');
const entityString = __getString(entity);
console.log('entity:', entityString);
const idString = __getString(id);
console.log('id:', idString);
// TODO: Implement store get to fetch from DB using entity and id.
// TODO: Fill entity with field values.
// return Entity.__new()
return null;
},
'store.set': async (entity: number, id: number, data: number) => {
console.log('store.set');
const entityString = __getString(entity);
console.log('entity:', entityString);
const idString = __getString(id);
console.log('id:', idString);
const entityInstance = await Entity.wrap(data);
const entityInstanceId = __getString(await entityInstance.getString(await __newString('id')));
console.log('entity instance id:', entityInstanceId);
// TODO: Implement store set to save entity in db with values from entityInstance.
},
'typeConversion.stringToH160': () => {
console.log('index typeConversion.stringToH160');
},
'typeConversion.bytesToHex': () => {
console.log('index typeConversion.bytesToHex');
},
// 'typeConversion.bytesToString': () => {
// console.log('typeConversion.bytesToString');
// },
'typeConversion.bigIntToString': () => {
console.log('index typeConversion.bigIntToString');
},
// 'bigDecimal.fromString': () => {
// console.log('bigDecimal.fromString');
// },
// 'bigDecimal.times': () => {
// console.log('bigDecimal.times');
// },
'bigDecimal.dividedBy': () => {
console.log('bigDecimal.dividedBy');
},
// 'bigDecimal.plus': () => {
// console.log('bigDecimal.plus');
// },
// 'bigDecimal.minus': () => {
// console.log('bigDecimal.minus');
// },
'bigInt.plus': () => {
console.log('bigInt.plus');
},
'bigInt.minus': () => {
console.log('bigInt.minus');
},
'bigInt.times': () => {
console.log('bigInt.times');
},
'bigInt.dividedBy': () => {
console.log('bigInt.dividedBy');
},
// 'bigInt.mod': () => {
// console.log('bigInt.mod');
// },
'bigInt.fromString': () => {
console.log('bigInt.fromString');
},
'log.log': (_: number, msg: number) => {
console.log('log.log', __getString(msg));
},
// 'dataSource.create': () => {
// console.log('dataSource.create');
// },
'dataSource.address': () => {
console.log('dataSource.address');
},
'test.asyncMethod': async () => {
console.log('before timer start');
await new Promise(resolve => {
setTimeout(() => {
resolve(1);
}, 3000);
});
console.log('after timer complete');
return 123;
}
},
ethereum: {
'ethereum.call': async (call: number) => {
const smartContractCall = await ethereum.SmartContractCall.wrap(call);
const contractAddress = await Address.wrap(await smartContractCall.contractAddress);
const contractName = __getString(await smartContractCall.contractName);
const functionName = __getString(await smartContractCall.functionName);
const functionSignature = __getString(await smartContractCall.functionSignature);
let functionParams = __getArray(await smartContractCall.functionParams);
console.log('ethereum.call params');
console.log('functionSignature:', functionSignature);
const abi = abis[contractName];
const contract = new Contract(__getString(await contractAddress.toHexString()), abi, provider);
try {
const functionParamsPromise = functionParams.map(async param => {
const ethereumValue = await ethereum.Value.wrap(param);
return fromEthereumValue(exports, ethereumValue);
});
functionParams = await Promise.all(functionParamsPromise);
// TODO: Check for function overloading.
let result = await contract[functionName](...functionParams);
if (!Array.isArray(result)) {
result = [result];
}
// TODO: Check for function overloading.
// Using function signature does not work.
const outputs = contract.interface.getFunction(functionName).outputs;
const resultPtrArrayPromise = result.map(async (value: any, index: number) => {
assert(outputs);
return toEthereumValue(exports, value, outputs[index].type);
});
const resultPtrArray: any[] = await Promise.all(resultPtrArrayPromise);
const res = await __newArray(await getIdOfType(TypeId.ArrayEthereumValue), resultPtrArray);
return res;
} catch (err) {
console.log('eth_call error', err);
return null;
}
}
},
conversion: {
'typeConversion.stringToH160': async (s: number) => {
const string = __getString(s);
const address = utils.getAddress(string);
const byteArray = utils.arrayify(address);
const uint8ArrayId = await getIdOfType(TypeId.Uint8Array);
const ptr = __newArray(uint8ArrayId, byteArray);
return ptr;
},
'typeConversion.bigIntToString': (bigInt: number) => {
const bigIntByteArray = __getArray(bigInt);
const bigNumber = BigNumber.from(bigIntByteArray);
const ptr = __newString(bigNumber.toString());
return ptr;
},
'typeConversion.bigIntToHex': () => {
console.log('index typeConversion.bigIntToHex');
},
'typeConversion.bytesToHex': async (bytes: number) => {
const byteArray = __getArray(bytes);
const hexString = utils.hexlify(byteArray);
const ptr = await __newString(hexString);
return ptr;
},
'typeConversion.bytesToString': () => {
console.log('index typeConversion.bytesToString');
},
'typeConversion.bytesToBase58': () => {
console.log('index typeConversion.bytesToBase58');
}
},
numbers: {
'bigDecimal.dividedBy': async (x: number, y: number) => {
console.log('numbers bigDecimal.dividedBy');
const bigDecimaly = BigDecimal.wrap(y);
const yDigitsBigIntArray = __getArray(await bigDecimaly.digits);
const yDigits = BigNumber.from(yDigitsBigIntArray);
const yExpBigIntArray = __getArray(await bigDecimaly.exp);
const yExp = BigNumber.from(yExpBigIntArray);
console.log('y digits and exp', yDigits, yExp);
},
'bigDecimal.toString': () => {
console.log('numbers bigDecimal.toString');
},
'bigDecimal.fromString': () => {
console.log('numbers bigDecimal.toString');
},
'bigDecimal.plus': () => {
console.log('bigDecimal.plus');
},
'bigDecimal.minus': () => {
console.log('bigDecimal.minus');
},
'bigDecimal.times': () => {
console.log('bigDecimal.times');
},
'bigInt.fromString': async (s: number) => {
const string = __getString(s);
const bigNumber = BigNumber.from(string);
const hex = bigNumber.toHexString();
const bytes = utils.arrayify(hex);
const uint8ArrayId = await getIdOfType(TypeId.Uint8Array);
const ptr = await __newArray(uint8ArrayId, bytes);
const bigInt = await BigInt.fromSignedBytes(ptr);
return bigInt;
},
'bigInt.plus': async (x: number, y: number) => {
const xBigInt = await BigInt.wrap(x);
const xBigNumber = BigNumber.from(__getString(await xBigInt.toString()));
const yBigInt = await BigInt.wrap(y);
const yBigNumber = BigNumber.from(__getString(await yBigInt.toString()));
const sum = xBigNumber.add(yBigNumber);
const ptr = await __newString(sum.toString());
const sumBigInt = await BigInt.fromString(ptr);
return sumBigInt;
},
'bigInt.minus': async (x: number, y: number) => {
const xBigInt = await BigInt.wrap(x);
const xBigNumber = BigNumber.from(__getString(await xBigInt.toString()));
const yBigInt = await BigInt.wrap(y);
const yBigNumber = BigNumber.from(__getString(await yBigInt.toString()));
const diff = xBigNumber.sub(yBigNumber);
const ptr = await __newString(diff.toString());
const diffBigInt = BigInt.fromString(ptr);
return diffBigInt;
},
'bigInt.times': async (x: number, y: number) => {
const xBigInt = await BigInt.wrap(x);
const xBigNumber = BigNumber.from(__getString(await xBigInt.toString()));
const yBigInt = await BigInt.wrap(y);
const yBigNumber = BigNumber.from(__getString(await yBigInt.toString()));
const product = xBigNumber.mul(yBigNumber);
const ptr = await __newString(product.toString());
const productBigInt = BigInt.fromString(ptr);
return productBigInt;
},
'bigInt.dividedBy': async (x: number, y: number) => {
const xBigInt = await BigInt.wrap(x);
const xBigNumber = BigNumber.from(__getString(await xBigInt.toString()));
const yBigInt = await BigInt.wrap(y);
const yBigNumber = BigNumber.from(__getString(await yBigInt.toString()));
const quotient = xBigNumber.div(yBigNumber);
const ptr = await __newString(quotient.toString());
const quotientBigInt = BigInt.fromString(ptr);
return quotientBigInt;
},
'bigInt.dividedByDecimal': () => {
console.log('bigInt.dividedByDecimal');
},
'bigInt.mod': () => {
console.log('bigInt.mod');
},
'bigInt.bitOr': () => {
console.log('bigInt.bitOr');
},
'bigInt.bitAnd': () => {
console.log('bigInt.bitAnd');
},
'bigInt.leftShift': () => {
console.log('bigInt.leftShift');
},
'bigInt.rightShift': () => {
console.log('bigInt.rightShift');
},
'bigInt.pow': () => {
console.log('bigInt.pow');
}
},
datasource: {
'dataSource.address': async () => {
assert(dataSource);
return Address.fromString(await __newString(dataSource.address));
}
}
};
const instance = await loader.instantiate(buffer, imports);
const { exports } = instance;
const { __getString, __newString, __getArray, __newArray } = exports;
// TODO: Assign from types file generated by graph-cli
const getIdOfType: idOfType = exports.id_of_type as idOfType;
const BigDecimal: any = exports.BigDecimal as any;
const BigInt: any = exports.BigInt as any;
const Address: any = exports.Address as any;
const ethereum: any = exports.ethereum as any;
const Entity: any = exports.Entity as any;
return instance;
};
+1 -1
View File
@@ -5,7 +5,7 @@
import path from 'path';
import { expect } from 'chai';
import { instantiate } from './index';
import { instantiate } from './loader';
const EXAMPLE_WASM_FILE_PATH = '../test/subgraph/example1/build/Example1/Example1.wasm';
@@ -5,7 +5,7 @@
import path from 'path';
import { expect } from 'chai';
import { instantiate } from './index';
import { instantiate } from './loader';
const EXAMPLE_WASM_FILE_PATH = '../test/subgraph/example1/build/Example1/Example1.wasm';
+22
View File
@@ -1,6 +1,13 @@
import { BigNumber } from 'ethers';
import path from 'path';
import fs from 'fs-extra';
import debug from 'debug';
import yaml from 'js-yaml';
import { TypeId, ValueKind } from './types';
const log = debug('vulcanize:utils');
interface EventParam {
name: string;
value: any;
@@ -215,3 +222,18 @@ export const toEthereumValue = async (exports: any, value: any, type: string): P
// For string type.
return ethereum.Value.fromString(await __newString(value));
};
export const getSubgraphConfig = async (subgraphPath: string): Promise<any> => {
const configFilePath = path.resolve(path.join(subgraphPath, 'subgraph.yaml'));
const fileExists = await fs.pathExists(configFilePath);
if (!fileExists) {
throw new Error(`Config file not found: ${configFilePath}`);
}
console.log(configFilePath);
const config = yaml.load(await fs.readFile(configFilePath, 'utf8'));
log('config', JSON.stringify(config, null, 2));
return config;
};
+76
View File
@@ -0,0 +1,76 @@
//
// Copyright 2021 Vulcanize, Inc.
//
import 'reflect-metadata';
import debug from 'debug';
import path from 'path';
import fs from 'fs';
import { ContractInterface } from 'ethers';
import { getSubgraphConfig } from './utils';
import { instantiate } from './loader';
import { ResultObject } from '@vulcanize/assemblyscript/lib/loader';
const log = debug('vulcanize:graph-watcher');
export class GraphWatcher {
_subgraphPath: string;
_dataSources: any[] = []
_instanceMap: { [key: string]: ResultObject & { exports: any } } = {};
constructor (subgraphPath: string) {
this._subgraphPath = subgraphPath;
}
async init () {
const { dataSources } = await getSubgraphConfig(this._subgraphPath);
this._dataSources = dataSources;
this._instanceMap = this._dataSources.reduce(async (acc: { [key: string]: ResultObject & { exports: any } }, dataSource: any) => {
const { source: { address }, mapping } = dataSource;
const { abis, file } = mapping;
const data = {
abis: abis.reduce((acc: {[key: string]: ContractInterface}, abi: any) => {
const { name, file } = abi;
const abiFilePath = path.join(this._subgraphPath, file);
acc[name] = JSON.parse(fs.readFileSync(abiFilePath).toString());
return acc;
}, {}),
dataSource: {
address
}
};
const filePath = path.join(this._subgraphPath, file);
const instance = await instantiate(filePath, data);
acc[address] = instance;
return acc;
}, {});
}
async handleEvent (eventData: any) {
const { contract } = eventData;
const dataSource = this._dataSources.find(dataSource => dataSource.source.address === contract);
if (!dataSource) {
log(`Subgraph doesnt have configuration for contract ${contract}`);
return;
}
// TODO: Call instance methods based on event signature.
// value should contain event signature.
const [{ handler }] = dataSource.mapping.eventHandlers;
const { exports } = this._instanceMap[contract];
// Create ethereum event to be passed to handler.
// TODO: Create ethereum event to be passed to handler.
// const ethereumEvent = await createEvent(exports, address, event);
await exports[handler]();
}
}