Skip to content

Commit

Permalink
use query storage helper (#1051)
Browse files Browse the repository at this point in the history
* use query storage helper

* test

* fix

* fix

* update

* add tests

* updatre

* skip test
  • Loading branch information
shunjizhan authored Nov 29, 2024
1 parent d865110 commit 521e9fa
Show file tree
Hide file tree
Showing 18 changed files with 198 additions and 47 deletions.
2 changes: 1 addition & 1 deletion packages/eth-providers/src/__tests__/BlockCache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { TransactionReceipt } from '@ethersproject/abstract-provider';

import { BlockCache } from '../utils/BlockCache';
import { describe, expect, it } from 'vitest';
import { mockChain } from './utils/testUtils';
import { mockChain } from './utils';

const sortReceipt = (r1: TransactionReceipt, r2: TransactionReceipt) => {
if (r1.blockNumber !== r2.blockNumber) {
Expand Down
5 changes: 3 additions & 2 deletions packages/eth-providers/src/__tests__/MaxSizeSet.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MaxSizeSet } from '../utils/MaxSizeSet';
import { describe, expect, it } from 'vitest';
import { mockChain } from './utils/testUtils';

import { MaxSizeSet } from '../utils/MaxSizeSet';
import { mockChain } from './utils';

describe('MaxSizeSet', () => {
const MAX_CACHED_BLOCK = 5;
Expand Down
1 change: 1 addition & 0 deletions packages/eth-providers/src/__tests__/decimals.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BigNumber } from '@ethersproject/bignumber';
import { describe, expect, it } from 'vitest';
import { hexValue } from '@ethersproject/bytes';

import { nativeToEthDecimal } from '../utils';

describe('decimals', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ERROR_PATTERN } from '../consts';
import { describe, expect, it } from 'vitest';

import { ERROR_PATTERN } from '../consts';

describe('filterLog', () => {
const err0 =
'Error: -32603: execution fatal: Module(ModuleError { index: 180, error: [11, 0, 0, 0], message: None })';
Expand Down
5 changes: 3 additions & 2 deletions packages/eth-providers/src/__tests__/evm-rpc-provider.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { EvmRpcProvider } from '../rpc-provider';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { runWithTiming, sleep } from '../utils';
import dotenv from 'dotenv';

import { EvmRpcProvider } from '../rpc-provider';
import { sleep } from '../utils';

dotenv.config();

const ACALA_NODE_URL = 'wss://acala-rpc.dwellir.com';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { Contract } from '@ethersproject/contracts';
import { Wallet } from '@ethersproject/wallet';
import { afterAll, describe, expect, it } from 'vitest';
import { parseUnits } from 'ethers/lib/utils';
import ACAABI from '@acala-network/contracts/build/contracts/Token.json';
import ADDRESS from '@acala-network/contracts/utils/AcalaAddress';

import { EvmRpcProvider } from '../rpc-provider';
import { parseUnits } from 'ethers/lib/utils';
import evmAccounts from './utils/evmAccounts';
import { evmAccounts, nodeUrl } from './utils';

describe('TransactionReceipt', async () => {
const endpoint = process.env.ENDPOINT_URL || 'ws://127.0.0.1:9944';
const provider = EvmRpcProvider.from(endpoint);
const provider = EvmRpcProvider.from(nodeUrl);
await provider.isReady();

afterAll(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import { describe, expect, it } from 'vitest';
import { hexZeroPad, parseEther } from 'ethers/lib/utils';

import { AcalaJsonRpcProvider } from '../json-rpc-provider';
import { ethRpc, evmAccounts } from './utils';
import echoJson from './abis/Echo.json';
import erc20Json from './abis/IERC20.json';
import evmAccounts from './utils/evmAccounts';

const localEthRpc = process.env.ETH_RPC || 'http://localhost:8545';

describe('JsonRpcProvider', async () => {
/* --------- karura --------- */
Expand All @@ -20,7 +18,7 @@ describe('JsonRpcProvider', async () => {

/* --------- local --------- */
const testKey = evmAccounts[0].privateKey; // 0x75E480dB528101a381Ce68544611C169Ad7EB342
const providerLocal = new AcalaJsonRpcProvider(localEthRpc);
const providerLocal = new AcalaJsonRpcProvider(ethRpc);
const wallet = new Wallet(testKey, providerLocal);

describe.concurrent('get chain data', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/eth-providers/src/__tests__/logs.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, expect, it } from 'vitest';

import { filterLog } from '../utils';

describe('filterLog', () => {
Expand Down
3 changes: 1 addition & 2 deletions packages/eth-providers/src/__tests__/parseBlock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { TransactionReceipt } from '@ethersproject/abstract-provider';
import { afterAll, beforeAll, describe, it } from 'vitest';
import { options } from '@acala-network/api';

import { getAllReceiptsAtBlock } from '../utils/parseBlock';
import { hexlifyRpcResult, sleep } from '../utils';
import { getAllReceiptsAtBlock, hexlifyRpcResult } from '../utils';

interface FormatedReceipt {
to?: string;
Expand Down
6 changes: 3 additions & 3 deletions packages/eth-providers/src/__tests__/safemode.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';

import { EvmRpcProvider } from '../rpc-provider';
import { nodeUrl } from './utils';
import { sleep } from '../utils';

const endpoint = process.env.ENDPOINT_URL || 'ws://127.0.0.1:9944';
const safeProvider = EvmRpcProvider.from(endpoint, { safeMode: true });
const provider = EvmRpcProvider.from(endpoint, { safeMode: false });
const safeProvider = EvmRpcProvider.from(nodeUrl, { safeMode: true });
const provider = EvmRpcProvider.from(nodeUrl, { safeMode: false });

const newBlock = async (finalize: boolean): Promise<void> => {
await provider.api.rpc.engine.createBlock(true /* create empty */, finalize);
Expand Down
8 changes: 3 additions & 5 deletions packages/eth-providers/src/__tests__/tx.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ import ACAABI from '@acala-network/contracts/build/contracts/Token.json';
import ADDRESS from '@acala-network/contracts/utils/MandalaAddress';

import { EvmRpcProvider } from '../rpc-provider';
import { calcEthereumTransactionParams } from '../utils';
import { computeDefaultSubstrateAddress } from '../utils/address';
import evmAccounts from './utils/evmAccounts';
import { calcEthereumTransactionParams, computeDefaultSubstrateAddress } from '../utils';
import { evmAccounts, nodeUrl } from './utils';

describe('transaction tests', () => {
const endpoint = process.env.ENDPOINT_URL || 'ws://127.0.0.1:9944';
const provider = EvmRpcProvider.from(endpoint);
const provider = EvmRpcProvider.from(nodeUrl);

const account1 = evmAccounts[0];
const account2 = evmAccounts[1];
Expand Down
74 changes: 73 additions & 1 deletion packages/eth-providers/src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { describe, expect, it, vi } from 'vitest';
import { ApiPromise, WsProvider } from '@polkadot/api';
import { FrameSystemAccountInfo } from '@polkadot/types/lookup';
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
import { hexValue } from '@ethersproject/bytes';

import { ALICE_ADDR, nodeUrl } from './utils';
import { CacheInspect } from '../utils/BlockCache';
import {
EthCallTimingResult,
Expand All @@ -13,8 +16,11 @@ import {
runWithTiming,
sleep,
} from '../utils';
import { EvmRpcProvider } from '../rpc-provider';
import { HeadsInfo } from '../base-provider';
import { _Metadata } from '../utils/gqlTypes';
import { queryStorage } from '../utils/queryStoarge';


describe('utils', () => {
it('connect chain', async () => {
Expand Down Expand Up @@ -507,3 +513,69 @@ describe('eth call error handling', () => {
});
});
});

describe('query storage', () => {
let api: ApiPromise;


beforeAll(async () => {
api = await ApiPromise.create({ provider: new WsProvider(nodeUrl) });
});

afterAll(async () => {
await api.disconnect();
});

it('timestamp.now', async () => {
const _testQueryStorage = async (blockHash: string) => {
const timestamp = await queryStorage(
api,
'timestamp.now',
[],
blockHash
);

const timestampReal = await (await api.at(blockHash)).query.timestamp.now();

console.log(timestamp.toJSON(), timestampReal.toJSON());
expect(timestamp.toJSON()).to.deep.eq(timestampReal.toJSON());
};

const curBlockHash = (await api.rpc.chain.getBlockHash()).toString();
const curBlockNum = (await api.rpc.chain.getHeader()).number.toNumber();
const randBlock = curBlockNum - Math.floor(Math.random() * 1000);
console.log(curBlockNum, randBlock);
const randBlockHash = (await api.rpc.chain.getBlockHash(randBlock)).toString();

await _testQueryStorage(curBlockHash);
await _testQueryStorage(randBlockHash);
});

// FIXME: improve query storage helper to return consistent results as apiAt.query
it.skip('system.account', async () => {
const _testQueryStorage = async (blockHash: string) => {
const accountInfo = await queryStorage<FrameSystemAccountInfo>(
api,
'system.account',
[ALICE_ADDR],
blockHash
);

const accountInfoReal = await (await api.at(blockHash)).query.system.account(ALICE_ADDR);

console.log(accountInfo.toJSON(), accountInfoReal.toJSON());
expect(accountInfo.toJSON()).to.deep.eq(accountInfoReal.toJSON());
};

const curBlockHash = (await api.rpc.chain.getBlockHash()).toString();
const curBlockNum = (await api.rpc.chain.getHeader()).number.toNumber();
const randBlock = curBlockNum - Math.floor(Math.random() * 1000);
const randBlockHash = (await api.rpc.chain.getBlockHash(randBlock)).toString();

console.log(curBlockNum, randBlock);
console.log(curBlockHash, randBlockHash);

await _testQueryStorage(curBlockHash);
await _testQueryStorage(randBlockHash); // fails on 7332027
});
});
2 changes: 1 addition & 1 deletion packages/eth-providers/src/__tests__/utils/evmAccounts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default [
export const evmAccounts = [
{
privateKey: '0xa872f6cbd25a0e04a08b1e21098017a9e6194d101d75e13111f71410c59cd57f',
evmAddress: '0x75E480dB528101a381Ce68544611C169Ad7EB342',
Expand Down
2 changes: 2 additions & 0 deletions packages/eth-providers/src/__tests__/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './testUtils';
export * from './evmAccounts';
5 changes: 5 additions & 0 deletions packages/eth-providers/src/__tests__/utils/testUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { TransactionReceipt } from '@ethersproject/abstract-provider';

export const nodeUrl = process.env.ENDPOINT_URL || 'ws://localhost:9944';
export const ethRpc = process.env.ETH_RPC || 'http://localhost:8545';

export const ALICE_ADDR = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';

type MochBlock = {
blockHash: string;
blockNumber: number;
Expand Down
56 changes: 38 additions & 18 deletions packages/eth-providers/src/base-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@ import {
} from '@ethersproject/abstract-provider';
import { AcalaEvmTX, checkSignatureType, parseTransaction } from '@acala-network/eth-transactions';
import { AccessList, accessListify } from 'ethers/lib/utils';
import { AccountId32, H160, H256, Header } from '@polkadot/types/interfaces';
import { ApiPromise } from '@polkadot/api';
import { AsyncAction } from 'rxjs/internal/scheduler/AsyncAction';
import { AsyncScheduler } from 'rxjs/internal/scheduler/AsyncScheduler';
import { BigNumber, BigNumberish, Wallet } from 'ethers';
import { Deferrable, defineReadOnly, resolveProperties } from '@ethersproject/properties';
import { Formatter } from '@ethersproject/providers';
import { Header } from '@polkadot/types/interfaces';
import { FrameSystemAccountInfo, ModuleEvmModuleAccountInfo } from '@polkadot/types/lookup';
import { ISubmittableResult } from '@polkadot/types/types';
import { Logger } from '@ethersproject/logger';
import { ModuleEvmModuleAccountInfo } from '@polkadot/types/lookup';
import { Network } from '@ethersproject/networks';
import { Observable, ReplaySubject, Subscription, firstValueFrom, throwError } from 'rxjs';
import { Option, u64 } from '@polkadot/types-codec';
import { SubmittableExtrinsic } from '@polkadot/api/types';
import { filter, first, timeout } from 'rxjs/operators';
import { getAddress } from '@ethersproject/address';
Expand Down Expand Up @@ -93,6 +94,7 @@ import { MaxSizeSet } from './utils/MaxSizeSet';
import { SubqlProvider } from './utils/subqlProvider';
import { _Metadata } from './utils/gqlTypes';
import { apiCache } from './utils/ApiAtCache';
import { queryStorage } from './utils/queryStoarge';

export interface HeadsInfo {
internalState: {
Expand Down Expand Up @@ -596,8 +598,7 @@ export abstract class BaseProvider extends AbstractProvider {
);

getTimestamp = async (blockHash: string): Promise<number> => {
const apiAt = await apiCache.getApiAt(this.api, blockHash);
const timestamp = await apiAt.query.timestamp.now();
const timestamp = await queryStorage<u64>(this.api, 'timestamp.now', [], blockHash);
return timestamp.toNumber();
};

Expand Down Expand Up @@ -704,8 +705,12 @@ export abstract class BaseProvider extends AbstractProvider {

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

const apiAt = await apiCache.getApiAt(this.api, blockHash);
const accountInfo = await apiAt.query.system.account(substrateAddress);
const accountInfo = await queryStorage<FrameSystemAccountInfo>(
this.api,
'system.account',
[substrateAddress],
blockHash
);

return nativeToEthDecimal(accountInfo.data.free.toBigInt());
};
Expand Down Expand Up @@ -746,9 +751,7 @@ export abstract class BaseProvider extends AbstractProvider {
const contractInfo = evmAccountInfo?.contractInfo.unwrapOr(null);
if (!contractInfo) { return '0x'; }

const apiAt = await apiCache.getApiAt(this.api, blockHash);
const code = await apiAt.query.evm.codes(contractInfo.codeHash);

const code = await queryStorage(this.api, 'evm.codes', [contractInfo.codeHash], blockHash);
return code.toHex();
};

Expand Down Expand Up @@ -844,8 +847,12 @@ export abstract class BaseProvider extends AbstractProvider {
Promise.resolve(position).then(hexValue),
]);

const apiAt = await apiCache.getApiAt(this.api, blockHash);
const code = await apiAt.query.evm.accountStorages(address, hexZeroPad(resolvedPosition, 32));
const code = await queryStorage<H256>(
this.api,
'evm.accountStorages',
[address, hexZeroPad(resolvedPosition, 32)],
blockHash
);

return code.toHex();
};
Expand Down Expand Up @@ -948,7 +955,8 @@ export abstract class BaseProvider extends AbstractProvider {
extrinsic: SubmittableExtrinsic<'promise', ISubmittableResult>,
at?: string,
) => {
const apiAt = await apiCache.getApiAt(this.api, at ?? await this.bestBlockHash);
const blockHash = at ?? this.bestBlockHash;
const apiAt = await apiCache.getApiAt(this.api, blockHash);

const u8a = extrinsic.toU8a();
const lenIncreaseAfterSignature = 100; // approximate length increase after signature
Expand Down Expand Up @@ -1128,8 +1136,12 @@ export abstract class BaseProvider extends AbstractProvider {

getSubstrateAddress = async (address: string, blockTag?: BlockTag): Promise<string> => {
const blockHash = await this._getBlockHash(blockTag);
const apiAt = await apiCache.getApiAt(this.api, blockHash);
const substrateAccount = await apiAt.query.evmAccounts.accounts(address);
const substrateAccount = await queryStorage<Option<AccountId32>>(
this.api,
'evmAccounts.accounts',
[address],
blockHash
);

return substrateAccount.isEmpty
? computeDefaultSubstrateAddress(address)
Expand All @@ -1138,8 +1150,12 @@ export abstract class BaseProvider extends AbstractProvider {

getEvmAddress = async (substrateAddress: string, blockTag?: BlockTag): Promise<string> => {
const blockHash = await this._getBlockHash(blockTag);
const apiAt = await apiCache.getApiAt(this.api, blockHash);
const evmAddress = await apiAt.query.evmAccounts.evmAddresses(substrateAddress);
const evmAddress = await queryStorage<Option<H160>>(
this.api,
'evmAccounts.evmAddresses',
[substrateAddress],
blockHash
);

return getAddress(evmAddress.isEmpty ? computeDefaultEvmAddress(substrateAddress) : evmAddress.toString());
};
Expand All @@ -1155,8 +1171,12 @@ export abstract class BaseProvider extends AbstractProvider {
this._getBlockHash(blockTag),
]);

const apiAt = await apiCache.getApiAt(this.api, blockHash);
const accountInfo = await apiAt.query.evm.accounts(address);
const accountInfo = await queryStorage<Option<ModuleEvmModuleAccountInfo>>(
this.api,
'evm.accounts',
[address],
blockHash
);

return accountInfo.unwrapOr(null);
};
Expand Down
Loading

0 comments on commit 521e9fa

Please sign in to comment.