mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-04-13 02:51:14 +00:00
Implement method for storage based access in subgraph mapping code (#162)
* Implement storage call in subgraph mapping code * Add test for mapping type variable storage call * Use vulcanize graph-ts * Revert to graph-ts version 0.22.1
This commit is contained in:
parent
80682e2755
commit
ec56de057f
@ -12,7 +12,7 @@ import { JsonFragment } from '@ethersproject/abi';
|
||||
import { BaseProvider } from '@ethersproject/providers';
|
||||
import * as codec from '@ipld/dag-cbor';
|
||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||
import { StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import { MappingKey, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import {
|
||||
IPLDIndexer as BaseIndexer,
|
||||
IPLDIndexerInterface,
|
||||
@ -171,6 +171,10 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
return this._serverConfig;
|
||||
}
|
||||
|
||||
get storageLayoutMap (): Map<string, StorageLayout> {
|
||||
return this._storageLayoutMap;
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
await this._baseIndexer.fetchContracts();
|
||||
await this._baseIndexer.fetchIPLDStatus();
|
||||
@ -317,6 +321,16 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
}
|
||||
|
||||
{{/each}}
|
||||
async getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult> {
|
||||
return this._baseIndexer.getStorageValue(
|
||||
storageLayout,
|
||||
blockHash,
|
||||
contractAddress,
|
||||
variable,
|
||||
...mappingKeys
|
||||
);
|
||||
}
|
||||
|
||||
async pushToIPFS (data: any): Promise<void> {
|
||||
await this._baseIndexer.pushToIPFS(data);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import { JsonFragment } from '@ethersproject/abi';
|
||||
import { BaseProvider } from '@ethersproject/providers';
|
||||
import * as codec from '@ipld/dag-cbor';
|
||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||
import { StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import { MappingKey, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import {
|
||||
IPLDIndexer as BaseIndexer,
|
||||
UNKNOWN_EVENT_NAME,
|
||||
@ -24,7 +24,8 @@ import {
|
||||
IPFSClient,
|
||||
StateKind,
|
||||
IPLDIndexerInterface,
|
||||
IpldStatus as IpldStatusInterface
|
||||
IpldStatus as IpldStatusInterface,
|
||||
ValueResult
|
||||
} from '@vulcanize/util';
|
||||
import { GraphWatcher } from '@vulcanize/graph-node';
|
||||
|
||||
@ -170,6 +171,10 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
return this._serverConfig;
|
||||
}
|
||||
|
||||
get storageLayoutMap (): Map<string, StorageLayout> {
|
||||
return this._storageLayoutMap;
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
await this._baseIndexer.fetchContracts();
|
||||
await this._baseIndexer.fetchIPLDStatus();
|
||||
@ -230,6 +235,16 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
};
|
||||
}
|
||||
|
||||
async getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult> {
|
||||
return this._baseIndexer.getStorageValue(
|
||||
storageLayout,
|
||||
blockHash,
|
||||
contractAddress,
|
||||
variable,
|
||||
...mappingKeys
|
||||
);
|
||||
}
|
||||
|
||||
async pushToIPFS (data: any): Promise<void> {
|
||||
await this._baseIndexer.pushToIPFS(data);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import { ethers } from 'ethers';
|
||||
import { BaseProvider } from '@ethersproject/providers';
|
||||
|
||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||
import { StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import { MappingKey, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import { IndexerInterface, Indexer as BaseIndexer, ValueResult, UNKNOWN_EVENT_NAME, JobQueue, Where, QueryOptions, ServerConfig } from '@vulcanize/util';
|
||||
|
||||
import { Database } from './database';
|
||||
@ -80,6 +80,10 @@ export class Indexer implements IndexerInterface {
|
||||
return this._serverConfig;
|
||||
}
|
||||
|
||||
get storageLayoutMap (): Map<string, StorageLayout> {
|
||||
return new Map([['ERC20', this._storageLayout]]);
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
await this._baseIndexer.fetchContracts();
|
||||
}
|
||||
@ -234,6 +238,16 @@ export class Indexer implements IndexerInterface {
|
||||
return result;
|
||||
}
|
||||
|
||||
async getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult> {
|
||||
return this._baseIndexer.getStorageValue(
|
||||
storageLayout,
|
||||
blockHash,
|
||||
contractAddress,
|
||||
variable,
|
||||
...mappingKeys
|
||||
);
|
||||
}
|
||||
|
||||
async triggerIndexingOnEvent (event: Event): Promise<void> {
|
||||
const { eventName, eventInfo, contract: token, block: { blockHash } } = event;
|
||||
const eventFields = JSON.parse(eventInfo);
|
||||
|
@ -12,7 +12,7 @@ import { JsonFragment } from '@ethersproject/abi';
|
||||
import { BaseProvider } from '@ethersproject/providers';
|
||||
import * as codec from '@ipld/dag-cbor';
|
||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||
import { StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import { MappingKey, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import {
|
||||
IPLDIndexer as BaseIndexer,
|
||||
IPLDIndexerInterface,
|
||||
@ -128,6 +128,10 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
return this._serverConfig;
|
||||
}
|
||||
|
||||
get storageLayoutMap (): Map<string, StorageLayout> {
|
||||
return this._storageLayoutMap;
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
await this._baseIndexer.fetchContracts();
|
||||
await this._baseIndexer.fetchIPLDStatus();
|
||||
@ -673,6 +677,16 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
return result;
|
||||
}
|
||||
|
||||
async getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult> {
|
||||
return this._baseIndexer.getStorageValue(
|
||||
storageLayout,
|
||||
blockHash,
|
||||
contractAddress,
|
||||
variable,
|
||||
...mappingKeys
|
||||
);
|
||||
}
|
||||
|
||||
async pushToIPFS (data: any): Promise<void> {
|
||||
await this._baseIndexer.pushToIPFS(data);
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ import {
|
||||
toEthereumValue,
|
||||
resolveEntityFieldConflicts,
|
||||
getEthereumTypes,
|
||||
jsonFromBytes
|
||||
jsonFromBytes,
|
||||
getStorageValueType
|
||||
} from './utils';
|
||||
import { Database } from './database';
|
||||
|
||||
@ -236,6 +237,41 @@ export const instantiate = async (
|
||||
const [decoded] = utils.defaultAbiCoder.decode([typesString], dataString);
|
||||
|
||||
return toEthereumValue(instanceExports, utils.ParamType.from(typesString), decoded);
|
||||
},
|
||||
'ethereum.storageValue': async (contractName: number, contractAddress: number, variable: number, mappingKeys: number) => {
|
||||
const contractNameString = __getString(contractName);
|
||||
const address = await Address.wrap(contractAddress);
|
||||
const addressStringPtr = await address.toHexString();
|
||||
const addressString = __getString(addressStringPtr);
|
||||
|
||||
const variableString = __getString(variable);
|
||||
const mappingKeyPtrs = __getArray(mappingKeys);
|
||||
|
||||
const mappingKeyPromises = mappingKeyPtrs.map(async mappingKeyPtr => {
|
||||
const ethereumValue = await ethereum.Value.wrap(mappingKeyPtr);
|
||||
return fromEthereumValue(instanceExports, ethereumValue);
|
||||
});
|
||||
|
||||
const mappingKeyValues = await Promise.all(mappingKeyPromises);
|
||||
const storageLayout = indexer.storageLayoutMap.get(contractNameString);
|
||||
assert(storageLayout);
|
||||
assert(context.block);
|
||||
|
||||
const result = await indexer.getStorageValue(
|
||||
storageLayout,
|
||||
context.block.blockHash,
|
||||
addressString,
|
||||
variableString,
|
||||
...mappingKeyValues
|
||||
);
|
||||
|
||||
const storageValueType = getStorageValueType(storageLayout, variableString, mappingKeyValues);
|
||||
|
||||
return toEthereumValue(
|
||||
instanceExports,
|
||||
storageValueType,
|
||||
result.value
|
||||
);
|
||||
}
|
||||
},
|
||||
conversion: {
|
||||
|
80
packages/graph-node/src/storage-call.test.ts
Normal file
80
packages/graph-node/src/storage-call.test.ts
Normal file
@ -0,0 +1,80 @@
|
||||
//
|
||||
// Copyright 2022 Vulcanize, Inc.
|
||||
//
|
||||
|
||||
import assert from 'assert';
|
||||
import path from 'path';
|
||||
|
||||
import { BaseProvider } from '@ethersproject/providers';
|
||||
|
||||
import { instantiate } from './loader';
|
||||
import exampleAbi from '../test/subgraph/example1/build/Example1/abis/Example1.json';
|
||||
import { storageLayout } from '../test/artifacts/Example1.json';
|
||||
import { getTestDatabase, getTestIndexer, getTestProvider, getDummyEventData } from '../test/utils';
|
||||
import { Database } from './database';
|
||||
import { Indexer } from '../test/utils/indexer';
|
||||
import { EventData } from './utils';
|
||||
|
||||
xdescribe('storage-call wasm tests', () => {
|
||||
let exports: any;
|
||||
let db: Database;
|
||||
let indexer: Indexer;
|
||||
let provider: BaseProvider;
|
||||
|
||||
const contractAddress = process.env.EXAMPLE_CONTRACT_ADDRESS;
|
||||
assert(contractAddress);
|
||||
|
||||
const data = {
|
||||
abis: {
|
||||
Example1: exampleAbi
|
||||
},
|
||||
dataSource: {
|
||||
address: contractAddress,
|
||||
network: 'mainnet'
|
||||
}
|
||||
};
|
||||
|
||||
let dummyEventData: EventData;
|
||||
|
||||
before(async () => {
|
||||
db = getTestDatabase();
|
||||
indexer = getTestIndexer(new Map([['Example1', storageLayout]]));
|
||||
provider = getTestProvider();
|
||||
|
||||
// Create dummy test data.
|
||||
dummyEventData = await getDummyEventData();
|
||||
});
|
||||
|
||||
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,
|
||||
{
|
||||
block: dummyEventData.block,
|
||||
contractAddress
|
||||
},
|
||||
filePath,
|
||||
data
|
||||
);
|
||||
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 execute contract getStorageValue function', async () => {
|
||||
const { testGetStorageValue } = exports;
|
||||
|
||||
await testGetStorageValue();
|
||||
});
|
||||
|
||||
it('should execute getStorageValue function for mapping type variable', async () => {
|
||||
const { testMapStorageValue } = exports;
|
||||
|
||||
await testMapStorageValue();
|
||||
});
|
||||
});
|
@ -4,10 +4,12 @@ import fs from 'fs-extra';
|
||||
import debug from 'debug';
|
||||
import yaml from 'js-yaml';
|
||||
import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata';
|
||||
import assert from 'assert';
|
||||
|
||||
import { GraphDecimal } from '@vulcanize/util';
|
||||
|
||||
import { TypeId, EthereumValueKind, ValueKind } from './types';
|
||||
import { MappingKey, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
|
||||
const log = debug('vulcanize:utils');
|
||||
|
||||
@ -767,3 +769,32 @@ export const jsonFromBytes = async (instanceExports: any, bytesPtr: number): Pro
|
||||
|
||||
return jsonValue;
|
||||
};
|
||||
|
||||
export const getStorageValueType = (storageLayout: StorageLayout, variableString: string, mappingKeys: MappingKey[]): utils.ParamType => {
|
||||
const storage = storageLayout.storage.find(({ label }) => label === variableString);
|
||||
assert(storage);
|
||||
|
||||
return getEthereumType(storageLayout.types, storage.type, mappingKeys);
|
||||
};
|
||||
|
||||
const getEthereumType = (storageTypes: StorageLayout['types'], type: string, mappingKeys: MappingKey[]): utils.ParamType => {
|
||||
const { label, encoding, members, value } = storageTypes[type];
|
||||
|
||||
if (encoding === 'mapping') {
|
||||
assert(value);
|
||||
|
||||
return getEthereumType(storageTypes, value, mappingKeys.slice(1));
|
||||
}
|
||||
|
||||
// Struct type contains members field.
|
||||
if (members) {
|
||||
const mappingKey = mappingKeys.shift();
|
||||
const member = members.find(({ label }) => label === mappingKey);
|
||||
assert(member);
|
||||
const { type } = member;
|
||||
|
||||
return getEthereumType(storageTypes, type, mappingKeys);
|
||||
}
|
||||
|
||||
return utils.ParamType.from(label);
|
||||
};
|
||||
|
1
packages/graph-node/test/.gitignore
vendored
Normal file
1
packages/graph-node/test/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
!artifacts
|
183
packages/graph-node/test/artifacts/Example1.json
Normal file
183
packages/graph-node/test/artifacts/Example1.json
Normal file
@ -0,0 +1,183 @@
|
||||
{
|
||||
"abi": [
|
||||
{
|
||||
"inputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "string",
|
||||
"name": "param1",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint8",
|
||||
"name": "param2",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "param3",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Test",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "bidAmount1",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "bidAmount2",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "addMethod",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "addressUintMap",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "emitEvent",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getMethod",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "string",
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "bidAmount1",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "bidAmount2",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "structMethod",
|
||||
"outputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "bidAmount1",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "bidAmount2",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"internalType": "struct Example.Bid",
|
||||
"name": "",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"storageLayout": {
|
||||
"storage": [
|
||||
{
|
||||
"astId": 3,
|
||||
"contract": "Example.sol:Example",
|
||||
"label": "_test",
|
||||
"offset": 0,
|
||||
"slot": "0",
|
||||
"type": "t_uint256"
|
||||
},
|
||||
{
|
||||
"astId": 7,
|
||||
"contract": "Example.sol:Example",
|
||||
"label": "addressUintMap",
|
||||
"offset": 0,
|
||||
"slot": "1",
|
||||
"type": "t_mapping(t_address,t_uint128)"
|
||||
}
|
||||
],
|
||||
"types": {
|
||||
"t_address": {
|
||||
"encoding": "inplace",
|
||||
"label": "address",
|
||||
"numberOfBytes": "20"
|
||||
},
|
||||
"t_mapping(t_address,t_uint128)": {
|
||||
"encoding": "mapping",
|
||||
"key": "t_address",
|
||||
"label": "mapping(address => uint128)",
|
||||
"numberOfBytes": "32",
|
||||
"value": "t_uint128"
|
||||
},
|
||||
"t_uint128": {
|
||||
"encoding": "inplace",
|
||||
"label": "uint128",
|
||||
"numberOfBytes": "16"
|
||||
},
|
||||
"t_uint256": {
|
||||
"encoding": "inplace",
|
||||
"label": "uint256",
|
||||
"numberOfBytes": "32"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ pragma solidity ^0.8.0;
|
||||
contract Example {
|
||||
uint256 private _test;
|
||||
|
||||
mapping (address => uint128) public addressUintMap;
|
||||
|
||||
struct Bid {
|
||||
uint128 bidAmount1;
|
||||
uint128 bidAmount2;
|
||||
@ -12,6 +14,11 @@ contract Example {
|
||||
|
||||
event Test(string param1, uint8 param2, uint256 param3);
|
||||
|
||||
constructor() {
|
||||
_test = 1;
|
||||
addressUintMap[address(0)] = 123;
|
||||
}
|
||||
|
||||
function getMethod() public view virtual returns (string memory)
|
||||
{
|
||||
return 'test';
|
||||
|
1
packages/graph-node/test/subgraph/example1/.npmrc
Normal file
1
packages/graph-node/test/subgraph/example1/.npmrc
Normal file
@ -0,0 +1 @@
|
||||
@graphprotocol:registry=https://npm.pkg.github.com
|
@ -10,7 +10,7 @@
|
||||
"deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 example1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@graphprotocol/graph-ts": "^0.22.1",
|
||||
"@graphprotocol/graph-ts": "npm:@vulcanize/graph-ts@0.22.1",
|
||||
"@vulcanize/graph-cli": "0.22.5"
|
||||
}
|
||||
}
|
||||
|
@ -159,6 +159,27 @@ export function testStructEthCall (): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function testGetStorageValue (): void {
|
||||
log.debug('In test get storage value', []);
|
||||
|
||||
// Bind the contract to the address.
|
||||
const contractAddress = dataSource.address();
|
||||
const contract = Example1.bind(contractAddress);
|
||||
const res = contract.getStorageValue('_test', []);
|
||||
log.debug('Storage call result: {}', [res!.toBigInt().toString()]);
|
||||
}
|
||||
|
||||
export function testMapStorageValue (): void {
|
||||
log.debug('In test map storage value', []);
|
||||
|
||||
// Bind the contract to the address.
|
||||
const contractAddress = dataSource.address();
|
||||
const contract = Example1.bind(contractAddress);
|
||||
const addressValue = ethereum.Value.fromAddress(Address.zero());
|
||||
const res = contract.getStorageValue('addressUintMap', [addressValue]);
|
||||
log.debug('Storage call result: {}', [res!.toBigInt().toString()]);
|
||||
}
|
||||
|
||||
export function testBytesToHex (): string {
|
||||
log.debug('In test bytesToHex', []);
|
||||
|
||||
|
@ -23,10 +23,10 @@
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@graphprotocol/graph-ts@^0.22.1":
|
||||
"@graphprotocol/graph-ts@npm:@vulcanize/graph-ts@0.22.1":
|
||||
version "0.22.1"
|
||||
resolved "https://registry.yarnpkg.com/@graphprotocol/graph-ts/-/graph-ts-0.22.1.tgz#3189b2495b33497280f617316cce68074d48e236"
|
||||
integrity sha512-T5xrHN0tHJwd7ZnSTLhk5hAL3rCIp6rJ40kBCrETnv1mfK9hVyoojJK6VtBQXTbLsYtKe4SYjjD0cdOsAR9QiA==
|
||||
resolved "https://npm.pkg.github.com/download/@vulcanize/graph-ts/0.22.1/7a14baaab8b99d4a88e19620dc7200aa501fbecf#7a14baaab8b99d4a88e19620dc7200aa501fbecf"
|
||||
integrity sha512-0CoKeFezskYjAsLmqfdxmS7q+gWy1V1wFgiNB4tMJSa2EiPTVG62qlPKkqTduApK2gZX9//rmE5Vb2xcF/v2+w==
|
||||
dependencies:
|
||||
assemblyscript "0.19.10"
|
||||
|
||||
|
@ -4,12 +4,15 @@
|
||||
|
||||
import { BaseProvider } from '@ethersproject/providers';
|
||||
import { getCustomProvider } from '@vulcanize/util';
|
||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||
import { StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
|
||||
import { EventData } from '../../src/utils';
|
||||
import { Database } from '../../src/database';
|
||||
import { Indexer } from './indexer';
|
||||
|
||||
const NETWORK_URL = 'http://127.0.0.1:8081';
|
||||
const IPLD_ETH_SERVER_GQL_URL = 'http://127.0.0.1:8082/graphql';
|
||||
|
||||
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
export const ZERO_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
||||
@ -71,8 +74,13 @@ export const getTestDatabase = (): Database => {
|
||||
return new Database({ type: 'postgres' }, '');
|
||||
};
|
||||
|
||||
export const getTestIndexer = (): Indexer => {
|
||||
return new Indexer();
|
||||
export const getTestIndexer = (storageLayout?: Map<string, StorageLayout>): Indexer => {
|
||||
const ethClient = new EthClient({
|
||||
gqlEndpoint: IPLD_ETH_SERVER_GQL_URL,
|
||||
cache: undefined
|
||||
});
|
||||
|
||||
return new Indexer(ethClient, storageLayout);
|
||||
};
|
||||
|
||||
export const getTestProvider = (): BaseProvider => {
|
||||
|
@ -6,14 +6,43 @@ import {
|
||||
BlockProgressInterface,
|
||||
EventInterface,
|
||||
SyncStatusInterface,
|
||||
ServerConfig as ServerConfigInterface
|
||||
ServerConfig as ServerConfigInterface,
|
||||
ValueResult
|
||||
} from '@vulcanize/util';
|
||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||
import { GetStorageAt, getStorageValue, MappingKey, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
|
||||
export class Indexer implements IndexerInterface {
|
||||
_getStorageAt: GetStorageAt;
|
||||
_storageLayoutMap: Map<string, StorageLayout> = new Map()
|
||||
|
||||
constructor (ethClient: EthClient, storageLayoutMap?: Map<string, StorageLayout>) {
|
||||
this._getStorageAt = ethClient.getStorageAt.bind(ethClient);
|
||||
|
||||
if (storageLayoutMap) {
|
||||
this._storageLayoutMap = storageLayoutMap;
|
||||
}
|
||||
}
|
||||
|
||||
get serverConfig () {
|
||||
return new ServerConfig();
|
||||
}
|
||||
|
||||
get storageLayoutMap (): Map<string, StorageLayout> {
|
||||
return this._storageLayoutMap;
|
||||
}
|
||||
|
||||
async getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult> {
|
||||
return getStorageValue(
|
||||
storageLayout,
|
||||
this._getStorageAt,
|
||||
blockHash,
|
||||
contractAddress,
|
||||
variable,
|
||||
...mappingKeys
|
||||
);
|
||||
}
|
||||
|
||||
async getBlockProgress (blockHash: string): Promise<BlockProgressInterface | undefined> {
|
||||
assert(blockHash);
|
||||
|
||||
|
@ -12,7 +12,7 @@ import { JsonFragment } from '@ethersproject/abi';
|
||||
import { BaseProvider } from '@ethersproject/providers';
|
||||
import * as codec from '@ipld/dag-cbor';
|
||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||
import { StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import { StorageLayout, MappingKey } from '@vulcanize/solidity-mapper';
|
||||
import {
|
||||
IPLDIndexer as BaseIndexer,
|
||||
ValueResult,
|
||||
@ -141,6 +141,10 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
return this._serverConfig;
|
||||
}
|
||||
|
||||
get storageLayoutMap (): Map<string, StorageLayout> {
|
||||
return this._storageLayoutMap;
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
await this._baseIndexer.fetchContracts();
|
||||
await this._baseIndexer.fetchIPLDStatus();
|
||||
@ -266,6 +270,16 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
return result;
|
||||
}
|
||||
|
||||
async getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult> {
|
||||
return this._baseIndexer.getStorageValue(
|
||||
storageLayout,
|
||||
blockHash,
|
||||
contractAddress,
|
||||
variable,
|
||||
...mappingKeys
|
||||
);
|
||||
}
|
||||
|
||||
async pushToIPFS (data: any): Promise<void> {
|
||||
await this._baseIndexer.pushToIPFS(data);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import { JsonFragment } from '@ethersproject/abi';
|
||||
import { JsonRpcProvider } from '@ethersproject/providers';
|
||||
import * as codec from '@ipld/dag-cbor';
|
||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||
import { StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import { MappingKey, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
import {
|
||||
IPLDIndexer as BaseIndexer,
|
||||
IPLDIndexerInterface,
|
||||
@ -133,6 +133,10 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
return this._serverConfig;
|
||||
}
|
||||
|
||||
get storageLayoutMap (): Map<string, StorageLayout> {
|
||||
return this._storageLayoutMap;
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
await this._baseIndexer.fetchContracts();
|
||||
await this._baseIndexer.fetchIPLDStatus();
|
||||
@ -400,6 +404,16 @@ export class Indexer implements IPLDIndexerInterface {
|
||||
} as any;
|
||||
}
|
||||
|
||||
async getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult> {
|
||||
return this._baseIndexer.getStorageValue(
|
||||
storageLayout,
|
||||
blockHash,
|
||||
contractAddress,
|
||||
variable,
|
||||
...mappingKeys
|
||||
);
|
||||
}
|
||||
|
||||
async pushToIPFS (data: any): Promise<void> {
|
||||
await this._baseIndexer.pushToIPFS(data);
|
||||
}
|
||||
|
@ -2,6 +2,6 @@
|
||||
// Copyright 2021 Vulcanize, Inc.
|
||||
//
|
||||
|
||||
export { getStorageValue, getStorageInfo, getValueByType, StorageLayout, GetStorageAt } from './storage';
|
||||
export { getStorageValue, getStorageInfo, getValueByType, StorageLayout, GetStorageAt, MappingKey } from './storage';
|
||||
|
||||
export { getEventNameTopics } from './logs';
|
||||
|
@ -23,7 +23,7 @@ interface Types {
|
||||
};
|
||||
}
|
||||
|
||||
type MappingKey = string | boolean | number;
|
||||
export type MappingKey = string | boolean | number;
|
||||
|
||||
export interface StorageLayout {
|
||||
storage: Storage[];
|
||||
|
@ -3,10 +3,12 @@
|
||||
//
|
||||
|
||||
import { Connection, DeepPartial, FindConditions, FindManyOptions, QueryRunner } from 'typeorm';
|
||||
import { MappingKey, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||
|
||||
import { ServerConfig } from './config';
|
||||
import { Where, QueryOptions } from './database';
|
||||
import { IpldStatus } from './ipld-indexer';
|
||||
import { ValueResult } from './indexer';
|
||||
|
||||
export enum StateKind {
|
||||
Diff = 'diff',
|
||||
@ -80,6 +82,7 @@ export interface IPLDBlockInterface {
|
||||
|
||||
export interface IndexerInterface {
|
||||
readonly serverConfig: ServerConfig
|
||||
readonly storageLayoutMap: Map<string, StorageLayout>
|
||||
getBlockProgress (blockHash: string): Promise<BlockProgressInterface | undefined>
|
||||
getBlockProgressEntities (where: FindConditions<BlockProgressInterface>, options: FindManyOptions<BlockProgressInterface>): Promise<BlockProgressInterface[]>
|
||||
getEvent (id: string): Promise<EventInterface | undefined>
|
||||
@ -108,6 +111,7 @@ export interface IndexerInterface {
|
||||
processStateCheckpoint?: (contractAddress: string, blockHash: string) => Promise<boolean>
|
||||
processBlock?: (blockHash: string, blockNumber: number) => Promise<void>
|
||||
processBlockAfterEvents?: (blockHash: string) => Promise<void>
|
||||
getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult>
|
||||
}
|
||||
|
||||
export interface IPLDIndexerInterface extends IndexerInterface {
|
||||
|
Loading…
Reference in New Issue
Block a user