ajna-watcher-ts/src/indexer.ts
Nabarun 588f22e645 Support fragments in GQL queries (#11)
Part of [Regenerate ajna watcher with updated subgraph config](https://www.notion.so/Regenerate-ajna-watcher-with-updated-subgraph-config-c9bbecb033024c13a7515c7f1efc3363)

Reviewed-on: #11
Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
Co-committed-by: Nabarun <nabarun@deepstacksoft.com>
2024-05-17 11:58:02 +00:00

2311 lines
66 KiB
TypeScript

//
// Copyright 2021 Vulcanize, Inc.
//
import assert from 'assert';
import { DeepPartial, FindConditions, FindManyOptions, ObjectLiteral } from 'typeorm';
import debug from 'debug';
import { ethers, constants } from 'ethers';
import { GraphQLResolveInfo } from 'graphql';
import { JsonFragment } from '@ethersproject/abi';
import { BaseProvider } from '@ethersproject/providers';
import { MappingKey, StorageLayout } from '@cerc-io/solidity-mapper';
import {
Indexer as BaseIndexer,
IndexerInterface,
ValueResult,
ServerConfig,
JobQueue,
Where,
QueryOptions,
BlockHeight,
ResultMeta,
updateSubgraphState,
dumpSubgraphState,
GraphWatcherInterface,
StateKind,
StateStatus,
ResultEvent,
getResultEvent,
DatabaseInterface,
Clients,
EthClient,
UpstreamConfig,
EthFullBlock,
EthFullTransaction,
ExtraEventData
} from '@cerc-io/util';
import { GraphWatcher } from '@cerc-io/graph-node';
import PositionManagerArtifacts from './artifacts/PositionManager.json';
import ERC20PoolFactoryArtifacts from './artifacts/ERC20PoolFactory.json';
import ERC721PoolFactoryArtifacts from './artifacts/ERC721PoolFactory.json';
import GrantFundArtifacts from './artifacts/GrantFund.json';
import AjnaTokenArtifacts from './artifacts/AjnaToken.json';
import BurnWrappedAjnaArtifacts from './artifacts/BurnWrappedAjna.json';
import ERC20PoolArtifacts from './artifacts/ERC20Pool.json';
import ERC721PoolArtifacts from './artifacts/ERC721Pool.json';
import { Database, ENTITIES, SUBGRAPH_ENTITIES } from './database';
import { createInitialState, handleEvent, createStateDiff, createStateCheckpoint } from './hooks';
import { Contract } from './entity/Contract';
import { Event } from './entity/Event';
import { SyncStatus } from './entity/SyncStatus';
import { StateSyncStatus } from './entity/StateSyncStatus';
import { BlockProgress } from './entity/BlockProgress';
import { State } from './entity/State';
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Token } from './entity/Token';
import { PoolFactory } from './entity/PoolFactory';
import { Pool } from './entity/Pool';
import { Bucket } from './entity/Bucket';
import { Lend } from './entity/Lend';
import { Loan } from './entity/Loan';
import { Account } from './entity/Account';
import { LiquidationAuction } from './entity/LiquidationAuction';
import { ReserveAuction } from './entity/ReserveAuction';
import { LPTransferorList } from './entity/LPTransferorList';
import { LPAllowance } from './entity/LPAllowance';
import { LPAllowanceList } from './entity/LPAllowanceList';
import { AddCollateral } from './entity/AddCollateral';
import { AddQuoteToken } from './entity/AddQuoteToken';
import { AuctionSettle } from './entity/AuctionSettle';
import { BondWithdrawn } from './entity/BondWithdrawn';
import { BucketBankruptcy } from './entity/BucketBankruptcy';
import { BucketTake } from './entity/BucketTake';
import { BucketTakeLPAwarded } from './entity/BucketTakeLPAwarded';
import { DrawDebt } from './entity/DrawDebt';
import { Flashloan } from './entity/Flashloan';
import { Kick } from './entity/Kick';
import { LoanStamped } from './entity/LoanStamped';
import { MoveQuoteToken } from './entity/MoveQuoteToken';
import { RemoveCollateral } from './entity/RemoveCollateral';
import { RemoveQuoteToken } from './entity/RemoveQuoteToken';
import { RepayDebt } from './entity/RepayDebt';
import { ReserveAuctionKick } from './entity/ReserveAuctionKick';
import { ReserveAuctionTake } from './entity/ReserveAuctionTake';
import { ResetInterestRate } from './entity/ResetInterestRate';
import { Settle } from './entity/Settle';
import { Take } from './entity/Take';
import { TransferLP } from './entity/TransferLP';
import { UpdateInterestRate } from './entity/UpdateInterestRate';
import { Approval } from './entity/Approval';
import { ApprovalForAll } from './entity/ApprovalForAll';
import { MoveLiquidity } from './entity/MoveLiquidity';
import { Transfer } from './entity/Transfer';
import { PoolCreated } from './entity/PoolCreated';
import { AddCollateralNFT } from './entity/AddCollateralNFT';
import { AuctionNFTSettle } from './entity/AuctionNFTSettle';
import { DrawDebtNFT } from './entity/DrawDebtNFT';
import { MergeOrRemoveCollateralNFT } from './entity/MergeOrRemoveCollateralNFT';
import { Position } from './entity/Position';
import { PositionLend } from './entity/PositionLend';
import { Burn } from './entity/Burn';
import { MemorializePosition } from './entity/MemorializePosition';
import { Mint } from './entity/Mint';
import { RedeemPosition } from './entity/RedeemPosition';
import { GrantFund } from './entity/GrantFund';
import { DistributionPeriod } from './entity/DistributionPeriod';
import { Proposal } from './entity/Proposal';
import { ProposalParams } from './entity/ProposalParams';
import { DistributionPeriodVote } from './entity/DistributionPeriodVote';
import { ScreeningVote } from './entity/ScreeningVote';
import { FundingVote } from './entity/FundingVote';
import { FundedSlate } from './entity/FundedSlate';
import { DelegateRewardClaimed } from './entity/DelegateRewardClaimed';
import { FundTreasury } from './entity/FundTreasury';
import { FundedSlateUpdated } from './entity/FundedSlateUpdated';
import { ProposalCreated } from './entity/ProposalCreated';
import { ProposalExecuted } from './entity/ProposalExecuted';
import { DistributionPeriodStarted } from './entity/DistributionPeriodStarted';
import { VoteCast } from './entity/VoteCast';
import { DelegateChanged } from './entity/DelegateChanged';
import { DelegateVotesChanged } from './entity/DelegateVotesChanged';
import { BurnWrap } from './entity/BurnWrap';
/* eslint-enable @typescript-eslint/no-unused-vars */
import { FrothyEntity } from './entity/FrothyEntity';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const log = debug('vulcanize:indexer');
const KIND_POSITIONMANAGER = 'PositionManager';
const KIND_ERC20POOLFACTORY = 'ERC20PoolFactory';
const KIND_ERC721POOLFACTORY = 'ERC721PoolFactory';
const KIND_GRANTFUND = 'GrantFund';
const KIND_AJNATOKEN = 'AjnaToken';
const KIND_BURNWRAPPEDAJNA = 'BurnWrappedAjna';
const KIND_ERC20POOL = 'ERC20Pool';
const KIND_ERC721POOL = 'ERC721Pool';
export class Indexer implements IndexerInterface {
_db: Database;
_ethClient: EthClient;
_ethProvider: BaseProvider;
_baseIndexer: BaseIndexer;
_serverConfig: ServerConfig;
_upstreamConfig: UpstreamConfig;
_graphWatcher: GraphWatcher;
_abiMap: Map<string, JsonFragment[]>;
_storageLayoutMap: Map<string, StorageLayout>;
_contractMap: Map<string, ethers.utils.Interface>;
eventSignaturesMap: Map<string, string[]>;
_entityTypesMap: Map<string, { [key: string]: string }>;
_relationsMap: Map<any, { [key: string]: any }>;
_subgraphStateMap: Map<string, any>;
constructor (
config: {
server: ServerConfig;
upstream: UpstreamConfig;
},
db: DatabaseInterface,
clients: Clients,
ethProvider: BaseProvider,
jobQueue: JobQueue,
graphWatcher?: GraphWatcherInterface
) {
assert(db);
assert(clients.ethClient);
this._db = db as Database;
this._ethClient = clients.ethClient;
this._ethProvider = ethProvider;
this._serverConfig = config.server;
this._upstreamConfig = config.upstream;
this._baseIndexer = new BaseIndexer(config, this._db, this._ethClient, this._ethProvider, jobQueue);
assert(graphWatcher);
this._graphWatcher = graphWatcher as GraphWatcher;
this._abiMap = new Map();
this._storageLayoutMap = new Map();
this._contractMap = new Map();
this.eventSignaturesMap = new Map();
const { abi: PositionManagerABI } = PositionManagerArtifacts;
const { abi: ERC20PoolFactoryABI } = ERC20PoolFactoryArtifacts;
const { abi: ERC721PoolFactoryABI } = ERC721PoolFactoryArtifacts;
const { abi: GrantFundABI } = GrantFundArtifacts;
const { abi: AjnaTokenABI } = AjnaTokenArtifacts;
const { abi: BurnWrappedAjnaABI } = BurnWrappedAjnaArtifacts;
const { abi: ERC20PoolABI } = ERC20PoolArtifacts;
const { abi: ERC721PoolABI } = ERC721PoolArtifacts;
assert(PositionManagerABI);
this._abiMap.set(KIND_POSITIONMANAGER, PositionManagerABI);
const PositionManagerContractInterface = new ethers.utils.Interface(PositionManagerABI);
this._contractMap.set(KIND_POSITIONMANAGER, PositionManagerContractInterface);
const PositionManagerEventSignatures = Object.values(PositionManagerContractInterface.events).map(value => {
return PositionManagerContractInterface.getEventTopic(value);
});
this.eventSignaturesMap.set(KIND_POSITIONMANAGER, PositionManagerEventSignatures);
assert(ERC20PoolFactoryABI);
this._abiMap.set(KIND_ERC20POOLFACTORY, ERC20PoolFactoryABI);
const ERC20PoolFactoryContractInterface = new ethers.utils.Interface(ERC20PoolFactoryABI);
this._contractMap.set(KIND_ERC20POOLFACTORY, ERC20PoolFactoryContractInterface);
const ERC20PoolFactoryEventSignatures = Object.values(ERC20PoolFactoryContractInterface.events).map(value => {
return ERC20PoolFactoryContractInterface.getEventTopic(value);
});
this.eventSignaturesMap.set(KIND_ERC20POOLFACTORY, ERC20PoolFactoryEventSignatures);
assert(ERC721PoolFactoryABI);
this._abiMap.set(KIND_ERC721POOLFACTORY, ERC721PoolFactoryABI);
const ERC721PoolFactoryContractInterface = new ethers.utils.Interface(ERC721PoolFactoryABI);
this._contractMap.set(KIND_ERC721POOLFACTORY, ERC721PoolFactoryContractInterface);
const ERC721PoolFactoryEventSignatures = Object.values(ERC721PoolFactoryContractInterface.events).map(value => {
return ERC721PoolFactoryContractInterface.getEventTopic(value);
});
this.eventSignaturesMap.set(KIND_ERC721POOLFACTORY, ERC721PoolFactoryEventSignatures);
assert(GrantFundABI);
this._abiMap.set(KIND_GRANTFUND, GrantFundABI);
const GrantFundContractInterface = new ethers.utils.Interface(GrantFundABI);
this._contractMap.set(KIND_GRANTFUND, GrantFundContractInterface);
const GrantFundEventSignatures = Object.values(GrantFundContractInterface.events).map(value => {
return GrantFundContractInterface.getEventTopic(value);
});
this.eventSignaturesMap.set(KIND_GRANTFUND, GrantFundEventSignatures);
assert(AjnaTokenABI);
this._abiMap.set(KIND_AJNATOKEN, AjnaTokenABI);
const AjnaTokenContractInterface = new ethers.utils.Interface(AjnaTokenABI);
this._contractMap.set(KIND_AJNATOKEN, AjnaTokenContractInterface);
const AjnaTokenEventSignatures = Object.values(AjnaTokenContractInterface.events).map(value => {
return AjnaTokenContractInterface.getEventTopic(value);
});
this.eventSignaturesMap.set(KIND_AJNATOKEN, AjnaTokenEventSignatures);
assert(BurnWrappedAjnaABI);
this._abiMap.set(KIND_BURNWRAPPEDAJNA, BurnWrappedAjnaABI);
const BurnWrappedAjnaContractInterface = new ethers.utils.Interface(BurnWrappedAjnaABI);
this._contractMap.set(KIND_BURNWRAPPEDAJNA, BurnWrappedAjnaContractInterface);
const BurnWrappedAjnaEventSignatures = Object.values(BurnWrappedAjnaContractInterface.events).map(value => {
return BurnWrappedAjnaContractInterface.getEventTopic(value);
});
this.eventSignaturesMap.set(KIND_BURNWRAPPEDAJNA, BurnWrappedAjnaEventSignatures);
assert(ERC20PoolABI);
this._abiMap.set(KIND_ERC20POOL, ERC20PoolABI);
const ERC20PoolContractInterface = new ethers.utils.Interface(ERC20PoolABI);
this._contractMap.set(KIND_ERC20POOL, ERC20PoolContractInterface);
const ERC20PoolEventSignatures = Object.values(ERC20PoolContractInterface.events).map(value => {
return ERC20PoolContractInterface.getEventTopic(value);
});
this.eventSignaturesMap.set(KIND_ERC20POOL, ERC20PoolEventSignatures);
assert(ERC721PoolABI);
this._abiMap.set(KIND_ERC721POOL, ERC721PoolABI);
const ERC721PoolContractInterface = new ethers.utils.Interface(ERC721PoolABI);
this._contractMap.set(KIND_ERC721POOL, ERC721PoolContractInterface);
const ERC721PoolEventSignatures = Object.values(ERC721PoolContractInterface.events).map(value => {
return ERC721PoolContractInterface.getEventTopic(value);
});
this.eventSignaturesMap.set(KIND_ERC721POOL, ERC721PoolEventSignatures);
this._entityTypesMap = new Map();
this._populateEntityTypesMap();
this._relationsMap = new Map();
this._populateRelationsMap();
this._subgraphStateMap = new Map();
}
get serverConfig (): ServerConfig {
return this._serverConfig;
}
get upstreamConfig (): UpstreamConfig {
return this._upstreamConfig;
}
get storageLayoutMap (): Map<string, StorageLayout> {
return this._storageLayoutMap;
}
get graphWatcher (): GraphWatcher {
return this._graphWatcher;
}
async init (): Promise<void> {
await this._baseIndexer.fetchContracts();
await this._baseIndexer.fetchStateStatus();
}
switchClients ({ ethClient, ethProvider }: { ethClient: EthClient, ethProvider: BaseProvider }): void {
this._ethClient = ethClient;
this._ethProvider = ethProvider;
this._baseIndexer.switchClients({ ethClient, ethProvider });
this._graphWatcher.switchClients({ ethClient, ethProvider });
}
async getMetaData (block: BlockHeight): Promise<ResultMeta | null> {
return this._baseIndexer.getMetaData(block);
}
getResultEvent (event: Event): ResultEvent {
return getResultEvent(event);
}
async getStorageValue (storageLayout: StorageLayout, blockHash: string, contractAddress: string, variable: string, ...mappingKeys: MappingKey[]): Promise<ValueResult> {
return this._baseIndexer.getStorageValue(
storageLayout,
blockHash,
contractAddress,
variable,
...mappingKeys
);
}
async getEntitiesForBlock (blockHash: string, tableName: string): Promise<any[]> {
return this._db.getEntitiesForBlock(blockHash, tableName);
}
async processInitialState (contractAddress: string, blockHash: string): Promise<any> {
// Call initial state hook.
return createInitialState(this, contractAddress, blockHash);
}
async processStateCheckpoint (contractAddress: string, blockHash: string): Promise<boolean> {
// Call checkpoint hook.
return createStateCheckpoint(this, contractAddress, blockHash);
}
async processCanonicalBlock (blockHash: string, blockNumber: number): Promise<void> {
console.time('time:indexer#processCanonicalBlock-finalize_auto_diffs');
// Finalize staged diff blocks if any.
await this._baseIndexer.finalizeDiffStaged(blockHash);
console.timeEnd('time:indexer#processCanonicalBlock-finalize_auto_diffs');
// Call custom stateDiff hook.
await createStateDiff(this, blockHash);
this._graphWatcher.pruneEntityCacheFrothyBlocks(blockHash, blockNumber);
}
async processCheckpoint (blockHash: string): Promise<void> {
// Return if checkpointInterval is <= 0.
const checkpointInterval = this._serverConfig.checkpointInterval;
if (checkpointInterval <= 0) return;
console.time('time:indexer#processCheckpoint-checkpoint');
await this._baseIndexer.processCheckpoint(this, blockHash, checkpointInterval);
console.timeEnd('time:indexer#processCheckpoint-checkpoint');
}
async processCLICheckpoint (contractAddress: string, blockHash?: string): Promise<string | undefined> {
return this._baseIndexer.processCLICheckpoint(this, contractAddress, blockHash);
}
async getPrevState (blockHash: string, contractAddress: string, kind?: string): Promise<State | undefined> {
return this._db.getPrevState(blockHash, contractAddress, kind);
}
async getLatestState (contractAddress: string, kind: StateKind | null, blockNumber?: number): Promise<State | undefined> {
return this._db.getLatestState(contractAddress, kind, blockNumber);
}
async getStatesByHash (blockHash: string): Promise<State[]> {
return this._baseIndexer.getStatesByHash(blockHash);
}
async getStateByCID (cid: string): Promise<State | undefined> {
return this._baseIndexer.getStateByCID(cid);
}
async getStates (where: FindConditions<State>): Promise<State[]> {
return this._db.getStates(where);
}
getStateData (state: State): any {
return this._baseIndexer.getStateData(state);
}
// Method used to create auto diffs (diff_staged).
async createDiffStaged (contractAddress: string, blockHash: string, data: any): Promise<void> {
console.time('time:indexer#createDiffStaged-auto_diff');
await this._baseIndexer.createDiffStaged(contractAddress, blockHash, data);
console.timeEnd('time:indexer#createDiffStaged-auto_diff');
}
// Method to be used by createStateDiff hook.
async createDiff (contractAddress: string, blockHash: string, data: any): Promise<void> {
const block = await this.getBlockProgress(blockHash);
assert(block);
await this._baseIndexer.createDiff(contractAddress, block, data);
}
// Method to be used by createStateCheckpoint hook.
async createStateCheckpoint (contractAddress: string, blockHash: string, data: any): Promise<void> {
const block = await this.getBlockProgress(blockHash);
assert(block);
return this._baseIndexer.createStateCheckpoint(contractAddress, block, data);
}
// Method to be used by export-state CLI.
async createCheckpoint (contractAddress: string, blockHash: string): Promise<string | undefined> {
const block = await this.getBlockProgress(blockHash);
assert(block);
return this._baseIndexer.createCheckpoint(this, contractAddress, block);
}
// Method to be used by fill-state CLI.
async createInit (blockHash: string, blockNumber: number): Promise<void> {
// Create initial state for contracts.
await this._baseIndexer.createInit(this, blockHash, blockNumber);
}
async saveOrUpdateState (state: State): Promise<State> {
return this._baseIndexer.saveOrUpdateState(state);
}
async removeStates (blockNumber: number, kind: StateKind): Promise<void> {
await this._baseIndexer.removeStates(blockNumber, kind);
}
async getSubgraphEntity<Entity extends ObjectLiteral> (
entity: new () => Entity,
id: string,
block: BlockHeight,
queryInfo: GraphQLResolveInfo
): Promise<any> {
const data = await this._graphWatcher.getEntity(entity, id, this._relationsMap, block, queryInfo);
return data;
}
async getSubgraphEntities<Entity extends ObjectLiteral> (
entity: new () => Entity,
block: BlockHeight,
where: { [key: string]: any } = {},
queryOptions: QueryOptions = {},
queryInfo: GraphQLResolveInfo
): Promise<any[]> {
return this._graphWatcher.getEntities(entity, this._relationsMap, block, where, queryOptions, queryInfo);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async triggerIndexingOnEvent (event: Event, extraData: ExtraEventData): Promise<void> {
const resultEvent = this.getResultEvent(event);
console.time('time:indexer#processEvent-mapping_code');
// Call subgraph handler for event.
await this._graphWatcher.handleEvent(resultEvent, extraData);
console.timeEnd('time:indexer#processEvent-mapping_code');
// Call custom hook function for indexing on event.
await handleEvent(this, resultEvent);
}
async processEvent (event: Event, extraData: ExtraEventData): Promise<void> {
// Trigger indexing of data based on the event.
await this.triggerIndexingOnEvent(event, extraData);
}
async processBlock (blockProgress: BlockProgress): Promise<void> {
console.time('time:indexer#processBlock-init_state');
// Call a function to create initial state for contracts.
await this._baseIndexer.createInit(this, blockProgress.blockHash, blockProgress.blockNumber);
console.timeEnd('time:indexer#processBlock-init_state');
this._graphWatcher.updateEntityCacheFrothyBlocks(blockProgress);
}
async processBlockAfterEvents (blockHash: string, blockNumber: number, extraData: ExtraEventData): Promise<void> {
console.time('time:indexer#processBlockAfterEvents-mapping_code');
// Call subgraph handler for block.
await this._graphWatcher.handleBlock(blockHash, blockNumber, extraData);
console.timeEnd('time:indexer#processBlockAfterEvents-mapping_code');
console.time('time:indexer#processBlockAfterEvents-dump_subgraph_state');
// Persist subgraph state to the DB.
await this.dumpSubgraphState(blockHash);
console.timeEnd('time:indexer#processBlockAfterEvents-dump_subgraph_state');
}
parseEventNameAndArgs (kind: string, logObj: any): { eventParsed: boolean, eventDetails: any } {
const { topics, data } = logObj;
const contract = this._contractMap.get(kind);
assert(contract);
let logDescription: ethers.utils.LogDescription;
try {
logDescription = contract.parseLog({ data, topics });
} catch (err) {
// Return if no matching event found
if ((err as Error).message.includes('no matching event')) {
log(`WARNING: Skipping event for contract ${kind} as no matching event found in the ABI`);
return { eventParsed: false, eventDetails: {} };
}
throw err;
}
const { eventName, eventInfo, eventSignature } = this._baseIndexer.parseEvent(logDescription);
return {
eventParsed: true,
eventDetails: {
eventName,
eventInfo,
eventSignature
}
};
}
async getStateSyncStatus (): Promise<StateSyncStatus | undefined> {
return this._db.getStateSyncStatus();
}
async updateStateSyncStatusIndexedBlock (blockNumber: number, force?: boolean): Promise<StateSyncStatus | undefined> {
if (!this._serverConfig.enableState) {
return;
}
const dbTx = await this._db.createTransactionRunner();
let res;
try {
res = await this._db.updateStateSyncStatusIndexedBlock(dbTx, blockNumber, force);
await dbTx.commitTransaction();
} catch (error) {
await dbTx.rollbackTransaction();
throw error;
} finally {
await dbTx.release();
}
return res;
}
async updateStateSyncStatusCheckpointBlock (blockNumber: number, force?: boolean): Promise<StateSyncStatus> {
const dbTx = await this._db.createTransactionRunner();
let res;
try {
res = await this._db.updateStateSyncStatusCheckpointBlock(dbTx, blockNumber, force);
await dbTx.commitTransaction();
} catch (error) {
await dbTx.rollbackTransaction();
throw error;
} finally {
await dbTx.release();
}
return res;
}
async getLatestCanonicalBlock (): Promise<BlockProgress | undefined> {
const syncStatus = await this.getSyncStatus();
assert(syncStatus);
if (syncStatus.latestCanonicalBlockHash === constants.HashZero) {
return;
}
const latestCanonicalBlock = await this.getBlockProgress(syncStatus.latestCanonicalBlockHash);
assert(latestCanonicalBlock);
return latestCanonicalBlock;
}
async getLatestStateIndexedBlock (): Promise<BlockProgress> {
return this._baseIndexer.getLatestStateIndexedBlock();
}
async addContracts (): Promise<void> {
// Watching all the contracts in the subgraph.
await this._graphWatcher.addContracts();
}
async watchContract (address: string, kind: string, checkpoint: boolean, startingBlock: number, context?: any): Promise<void> {
return this._baseIndexer.watchContract(address, kind, checkpoint, startingBlock, context);
}
updateStateStatusMap (address: string, stateStatus: StateStatus): void {
this._baseIndexer.updateStateStatusMap(address, stateStatus);
}
cacheContract (contract: Contract): void {
return this._baseIndexer.cacheContract(contract);
}
async saveEventEntity (dbEvent: Event): Promise<Event> {
return this._baseIndexer.saveEventEntity(dbEvent);
}
async saveEvents (dbEvents: Event[]): Promise<void> {
return this._baseIndexer.saveEvents(dbEvents);
}
async getEventsByFilter (blockHash: string, contract?: string, name?: string): Promise<Array<Event>> {
return this._baseIndexer.getEventsByFilter(blockHash, contract, name);
}
isWatchedContract (address : string): Contract | undefined {
return this._baseIndexer.isWatchedContract(address);
}
getWatchedContracts (): Contract[] {
return this._baseIndexer.getWatchedContracts();
}
getContractsByKind (kind: string): Contract[] {
return this._baseIndexer.getContractsByKind(kind);
}
async getProcessedBlockCountForRange (fromBlockNumber: number, toBlockNumber: number): Promise<{ expected: number, actual: number }> {
return this._baseIndexer.getProcessedBlockCountForRange(fromBlockNumber, toBlockNumber);
}
async getEventsInRange (fromBlockNumber: number, toBlockNumber: number): Promise<Array<Event>> {
return this._baseIndexer.getEventsInRange(fromBlockNumber, toBlockNumber, this._serverConfig.maxEventsBlockRange);
}
async getSyncStatus (): Promise<SyncStatus | undefined> {
return this._baseIndexer.getSyncStatus();
}
async getBlocks (blockFilter: { blockHash?: string, blockNumber?: number }): Promise<any> {
return this._baseIndexer.getBlocks(blockFilter);
}
async updateSyncStatusIndexedBlock (blockHash: string, blockNumber: number, force = false): Promise<SyncStatus> {
return this._baseIndexer.updateSyncStatusIndexedBlock(blockHash, blockNumber, force);
}
async updateSyncStatusChainHead (blockHash: string, blockNumber: number, force = false): Promise<SyncStatus> {
return this._baseIndexer.updateSyncStatusChainHead(blockHash, blockNumber, force);
}
async updateSyncStatusCanonicalBlock (blockHash: string, blockNumber: number, force = false): Promise<SyncStatus> {
const syncStatus = this._baseIndexer.updateSyncStatusCanonicalBlock(blockHash, blockNumber, force);
await this.pruneFrothyEntities(blockNumber);
return syncStatus;
}
async updateSyncStatusProcessedBlock (blockHash: string, blockNumber: number, force = false): Promise<SyncStatus> {
return this._baseIndexer.updateSyncStatusProcessedBlock(blockHash, blockNumber, force);
}
async updateSyncStatusIndexingError (hasIndexingError: boolean): Promise<SyncStatus | undefined> {
return this._baseIndexer.updateSyncStatusIndexingError(hasIndexingError);
}
async updateSyncStatus (syncStatus: DeepPartial<SyncStatus>): Promise<SyncStatus> {
return this._baseIndexer.updateSyncStatus(syncStatus);
}
async getEvent (id: string): Promise<Event | undefined> {
return this._baseIndexer.getEvent(id);
}
async getBlockProgress (blockHash: string): Promise<BlockProgress | undefined> {
return this._baseIndexer.getBlockProgress(blockHash);
}
async getBlockProgressEntities (where: FindConditions<BlockProgress>, options: FindManyOptions<BlockProgress>): Promise<BlockProgress[]> {
return this._baseIndexer.getBlockProgressEntities(where, options);
}
async getBlocksAtHeight (height: number, isPruned: boolean): Promise<BlockProgress[]> {
return this._baseIndexer.getBlocksAtHeight(height, isPruned);
}
async fetchAndSaveFilteredEventsAndBlocks (startBlock: number, endBlock: number): Promise<{
blockProgress: BlockProgress,
events: DeepPartial<Event>[],
ethFullBlock: EthFullBlock;
ethFullTransactions: EthFullTransaction[];
}[]> {
return this._baseIndexer.fetchAndSaveFilteredEventsAndBlocks(startBlock, endBlock, this.eventSignaturesMap, this.parseEventNameAndArgs.bind(this));
}
async fetchEventsForContracts (blockHash: string, blockNumber: number, addresses: string[]): Promise<DeepPartial<Event>[]> {
return this._baseIndexer.fetchEventsForContracts(blockHash, blockNumber, addresses, this.eventSignaturesMap, this.parseEventNameAndArgs.bind(this));
}
async saveBlockAndFetchEvents (block: DeepPartial<BlockProgress>): Promise<[
BlockProgress,
DeepPartial<Event>[],
EthFullTransaction[]
]> {
return this._saveBlockAndFetchEvents(block);
}
async getBlockEvents (blockHash: string, where: Where, queryOptions: QueryOptions): Promise<Array<Event>> {
return this._baseIndexer.getBlockEvents(blockHash, where, queryOptions);
}
async removeUnknownEvents (block: BlockProgress): Promise<void> {
return this._baseIndexer.removeUnknownEvents(Event, block);
}
async markBlocksAsPruned (blocks: BlockProgress[]): Promise<void> {
await this._baseIndexer.markBlocksAsPruned(blocks);
await this._graphWatcher.pruneEntities(FrothyEntity, blocks, SUBGRAPH_ENTITIES);
}
async pruneFrothyEntities (blockNumber: number): Promise<void> {
await this._graphWatcher.pruneFrothyEntities(FrothyEntity, blockNumber);
}
async resetLatestEntities (blockNumber: number): Promise<void> {
await this._graphWatcher.resetLatestEntities(blockNumber);
}
async updateBlockProgress (block: BlockProgress, lastProcessedEventIndex: number): Promise<BlockProgress> {
return this._baseIndexer.updateBlockProgress(block, lastProcessedEventIndex);
}
async getAncestorAtHeight (blockHash: string, height: number): Promise<string> {
return this._baseIndexer.getAncestorAtHeight(blockHash, height);
}
async resetWatcherToBlock (blockNumber: number): Promise<void> {
const entities = [...ENTITIES, FrothyEntity];
await this._baseIndexer.resetWatcherToBlock(blockNumber, entities);
await this.resetLatestEntities(blockNumber);
}
async clearProcessedBlockData (block: BlockProgress): Promise<void> {
const entities = [...ENTITIES, FrothyEntity];
await this._baseIndexer.clearProcessedBlockData(block, entities);
await this.resetLatestEntities(block.blockNumber);
}
getEntityTypesMap (): Map<string, { [key: string]: string }> {
return this._entityTypesMap;
}
getRelationsMap (): Map<any, { [key: string]: any }> {
return this._relationsMap;
}
updateSubgraphState (contractAddress: string, data: any): void {
return updateSubgraphState(this._subgraphStateMap, contractAddress, data);
}
async dumpSubgraphState (blockHash: string, isStateFinalized = false): Promise<void> {
return dumpSubgraphState(this, this._subgraphStateMap, blockHash, isStateFinalized);
}
_populateEntityTypesMap (): void {
this._entityTypesMap.set('Token', {
id: 'Bytes',
symbol: 'String',
name: 'String',
decimals: 'Int',
tokenType: 'String',
poolCount: 'BigInt',
pools: 'Pool',
totalSupply: 'BigInt',
txCount: 'BigInt'
});
this._entityTypesMap.set('PoolFactory', {
id: 'Bytes',
poolType: 'String',
poolCount: 'BigInt',
pools: 'Pool',
txCount: 'BigInt'
});
this._entityTypesMap.set('Pool', {
id: 'Bytes',
createdAtBlockNumber: 'BigInt',
createdAtTimestamp: 'BigInt',
collateralToken: 'Token',
quoteToken: 'Token',
poolSize: 'BigDecimal',
t0debt: 'BigDecimal',
inflator: 'BigDecimal',
borrowRate: 'BigDecimal',
lendRate: 'BigDecimal',
borrowFeeRate: 'BigDecimal',
depositFeeRate: 'BigDecimal',
pledgedCollateral: 'BigDecimal',
totalInterestEarned: 'BigDecimal',
txCount: 'BigInt',
poolType: 'String',
loansCount: 'BigInt',
maxBorrower: 'Bytes',
quoteTokenFlashloaned: 'BigDecimal',
collateralFlashloaned: 'BigDecimal',
hpb: 'BigDecimal',
hpbIndex: 'Int',
htp: 'BigDecimal',
htpIndex: 'Int',
lup: 'BigDecimal',
lupIndex: 'Int',
reserves: 'BigDecimal',
claimableReserves: 'BigDecimal',
claimableReservesRemaining: 'BigDecimal',
burnEpoch: 'BigInt',
totalAjnaBurned: 'BigDecimal',
reserveAuctions: 'ReserveAuction',
minDebtAmount: 'BigDecimal',
actualUtilization: 'BigDecimal',
targetUtilization: 'BigDecimal',
totalBondEscrowed: 'BigDecimal',
liquidationAuctions: 'LiquidationAuction',
quoteTokenBalance: 'BigDecimal',
collateralBalance: 'BigDecimal',
subsetHash: 'Bytes',
tokenIdsPledged: 'BigInt',
bucketTokenIds: 'BigInt',
tokenIdsAllowed: 'BigInt'
});
this._entityTypesMap.set('Bucket', {
id: 'Bytes',
bucketIndex: 'Int',
bucketPrice: 'BigDecimal',
exchangeRate: 'BigDecimal',
poolAddress: 'String',
pool: 'Pool',
collateral: 'BigDecimal',
deposit: 'BigDecimal',
lpb: 'BigDecimal',
lends: 'Lend',
positionLends: 'PositionLend'
});
this._entityTypesMap.set('Lend', {
id: 'Bytes',
bucket: 'Bucket',
bucketIndex: 'Int',
poolAddress: 'String',
lender: 'Bytes',
pool: 'Pool',
lpb: 'BigDecimal',
lpbValueInQuote: 'BigDecimal',
depositTime: 'BigInt'
});
this._entityTypesMap.set('Loan', {
id: 'Bytes',
poolAddress: 'String',
borrower: 'Bytes',
pool: 'Pool',
inLiquidation: 'Boolean',
liquidationAuction: 'LiquidationAuction',
collateralPledged: 'BigDecimal',
thresholdPrice: 'BigDecimal',
tokenIdsPledged: 'BigInt',
t0debt: 'BigDecimal',
t0Np: 'BigDecimal'
});
this._entityTypesMap.set('Account', {
id: 'Bytes',
pools: 'Pool',
kicks: 'Kick',
lends: 'Lend',
loans: 'Loan',
settles: 'Settle',
takes: 'Take',
reserveAuctions: 'ReserveAuction',
proposalsCreated: 'Proposal',
proposalsExecuted: 'Proposal',
delegatedTo: 'Account',
delegatedFrom: 'Account',
rewardsClaimed: 'BigDecimal',
distributionPeriodVotes: 'DistributionPeriodVote',
tokensDelegated: 'BigDecimal',
positions: 'Position',
txCount: 'BigInt'
});
this._entityTypesMap.set('LiquidationAuction', {
id: 'Bytes',
pool: 'Pool',
borrower: 'Bytes',
lastTakePrice: 'BigDecimal',
collateral: 'BigDecimal',
collateralRemaining: 'BigDecimal',
debt: 'BigDecimal',
debtRemaining: 'BigDecimal',
loan: 'Loan',
kicker: 'Bytes',
kick: 'Kick',
kickTime: 'BigInt',
takes: 'Take',
bucketTakes: 'BucketTake',
settles: 'Settle',
settle: 'AuctionSettle',
settleTime: 'BigInt',
settled: 'Boolean',
bondSize: 'BigDecimal',
bondFactor: 'BigDecimal',
neutralPrice: 'BigDecimal',
referencePrice: 'BigDecimal',
thresholdPrice: 'BigDecimal'
});
this._entityTypesMap.set('ReserveAuction', {
id: 'Bytes',
pool: 'Pool',
claimableReservesRemaining: 'BigDecimal',
lastTakePrice: 'BigDecimal',
burnEpoch: 'BigInt',
kick: 'ReserveAuctionKick',
takes: 'ReserveAuctionTake',
ajnaBurned: 'BigDecimal'
});
this._entityTypesMap.set('LPTransferorList', {
id: 'Bytes',
pool: 'Pool',
lender: 'Bytes',
transferors: 'Bytes'
});
this._entityTypesMap.set('LPAllowance', {
id: 'Bytes',
index: 'Int',
amount: 'BigDecimal'
});
this._entityTypesMap.set('LPAllowanceList', {
id: 'Bytes',
pool: 'Pool',
lender: 'Bytes',
spender: 'Bytes',
allowances: 'LPAllowance'
});
this._entityTypesMap.set('AddCollateral', {
id: 'Bytes',
pool: 'Pool',
bucket: 'Bucket',
actor: 'Bytes',
index: 'Int',
amount: 'BigDecimal',
lpAwarded: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('AddQuoteToken', {
id: 'Bytes',
pool: 'Pool',
bucket: 'Bucket',
lender: 'Bytes',
index: 'Int',
amount: 'BigDecimal',
lpAwarded: 'BigDecimal',
lup: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('AuctionSettle', {
id: 'Bytes',
pool: 'Pool',
loan: 'Loan',
borrower: 'Bytes',
collateral: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('BondWithdrawn', {
id: 'Bytes',
kicker: 'Bytes',
reciever: 'Bytes',
amount: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('BucketBankruptcy', {
id: 'Bytes',
bucket: 'Bucket',
index: 'Int',
pool: 'Pool',
lpForfeited: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('BucketTake', {
id: 'Bytes',
borrower: 'Bytes',
taker: 'Bytes',
liquidationAuction: 'LiquidationAuction',
loan: 'Loan',
pool: 'Pool',
index: 'Int',
auctionPrice: 'BigDecimal',
amount: 'BigDecimal',
collateral: 'BigDecimal',
bondChange: 'BigDecimal',
isReward: 'Boolean',
lpAwarded: 'BucketTakeLPAwarded',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('BucketTakeLPAwarded', {
id: 'Bytes',
taker: 'Bytes',
pool: 'Pool',
kicker: 'Bytes',
lpAwardedTaker: 'BigDecimal',
lpAwardedKicker: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('DrawDebt', {
id: 'Bytes',
pool: 'Pool',
borrower: 'Bytes',
amountBorrowed: 'BigDecimal',
collateralPledged: 'BigDecimal',
lup: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('Flashloan', {
id: 'Bytes',
pool: 'Pool',
borrower: 'Bytes',
amount: 'BigDecimal'
});
this._entityTypesMap.set('Kick', {
id: 'Bytes',
kicker: 'Bytes',
pool: 'Pool',
loan: 'Loan',
locked: 'BigDecimal',
claimable: 'BigDecimal',
liquidationAuction: 'LiquidationAuction',
borrower: 'Bytes',
debt: 'BigDecimal',
collateral: 'BigDecimal',
bond: 'BigDecimal',
startingPrice: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('LoanStamped', {
id: 'Bytes',
pool: 'Pool',
borrower: 'Bytes',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('MoveQuoteToken', {
id: 'Bytes',
pool: 'Pool',
lender: 'Bytes',
from: 'Bucket',
to: 'Bucket',
amount: 'BigDecimal',
lpRedeemedFrom: 'BigDecimal',
lpAwardedTo: 'BigDecimal',
lup: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('RemoveCollateral', {
id: 'Bytes',
pool: 'Pool',
bucket: 'Bucket',
claimer: 'Bytes',
index: 'Int',
amount: 'BigDecimal',
lpRedeemed: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('RemoveQuoteToken', {
id: 'Bytes',
pool: 'Pool',
bucket: 'Bucket',
lender: 'Bytes',
index: 'Int',
amount: 'BigDecimal',
lpRedeemed: 'BigDecimal',
lup: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('RepayDebt', {
id: 'Bytes',
pool: 'Pool',
borrower: 'Bytes',
quoteRepaid: 'BigDecimal',
collateralPulled: 'BigDecimal',
lup: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('ReserveAuctionKick', {
id: 'Bytes',
kicker: 'Bytes',
reserveAuction: 'ReserveAuction',
pool: 'Pool',
claimableReserves: 'BigDecimal',
startingPrice: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('ReserveAuctionTake', {
id: 'Bytes',
taker: 'Bytes',
reserveAuction: 'ReserveAuction',
pool: 'Pool',
claimableReservesRemaining: 'BigDecimal',
auctionPrice: 'BigDecimal',
quotePurchased: 'BigDecimal',
ajnaBurned: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('ResetInterestRate', {
id: 'Bytes',
pool: 'Pool',
oldBorrowRate: 'BigDecimal',
newBorrowRate: 'BigDecimal',
oldLendRate: 'BigDecimal',
newLendRate: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('Settle', {
id: 'Bytes',
pool: 'Pool',
liquidationAuction: 'LiquidationAuction',
loan: 'Loan',
borrower: 'Bytes',
settledDebt: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('Take', {
id: 'Bytes',
taker: 'Bytes',
pool: 'Pool',
borrower: 'Bytes',
liquidationAuction: 'LiquidationAuction',
loan: 'Loan',
auctionPrice: 'BigDecimal',
amount: 'BigDecimal',
collateral: 'BigDecimal',
bondChange: 'BigDecimal',
isReward: 'Boolean',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('TransferLP', {
id: 'Bytes',
owner: 'Bytes',
newOwner: 'Bytes',
indexes: 'Int',
lp: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('UpdateInterestRate', {
id: 'Bytes',
pool: 'Pool',
oldBorrowRate: 'BigDecimal',
newBorrowRate: 'BigDecimal',
oldLendRate: 'BigDecimal',
newLendRate: 'BigDecimal',
borrowFeeRate: 'BigDecimal',
depositFeeRate: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('Approval', {
id: 'Bytes',
owner: 'Bytes',
approved: 'Bytes',
tokenId: 'BigInt',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('ApprovalForAll', {
id: 'Bytes',
owner: 'Bytes',
operator: 'Bytes',
approved: 'Boolean',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('MoveLiquidity', {
id: 'Bytes',
lender: 'Bytes',
tokenId: 'BigInt',
pool: 'Pool',
fromIndex: 'Int',
toIndex: 'Int',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('Transfer', {
id: 'Bytes',
token: 'Token',
pool: 'Pool',
from: 'Bytes',
to: 'Bytes',
tokenId: 'BigInt',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('PoolCreated', {
id: 'Bytes',
pool: 'Pool',
poolType: 'String',
factory: 'PoolFactory',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('AddCollateralNFT', {
id: 'Bytes',
pool: 'Pool',
bucket: 'Bucket',
actor: 'Bytes',
index: 'BigInt',
tokenIds: 'BigInt',
lpAwarded: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('AuctionNFTSettle', {
id: 'Bytes',
pool: 'Pool',
loan: 'Loan',
borrower: 'Bytes',
collateral: 'BigDecimal',
lp: 'BigDecimal',
index: 'Int',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('DrawDebtNFT', {
id: 'Bytes',
pool: 'Pool',
borrower: 'Bytes',
amountBorrowed: 'BigDecimal',
tokenIdsPledged: 'BigInt',
lup: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('MergeOrRemoveCollateralNFT', {
id: 'Bytes',
pool: 'Pool',
actor: 'Bytes',
collateralMerged: 'BigDecimal',
toIndexLps: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('Position', {
id: 'Bytes',
tokenId: 'BigInt',
indexes: 'PositionLend',
owner: 'Bytes',
pool: 'Pool',
token: 'Token',
tokenURI: 'String'
});
this._entityTypesMap.set('PositionLend', {
id: 'Bytes',
bucket: 'Bucket',
bucketIndex: 'Int',
depositTime: 'BigInt',
lpb: 'BigDecimal',
lpbValueInQuote: 'BigDecimal',
tokenId: 'BigInt'
});
this._entityTypesMap.set('Burn', {
id: 'Bytes',
lender: 'Bytes',
tokenId: 'BigInt',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('MemorializePosition', {
id: 'Bytes',
pool: 'Pool',
lender: 'Bytes',
tokenId: 'BigInt',
indexes: 'Int',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('Mint', {
id: 'Bytes',
lender: 'Bytes',
pool: 'Pool',
tokenId: 'BigInt',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('RedeemPosition', {
id: 'Bytes',
pool: 'Pool',
lender: 'Bytes',
tokenId: 'BigInt',
indexes: 'Int',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('GrantFund', {
id: 'Bytes',
treasury: 'BigDecimal',
distributionPeriods: 'DistributionPeriod',
totalDelegationRewardsClaimed: 'BigDecimal'
});
this._entityTypesMap.set('DistributionPeriod', {
id: 'Bytes',
distributionId: 'BigInt',
startBlock: 'BigInt',
endBlock: 'BigInt',
topSlate: 'FundedSlate',
slatesSubmitted: 'FundedSlate',
fundsAvailable: 'BigDecimal',
delegationRewardsClaimed: 'BigDecimal',
fundingVotePowerUsed: 'BigDecimal',
screeningVotesCast: 'BigDecimal',
votes: 'DistributionPeriodVote',
proposals: 'Proposal',
totalTokensDistributed: 'BigDecimal'
});
this._entityTypesMap.set('Proposal', {
id: 'Bytes',
proposalId: 'BigInt',
description: 'String',
distribution: 'DistributionPeriod',
executed: 'Boolean',
screeningVotesReceived: 'BigDecimal',
fundingVotesReceived: 'BigDecimal',
fundingVotesNegative: 'BigDecimal',
fundingVotesPositive: 'BigDecimal',
totalTokensRequested: 'BigDecimal',
params: 'ProposalParams'
});
this._entityTypesMap.set('ProposalParams', {
id: 'Bytes',
target: 'Bytes',
value: 'BigInt',
calldata: 'Bytes',
recipient: 'Bytes',
tokensRequested: 'BigDecimal'
});
this._entityTypesMap.set('DistributionPeriodVote', {
id: 'Bytes',
voter: 'Account',
distribution: 'DistributionPeriod',
initialFundingStageVotingPowerRecordedPostVote: 'BigDecimal',
remainingFundingStageVotingPowerRecordedPostVote: 'BigDecimal',
initialScreeningStageVotingPowerRecordedPostVote: 'BigDecimal',
remainingScreeningStageVotingPowerRecordedPostVote: 'BigDecimal',
screeningVotes: 'ScreeningVote',
fundingVotes: 'FundingVote'
});
this._entityTypesMap.set('ScreeningVote', {
id: 'Bytes',
distribution: 'DistributionPeriod',
voter: 'Account',
proposal: 'Proposal',
totalVotesCast: 'BigDecimal',
votesCast: 'VoteCast'
});
this._entityTypesMap.set('FundingVote', {
id: 'Bytes',
distribution: 'DistributionPeriod',
voter: 'Account',
proposal: 'Proposal',
totalVotesCast: 'BigDecimal',
votingPowerUsed: 'BigDecimal',
votesCast: 'VoteCast'
});
this._entityTypesMap.set('FundedSlate', {
id: 'Bytes',
distribution: 'DistributionPeriod',
proposals: 'Proposal',
totalTokensRequested: 'BigDecimal',
totalFundingVotesReceived: 'BigDecimal',
updateBlock: 'BigInt'
});
this._entityTypesMap.set('DelegateRewardClaimed', {
id: 'Bytes',
delegateeAddress_: 'Bytes',
distribution: 'DistributionPeriod',
rewardClaimed_: 'BigInt',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('FundTreasury', {
id: 'Bytes',
amount: 'BigInt',
treasuryBalance: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('FundedSlateUpdated', {
id: 'Bytes',
distributionId_: 'BigInt',
fundedSlateHash_: 'Bytes',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('ProposalCreated', {
id: 'Bytes',
proposal: 'Proposal',
proposer: 'Bytes',
targets: 'Bytes',
values: 'BigDecimal',
signatures: 'String',
calldatas: 'Bytes',
startBlock: 'BigInt',
endBlock: 'BigInt',
description: 'String',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('ProposalExecuted', {
id: 'Bytes',
proposalId: 'BigInt',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('DistributionPeriodStarted', {
id: 'Bytes',
distribution: 'DistributionPeriod',
startBlock: 'BigInt',
endBlock: 'BigInt',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('VoteCast', {
id: 'Bytes',
voter: 'Bytes',
proposalId: 'BigInt',
support: 'Int',
weight: 'BigDecimal',
reason: 'String',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('DelegateChanged', {
id: 'Bytes',
delegator: 'Bytes',
fromDelegate: 'Bytes',
toDelegate: 'Bytes',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('DelegateVotesChanged', {
id: 'Bytes',
delegate: 'Bytes',
previousBalance: 'BigDecimal',
newBalance: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
this._entityTypesMap.set('BurnWrap', {
id: 'Bytes',
wrapper: 'Bytes',
account: 'Account',
amount: 'BigDecimal',
blockNumber: 'BigInt',
blockTimestamp: 'BigInt',
transactionHash: 'Bytes'
});
}
_populateRelationsMap (): void {
this._relationsMap.set(Token, {
pools: {
entity: Pool,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(PoolFactory, {
pools: {
entity: Pool,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(Pool, {
collateralToken: {
entity: Token,
isArray: false,
isDerived: false
},
quoteToken: {
entity: Token,
isArray: false,
isDerived: false
},
reserveAuctions: {
entity: ReserveAuction,
isArray: true,
isDerived: false
},
liquidationAuctions: {
entity: LiquidationAuction,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(Bucket, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
lends: {
entity: Lend,
isArray: true,
isDerived: false
},
positionLends: {
entity: PositionLend,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(Lend, {
bucket: {
entity: Bucket,
isArray: false,
isDerived: false
},
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Loan, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
liquidationAuction: {
entity: LiquidationAuction,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Account, {
pools: {
entity: Pool,
isArray: true,
isDerived: false
},
kicks: {
entity: Kick,
isArray: true,
isDerived: false
},
lends: {
entity: Lend,
isArray: true,
isDerived: false
},
loans: {
entity: Loan,
isArray: true,
isDerived: false
},
settles: {
entity: Settle,
isArray: true,
isDerived: false
},
takes: {
entity: Take,
isArray: true,
isDerived: false
},
reserveAuctions: {
entity: ReserveAuction,
isArray: true,
isDerived: false
},
proposalsCreated: {
entity: Proposal,
isArray: true,
isDerived: false
},
proposalsExecuted: {
entity: Proposal,
isArray: true,
isDerived: false
},
delegatedTo: {
entity: Account,
isArray: false,
isDerived: false
},
delegatedFrom: {
entity: Account,
isArray: true,
isDerived: false
},
distributionPeriodVotes: {
entity: DistributionPeriodVote,
isArray: true,
isDerived: false
},
positions: {
entity: Position,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(LiquidationAuction, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
loan: {
entity: Loan,
isArray: false,
isDerived: false
},
kick: {
entity: Kick,
isArray: false,
isDerived: false
},
takes: {
entity: Take,
isArray: true,
isDerived: false
},
bucketTakes: {
entity: BucketTake,
isArray: true,
isDerived: false
},
settles: {
entity: Settle,
isArray: true,
isDerived: false
},
settle: {
entity: AuctionSettle,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(ReserveAuction, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
kick: {
entity: ReserveAuctionKick,
isArray: false,
isDerived: false
},
takes: {
entity: ReserveAuctionTake,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(LPTransferorList, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(LPAllowanceList, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
allowances: {
entity: LPAllowance,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(AddCollateral, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
bucket: {
entity: Bucket,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(AddQuoteToken, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
bucket: {
entity: Bucket,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(AuctionSettle, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
loan: {
entity: Loan,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(BucketBankruptcy, {
bucket: {
entity: Bucket,
isArray: false,
isDerived: false
},
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(BucketTake, {
liquidationAuction: {
entity: LiquidationAuction,
isArray: false,
isDerived: false
},
loan: {
entity: Loan,
isArray: false,
isDerived: false
},
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
lpAwarded: {
entity: BucketTakeLPAwarded,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(BucketTakeLPAwarded, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(DrawDebt, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Flashloan, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Kick, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
loan: {
entity: Loan,
isArray: false,
isDerived: false
},
liquidationAuction: {
entity: LiquidationAuction,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(LoanStamped, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(MoveQuoteToken, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
from: {
entity: Bucket,
isArray: false,
isDerived: false
},
to: {
entity: Bucket,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(RemoveCollateral, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
bucket: {
entity: Bucket,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(RemoveQuoteToken, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
bucket: {
entity: Bucket,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(RepayDebt, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(ReserveAuctionKick, {
reserveAuction: {
entity: ReserveAuction,
isArray: false,
isDerived: false
},
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(ReserveAuctionTake, {
reserveAuction: {
entity: ReserveAuction,
isArray: false,
isDerived: false
},
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(ResetInterestRate, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Settle, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
liquidationAuction: {
entity: LiquidationAuction,
isArray: false,
isDerived: false
},
loan: {
entity: Loan,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Take, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
liquidationAuction: {
entity: LiquidationAuction,
isArray: false,
isDerived: false
},
loan: {
entity: Loan,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(UpdateInterestRate, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(MoveLiquidity, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Transfer, {
token: {
entity: Token,
isArray: false,
isDerived: false
},
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(PoolCreated, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
factory: {
entity: PoolFactory,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(AddCollateralNFT, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
bucket: {
entity: Bucket,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(AuctionNFTSettle, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
loan: {
entity: Loan,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(DrawDebtNFT, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(MergeOrRemoveCollateralNFT, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Position, {
indexes: {
entity: PositionLend,
isArray: true,
isDerived: false
},
pool: {
entity: Pool,
isArray: false,
isDerived: false
},
token: {
entity: Token,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(PositionLend, {
bucket: {
entity: Bucket,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(MemorializePosition, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(Mint, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(RedeemPosition, {
pool: {
entity: Pool,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(GrantFund, {
distributionPeriods: {
entity: DistributionPeriod,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(DistributionPeriod, {
topSlate: {
entity: FundedSlate,
isArray: false,
isDerived: false
},
slatesSubmitted: {
entity: FundedSlate,
isArray: true,
isDerived: false
},
votes: {
entity: DistributionPeriodVote,
isArray: true,
isDerived: false
},
proposals: {
entity: Proposal,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(Proposal, {
distribution: {
entity: DistributionPeriod,
isArray: false,
isDerived: false
},
params: {
entity: ProposalParams,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(DistributionPeriodVote, {
voter: {
entity: Account,
isArray: false,
isDerived: false
},
distribution: {
entity: DistributionPeriod,
isArray: false,
isDerived: false
},
screeningVotes: {
entity: ScreeningVote,
isArray: true,
isDerived: false
},
fundingVotes: {
entity: FundingVote,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(ScreeningVote, {
distribution: {
entity: DistributionPeriod,
isArray: false,
isDerived: false
},
voter: {
entity: Account,
isArray: false,
isDerived: false
},
proposal: {
entity: Proposal,
isArray: false,
isDerived: false
},
votesCast: {
entity: VoteCast,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(FundingVote, {
distribution: {
entity: DistributionPeriod,
isArray: false,
isDerived: false
},
voter: {
entity: Account,
isArray: false,
isDerived: false
},
proposal: {
entity: Proposal,
isArray: false,
isDerived: false
},
votesCast: {
entity: VoteCast,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(FundedSlate, {
distribution: {
entity: DistributionPeriod,
isArray: false,
isDerived: false
},
proposals: {
entity: Proposal,
isArray: true,
isDerived: false
}
});
this._relationsMap.set(DelegateRewardClaimed, {
distribution: {
entity: DistributionPeriod,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(ProposalCreated, {
proposal: {
entity: Proposal,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(DistributionPeriodStarted, {
distribution: {
entity: DistributionPeriod,
isArray: false,
isDerived: false
}
});
this._relationsMap.set(BurnWrap, {
account: {
entity: Account,
isArray: false,
isDerived: false
}
});
}
async _saveBlockAndFetchEvents ({
cid: blockCid,
blockHash,
blockNumber,
blockTimestamp,
parentHash
}: DeepPartial<BlockProgress>): Promise<[
BlockProgress,
DeepPartial<Event>[],
EthFullTransaction[]
]> {
assert(blockHash);
assert(blockNumber);
const { events: dbEvents, transactions } = await this._baseIndexer.fetchEvents(blockHash, blockNumber, this.eventSignaturesMap, this.parseEventNameAndArgs.bind(this));
const dbTx = await this._db.createTransactionRunner();
try {
const block = {
cid: blockCid,
blockHash,
blockNumber,
blockTimestamp,
parentHash
};
console.time(`time:indexer#_saveBlockAndFetchEvents-db-save-${blockNumber}`);
const blockProgress = await this._db.saveBlockWithEvents(dbTx, block, dbEvents);
await dbTx.commitTransaction();
console.timeEnd(`time:indexer#_saveBlockAndFetchEvents-db-save-${blockNumber}`);
return [blockProgress, [], transactions];
} catch (error) {
await dbTx.rollbackTransaction();
throw error;
} finally {
await dbTx.release();
}
}
async getFullTransactions (txHashList: string[]): Promise<EthFullTransaction[]> {
return this._baseIndexer.getFullTransactions(txHashList);
}
}