mirror of
https://github.com/cerc-io/watcher-ts
synced 2024-11-19 20:36:19 +00:00
Example subgraph, ethCall test to drive implementation (#18)
* Setup example subgraph. * Implement eth_call in subgraph. * eth-call test stub Co-authored-by: nabarun <nabarun@deepstacksoft.com>
This commit is contained in:
parent
f078db688a
commit
d247815ce2
@ -3,3 +3,6 @@ node_modules
|
||||
|
||||
# Don't lint build output.
|
||||
dist
|
||||
|
||||
# Don't lint generated code from graph-cli.
|
||||
generated
|
||||
|
27
packages/graph-node/src/eth-call.test.ts
Normal file
27
packages/graph-node/src/eth-call.test.ts
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright 2021 Vulcanize, Inc.
|
||||
//
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import { instantiate } from './index';
|
||||
|
||||
describe('eth-call wasm tests', () => {
|
||||
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 exported function', () => {
|
||||
const { _start, testEthCall } = 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();
|
||||
|
||||
testEthCall();
|
||||
});
|
||||
});
|
@ -36,10 +36,10 @@ describe('wasm loader tests', () => {
|
||||
it('should instantiate a class in wasm from JS', async () => {
|
||||
const { Foo, FooID, __getString, __new, __pin, __unpin } = exports;
|
||||
|
||||
const newFooPtr = __pin(__new(FooID));
|
||||
const newFoo = Foo.wrap(newFooPtr);
|
||||
const newStrPtr = newFoo.getString();
|
||||
expect(__getString(newStrPtr)).to.equal('hello world!');
|
||||
__unpin(newFooPtr);
|
||||
const fooPtr = __pin(__new(FooID));
|
||||
const foo = Foo.wrap(fooPtr);
|
||||
const strPtr = foo.getString();
|
||||
expect(__getString(strPtr)).to.equal('hello world!');
|
||||
__unpin(fooPtr);
|
||||
});
|
||||
});
|
||||
|
@ -5,82 +5,94 @@
|
||||
import fs from 'fs/promises';
|
||||
import loader from '@assemblyscript/loader';
|
||||
|
||||
const imports = {
|
||||
index: {
|
||||
'store.get': () => {
|
||||
console.log('store.get');
|
||||
},
|
||||
'store.set': () => {
|
||||
console.log('store.set');
|
||||
},
|
||||
|
||||
'typeConversion.stringToH160': () => {
|
||||
console.log('typeConversion.stringToH160');
|
||||
},
|
||||
'typeConversion.bytesToHex': () => {
|
||||
console.log('typeConversion.bytesToHex');
|
||||
},
|
||||
// 'typeConversion.bytesToString': () => {
|
||||
// console.log('typeConversion.bytesToString');
|
||||
// },
|
||||
'typeConversion.bigIntToString': () => {
|
||||
console.log('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': () => {
|
||||
console.log('log.log');
|
||||
},
|
||||
|
||||
// 'dataSource.create': () => {
|
||||
// console.log('dataSource.create');
|
||||
// },
|
||||
'dataSource.address': () => {
|
||||
console.log('dataSource.address');
|
||||
}
|
||||
},
|
||||
ethereum: {
|
||||
'ethereum.call': () => {
|
||||
console.log('ethereum.call');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const instantiate = async (filePath: string): Promise<loader.ResultObject & { exports: any }> => {
|
||||
const buffer = await fs.readFile(filePath);
|
||||
return loader.instantiate(buffer, imports);
|
||||
|
||||
const imports = {
|
||||
index: {
|
||||
'store.get': () => {
|
||||
console.log('store.get');
|
||||
},
|
||||
'store.set': () => {
|
||||
console.log('store.set');
|
||||
},
|
||||
|
||||
'typeConversion.stringToH160': () => {
|
||||
console.log('typeConversion.stringToH160');
|
||||
},
|
||||
'typeConversion.bytesToHex': () => {
|
||||
console.log('typeConversion.bytesToHex');
|
||||
},
|
||||
// 'typeConversion.bytesToString': () => {
|
||||
// console.log('typeConversion.bytesToString');
|
||||
// },
|
||||
'typeConversion.bigIntToString': () => {
|
||||
console.log('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('console.log', __getString(msg));
|
||||
},
|
||||
|
||||
// 'dataSource.create': () => {
|
||||
// console.log('dataSource.create');
|
||||
// },
|
||||
'dataSource.address': () => {
|
||||
console.log('dataSource.address');
|
||||
}
|
||||
},
|
||||
ethereum: {
|
||||
'ethereum.call': () => {
|
||||
console.log('ethereum.call');
|
||||
return null;
|
||||
}
|
||||
},
|
||||
conversion: {
|
||||
'typeConversion.stringToH160': () => {
|
||||
console.log('typeConversion.stringToH160');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const instance = await loader.instantiate(buffer, imports);
|
||||
|
||||
const exports = instance.exports;
|
||||
const { __getString } = exports;
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
10
packages/graph-node/test/contracts/Example.sol
Normal file
10
packages/graph-node/test/contracts/Example.sol
Normal file
@ -0,0 +1,10 @@
|
||||
pragma solidity >=0.4.22 <0.8.0;
|
||||
|
||||
contract Example {
|
||||
event Test(string param1, uint param2);
|
||||
|
||||
function getMethod() public view virtual returns (string memory)
|
||||
{
|
||||
return 'test';
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "string",
|
||||
"name": "param1",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "param2",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Test",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getMethod",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "string",
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
@ -0,0 +1,54 @@
|
||||
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
|
||||
import {
|
||||
ethereum,
|
||||
JSONValue,
|
||||
TypedMap,
|
||||
Entity,
|
||||
Bytes,
|
||||
Address,
|
||||
BigInt
|
||||
} from "@graphprotocol/graph-ts";
|
||||
|
||||
export class Test extends ethereum.Event {
|
||||
get params(): Test__Params {
|
||||
return new Test__Params(this);
|
||||
}
|
||||
}
|
||||
|
||||
export class Test__Params {
|
||||
_event: Test;
|
||||
|
||||
constructor(event: Test) {
|
||||
this._event = event;
|
||||
}
|
||||
|
||||
get param1(): string {
|
||||
return this._event.parameters[0].value.toString();
|
||||
}
|
||||
|
||||
get param2(): BigInt {
|
||||
return this._event.parameters[1].value.toBigInt();
|
||||
}
|
||||
}
|
||||
|
||||
export class Example1 extends ethereum.SmartContract {
|
||||
static bind(address: Address): Example1 {
|
||||
return new Example1("Example1", address);
|
||||
}
|
||||
|
||||
getMethod(): string {
|
||||
let result = super.call("getMethod", "getMethod():(string)", []);
|
||||
|
||||
return result[0].toString();
|
||||
}
|
||||
|
||||
try_getMethod(): ethereum.CallResult<string> {
|
||||
let result = super.tryCall("getMethod", "getMethod():(string)", []);
|
||||
if (result.reverted) {
|
||||
return new ethereum.CallResult();
|
||||
}
|
||||
let value = result.value;
|
||||
return ethereum.CallResult.fromValue(value[0].toString());
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
|
||||
import {
|
||||
TypedMap,
|
||||
Entity,
|
||||
Value,
|
||||
ValueKind,
|
||||
store,
|
||||
Address,
|
||||
Bytes,
|
||||
BigInt,
|
||||
BigDecimal
|
||||
} from "@graphprotocol/graph-ts";
|
||||
|
||||
export class ExampleEntity extends Entity {
|
||||
constructor(id: string) {
|
||||
super();
|
||||
this.set("id", Value.fromString(id));
|
||||
|
||||
this.set("count", Value.fromBigInt(BigInt.zero()));
|
||||
this.set("param1", Value.fromString(""));
|
||||
this.set("param2", Value.fromBigInt(BigInt.zero()));
|
||||
}
|
||||
|
||||
save(): void {
|
||||
let id = this.get("id");
|
||||
assert(id != null, "Cannot save ExampleEntity entity without an ID");
|
||||
if (id) {
|
||||
assert(
|
||||
id.kind == ValueKind.STRING,
|
||||
"Cannot save ExampleEntity entity with non-string ID. " +
|
||||
'Considering using .toHex() to convert the "id" to a string.'
|
||||
);
|
||||
store.set("ExampleEntity", id.toString(), this);
|
||||
}
|
||||
}
|
||||
|
||||
static load(id: string): ExampleEntity | null {
|
||||
return changetype<ExampleEntity | null>(store.get("ExampleEntity", id));
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
let value = this.get("id");
|
||||
return value!.toString();
|
||||
}
|
||||
|
||||
set id(value: string) {
|
||||
this.set("id", Value.fromString(value));
|
||||
}
|
||||
|
||||
get count(): BigInt {
|
||||
let value = this.get("count");
|
||||
return value!.toBigInt();
|
||||
}
|
||||
|
||||
set count(value: BigInt) {
|
||||
this.set("count", Value.fromBigInt(value));
|
||||
}
|
||||
|
||||
get param1(): string {
|
||||
let value = this.get("param1");
|
||||
return value!.toString();
|
||||
}
|
||||
|
||||
set param1(value: string) {
|
||||
this.set("param1", Value.fromString(value));
|
||||
}
|
||||
|
||||
get param2(): BigInt {
|
||||
let value = this.get("param2");
|
||||
return value!.toBigInt();
|
||||
}
|
||||
|
||||
set param2(value: BigInt) {
|
||||
this.set("param2", Value.fromBigInt(value));
|
||||
}
|
||||
}
|
16
packages/graph-node/test/subgraph/example1/package.json
Normal file
16
packages/graph-node/test/subgraph/example1/package.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "example1",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"codegen": "graph codegen",
|
||||
"build": "graph build",
|
||||
"deploy": "graph deploy --node https://api.studio.thegraph.com/deploy/ example1",
|
||||
"create-local": "graph create --node http://localhost:8020/ example1",
|
||||
"remove-local": "graph remove --node http://localhost:8020/ example1",
|
||||
"deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 example1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@graphprotocol/graph-cli": "0.22.0",
|
||||
"@graphprotocol/graph-ts": "0.22.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
type ExampleEntity @entity {
|
||||
id: ID!
|
||||
count: BigInt!
|
||||
param1: String! # string
|
||||
param2: BigInt! # uint256
|
||||
}
|
64
packages/graph-node/test/subgraph/example1/src/mapping.ts
Normal file
64
packages/graph-node/test/subgraph/example1/src/mapping.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { Address, log } from '@graphprotocol/graph-ts';
|
||||
|
||||
import {
|
||||
Example1
|
||||
} from '../generated/Example1/Example1';
|
||||
|
||||
// export function handleTest (event: Test): void {
|
||||
// // Entities can be loaded from the store using a string ID; this ID
|
||||
// // needs to be unique across all entities of the same type
|
||||
// let entity = ExampleEntity.load(event.transaction.from.toHex());
|
||||
|
||||
// // Entities only exist after they have been saved to the store;
|
||||
// // `null` checks allow to create entities on demand
|
||||
// if (!entity) {
|
||||
// entity = new ExampleEntity(event.transaction.from.toHex());
|
||||
|
||||
// // Entity fields can be set using simple assignments
|
||||
// entity.count = BigInt.fromI32(0);
|
||||
// }
|
||||
|
||||
// // BigInt and BigDecimal math are supported
|
||||
// // entity.count = entity.count + BigInt.fromI32(1)
|
||||
|
||||
// // Entity fields can be set based on event parameters
|
||||
// entity.param1 = event.params.param1;
|
||||
// entity.param2 = event.params.param2;
|
||||
|
||||
// // Entities can be written to the store with `.save()`
|
||||
// entity.save();
|
||||
|
||||
// // Note: If a handler doesn't require existing field values, it is faster
|
||||
// // _not_ to load the entity from the store. Instead, create it fresh with
|
||||
// // `new Entity(...)`, set the fields that should be updated and save the
|
||||
// // entity back to the store. Fields that were not set or unset remain
|
||||
// // unchanged, allowing for partial updates to be applied.
|
||||
|
||||
// // It is also possible to access smart contracts from mappings. For
|
||||
// // example, the contract that has emitted the event can be connected to
|
||||
// // with:
|
||||
// //
|
||||
// // let contract = Contract.bind(event.address)
|
||||
// //
|
||||
// // The following functions can then be called on this contract to access
|
||||
// // state variables and other data:
|
||||
// //
|
||||
// // - contract.getMethod(...)
|
||||
// }
|
||||
|
||||
export function testEthCall (): void {
|
||||
log.debug('In test eth call', []);
|
||||
|
||||
// Bind the contract to the address that emitted the event.
|
||||
// TODO: Address.fromString throws error in WASM module instantiation.
|
||||
const contractAddress = Address.fromString('0xafAd925B5eAE1E370196cBa39893E858ff7257d5');
|
||||
const contract = Example1.bind(contractAddress);
|
||||
|
||||
// Access functions by calling them.
|
||||
const res = contract.try_getMethod();
|
||||
if (res.reverted) {
|
||||
log.debug('Contract eth call reverted', []);
|
||||
} else {
|
||||
log.debug('Contract eth call result', []);
|
||||
}
|
||||
}
|
23
packages/graph-node/test/subgraph/example1/subgraph.yaml
Normal file
23
packages/graph-node/test/subgraph/example1/subgraph.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
specVersion: 0.0.2
|
||||
schema:
|
||||
file: ./schema.graphql
|
||||
dataSources:
|
||||
- kind: ethereum/contract
|
||||
name: Example1
|
||||
network: mainnet
|
||||
source:
|
||||
address: "0xafAd925B5eAE1E370196cBa39893E858ff7257d5"
|
||||
abi: Example1
|
||||
mapping:
|
||||
kind: ethereum/events
|
||||
apiVersion: 0.0.5
|
||||
language: wasm/assemblyscript
|
||||
entities:
|
||||
- Test
|
||||
abis:
|
||||
- name: Example1
|
||||
file: ./abis/Example1.json
|
||||
eventHandlers:
|
||||
- event: Test(string,uint256)
|
||||
handler: handleTest
|
||||
file: ./src/mapping.ts
|
2863
packages/graph-node/test/subgraph/example1/yarn.lock
Normal file
2863
packages/graph-node/test/subgraph/example1/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user