mirror of
https://github.com/cerc-io/watcher-ts
synced 2026-09-09 17:24:07 +00:00
eth_call and invoking event handler in WASM (#25)
* Perform eth_call and get result in js import * Use dummy value for eth_call * Called handler in wasm with event param * Implement passing event to subgraph handler function * Use generated event class Test for passing to handler * Pass event params to handler Co-authored-by: nabarun <nabarun@deepstacksoft.com>
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// Copyright 2021 Vulcanize, Inc.
|
||||
//
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import { instantiate } from './index';
|
||||
import { TypeId } from './types';
|
||||
|
||||
describe('call handler in mapping code', () => {
|
||||
let exports: any;
|
||||
|
||||
it('should load the subgraph example wasm', async () => {
|
||||
const filePath = path.resolve(__dirname, '../test/subgraph/example1/build/Example1/Example1.wasm');
|
||||
const instance = await instantiate(filePath);
|
||||
exports = instance.exports;
|
||||
});
|
||||
|
||||
it('should execute the handler function', () => {
|
||||
const {
|
||||
_start,
|
||||
__newString,
|
||||
__newArray,
|
||||
handleTest,
|
||||
Address,
|
||||
BigInt,
|
||||
ethereum,
|
||||
Bytes,
|
||||
Test,
|
||||
id_of_type: idOfType
|
||||
} = exports;
|
||||
|
||||
// Important to call _start for built subgraphs on instantiation!
|
||||
// TODO: Check api version https://github.com/graphprotocol/graph-node/blob/6098daa8955bdfac597cec87080af5449807e874/runtime/wasm/src/module/mod.rs#L533
|
||||
_start();
|
||||
|
||||
// Create dummy block data.
|
||||
const block = new ethereum.Block(
|
||||
Bytes.empty(),
|
||||
Bytes.empty(),
|
||||
Bytes.empty(),
|
||||
Address.zero(),
|
||||
Bytes.empty(),
|
||||
Bytes.empty(),
|
||||
Bytes.empty(),
|
||||
BigInt.fromI32(0),
|
||||
BigInt.fromI32(0),
|
||||
BigInt.fromI32(0),
|
||||
BigInt.fromI32(0),
|
||||
BigInt.fromI32(0),
|
||||
BigInt.fromI32(0),
|
||||
null
|
||||
);
|
||||
|
||||
// Create dummy transaction data.
|
||||
const transaction = new ethereum.Transaction(
|
||||
Bytes.empty(),
|
||||
BigInt.fromI32(0),
|
||||
Address.zero(),
|
||||
null,
|
||||
BigInt.fromI32(0),
|
||||
BigInt.fromI32(0),
|
||||
BigInt.fromI32(0),
|
||||
Bytes.empty()
|
||||
);
|
||||
|
||||
// Create event params data.
|
||||
const eventParamsData = [
|
||||
{
|
||||
name: 'param1',
|
||||
value: 'abc',
|
||||
kind: 'string'
|
||||
},
|
||||
{
|
||||
name: 'param2',
|
||||
value: 123,
|
||||
kind: 'uint'
|
||||
}
|
||||
];
|
||||
|
||||
const eventParamArray = eventParamsData.map(data => {
|
||||
const { name, value, kind } = data;
|
||||
let ethValue;
|
||||
|
||||
switch (kind) {
|
||||
case 'uint': {
|
||||
const bigIntString = __newString(value.toString());
|
||||
ethValue = ethereum.Value.fromUnsignedBigInt(BigInt.fromString(bigIntString));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'string': {
|
||||
ethValue = ethereum.Value.fromString(__newString(value));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return new ethereum.EventParam(
|
||||
__newString(name),
|
||||
ethValue
|
||||
);
|
||||
});
|
||||
|
||||
const eventParams = __newArray(idOfType(TypeId.ArrayEventParam), eventParamArray);
|
||||
|
||||
// Dummy contract address string.
|
||||
const addStrPtr = __newString('0xCA6D29232D1435D8198E3E5302495417dD073d61');
|
||||
|
||||
// Create Test event to be passed to handler.
|
||||
const test = new Test(
|
||||
Address.fromString(addStrPtr),
|
||||
BigInt.fromI32(0),
|
||||
BigInt.fromI32(0),
|
||||
null,
|
||||
block,
|
||||
transaction,
|
||||
eventParams
|
||||
);
|
||||
|
||||
handleTest(test);
|
||||
});
|
||||
});
|
||||
@@ -4,14 +4,23 @@
|
||||
|
||||
import fs from 'fs/promises';
|
||||
import loader from '@assemblyscript/loader';
|
||||
import { utils, BigNumber } from 'ethers';
|
||||
import {
|
||||
utils,
|
||||
BigNumber
|
||||
// getDefaultProvider,
|
||||
// Contract
|
||||
} from 'ethers';
|
||||
|
||||
import { TypeId } from './types';
|
||||
// import exampleAbi from '../test/subgraph/example1/build/Example1/abis/Example1.json';
|
||||
|
||||
// const NETWORK_URL = 'http://127.0.0.1:8545';
|
||||
|
||||
type idOfType = (TypeId: number) => number
|
||||
|
||||
export const instantiate = async (filePath: string): Promise<loader.ResultObject & { exports: any }> => {
|
||||
const buffer = await fs.readFile(filePath);
|
||||
// const provider = getDefaultProvider(NETWORK_URL);
|
||||
|
||||
const imports = {
|
||||
index: {
|
||||
@@ -82,9 +91,42 @@ export const instantiate = async (filePath: string): Promise<loader.ResultObject
|
||||
}
|
||||
},
|
||||
ethereum: {
|
||||
'ethereum.call': () => {
|
||||
console.log('ethereum.call');
|
||||
return null;
|
||||
'ethereum.call': (call: number) => {
|
||||
const smartContractCall = ethereum.SmartContractCall.wrap(call);
|
||||
|
||||
const contractAddress = Address.wrap(smartContractCall.contractAddress);
|
||||
const contractName = __getString(smartContractCall.contractName);
|
||||
const functionName = __getString(smartContractCall.functionName);
|
||||
const functionSignature = __getString(smartContractCall.functionSignature);
|
||||
const functionParams = __getArray(smartContractCall.functionParams);
|
||||
console.log('ethereum.call params', __getString(contractAddress.toHexString()), contractName, functionName, functionSignature, functionParams);
|
||||
|
||||
// TODO: Get ABI according to contractName.
|
||||
// const contract = new Contract(__getString(contractAddress.toHexString()), exampleAbi, provider);
|
||||
|
||||
try {
|
||||
// TODO: Implement async function to perform eth_call.
|
||||
// let result = await contract[functionName](...functionParams);
|
||||
let result: any = 'test';
|
||||
|
||||
if (!Array.isArray(result)) {
|
||||
result = [result];
|
||||
}
|
||||
|
||||
const resultPtrArray = result.map((value: any) => {
|
||||
// TODO: Create Value instance according to type.
|
||||
const ethValue = ethereum.Value.fromString(__newString(value));
|
||||
|
||||
return ethValue;
|
||||
});
|
||||
|
||||
const res = __newArray(getIdOfType(TypeId.ArrayEthereumValue), resultPtrArray);
|
||||
|
||||
return res;
|
||||
} catch (err) {
|
||||
console.log('eth_call error', err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
conversion: {
|
||||
@@ -230,6 +272,8 @@ export const instantiate = async (filePath: string): Promise<loader.ResultObject
|
||||
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;
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('numbers wasm tests', () => {
|
||||
expect(__getString(ptr)).to.equal('100');
|
||||
});
|
||||
|
||||
it('should execute bigDecimal dividedBy API', () => {
|
||||
xit('should execute bigDecimal dividedBy API', () => {
|
||||
const { testBigDecimalDividedBy, __getString } = exports;
|
||||
|
||||
const ptr = testBigDecimalDividedBy();
|
||||
|
||||
Reference in New Issue
Block a user