feat: caching provider (#4615)
* feat: caching providers * feat: clear cache per block
This commit is contained in:
parent
382a44f040
commit
86f3b5a036
@ -1,14 +1,49 @@
|
||||
import { deepCopy } from '@ethersproject/properties'
|
||||
// This is the only file which should instantiate new Providers.
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import { StaticJsonRpcProvider } from '@ethersproject/providers'
|
||||
import { isPlain } from '@reduxjs/toolkit'
|
||||
|
||||
import { SupportedChainId } from './chains'
|
||||
import { RPC_URLS } from './networks'
|
||||
|
||||
class AppJsonRpcProvider extends StaticJsonRpcProvider {
|
||||
private _blockCache = new Map<string, Promise<any>>()
|
||||
get blockCache() {
|
||||
// If the blockCache has not yet been initialized this block, do so by
|
||||
// setting a listener to clear it on the next block.
|
||||
if (!this._blockCache.size) {
|
||||
this.once('block', () => this._blockCache.clear())
|
||||
}
|
||||
return this._blockCache
|
||||
}
|
||||
|
||||
constructor(urls: string[]) {
|
||||
super(urls[0])
|
||||
}
|
||||
|
||||
send(method: string, params: Array<any>): Promise<any> {
|
||||
// Only cache eth_call's.
|
||||
if (method !== 'eth_call') return super.send(method, params)
|
||||
|
||||
// Only cache if params are serializable.
|
||||
if (!isPlain(params)) return super.send(method, params)
|
||||
|
||||
const key = `call:${JSON.stringify(params)}`
|
||||
const cached = this.blockCache.get(key)
|
||||
if (cached) {
|
||||
this.emit('debug', {
|
||||
action: 'request',
|
||||
request: deepCopy({ method, params, id: 'cache' }),
|
||||
provider: this,
|
||||
})
|
||||
return cached
|
||||
}
|
||||
|
||||
const result = super.send(method, params)
|
||||
this.blockCache.set(key, result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user