mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-02-09 11:32:49 +00:00
173 lines
7.4 KiB
TypeScript
173 lines
7.4 KiB
TypeScript
|
//
|
||
|
// Copyright 2021 Vulcanize, Inc.
|
||
|
//
|
||
|
|
||
|
import assert from 'assert';
|
||
|
import BigInt from 'apollo-type-bigint';
|
||
|
import debug from 'debug';
|
||
|
import Decimal from 'decimal.js';
|
||
|
import { GraphQLScalarType } from 'graphql';
|
||
|
|
||
|
import { ValueResult, BlockHeight, StateKind } from '@vulcanize/util';
|
||
|
|
||
|
import { Indexer } from './indexer';
|
||
|
import { EventWatcher } from './events';
|
||
|
|
||
|
const log = debug('vulcanize:resolver');
|
||
|
|
||
|
export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatcher): Promise<any> => {
|
||
|
assert(indexer);
|
||
|
|
||
|
return {
|
||
|
BigInt: new BigInt('bigInt'),
|
||
|
|
||
|
BigDecimal: new GraphQLScalarType({
|
||
|
name: 'BigDecimal',
|
||
|
description: 'BigDecimal custom scalar type',
|
||
|
parseValue (value) {
|
||
|
// value from the client
|
||
|
return new Decimal(value);
|
||
|
},
|
||
|
serialize (value: Decimal) {
|
||
|
// value sent to the client
|
||
|
return value.toFixed();
|
||
|
}
|
||
|
}),
|
||
|
|
||
|
Event: {
|
||
|
__resolveType: (obj: any) => {
|
||
|
assert(obj.__typename);
|
||
|
|
||
|
return obj.__typename;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
Subscription: {
|
||
|
onEvent: {
|
||
|
subscribe: () => eventWatcher.getEventIterator()
|
||
|
}
|
||
|
},
|
||
|
|
||
|
Mutation: {
|
||
|
watchContract: async (_: any, { address, kind, checkpoint, startingBlock = 1 }: { address: string, kind: string, checkpoint: boolean, startingBlock: number }): Promise<boolean> => {
|
||
|
log('watchContract', address, kind, checkpoint, startingBlock);
|
||
|
await indexer.watchContract(address, kind, checkpoint, startingBlock);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
Query: {
|
||
|
supportsInterface: (_: any, { blockHash, contractAddress, interfaceId }: { blockHash: string, contractAddress: string, interfaceId: string }): Promise<ValueResult> => {
|
||
|
log('supportsInterface', blockHash, contractAddress, interfaceId);
|
||
|
return indexer.supportsInterface(blockHash, contractAddress, interfaceId);
|
||
|
},
|
||
|
|
||
|
balanceOf: (_: any, { blockHash, contractAddress, owner }: { blockHash: string, contractAddress: string, owner: string }): Promise<ValueResult> => {
|
||
|
log('balanceOf', blockHash, contractAddress, owner);
|
||
|
return indexer.balanceOf(blockHash, contractAddress, owner);
|
||
|
},
|
||
|
|
||
|
ownerOf: (_: any, { blockHash, contractAddress, tokenId }: { blockHash: string, contractAddress: string, tokenId: bigint }): Promise<ValueResult> => {
|
||
|
log('ownerOf', blockHash, contractAddress, tokenId);
|
||
|
return indexer.ownerOf(blockHash, contractAddress, tokenId);
|
||
|
},
|
||
|
|
||
|
getApproved: (_: any, { blockHash, contractAddress, tokenId }: { blockHash: string, contractAddress: string, tokenId: bigint }): Promise<ValueResult> => {
|
||
|
log('getApproved', blockHash, contractAddress, tokenId);
|
||
|
return indexer.getApproved(blockHash, contractAddress, tokenId);
|
||
|
},
|
||
|
|
||
|
isApprovedForAll: (_: any, { blockHash, contractAddress, owner, operator }: { blockHash: string, contractAddress: string, owner: string, operator: string }): Promise<ValueResult> => {
|
||
|
log('isApprovedForAll', blockHash, contractAddress, owner, operator);
|
||
|
return indexer.isApprovedForAll(blockHash, contractAddress, owner, operator);
|
||
|
},
|
||
|
|
||
|
name: (_: any, { blockHash, contractAddress }: { blockHash: string, contractAddress: string }): Promise<ValueResult> => {
|
||
|
log('name', blockHash, contractAddress);
|
||
|
return indexer.name(blockHash, contractAddress);
|
||
|
},
|
||
|
|
||
|
symbol: (_: any, { blockHash, contractAddress }: { blockHash: string, contractAddress: string }): Promise<ValueResult> => {
|
||
|
log('symbol', blockHash, contractAddress);
|
||
|
return indexer.symbol(blockHash, contractAddress);
|
||
|
},
|
||
|
|
||
|
tokenURI: (_: any, { blockHash, contractAddress, tokenId }: { blockHash: string, contractAddress: string, tokenId: bigint }): Promise<ValueResult> => {
|
||
|
log('tokenURI', blockHash, contractAddress, tokenId);
|
||
|
return indexer.tokenURI(blockHash, contractAddress, tokenId);
|
||
|
},
|
||
|
|
||
|
_name: (_: any, { blockHash, contractAddress }: { blockHash: string, contractAddress: string }): Promise<ValueResult> => {
|
||
|
log('_name', blockHash, contractAddress);
|
||
|
return indexer._name(blockHash, contractAddress);
|
||
|
},
|
||
|
|
||
|
_symbol: (_: any, { blockHash, contractAddress }: { blockHash: string, contractAddress: string }): Promise<ValueResult> => {
|
||
|
log('_symbol', blockHash, contractAddress);
|
||
|
return indexer._symbol(blockHash, contractAddress);
|
||
|
},
|
||
|
|
||
|
_owners: (_: any, { blockHash, contractAddress, key0 }: { blockHash: string, contractAddress: string, key0: bigint }): Promise<ValueResult> => {
|
||
|
log('_owners', blockHash, contractAddress, key0);
|
||
|
return indexer._owners(blockHash, contractAddress, key0);
|
||
|
},
|
||
|
|
||
|
_balances: (_: any, { blockHash, contractAddress, key0 }: { blockHash: string, contractAddress: string, key0: string }): Promise<ValueResult> => {
|
||
|
log('_balances', blockHash, contractAddress, key0);
|
||
|
return indexer._balances(blockHash, contractAddress, key0);
|
||
|
},
|
||
|
|
||
|
_tokenApprovals: (_: any, { blockHash, contractAddress, key0 }: { blockHash: string, contractAddress: string, key0: bigint }): Promise<ValueResult> => {
|
||
|
log('_tokenApprovals', blockHash, contractAddress, key0);
|
||
|
return indexer._tokenApprovals(blockHash, contractAddress, key0);
|
||
|
},
|
||
|
|
||
|
_operatorApprovals: (_: any, { blockHash, contractAddress, key0, key1 }: { blockHash: string, contractAddress: string, key0: string, key1: string }): Promise<ValueResult> => {
|
||
|
log('_operatorApprovals', blockHash, contractAddress, key0, key1);
|
||
|
return indexer._operatorApprovals(blockHash, contractAddress, key0, key1);
|
||
|
},
|
||
|
|
||
|
events: async (_: any, { blockHash, contractAddress, name }: { blockHash: string, contractAddress: string, name?: string }) => {
|
||
|
log('events', blockHash, contractAddress, name);
|
||
|
|
||
|
const block = await indexer.getBlockProgress(blockHash);
|
||
|
if (!block || !block.isComplete) {
|
||
|
throw new Error(`Block hash ${blockHash} number ${block?.blockNumber} not processed yet`);
|
||
|
}
|
||
|
|
||
|
const events = await indexer.getEventsByFilter(blockHash, contractAddress, name);
|
||
|
return events.map(event => indexer.getResultEvent(event));
|
||
|
},
|
||
|
|
||
|
eventsInRange: async (_: any, { fromBlockNumber, toBlockNumber }: { fromBlockNumber: number, toBlockNumber: number }) => {
|
||
|
log('eventsInRange', fromBlockNumber, toBlockNumber);
|
||
|
|
||
|
const { expected, actual } = await indexer.getProcessedBlockCountForRange(fromBlockNumber, toBlockNumber);
|
||
|
if (expected !== actual) {
|
||
|
throw new Error(`Range not available, expected ${expected}, got ${actual} blocks in range`);
|
||
|
}
|
||
|
|
||
|
const events = await indexer.getEventsInRange(fromBlockNumber, toBlockNumber);
|
||
|
return events.map(event => indexer.getResultEvent(event));
|
||
|
},
|
||
|
|
||
|
getStateByCID: async (_: any, { cid }: { cid: string }) => {
|
||
|
log('getStateByCID', cid);
|
||
|
|
||
|
const ipldBlock = await indexer.getIPLDBlockByCid(cid);
|
||
|
|
||
|
return ipldBlock && ipldBlock.block.isComplete ? indexer.getResultIPLDBlock(ipldBlock) : undefined;
|
||
|
},
|
||
|
|
||
|
getState: async (_: any, { blockHash, contractAddress, kind = StateKind.Diff }: { blockHash: string, contractAddress: string, kind: string }) => {
|
||
|
log('getState', blockHash, contractAddress, kind);
|
||
|
|
||
|
const ipldBlock = await indexer.getPrevIPLDBlock(blockHash, contractAddress, kind);
|
||
|
|
||
|
return ipldBlock && ipldBlock.block.isComplete ? indexer.getResultIPLDBlock(ipldBlock) : undefined;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
};
|