Skip to content

Commit 5102af2

Browse files
committed
update
1 parent a46f904 commit 5102af2

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

packages/eth-providers/src/base-provider.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from '@ethersproject/abstract-provider';
1515
import { AcalaEvmTX, checkSignatureType, parseTransaction } from '@acala-network/eth-transactions';
1616
import { AccessList, accessListify } from 'ethers/lib/utils';
17+
import { ApiDecoration, SubmittableExtrinsic } from '@polkadot/api/types';
1718
import { ApiPromise } from '@polkadot/api';
1819
import { AsyncAction } from 'rxjs/internal/scheduler/AsyncAction';
1920
import { AsyncScheduler } from 'rxjs/internal/scheduler/AsyncScheduler';
@@ -26,7 +27,6 @@ import { Logger } from '@ethersproject/logger';
2627
import { ModuleEvmModuleAccountInfo } from '@polkadot/types/lookup';
2728
import { Network } from '@ethersproject/networks';
2829
import { Observable, ReplaySubject, Subscription, firstValueFrom, throwError } from 'rxjs';
29-
import { SubmittableExtrinsic } from '@polkadot/api/types';
3030
import { filter, first, timeout } from 'rxjs/operators';
3131
import { getAddress } from '@ethersproject/address';
3232
import { hexDataLength, hexValue, hexZeroPad, hexlify, isHexString, joinSignature } from '@ethersproject/bytes';
@@ -304,6 +304,7 @@ export abstract class BaseProvider extends AbstractProvider {
304304
readonly verbose: boolean;
305305
readonly maxBlockCacheSize: number;
306306
readonly queryCache: LRUCache<string, any>;
307+
readonly apiCache: LRUCache<string, ApiDecoration<'promise'>>;
307308
readonly blockCache: BlockCache;
308309
readonly finalizedBlockHashes: MaxSizeSet;
309310

@@ -341,6 +342,7 @@ export abstract class BaseProvider extends AbstractProvider {
341342
this.verbose = verbose;
342343
this.maxBlockCacheSize = maxBlockCacheSize;
343344
this.queryCache = new LRUCache({ max: storageCacheSize });
345+
this.apiCache = new LRUCache({ max: storageCacheSize });
344346
this.blockCache = new BlockCache(this.maxBlockCacheSize);
345347
this.finalizedBlockHashes = new MaxSizeSet(this.maxBlockCacheSize);
346348

@@ -571,6 +573,16 @@ export abstract class BaseProvider extends AbstractProvider {
571573
await this.api.disconnect();
572574
};
573575

576+
getApiAt = async (blockHash: string): Promise<ApiDecoration<'promise'>> => {
577+
const cached = this.apiCache.get(blockHash);
578+
if (cached) return cached;
579+
580+
const apiAt = await this.getApiAt(blockHash);
581+
this.apiCache.set(blockHash, apiAt); // cache key is blockhash, so no need to check for finalization
582+
583+
return apiAt;
584+
};
585+
574586
getNetwork = async (): Promise<Network> => {
575587
await this.isReady();
576588

@@ -678,7 +690,7 @@ export abstract class BaseProvider extends AbstractProvider {
678690

679691
const substrateAddress = await this.getSubstrateAddress(address, blockHash);
680692

681-
const apiAt = await this.api.at(blockHash);
693+
const apiAt = await this.getApiAt(blockHash);
682694
const accountInfo = await apiAt.query.system.account(substrateAddress);
683695

684696
return nativeToEthDecimal(accountInfo.data.free.toBigInt());
@@ -720,7 +732,7 @@ export abstract class BaseProvider extends AbstractProvider {
720732
const contractInfo = evmAccountInfo?.contractInfo.unwrapOr(null);
721733
if (!contractInfo) { return '0x'; }
722734

723-
const apiAt = await this.api.at(blockHash);
735+
const apiAt = await this.getApiAt(blockHash);
724736
const code = await apiAt.query.evm.codes(contractInfo.codeHash);
725737

726738
return code.toHex();
@@ -818,7 +830,7 @@ export abstract class BaseProvider extends AbstractProvider {
818830
Promise.resolve(position).then(hexValue),
819831
]);
820832

821-
const apiAt = await this.api.at(blockHash);
833+
const apiAt = await this.getApiAt(blockHash);
822834
const code = await apiAt.query.evm.accountStorages(address, hexZeroPad(resolvedPosition, 32));
823835

824836
return code.toHex();
@@ -1102,7 +1114,7 @@ export abstract class BaseProvider extends AbstractProvider {
11021114

11031115
getSubstrateAddress = async (address: string, blockTag?: BlockTag): Promise<string> => {
11041116
const blockHash = await this._getBlockHash(blockTag);
1105-
const apiAt = await this.api.at(blockHash);
1117+
const apiAt = await this.getApiAt(blockHash);
11061118
const substrateAccount = await apiAt.query.evmAccounts.accounts(address);
11071119

11081120
return substrateAccount.isEmpty
@@ -1112,7 +1124,7 @@ export abstract class BaseProvider extends AbstractProvider {
11121124

11131125
getEvmAddress = async (substrateAddress: string, blockTag?: BlockTag): Promise<string> => {
11141126
const blockHash = await this._getBlockHash(blockTag);
1115-
const apiAt = await this.api.at(blockHash);
1127+
const apiAt = await this.getApiAt(blockHash);
11161128
const evmAddress = await apiAt.query.evmAccounts.evmAddresses(substrateAddress);
11171129

11181130
return getAddress(evmAddress.isEmpty ? computeDefaultEvmAddress(substrateAddress) : evmAddress.toString());
@@ -1129,7 +1141,7 @@ export abstract class BaseProvider extends AbstractProvider {
11291141
this._getBlockHash(blockTag),
11301142
]);
11311143

1132-
const apiAt = await this.api.at(blockHash);
1144+
const apiAt = await this.getApiAt(blockHash);
11331145
const accountInfo = await apiAt.query.evm.accounts(address);
11341146

11351147
return accountInfo.unwrapOr(null);
@@ -1474,11 +1486,12 @@ export abstract class BaseProvider extends AbstractProvider {
14741486
}
14751487
}
14761488

1477-
// TODO: test header not found should throw
1478-
const blockHash = (await this.api.rpc.chain.getBlockHash(blockNumber.toBigInt())).toHex();
1479-
// if (_blockHash.isEmpty) {
1480-
// return logger.throwError('header not found', Logger.errors.CALL_EXCEPTION, { blockNumber });
1481-
// }
1489+
const _blockHash = await this.api.rpc.chain.getBlockHash(blockNumber.toBigInt());
1490+
if (_blockHash.isEmpty) {
1491+
//@ts-ignore
1492+
return logger.throwError('header not found', PROVIDER_ERRORS.HEADER_NOT_FOUND, { blockNumber });
1493+
}
1494+
const blockHash = _blockHash.toHex();
14821495

14831496
if (isFinalized) {
14841497
this.queryCache.set(cacheKey, blockHash);
@@ -1501,6 +1514,9 @@ export abstract class BaseProvider extends AbstractProvider {
15011514

15021515
const blockNumber = _blockNumber ?? (await this._getBlockNumber(blockHash));
15031516
const canonicalHash = await this.api.rpc.chain.getBlockHash(blockNumber);
1517+
if (canonicalHash.isEmpty) {
1518+
return logger.throwError('header not found', Logger.errors.CALL_EXCEPTION, { blockNumber });
1519+
}
15041520

15051521
return canonicalHash.toString() === blockHash;
15061522
};

packages/eth-rpc-adapter/src/__tests__/endpoint-tests/eth_getBlockByNumber.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,9 @@ describe('eth_getBlockByNumber', () => {
2525
value: '0x0',
2626
});
2727
});
28+
29+
it('returns null when block not found', async () => {
30+
const res = (await eth_getBlockByNumber([0x12345678, false])).data.result;
31+
expect(res).toBeNull();
32+
});
2833
});

0 commit comments

Comments
 (0)