@atomiqlabs/chain-evm
Version:
EVM specific base implementation
76 lines (64 loc) • 2.23 kB
text/typescript
import {EVMModule} from "../EVMModule";
export type EVMBlockTag = "safe" | "pending" | "latest" | "finalized";
export class EVMBlocks extends EVMModule<any> {
private BLOCK_CACHE_TIME = 5*1000;
private blockCache: {
[key: string]: {
blockTime: Promise<number>,
timestamp: number
}
} = {};
/**
* Initiates fetch of a given block & saves it to cache
*
* @private
* @param blockTag
*/
private fetchAndSaveBlockTime(blockTag: EVMBlockTag | number): {
blockTime: Promise<number>,
timestamp: number
} {
const blockTagStr = blockTag.toString(10);
const blockTimePromise = this.provider.getBlock(blockTag, false).then(result => result.timestamp);
const timestamp = Date.now();
this.blockCache[blockTagStr] = {
blockTime: blockTimePromise,
timestamp
};
blockTimePromise.catch(e => {
if(this.blockCache[blockTagStr]!=null && this.blockCache[blockTagStr].blockTime===blockTimePromise) delete this.blockCache[blockTagStr];
throw e;
})
return {
blockTime: blockTimePromise,
timestamp
};
}
private cleanupBlocks() {
const currentTime = Date.now();
//Keys are in order that they were added, so we can stop at the first non-expired block
for(let key in this.blockCache) {
const block = this.blockCache[key];
if(currentTime - block.timestamp > this.BLOCK_CACHE_TIME) {
delete this.blockCache[key];
} else {
break;
}
}
}
///////////////////
//// Blocks
/**
* Gets the block for a given blocktag, with caching
*
* @param blockTag
*/
public getBlockTime(blockTag: EVMBlockTag | number): Promise<number> {
this.cleanupBlocks();
let cachedBlockData = this.blockCache[blockTag.toString(10)];
if(cachedBlockData==null || Date.now()-cachedBlockData.timestamp>this.BLOCK_CACHE_TIME) {
cachedBlockData = this.fetchAndSaveBlockTime(blockTag);
}
return cachedBlockData.blockTime;
}
}