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

feat: add methods for fork MM #187

Merged
merged 21 commits into from
Oct 22, 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
35 changes: 34 additions & 1 deletion packages/nodes/src/ethereum.node.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
import { Logger } from '@nestjs/common';
import * as ganache from 'ganache';
import { Server } from 'ganache';
import {
Expand Down Expand Up @@ -26,18 +27,50 @@ export class EthereumNodeService {
accounts: Account[];
}
| undefined;
private readonly logger = new Logger(EthereumNodeService.name);

constructor(@Inject(OPTIONS) private options: EthereumNodeServiceOptions) {}

async startNode() {
if (this.state !== undefined) return;

if (this.options.accounts) {
itaven marked this conversation as resolved.
Show resolved Hide resolved
for (const account of this.options.accounts) {
account.balance = utils.hexValue(
itaven marked this conversation as resolved.
Show resolved Hide resolved
utils.parseEther(account.balance.toString()),
);
}
}
this.logger.debug('Starting a fork node...');
const node = ganache.server({
chainId: this.options.chainId || 0x1,
fork: { url: this.options.rpcUrl },
logging: { quiet: true },
miner: { blockTime: 2 },
wallet: { defaultBalance: this.options.defaultBalance || 1000 },
wallet: {
/**
* If you would like to use specific account, you can pass it for `account` option.
*
* Example:
*
* ```ts
* new EthereumNodeService(
* chainId: this.widgetConfig.chainId,
* rpcUrl: WIDGET_CONFIG.STAND_CONFIG.rpcUrl,
* defaultBalance: 100,
* accounts: [{
* account: '<secret_key>',
* balance: 50
* }]
*
* )
* ```
*/
accounts: this.options.accounts,
defaultBalance: this.options.defaultBalance || 1000,
},
});

await node.listen(this.options.port || 7545);
const nodeUrl = `http://127.0.0.1:${this.options.port || 7545}`;
const initialAccounts = await node.provider.getInitialAccounts();
Expand Down
6 changes: 6 additions & 0 deletions packages/nodes/src/node.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ export type EthereumNodeServiceOptions = {
port?: number;
chainId?: number;
defaultBalance?: number;
accounts?: OptionsAccount[];
};

type OptionsAccount = {
secretKey: string;
balance: number | string;
};

export type Account = {
Expand Down
35 changes: 31 additions & 4 deletions packages/wallets/src/metamask/metamask.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,40 @@ export class MetamaskPage implements WalletPage {
});
}

async changeWalletAddress(addressName: string) {
await test.step('Change wallet address', async () => {
async changeWalletAccountByAddress(address: string) {
await test.step('Change wallet account by address', async () => {
await this.navigate();
await this.header.accountMenuButton.click();
await this.accountMenu.clickToAddress(addressName);
await this.accountMenu.clickToAddress(address);
});
}

async isWalletAddressExist(address: string) {
return await test.step(`Checking to the wallet address ${address} is exist`, async () => {
await this.navigate();
await this.header.accountMenuButton.click();
const listOfAddress = await this.accountMenu.getListOfAddress();

const addressStart = address.slice(0, 7).toLowerCase();
const addressEnd = address.slice(-5).toLowerCase();

const isExist = listOfAddress.some(
(listAddress) =>
listAddress.toLowerCase().startsWith(addressStart) &&
listAddress.toLowerCase().endsWith(addressEnd),
);
await this.page.close();
return isExist;
});
}

async changeWalletAccountByName(accountName: string) {
await test.step('Change wallet account', async () => {
await this.navigate();
await this.header.accountMenuButton.click();
await this.accountMenu.clickToAccount(accountName);
const accountNumber =
this.header.accountMenuButton.getByText(addressName);
this.header.accountMenuButton.getByText(accountName);
await accountNumber.waitFor({ state: 'visible', timeout: 2000 });
await this.page.waitForTimeout(2000);
await this.page.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export class AccountMenu {
importAccountButton: Locator;
privateKeyInput: Locator;
importAccountConfirmButton: Locator;
accountListAddress: Locator;

constructor(page: Page) {
this.page = page;
Expand All @@ -21,11 +22,33 @@ export class AccountMenu {
this.importAccountConfirmButton = this.page.getByTestId(
'import-account-confirm-button',
);
this.accountListAddress = this.page.getByTestId('account-list-address');
}

async clickToAddress(addressName: string) {
await test.step(`Click to "${addressName}" account`, async () => {
await this.accountListModal.getByText(addressName).click();
async clickToAccount(accountName: string) {
await test.step(`Click to "${accountName}" account`, async () => {
await this.accountListModal.getByText(accountName).click();
});
}

async clickToAddress(address: string) {
await test.step(`Click to account by "${address}"`, async () => {
const addressStart = address.slice(0, 7);
const addressEnd = address.slice(-5);

await this.accountListModal
.getByText(`${addressStart}...${addressEnd}`)
.click();
});
}

async getListOfAddress() {
return test.step('Get all exists accounts', async () => {
const listOfAddressText = [];
for (const address of await this.accountListAddress.all()) {
listOfAddressText.push(await address.textContent());
}
return listOfAddressText;
});
}

Expand Down
30 changes: 16 additions & 14 deletions packages/wallets/src/metamask/pages/walletOperations.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,23 @@ export class WalletOperationPage {
}

async cancelAllTxInQueue() {
//Is there is any tx in queue.
try {
await this.cancelButton.waitFor({
state: 'visible',
timeout: 1000,
});
} catch (er) {
return;
}
test.step('Cancel all tx in queue', async () => {
//Is there is any tx in queue.
try {
await this.cancelButton.waitFor({
state: 'visible',
timeout: 1000,
});
} catch (er) {
return;
}

if (await this.cancelAllTxsButton.isVisible()) {
await this.cancelAllTxsButton.click();
} else {
await this.cancelButton.click();
}
if (await this.cancelAllTxsButton.isVisible()) {
await this.cancelAllTxsButton.click();
} else {
await this.cancelButton.click();
}
});
}

async cancelTransaction() {
Expand Down
4 changes: 3 additions & 1 deletion packages/wallets/src/wallet.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,7 @@ export interface WalletPage {

changeNetwork?(networkName: string): Promise<void>;

changeWalletAddress?(addressName: string): Promise<void>;
changeWalletAccountByName?(accountName: string): Promise<void>;
changeWalletAccountByAddress?(address: string): Promise<void>;
isWalletAddressExist?(address: string): Promise<boolean>;
}
Loading