Implement data source and crypto host APIs (#104)

* Implement data source host APIs

* Implement crypto host API
This commit is contained in:
nikugogoi 2021-12-30 17:57:34 +05:30 committed by GitHub
parent 8b913af93f
commit 6a2c99a0bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 106 additions and 10 deletions

View File

@ -0,0 +1,57 @@
//
// Copyright 2021 Vulcanize, Inc.
//
import path from 'path';
import { expect } from 'chai';
import { utils } from 'ethers';
import { BaseProvider } from '@ethersproject/providers';
import { instantiate } from './loader';
import { getTestDatabase, getTestIndexer, getTestProvider } from '../test/utils';
import { Database } from './database';
import { Indexer } from '../test/utils/indexer';
describe('crypto host api', () => {
let exports: any;
let db: Database;
let indexer: Indexer;
let provider: BaseProvider;
before(async () => {
db = getTestDatabase();
indexer = getTestIndexer();
provider = getTestProvider();
});
it('should load the subgraph example wasm', async () => {
const filePath = path.resolve(__dirname, '../test/subgraph/example1/build/Example1/Example1.wasm');
const instance = await instantiate(
db,
indexer,
provider,
{},
filePath
);
exports = instance.exports;
const { _start } = 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();
});
it('should return keccak256 hash', async () => {
const { testCrypto, __getString, __newString } = exports;
const hexString = '0x1234';
const hexStringPtr = await __newString(hexString);
const keccak256Ptr = await testCrypto(hexStringPtr);
const keccak256 = __getString(keccak256Ptr);
expect(keccak256)
.to
.equal(utils.keccak256(hexString));
});
});

View File

@ -76,7 +76,8 @@ describe('eden wasm loader tests', async () => {
EdenNetwork: edenNetworkAbi
},
dataSource: {
address: contractAddress
address: contractAddress,
network: 'mainnet'
}
};
@ -192,7 +193,8 @@ describe('eden wasm loader tests', async () => {
Distribution: merkleDistributorAbi
},
dataSource: {
address: contractAddress
address: contractAddress,
network: 'mainnet'
}
};
@ -304,7 +306,8 @@ describe('eden wasm loader tests', async () => {
Governance: distributorGovernanceAbi
},
dataSource: {
address: contractAddress
address: contractAddress,
network: 'mainnet'
}
};

View File

@ -28,7 +28,8 @@ describe('eth-call wasm tests', () => {
Example1: exampleAbi
},
dataSource: {
address: contractAddress
address: contractAddress,
network: 'mainnet'
}
};

View File

@ -38,7 +38,8 @@ type idOfType = (TypeId: number) => number
export interface GraphData {
abis?: {[key: string]: ContractInterface};
dataSource?: {
address: string
address: string,
network: string;
};
}
@ -114,6 +115,16 @@ export const instantiate = async (
log('log %s | %s', Level[level], __getString(msg));
},
'crypto.keccak256': async (input: number) => {
const byteArray = await ByteArray.wrap(input);
const hexStringPtr = await byteArray.toHexString();
const hexString = __getString(hexStringPtr);
const keccak256 = utils.keccak256(hexString);
const keccak256Ptr = await __newString(keccak256);
return ByteArray.fromHexString(keccak256Ptr);
},
'test.asyncMethod': async () => {
console.log('before timer start');
await new Promise(resolve => {
@ -599,6 +610,16 @@ export const instantiate = async (
assert(dataSource);
const addressStringPtr = await __newString(dataSource.address);
return Address.fromString(addressStringPtr);
},
'dataSource.context': async () => {
// TODO: Implement use in data source templates.
// https://thegraph.com/docs/en/developer/create-subgraph-hosted/#data-source-context
return Entity.__new();
},
'dataSource.network': async () => {
assert(dataSource);
return __newString(dataSource.network);
}
}
};

View File

@ -36,7 +36,7 @@ export class GraphWatcher {
_dataSourceMap: { [key: string]: DataSource } = {};
_transactionsMap: Map<string, Transaction> = new Map()
_context: Context = {}
_context: Context = {};
constructor (database: Database, postgraphileClient: EthClient, ethProvider: providers.BaseProvider, serverConfig: ServerConfig) {
this._database = database;
@ -52,7 +52,7 @@ export class GraphWatcher {
// Create wasm instance and contract interface for each dataSource in subgraph yaml.
const dataPromises = this._dataSources.map(async (dataSource: any) => {
const { source: { address, abi }, mapping } = dataSource;
const { source: { address, abi }, mapping, network } = dataSource;
const { abis, file } = mapping;
const abisMap = abis.reduce((acc: {[key: string]: ContractInterface}, abi: any) => {
@ -68,7 +68,8 @@ export class GraphWatcher {
const data = {
abis: abisMap,
dataSource: {
address
address,
network
}
};

View File

@ -1,4 +1,4 @@
import { Address, log, BigInt, BigDecimal, ByteArray, dataSource, ethereum, Bytes } from '@graphprotocol/graph-ts';
import { Address, log, BigInt, BigDecimal, ByteArray, dataSource, ethereum, Bytes, crypto } from '@graphprotocol/graph-ts';
import {
Example1,
@ -14,6 +14,9 @@ export function handleTest (event: Test): void {
log.debug('event.block.hash: {}', [event.block.hash.toHexString()]);
log.debug('event.block.stateRoot: {}', [event.block.stateRoot.toHexString()]);
log.debug('dataSource.network: {}', [dataSource.network()]);
log.debug('dataSource.context: {}', [dataSource.context().entries.length.toString()]);
// 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 author = Author.load(event.transaction.from.toHex());
@ -504,3 +507,12 @@ export function testEthereumDecode (encoded: string): string[] {
decodedBool.toString()
];
}
export function testCrypto (hexString: string): string {
const byteArray = ByteArray.fromHexString(hexString);
const keccak256 = crypto.keccak256(byteArray);
const keccak256String = keccak256.toHex();
log.debug('keccak256 string: {}', [keccak256String]);
return keccak256String;
}

View File

@ -61,7 +61,8 @@ export const getDummyEventData = async (): Promise<EventData> => {
export const getDummyGraphData = (): any => {
return {
dataSource: {
address: ZERO_ADDRESS
address: ZERO_ADDRESS,
network: 'mainnet'
}
};
};