Skip to content

test: Create anvil manager class #15046

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

Merged
merged 22 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
280b2a5
test: Create anvil manager class
cortisiko May 1, 2025
1a826c3
got server running with e2e + funding wallet
cortisiko May 2, 2025
6078a01
Merge branch 'main' into MMQA-524-Create-Anvil-Manager-Util
cortisiko May 2, 2025
7bc97e7
add '--experimental-vm-modules' so test using anvil can run
cortisiko May 2, 2025
d743500
fix manager class. Set balance on default account if none is passed in
cortisiko May 2, 2025
8c8cf7b
use default anvil options if none is specified
cortisiko May 3, 2025
0e08275
Merge branch 'main' into MMQA-524-Create-Anvil-Manager-Util
cortisiko May 5, 2025
a9feaf6
get anvil working with node options
cortisiko May 6, 2025
c834a15
use ganache as default node until we are ready to fully move to anvil
cortisiko May 6, 2025
418fdf8
handle default options for anvil
cortisiko May 6, 2025
6314ab8
delay for network switch
cortisiko May 7, 2025
1f77c59
fix failing networks tests
cortisiko May 7, 2025
6cc8370
fix bug with defaulting to ganche
cortisiko May 7, 2025
8a19ecf
temp disable ios specs test
cortisiko May 7, 2025
5083887
enable api specs, include ts import
cortisiko May 7, 2025
54f207a
removing example anvil e2e test
cortisiko May 7, 2025
dce26bd
clean up fixture builder
cortisiko May 7, 2025
3d75784
Merge branch 'main' into MMQA-524-Create-Anvil-Manager-Util
cortisiko May 7, 2025
c3022c8
set prague as hardfork default
cortisiko May 7, 2025
737a96a
add jsdocs
cortisiko May 7, 2025
e88d7d3
add ts-node
cortisiko May 7, 2025
77e705c
fix dedupe
cortisiko May 7, 2025
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
1 change: 1 addition & 0 deletions e2e/api-specs/run-api-spec-tests.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-commonjs */
require('@babel/register');
require('ts-node/register');
require('./json-rpc-coverage.js');
183 changes: 149 additions & 34 deletions e2e/fixtures/fixture-helper.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
/* eslint-disable no-console, import/no-nodejs-modules */
import FixtureServer, { DEFAULT_FIXTURE_SERVER_PORT } from './fixture-server';
import FixtureBuilder from './fixture-builder';
import { AnvilManager, defaultOptions } from '../seeder/anvil-manager';
import Ganache from '../../app/util/test/ganache';

import GanacheSeeder from '../../app/util/test/ganache-seeder';
import axios from 'axios';
import path from 'path';
import createStaticServer from '../create-static-server';
import { DEFAULT_MOCKSERVER_PORT, getFixturesServerPort, getLocalTestDappPort, getMockServerPort } from './utils';
import {
DEFAULT_MOCKSERVER_PORT,
getFixturesServerPort,
getLocalTestDappPort,
getMockServerPort,
} from './utils';
import Utilities from '../utils/Utilities';
import { device } from 'detox';
import TestHelpers from '../helpers';
import { startMockServer, stopMockServer } from '../api-mocking/mock-server';

Expand All @@ -31,6 +37,84 @@ const isFixtureServerStarted = async () => {
}
};

// SRP corresponding to the vault set in the default fixtures - it's an empty test account, not secret
export const defaultGanacheOptions = {
hardfork: 'london',
mnemonic:
'drive manage close raven tape average sausage pledge riot furnace august tip',
};

/**
*
* Normalizes the localNodeOptions into a consistent format to handle different data structures.
* Case 1: A string: localNodeOptions = 'anvil'
* Case 2: Array of strings: localNodeOptions = ['anvil', 'bitcoin']
* Case 3: Array of objects: localNodeOptions =
* [
* { type: 'anvil', options: {anvilOpts}},
* { type: 'bitcoin',options: {bitcoinOpts}},
* ]
* Case 4: Options object without type: localNodeOptions = {options}
*
* @param {string | object | Array} localNodeOptions - The input local node options.
* @returns {Array} The normalized local node options.
*/
function normalizeLocalNodeOptions(localNodeOptions) {
if (typeof localNodeOptions === 'string') {
// Case 1: Passing a string
return [
{
type: localNodeOptions,
options:
localNodeOptions === 'ganache'
? defaultGanacheOptions
: localNodeOptions === 'anvil'
? defaultOptions
: {},
},
];
} else if (Array.isArray(localNodeOptions)) {
return localNodeOptions.map((node) => {
if (typeof node === 'string') {
// Case 2: Array of strings
return {
type: node,
options:
node === 'ganache'
? defaultGanacheOptions
: node === 'anvil'
? defaultOptions
: {},
};
}
if (typeof node === 'object' && node !== null) {
// Case 3: Array of objects
const type = node.type || 'ganache';
return {
type,
options:
type === 'ganache'
? { ...defaultGanacheOptions, ...(node.options || {}) }
: type === 'anvil'
? { ...defaultOptions, ...(node.options || {}) }
: node.options || {},
};
}
throw new Error(`Invalid localNodeOptions entry: ${node}`);
});
}
if (typeof localNodeOptions === 'object' && localNodeOptions !== null) {
// Case 4: Passing an options object without type
return [
{
type: 'ganache',
options: { ...defaultGanacheOptions, ...localNodeOptions },
},
];
}
throw new Error(`Invalid localNodeOptions type: ${typeof localNodeOptions}`);
}

/**
* Loads a fixture into the fixture server.
*
Expand Down Expand Up @@ -99,40 +183,74 @@ export async function withFixtures(options, testSuite) {
smartContract,
disableGanache,
dapp,
localNodeOptions = 'ganache',
dappOptions,
dappPath = undefined,
dappPaths,
testSpecificMock,
launchArgs
launchArgs,
} = options;

const fixtureServer = new FixtureServer();
let mockServer;
let mockServerPort = DEFAULT_MOCKSERVER_PORT;
const localNodeOptsNormalized = normalizeLocalNodeOptions(localNodeOptions);

if (testSpecificMock) {
mockServerPort = getMockServerPort();
mockServer = await startMockServer(testSpecificMock, mockServerPort);
}

let ganacheServer;
if (!disableGanache) {
ganacheServer = new Ganache();
let localNode;
const localNodes = [];

try {
// Start servers based on the localNodes array
if (!disableGanache) {
for (let i = 0; i < localNodeOptsNormalized.length; i++) {
const nodeType = localNodeOptsNormalized[i].type;
const nodeOptions = localNodeOptsNormalized[i].options || {};

switch (nodeType) {
case 'anvil':
localNode = new AnvilManager();
await localNode.start(nodeOptions);
localNodes.push(localNode);
await localNode.setAccountBalance('1200');

break;

case 'ganache':
localNode = new Ganache();
await localNode.start(nodeOptions);
localNodes.push(localNode);
break;

case 'none':
break;

default:
throw new Error(
`Unsupported localNode: '${nodeType}'. Cannot start the server.`,
);
}
}
}
} catch (error) {
console.error(error);
throw error;
}

const dappBasePort = getLocalTestDappPort();
let numberOfDapps = dapp ? 1 : 0;
const dappServer = [];

try {
let contractRegistry;
if (ganacheOptions && !disableGanache) {
await ganacheServer.start(ganacheOptions);

if (smartContract) {
const ganacheSeeder = new GanacheSeeder(ganacheServer.getProvider());
await ganacheSeeder.deploySmartContract(smartContract);
contractRegistry = ganacheSeeder.getContractRegistry();
}
if (!disableGanache && smartContract) {
const ganacheSeeder = new GanacheSeeder(localNodes[0].getProvider());
await ganacheSeeder.deploySmartContract(smartContract);
contractRegistry = ganacheSeeder.getContractRegistry();
}

if (dapp) {
Expand Down Expand Up @@ -171,26 +289,30 @@ export async function withFixtures(options, testSuite) {
);
// Due to the fact that the app was already launched on `init.js`, it is necessary to
// launch into a fresh installation of the app to apply the new fixture loaded perviously.
if (restartDevice) {
await TestHelpers.launchApp({
delete: true,
launchArgs: {
fixtureServerPort: `${getFixturesServerPort()}`,
detoxURLBlacklistRegex: Utilities.BlacklistURLs,
mockServerPort: `${mockServerPort}`,
...(launchArgs || {}),
},
});
if (restartDevice) {
await TestHelpers.launchApp({
delete: true,
launchArgs: {
fixtureServerPort: `${getFixturesServerPort()}`,
detoxURLBlacklistRegex: Utilities.BlacklistURLs,
mockServerPort: `${mockServerPort}`,
...(launchArgs || {}),
},
});
}

await testSuite({ contractRegistry, mockServer });
await testSuite({ contractRegistry, mockServer, localNodes }); // Pass localNodes instead of anvilServer
} catch (error) {
console.error(error);
throw error;
} finally {
if (ganacheOptions && !disableGanache) {
await ganacheServer.quit();
// Clean up all local nodes
for (const server of localNodes) {
if (server) {
await server.quit();
}
}

if (dapp) {
for (let i = 0; i < numberOfDapps; i++) {
if (dappServer[i] && dappServer[i].listening) {
Expand All @@ -213,10 +335,3 @@ export async function withFixtures(options, testSuite) {
await stopFixtureServer(fixtureServer);
}
}

// SRP corresponding to the vault set in the default fixtures - it's an empty test account, not secret
export const defaultGanacheOptions = {
hardfork: 'london',
mnemonic:
'drive manage close raven tape average sausage pledge riot furnace august tip',
};
2 changes: 2 additions & 0 deletions e2e/pages/Network/NetworkListModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class NetworkListModal {

async changeNetworkTo(networkName, custom) {
const elem = this.getCustomNetwork(networkName, custom);
await TestHelpers.delay(3000);
await Gestures.waitAndTap(elem);
await TestHelpers.delay(3000);
}
Expand Down Expand Up @@ -103,6 +104,7 @@ class NetworkListModal {
}

async tapAddNetworkButton() {
await TestHelpers.delay(3000);
await Gestures.waitAndTap(this.addPopularNetworkButton);
}
async deleteNetwork() {
Expand Down
1 change: 0 additions & 1 deletion e2e/seeder/anvil-clients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
http,
} from 'viem';
import { anvil as baseAnvil } from 'viem/chains';

/**
* Creates a set of clients for interacting with an Anvil test node
* @param {number} chainId - The chain ID for the network
Expand Down
Loading
Loading