mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-07-31 04:02:06 +00:00
Handle template create events processing order during reorgs
This commit is contained in:
parent
a585500012
commit
74a85039e6
@ -635,6 +635,10 @@ export class Indexer implements IndexerInterface {
|
|||||||
return this._baseIndexer.watchContract(address, kind, checkpoint, startingBlock, context);
|
return this._baseIndexer.watchContract(address, kind, checkpoint, startingBlock, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async removeContract (address: string, kind: string): Promise<void> {
|
||||||
|
return this._baseIndexer.removeContract(address, kind);
|
||||||
|
}
|
||||||
|
|
||||||
updateStateStatusMap (address: string, stateStatus: StateStatus): void {
|
updateStateStatusMap (address: string, stateStatus: StateStatus): void {
|
||||||
this._baseIndexer.updateStateStatusMap(address, stateStatus);
|
this._baseIndexer.updateStateStatusMap(address, stateStatus);
|
||||||
}
|
}
|
||||||
|
@ -734,25 +734,13 @@ export const instantiate = async (
|
|||||||
return __newString(dataSource.network);
|
return __newString(dataSource.network);
|
||||||
},
|
},
|
||||||
'dataSource.create': async (name: number, params: number) => {
|
'dataSource.create': async (name: number, params: number) => {
|
||||||
const [addressStringPtr] = __getArray(params);
|
await handleDataSourceCreate(name, params);
|
||||||
const addressString = __getString(addressStringPtr);
|
|
||||||
const contractKind = __getString(name);
|
|
||||||
|
|
||||||
assert(indexer.watchContract);
|
|
||||||
assert(context.block);
|
|
||||||
await indexer.watchContract(utils.getAddress(addressString), contractKind, true, Number(context.block.blockNumber));
|
|
||||||
},
|
},
|
||||||
'dataSource.createWithContext': async (name: number, params: number, dataSourceContext: number) => {
|
'dataSource.createWithContext': async (name: number, params: number, dataSourceContext: number) => {
|
||||||
const [addressStringPtr] = __getArray(params);
|
|
||||||
const addressString = __getString(addressStringPtr);
|
|
||||||
const contractKind = __getString(name);
|
|
||||||
|
|
||||||
const contextInstance = await Entity.wrap(dataSourceContext);
|
const contextInstance = await Entity.wrap(dataSourceContext);
|
||||||
const dbData = await database.fromGraphContext(instanceExports, contextInstance);
|
const dbData = await database.fromGraphContext(instanceExports, contextInstance);
|
||||||
|
|
||||||
assert(indexer.watchContract);
|
await handleDataSourceCreate(name, params, dbData);
|
||||||
assert(context.block);
|
|
||||||
await indexer.watchContract(utils.getAddress(addressString), contractKind, true, Number(context.block.blockNumber), dbData);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
json: {
|
json: {
|
||||||
@ -786,6 +774,34 @@ export const instantiate = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDataSourceCreate = async (name: number, params: number, dbData?: {[key: string]: any}) => {
|
||||||
|
const [addressStringPtr] = __getArray(params);
|
||||||
|
const addressString = __getString(addressStringPtr);
|
||||||
|
const contractKind = __getString(name);
|
||||||
|
|
||||||
|
assert(context.block);
|
||||||
|
const contractAddress = utils.getAddress(addressString);
|
||||||
|
const watchedContracts = indexer.isContractAddressWatched(contractAddress);
|
||||||
|
|
||||||
|
// If template contract is already watched (incase of reorgs)
|
||||||
|
// Remove from watched contracts and throw error to reprocess block with correct order of template contract events
|
||||||
|
if (
|
||||||
|
watchedContracts &&
|
||||||
|
watchedContracts.some(watchedContract => watchedContract.kind === contractKind)
|
||||||
|
) {
|
||||||
|
await indexer.removeContract(contractAddress, contractKind);
|
||||||
|
throw new Error(`Template contract ${contractAddress} of kind ${contractKind} already exists; removed from watched contracts`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await indexer.watchContract(
|
||||||
|
contractAddress,
|
||||||
|
contractKind,
|
||||||
|
true,
|
||||||
|
Number(context.block.blockNumber),
|
||||||
|
dbData
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const instance = await loader.instantiate(source, imports);
|
const instance = await loader.instantiate(source, imports);
|
||||||
const { exports: instanceExports } = instance;
|
const { exports: instanceExports } = instance;
|
||||||
|
|
||||||
|
@ -920,6 +920,22 @@ export class Indexer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async removeContract (address: string, kind: string): Promise<void> {
|
||||||
|
const dbTx = await this._db.createTransactionRunner();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this._db.deleteEntitiesByConditions(dbTx, 'contract', { kind, address });
|
||||||
|
this._clearWatchedContracts(
|
||||||
|
watchedContract => watchedContract.kind === kind && watchedContract.address === address
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
await dbTx.rollbackTransaction();
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
await dbTx.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cacheContract (contract: ContractInterface): void {
|
cacheContract (contract: ContractInterface): void {
|
||||||
if (!this._watchedContractsByAddressMap[contract.address]) {
|
if (!this._watchedContractsByAddressMap[contract.address]) {
|
||||||
this._watchedContractsByAddressMap[contract.address] = [];
|
this._watchedContractsByAddressMap[contract.address] = [];
|
||||||
|
@ -217,6 +217,7 @@ export interface IndexerInterface {
|
|||||||
addContracts?: () => Promise<void>
|
addContracts?: () => Promise<void>
|
||||||
cacheContract: (contract: ContractInterface) => void;
|
cacheContract: (contract: ContractInterface) => void;
|
||||||
watchContract: (address: string, kind: string, checkpoint: boolean, startingBlock: number, context?: any) => Promise<void>
|
watchContract: (address: string, kind: string, checkpoint: boolean, startingBlock: number, context?: any) => Promise<void>
|
||||||
|
removeContract: (address: string, kind: string) => Promise<void>;
|
||||||
getEntityTypesMap?: () => Map<string, { [key: string]: string }>
|
getEntityTypesMap?: () => Map<string, { [key: string]: string }>
|
||||||
getRelationsMap?: () => Map<any, { [key: string]: any }>
|
getRelationsMap?: () => Map<any, { [key: string]: any }>
|
||||||
processInitialState: (contractAddress: string, blockHash: string) => Promise<any>
|
processInitialState: (contractAddress: string, blockHash: string) => Promise<any>
|
||||||
|
Loading…
Reference in New Issue
Block a user