Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use query storage helper #1051

Merged
merged 9 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading