Feat: add winston logger in e2e tests (#489)

* feat: add winston logger in e2e tests

* fix: rename appendTestName function to prefixWithTestName

* fix: change some log level
This commit is contained in:
Victorien Gauch
2025-01-06 10:50:44 +01:00
committed by GitHub
parent 3b875fd8d6
commit f9c49099c5
21 changed files with 267 additions and 193 deletions

View File

@@ -8,6 +8,7 @@ const config: Config = {
verbose: true,
globalSetup: "./config/jest/global-setup.ts",
globalTeardown: "./config/jest/global-teardown.ts",
setupFilesAfterEnv: ["./config/jest/setup.ts"],
testTimeout: 3 * 60 * 1000,
maxConcurrency: 7,
maxWorkers: "75%",

View File

@@ -6,8 +6,11 @@ const config: Config = {
rootDir: "src",
testRegex: ".spec.ts$",
verbose: true,
maxWorkers: "50%",
setupFilesAfterEnv: ["./config/jest/setup.ts"],
testTimeout: 3 * 60 * 1000,
maxConcurrency: 7,
maxWorkers: "75%",
workerThreads: true,
};
export default config;

View File

@@ -28,6 +28,7 @@
"ethers": "6.13.3",
"jest": "29.7.0",
"ts-jest": "29.2.5",
"typechain": "8.3.2"
"typechain": "8.3.2",
"winston": "3.17.0"
}
}

View File

@@ -24,12 +24,12 @@ describe("Bridge ERC20 Tokens L1 -> L2 and L2 -> L1", () => {
const l1Token = config.getL1TokenContract();
const l1Provider = config.getL1Provider();
console.log("Minting ERC20 tokens to L1 Account");
logger.debug("Minting ERC20 tokens to L1 Account");
let { maxPriorityFeePerGas: l1MaxPriorityFeePerGas, maxFeePerGas: l1MaxFeePerGas } = await l1Provider.getFeeData();
let nonce = await l1Provider.getTransactionCount(l1Account.address, "pending");
console.log("Minting and approving tokens to L1 TokenBridge");
logger.debug("Minting and approving tokens to L1 TokenBridge");
await Promise.all([
(
@@ -52,9 +52,9 @@ describe("Bridge ERC20 Tokens L1 -> L2 and L2 -> L1", () => {
const l1TokenAddress = await l1Token.getAddress();
const allowanceL1Account = await l1Token.allowance(l1Account.address, l1TokenBridgeAddress);
console.log("Current allowance of L1 account to L1 TokenBridge is :", allowanceL1Account.toString());
logger.info(`Current allowance of L1 account to L1 TokenBridge is ${allowanceL1Account.toString()}`);
console.log("Calling the bridgeToken function on the L1 TokenBridge contract");
logger.debug("Calling the bridgeToken function on the L1 TokenBridge contract");
({ maxPriorityFeePerGas: l1MaxPriorityFeePerGas, maxFeePerGas: l1MaxFeePerGas } = await l1Provider.getFeeData());
nonce = await l1Provider.getTransactionCount(l1Account.address, "pending");
@@ -79,18 +79,18 @@ describe("Bridge ERC20 Tokens L1 -> L2 and L2 -> L1", () => {
);
const l1TokenBalance = await l1Token.balanceOf(l1Account.address);
console.log("Token balance of L1 account :", l1TokenBalance.toString());
logger.info(`Token balance of L1 account is ${l1TokenBalance.toString()}`);
expect(l1TokenBalance).toEqual(0n);
console.log("Waiting for MessageSent event on L1.");
logger.info("Waiting for MessageSent event on L1.");
const messageNumber = messageSentEvent[messageSentEventMessageNumberIndex];
const messageHash = messageSentEvent[messageSentEventMessageHashIndex];
console.log(`Message sent on L1 : messageHash=${messageHash}`);
logger.info(`Message sent on L1. messageHash=${messageHash}`);
console.log("Waiting for anchoring...");
logger.info("Waiting for anchoring...");
const [rollingHashUpdatedEvent] = await waitForEvents(
l2MessageService,
@@ -106,9 +106,9 @@ describe("Bridge ERC20 Tokens L1 -> L2 and L2 -> L1", () => {
expect(anchoredStatus).toBeGreaterThan(0);
console.log(`Message anchored : ${JSON.stringify(rollingHashUpdatedEvent)}`);
logger.info(`Message anchored. event=${JSON.stringify(rollingHashUpdatedEvent)}`);
console.log("Waiting for MessageClaimed event on L2...");
logger.info("Waiting for MessageClaimed event on L2...");
const [claimedEvent] = await waitForEvents(l2MessageService, l2MessageService.filters.MessageClaimed(messageHash));
expect(claimedEvent).not.toBeNull();
@@ -116,14 +116,14 @@ describe("Bridge ERC20 Tokens L1 -> L2 and L2 -> L1", () => {
const [newTokenDeployed] = await waitForEvents(l2TokenBridge, l2TokenBridge.filters.NewTokenDeployed());
expect(newTokenDeployed).not.toBeNull();
console.log(`Message claimed on L2 : ${JSON.stringify(claimedEvent)}.`);
logger.info(`Message claimed on L2. event=${JSON.stringify(claimedEvent)}.`);
const l2Token = config.getL2BridgedTokenContract(newTokenDeployed.args.bridgedToken);
console.log("Verify the token balance on L2");
logger.info("Verify the token balance on L2");
const l2TokenBalance = await l2Token.balanceOf(l2Account.address);
console.log("Token balance of L2 account :", l2TokenBalance.toString());
logger.info(`Token balance of L2 account is ${l2TokenBalance.toString()}`);
expect(l2TokenBalance).toEqual(bridgeAmount);
});
@@ -163,10 +163,10 @@ describe("Bridge ERC20 Tokens L1 -> L2 and L2 -> L1", () => {
]);
const allowanceL2Account = await l2Token.allowance(l2Account.address, l2TokenBridge.getAddress());
console.log("Current allowance of L2 account to L2 TokenBridge is :", allowanceL2Account.toString());
console.log("Current balance of L2 account is :", await l2Token.balanceOf(l2Account));
logger.info(`Current allowance of L2 account to L2 TokenBridge is ${allowanceL2Account.toString()}`);
logger.info(`Current balance of L2 account is ${await l2Token.balanceOf(l2Account)}`);
console.log("Calling the bridgeToken function on the L2 TokenBridge contract");
logger.debug("Calling the bridgeToken function on the L2 TokenBridge contract");
nonce = await l2Provider.getTransactionCount(l2Account.address, "pending");
@@ -189,22 +189,22 @@ describe("Bridge ERC20 Tokens L1 -> L2 and L2 -> L1", () => {
);
const messageHash = messageSentEvent[messageSentEventMessageHashIndex];
console.log("Waiting for L1 MessageClaimed event.");
logger.info("Waiting for L1 MessageClaimed event.");
const [claimedEvent] = await waitForEvents(lineaRollup, lineaRollup.filters.MessageClaimed(messageHash));
expect(claimedEvent).not.toBeNull();
console.log(`Message claimed on L1 : ${JSON.stringify(claimedEvent)}`);
logger.info(`Message claimed on L1. event=${JSON.stringify(claimedEvent)}`);
const [newTokenDeployed] = await waitForEvents(l1TokenBridge, l1TokenBridge.filters.NewTokenDeployed());
expect(newTokenDeployed).not.toBeNull();
const l1BridgedToken = config.getL1BridgedTokenContract(newTokenDeployed.args.bridgedToken);
console.log("Verify the token balance on L1");
logger.info("Verify the token balance on L1");
const l1BridgedTokenBalance = await l1BridgedToken.balanceOf(l1Account.address);
console.log("Token balance of L1 account :", l1BridgedTokenBalance.toString());
logger.info(`Token balance of L1 account is ${l1BridgedTokenBalance.toString()}`);
expect(l1BridgedTokenBalance).toEqual(bridgeAmount);
});

View File

@@ -56,7 +56,7 @@ export async function deployUpgradableContractWithProxyAdmin<T extends ContractF
const proxyFactory = new ProxyAdmin__factory(deployer);
const proxyAdmin = await proxyFactory.connect(deployer).deploy();
await proxyAdmin.waitForDeployment();
console.log(`ProxyAdmin contract deployed at address: ${await proxyAdmin.getAddress()}`);
logger.info(`ProxyAdmin contract deployed. address=${await proxyAdmin.getAddress()}`);
const contract = await deployUpgradableContract(
contractFactory,
@@ -64,6 +64,6 @@ export async function deployUpgradableContractWithProxyAdmin<T extends ContractF
proxyAdmin,
getInitializerData(contractFactory.interface, args),
);
console.log(`Contract deployed at address: ${await contract.getAddress()}`);
logger.info(`Contract deployed. address=${await contract.getAddress()}`);
return contract;
}

View File

@@ -12,6 +12,9 @@ import {
TypedContractMethod,
} from "../typechain/common";
import { MessageEvent, SendMessageArgs } from "./types";
import { createTestLogger } from "../config/logger";
const logger = createTestLogger();
export function etherToWei(amount: string): bigint {
return ethers.parseEther(amount.toString());
@@ -293,7 +296,7 @@ export async function sendTransactionsToGenerateTrafficWithInterval(
const tx = await signer.sendTransaction(transactionRequest);
await tx.wait();
} catch (error) {
console.error("Error sending transaction:", error);
logger.error(`Error sending transaction. error=${JSON.stringify(error)}`);
} finally {
if (isRunning) {
timeoutId = setTimeout(sendTransaction, pollingInterval);
@@ -307,7 +310,7 @@ export async function sendTransactionsToGenerateTrafficWithInterval(
clearTimeout(timeoutId);
timeoutId = null;
}
console.log("Transaction loop stopped.");
logger.info("Transaction loop stopped.");
};
sendTransaction();
@@ -364,14 +367,14 @@ export const sendMessage = async <T extends LineaRollupV6 | L2MessageService>(
export async function execDockerCommand(command: string, containerName: string): Promise<string> {
const dockerCommand = `docker ${command} ${containerName}`;
console.log(`Executing: ${dockerCommand}...`);
logger.info(`Executing ${dockerCommand}...`);
return new Promise((resolve, reject) => {
exec(dockerCommand, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing (${dockerCommand}): ${stderr}`);
logger.error(`Error executing (${dockerCommand}). error=${stderr}`);
reject(error);
}
console.log(`Execution success (${dockerCommand}): ${stdout}`);
logger.info(`Execution success (${dockerCommand}). output=${stdout}`);
resolve(stdout);
});
});

10
e2e/src/config/global.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/* eslint-disable no-var */
import { Logger } from "winston";
declare global {
var stopL2TrafficGeneration: () => void;
var logger: Logger;
}
export {};

View File

@@ -5,21 +5,20 @@ import { deployContract } from "../../common/deployments";
import { DummyContract__factory, TestContract__factory, OpcodeTestContract__factory } from "../../typechain";
import { etherToWei, sendTransactionsToGenerateTrafficWithInterval } from "../../common/utils";
import { EMPTY_CONTRACT_CODE } from "../../common/constants";
import { createTestLogger } from "../logger";
declare global {
var stopL2TrafficGeneration: () => void;
}
const logger = createTestLogger();
export default async (): Promise<void> => {
const dummyContractCode = await config.getL1Provider().getCode(config.getL1DummyContractAddress());
// If this is empty, we have not deployed and prerequisites or configured token bridges.
if (dummyContractCode === EMPTY_CONTRACT_CODE) {
console.log("Configuring once-off prerequisite contracts");
logger.info("Configuring once-off prerequisite contracts");
await configureOnceOffPrerequisities();
}
console.log("Generating L2 traffic...");
logger.info("Generating L2 traffic...");
const pollingAccount = await config.getL2AccountManager().generateAccount(etherToWei("200"));
const stopPolling = await sendTransactionsToGenerateTrafficWithInterval(pollingAccount, 2_000);
@@ -71,8 +70,8 @@ async function configureOnceOffPrerequisities() {
).wait(),
]);
console.log(`L1 Dummy contract deployed at address: ${await dummyContract.getAddress()}`);
console.log(`L2 Dummy contract deployed at address: ${await l2DummyContract.getAddress()}`);
console.log(`L2 Test contract deployed at address: ${await l2TestContract.getAddress()}`);
console.log(`L2 OpcodeTest contract deployed at address: ${await opcodeTestContract.getAddress()}`);
logger.info(`L1 Dummy contract deployed. address=${await dummyContract.getAddress()}`);
logger.info(`L2 Dummy contract deployed. address=${await l2DummyContract.getAddress()}`);
logger.info(`L2 Test contract deployed. address=${await l2TestContract.getAddress()}`);
logger.info(`L2 OpcodeTest contract deployed. address=${await opcodeTestContract.getAddress()}`);
}

View File

@@ -0,0 +1,3 @@
import { createTestLogger } from "../logger";
global.logger = createTestLogger();

View File

@@ -0,0 +1,17 @@
import { createLogger, format, transports, Logger } from "winston";
const { splat, combine, colorize, timestamp, printf } = format;
export const baseLogger: Logger = createLogger({
level: process.env.LOG_LEVEL || "info",
format: combine(
timestamp(),
colorize({ level: true }),
splat(),
printf(({ level, message, timestamp, testName }) => {
const testContext = testName ? ` test=${testName}` : "";
return `timestamp=${timestamp} level=${level}${testContext} | message=${message}`;
}),
),
transports: [new transports.Console()],
});

View File

@@ -0,0 +1 @@
export { createTestLogger } from "./logger";

View File

@@ -0,0 +1,62 @@
import { Logger, LeveledLogMethod } from "winston";
import { baseLogger } from "./base-logger";
type LogLevel = "error" | "warn" | "info" | "verbose" | "debug" | "silly";
function getActiveTestName(): string | undefined {
if (typeof expect !== "function" || typeof expect.getState !== "function") {
return undefined;
}
const { currentTestName, currentConcurrentTestName } = expect.getState() || {};
if (!currentConcurrentTestName) {
return currentTestName;
}
return currentConcurrentTestName();
}
function prefixWithTestName(level: LogLevel, args: unknown[]): Logger {
const testName = getActiveTestName();
if (!testName) {
return baseLogger[level as keyof Logger](...args);
}
const [firstArg] = args;
if (typeof firstArg === "string") {
return baseLogger[level](firstArg, { testName });
}
if (firstArg && typeof firstArg === "object" && !Array.isArray(firstArg)) {
return baseLogger[level]({ testName, ...firstArg });
}
return baseLogger[level as keyof Logger](...args);
}
export function createTestLogger(): Logger {
return {
...baseLogger,
error(...args: Parameters<LeveledLogMethod>) {
return prefixWithTestName("error", args);
},
warn(...args: Parameters<LeveledLogMethod>) {
return prefixWithTestName("warn", args);
},
info(...args: Parameters<LeveledLogMethod>) {
return prefixWithTestName("info", args);
},
verbose(...args: Parameters<LeveledLogMethod>) {
return prefixWithTestName("verbose", args);
},
debug(...args: Parameters<LeveledLogMethod>) {
return prefixWithTestName("debug", args);
},
silly(...args: Parameters<LeveledLogMethod>) {
return prefixWithTestName("silly", args);
},
} as Logger;
}

View File

@@ -1,7 +1,9 @@
import { ethers, NonceManager, Provider, TransactionResponse, Wallet } from "ethers";
import { Mutex } from "async-mutex";
import type { Logger } from "winston";
import Account from "./account";
import { etherToWei } from "../../../common/utils";
import { createTestLogger } from "../../../config/logger";
interface IAccountManager {
whaleAccount(accIndex?: number): NonceManager;
@@ -29,6 +31,7 @@ abstract class AccountManager implements IAccountManager {
protected provider: Provider;
protected accountWallets: NonceManager[];
private whaleAccountMutex: Mutex;
private logger: Logger;
constructor(provider: Provider, whaleAccounts: Account[], chainId: number) {
this.provider = provider;
@@ -38,6 +41,8 @@ abstract class AccountManager implements IAccountManager {
(account) => new NonceManager(getWallet(this.provider, account.privateKey)),
);
this.whaleAccountMutex = new Mutex();
this.logger = createTestLogger();
}
selectWhaleAccount(accIndex?: number): { account: Account; accountWallet: NonceManager } {
@@ -65,8 +70,8 @@ abstract class AccountManager implements IAccountManager {
async generateAccounts(numberOfAccounts: number, initialBalanceWei = etherToWei("10")): Promise<Wallet[]> {
const { account: whaleAccount, accountWallet: whaleAccountWallet } = this.selectWhaleAccount();
console.log(
`Generating accounts: chainId=${this.chainId} numberOfAccounts=${numberOfAccounts} whaleAccount=${whaleAccount.address}`,
this.logger.debug(
`Generating accounts... chainId=${this.chainId} numberOfAccounts=${numberOfAccounts} whaleAccount=${whaleAccount.address}`,
);
const accounts: Account[] = [];
@@ -88,13 +93,13 @@ abstract class AccountManager implements IAccountManager {
const release = await this.whaleAccountMutex.acquire();
try {
const transactionResponse = await whaleAccountWallet.sendTransaction(tx);
console.log(
`Transaction sent: newAccount=${newAccount.address} txHash=${transactionResponse.hash} whaleAccount=${whaleAccount.address}`,
this.logger.debug(
`Transaction sent. newAccount=${newAccount.address} txHash=${transactionResponse.hash} whaleAccount=${whaleAccount.address}`,
);
transactionResponses.push(transactionResponse);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
console.error(`Failed to fund account ${newAccount.address}: ${error.message}`);
logger.error(`Failed to fund account. address=${newAccount.address} error=${error.message}`);
whaleAccountWallet.reset();
} finally {
release();
@@ -103,8 +108,8 @@ abstract class AccountManager implements IAccountManager {
await Promise.all(transactionResponses.map((tx) => tx.wait()));
console.log(
`Accounts funded: newAccounts=${accounts.map((account) => account.address).join(",")} balance=${initialBalanceWei.toString()} wei`,
this.logger.debug(
`Accounts funded. newAccounts=${accounts.map((account) => account.address).join(",")} balance=${initialBalanceWei.toString()} wei`,
);
return accounts.map((account) => this.getWallet(account));

View File

@@ -42,7 +42,7 @@ describe("Gas limit test suite", () => {
// Ok to type assertion here, because txReceipt won't be null if it passed above assertion.
const txBlockNumber = <number>txReceipt?.blockNumber;
console.log(`Waiting for ${txBlockNumber} to be finalized...`);
logger.info(`Waiting for ${txBlockNumber} to be finalized...`);
const isBlockFinalized = await pollForContractMethodReturnValueExceedTarget(
lineaRollupV6.currentL2BlockNumber,
@@ -60,13 +60,13 @@ describe("Gas limit test suite", () => {
const account = await l2AccountManager.generateAccount();
const lineaRollupV6 = config.getLineaRollupContract();
console.log(`Target block gas limit: ${targetBlockGasLimit}`);
logger.info(`Target block gas limit: ${targetBlockGasLimit}`);
while (!isTargetBlockGasLimitReached) {
const txReceipt = await setGasLimit(account);
expect(txReceipt?.status).toEqual(1);
const blockGasLimit = await getGasLimit();
console.log("blockGasLimit: ", blockGasLimit);
logger.info("blockGasLimit: ", blockGasLimit);
if (blockGasLimit === targetBlockGasLimit) {
isTargetBlockGasLimitReached = true;
// Ok to type assertion here, because txReceipt won't be null if it passed above assertion.
@@ -75,7 +75,7 @@ describe("Gas limit test suite", () => {
await wait(1000);
}
console.log(`Waiting for ${blockNumberToCheckFinalization} to be finalized...`);
logger.info(`Waiting for ${blockNumberToCheckFinalization} to be finalized...`);
const isBlockFinalized = await pollForContractMethodReturnValueExceedTarget(
lineaRollupV6.currentL2BlockNumber,

View File

@@ -151,7 +151,7 @@ describe("Layer 2 test suite", () => {
shomeiClient.rollupGetZkEVMBlockNumber(),
shomeiFrontendClient.rollupGetZkEVMBlockNumber(),
]);
console.log(`shomeiBlock = ${shomeiBlock}, shomeiFrontendBlock = ${shomeiFrontendBlock}`);
logger.debug(`shomeiBlock=${shomeiBlock}, shomeiFrontendBlock=${shomeiFrontendBlock}`);
expect(shomeiBlock).toBeGreaterThan(shomeiFrontendBlock);
}

View File

@@ -1,18 +1,22 @@
import { ethers, Wallet } from "ethers";
import { describe, expect, it } from "@jest/globals";
import type { Logger } from "winston";
import { config } from "./config/tests-config";
import { encodeFunctionCall, etherToWei, waitForEvents } from "./common/utils";
import { MESSAGE_SENT_EVENT_SIGNATURE } from "./common/constants";
async function sendL1ToL2Message({
l1Account,
l2Account,
withCalldata = false,
}: {
l1Account: Wallet;
l2Account: Wallet;
withCalldata: boolean;
}) {
async function sendL1ToL2Message(
logger: Logger,
{
l1Account,
l2Account,
withCalldata = false,
}: {
l1Account: Wallet;
l2Account: Wallet;
withCalldata: boolean;
},
) {
const dummyContract = config.getL2DummyContract(l2Account);
const lineaRollup = config.getLineaRollupContract(l1Account);
@@ -36,22 +40,25 @@ async function sendL1ToL2Message({
let receipt = await tx.wait();
while (!receipt) {
console.log("Waiting for transaction to be mined...");
logger.info("Waiting for transaction to be mined...");
receipt = await tx.wait();
}
return { tx, receipt };
}
async function sendL2ToL1Message({
l1Account,
l2Account,
withCalldata = false,
}: {
l1Account: Wallet;
l2Account: Wallet;
withCalldata: boolean;
}) {
async function sendL2ToL1Message(
logger: Logger,
{
l1Account,
l2Account,
withCalldata = false,
}: {
l1Account: Wallet;
l2Account: Wallet;
withCalldata: boolean;
},
) {
const l2Provider = config.getL2Provider();
const dummyContract = config.getL1DummyContract(l1Account);
const l2MessageService = config.getL2MessageServiceContract(l2Account);
@@ -75,7 +82,7 @@ async function sendL2ToL1Message({
let receipt = await tx.wait();
while (!receipt) {
console.log("Waiting for transaction to be mined...");
logger.info("Waiting for transaction to be mined...");
receipt = await tx.wait();
}
@@ -94,20 +101,20 @@ describe("Messaging test suite", () => {
l2AccountManager.generateAccount(),
]);
const { tx, receipt } = await sendL1ToL2Message({ l1Account, l2Account, withCalldata: true });
const { tx, receipt } = await sendL1ToL2Message(logger, { l1Account, l2Account, withCalldata: true });
const [messageSentEvent] = receipt.logs.filter((log) => log.topics[0] === MESSAGE_SENT_EVENT_SIGNATURE);
const messageHash = messageSentEvent.topics[3];
console.log(`L1 message sent: messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
logger.info(`L1 message sent. messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
console.log("Waiting for MessageClaimed event on L2.");
logger.info("Waiting for MessageClaimed event on L2.");
const l2MessageService = config.getL2MessageServiceContract();
const [messageClaimedEvent] = await waitForEvents(
l2MessageService,
l2MessageService.filters.MessageClaimed(messageHash),
);
console.log(`Message claimed on L2: ${JSON.stringify(messageClaimedEvent)}`);
logger.info(`Message claimed on L2. event=${JSON.stringify(messageClaimedEvent)}`);
expect(messageClaimedEvent).toBeDefined();
},
100_000,
@@ -121,19 +128,19 @@ describe("Messaging test suite", () => {
l2AccountManager.generateAccount(),
]);
const { tx, receipt } = await sendL1ToL2Message({ l1Account, l2Account, withCalldata: false });
const { tx, receipt } = await sendL1ToL2Message(logger, { l1Account, l2Account, withCalldata: false });
const [messageSentEvent] = receipt.logs.filter((log) => log.topics[0] === MESSAGE_SENT_EVENT_SIGNATURE);
const messageHash = messageSentEvent.topics[3];
console.log(`L1 message sent: messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
logger.info(`L1 message sent. messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
console.log("Waiting for MessageClaimed event on L2.");
logger.info("Waiting for MessageClaimed event on L2.");
const l2MessageService = config.getL2MessageServiceContract();
const [messageClaimedEvent] = await waitForEvents(
l2MessageService,
l2MessageService.filters.MessageClaimed(messageHash),
);
console.log(`Message claimed on L2: ${JSON.stringify(messageClaimedEvent)}`);
logger.info(`Message claimed on L2. event=${JSON.stringify(messageClaimedEvent)}`);
expect(messageClaimedEvent).toBeDefined();
},
100_000,
@@ -148,27 +155,27 @@ describe("Messaging test suite", () => {
]);
const lineaRollup = config.getLineaRollupContract();
const { tx, receipt } = await sendL2ToL1Message({ l1Account, l2Account, withCalldata: true });
const { tx, receipt } = await sendL2ToL1Message(logger, { l1Account, l2Account, withCalldata: true });
const [messageSentEvent] = receipt.logs.filter((log) => log.topics[0] === MESSAGE_SENT_EVENT_SIGNATURE);
const messageHash = messageSentEvent.topics[3];
console.log(`L2 message sent: messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
logger.info(`L2 message sent. messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
console.log(`Waiting for L2MessagingBlockAnchored... with blockNumber=${messageSentEvent.blockNumber}`);
logger.info(`Waiting for L2MessagingBlockAnchored with blockNumber=${messageSentEvent.blockNumber}...`);
await waitForEvents(
lineaRollup,
lineaRollup.filters.L2MessagingBlockAnchored(messageSentEvent.blockNumber),
1_000,
);
console.log("Waiting for MessageClaimed event on L1.");
logger.info("Waiting for MessageClaimed event on L1.");
const [messageClaimedEvent] = await waitForEvents(
lineaRollup,
lineaRollup.filters.MessageClaimed(messageHash),
1_000,
);
console.log(`Message claimed on L1: ${JSON.stringify(messageClaimedEvent)}`);
logger.info(`Message claimed on L1. event=${JSON.stringify(messageClaimedEvent)}`);
expect(messageClaimedEvent).toBeDefined();
},
150_000,
@@ -183,27 +190,27 @@ describe("Messaging test suite", () => {
]);
const lineaRollup = config.getLineaRollupContract();
const { tx, receipt } = await sendL2ToL1Message({ l1Account, l2Account, withCalldata: false });
const { tx, receipt } = await sendL2ToL1Message(logger, { l1Account, l2Account, withCalldata: false });
const [messageSentEvent] = receipt.logs.filter((log) => log.topics[0] === MESSAGE_SENT_EVENT_SIGNATURE);
const messageHash = messageSentEvent.topics[3];
console.log(`L2 message sent: messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
logger.info(`L2 message sent. messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
console.log(`Waiting for L2MessagingBlockAnchored... with blockNumber=${messageSentEvent.blockNumber}`);
logger.info(`Waiting for L2MessagingBlockAnchored with blockNumber=${messageSentEvent.blockNumber}...`);
await waitForEvents(
lineaRollup,
lineaRollup.filters.L2MessagingBlockAnchored(messageSentEvent.blockNumber),
1_000,
);
console.log("Waiting for MessageClaimed event on L1.");
logger.info("Waiting for MessageClaimed event on L1.");
const [messageClaimedEvent] = await waitForEvents(
lineaRollup,
lineaRollup.filters.MessageClaimed(messageHash),
1_000,
);
console.log(`Message claimed on L1: ${JSON.stringify(messageClaimedEvent)}`);
logger.info(`Message claimed on L1. event=${JSON.stringify(messageClaimedEvent)}`);
expect(messageClaimedEvent).toBeDefined();
},
150_000,

View File

@@ -1,4 +1,5 @@
import { describe, expect, it } from "@jest/globals";
import type { Logger } from "winston";
import {
execDockerCommand,
waitForEvents,
@@ -13,19 +14,19 @@ let testsWaitingForRestart = 0;
const TOTAL_TESTS_WAITING = 2;
let coordinatorHasRestarted = false;
async function waitForCoordinatorRestart() {
async function waitForCoordinatorRestart(logger: Logger) {
testsWaitingForRestart += 1;
while (testsWaitingForRestart < TOTAL_TESTS_WAITING) {
console.log("Both tests have reached the restart point. Restarting coordinator...");
logger.info("Both tests have reached the restart point. Restarting coordinator...");
await wait(1_000);
if (!coordinatorHasRestarted) {
coordinatorHasRestarted = true;
try {
await execDockerCommand("restart", "coordinator");
console.log("Coordinator restarted.");
logger.info("Coordinator restarted.");
return;
} catch (error) {
console.error("Failed to restart coordinator:", error);
logger.error(`Failed to restart coordinator: ${error}`);
throw error;
}
}
@@ -39,7 +40,7 @@ describe("Coordinator restart test suite", () => {
"When the coordinator restarts it should resume blob submission and finalization",
async () => {
if (process.env.TEST_ENV !== "local") {
console.log("Skipping test because it's not running on a local environment.");
logger.info("Skipping test because it's not running on a local environment.");
return;
}
const lineaRollup = config.getLineaRollupContract();
@@ -58,11 +59,11 @@ describe("Coordinator restart test suite", () => {
expect(lastDataSubmittedEventBeforeRestart.blockNumber).toBeGreaterThan(0n);
expect(lastDataFinalizedEventsBeforeRestart.args.endBlockNumber).toBeGreaterThan(0n);
await waitForCoordinatorRestart();
await waitForCoordinatorRestart(logger);
const currentBlockNumberAfterRestart = await l1Provider.getBlockNumber();
console.log("Waiting for DataSubmittedV3 event after coordinator restart...");
logger.info("Waiting for DataSubmittedV3 event after coordinator restart...");
const [dataSubmittedV3EventAfterRestart] = await waitForEvents(
lineaRollup,
lineaRollup.filters.DataSubmittedV3(),
@@ -71,9 +72,9 @@ describe("Coordinator restart test suite", () => {
"latest",
async (events) => events.filter((event) => event.blockNumber > lastDataSubmittedEventBeforeRestart.blockNumber),
);
console.log(`New DataSubmittedV3 event found: event=${JSON.stringify(dataSubmittedV3EventAfterRestart)}`);
logger.info(`New DataSubmittedV3 event found. event=${JSON.stringify(dataSubmittedV3EventAfterRestart)}`);
console.log("Waiting for DataFinalized event after coordinator restart...");
logger.info("Waiting for DataFinalized event after coordinator restart...");
const [dataFinalizedEventAfterRestart] = await waitForEvents(
lineaRollup,
lineaRollup.filters.DataFinalizedV3(),
@@ -85,7 +86,7 @@ describe("Coordinator restart test suite", () => {
(event) => event.args.endBlockNumber > lastDataFinalizedEventsBeforeRestart.args.endBlockNumber,
),
);
console.log(`New DataFinalized event found: event=${JSON.stringify(dataFinalizedEventAfterRestart)}`);
logger.info(`New DataFinalized event found. event=${JSON.stringify(dataFinalizedEventAfterRestart)}`);
expect(dataFinalizedEventAfterRestart.args.endBlockNumber).toBeGreaterThan(
lastDataFinalizedEventsBeforeRestart.args.endBlockNumber,
@@ -98,7 +99,7 @@ describe("Coordinator restart test suite", () => {
"When the coordinator restarts it should resume anchoring",
async () => {
if (process.env.TEST_ENV !== "local") {
console.log("Skipping test because it's not running on a local environment.");
logger.info("Skipping test because it's not running on a local environment.");
return;
}
@@ -144,7 +145,7 @@ describe("Coordinator restart test suite", () => {
// Wait for L2 Anchoring
const lastNewL1MessageNumber = l1Messages.slice(-1)[0].messageNumber;
console.log(`Waiting L1->L2 anchoring messageNumber=${lastNewL1MessageNumber}`);
logger.info(`Waiting for L1->L2 anchoring. messageNumber=${lastNewL1MessageNumber}`);
await waitForEvents(
l2MessageService,
l2MessageService.filters.RollingHashUpdated(),
@@ -157,7 +158,7 @@ describe("Coordinator restart test suite", () => {
);
// Restart Coordinator
await waitForCoordinatorRestart();
await waitForCoordinatorRestart(logger);
const l1Fees = await l1Provider.getFeeData();
// Send more messages L1 -> L2
@@ -188,8 +189,8 @@ describe("Coordinator restart test suite", () => {
// Wait for messages to be anchored on L2
const lastNewL1MessageNumberAfterRestart = l1MessagesAfterRestart.slice(-1)[0].messageNumber;
console.log(
`Waiting L1->L2 anchoring after coordinator restart messageNumber=${lastNewL1MessageNumberAfterRestart}`,
logger.info(
`Waiting for L1->L2 anchoring after coordinator restart. messageNumber=${lastNewL1MessageNumberAfterRestart}`,
);
const [rollingHashUpdatedEventAfterRestart] = await waitForEvents(
l2MessageService,

View File

@@ -21,7 +21,7 @@ describe("Submission and finalization test suite", () => {
const l1MessageSender = new NonceManager(await l1AccountManager.generateAccount());
const lineaRollup = config.getLineaRollupContract();
console.log("Sending messages on L1");
logger.info("Sending messages on L1");
// Send L1 messages
const l1MessagesPromises = [];
@@ -45,7 +45,7 @@ describe("Submission and finalization test suite", () => {
const l1Receipts = await Promise.all(l1MessagesPromises);
console.log("Messages sent on L1.");
logger.info("Messages sent on L1.");
// Extract message events
const l1Messages = getMessageSentEventFromLogs(lineaRollup, l1Receipts);
@@ -65,7 +65,7 @@ describe("Submission and finalization test suite", () => {
// Wait for the last L1->L2 message to be anchored on L2
const lastNewL1MessageNumber = l1Messages.slice(-1)[0].messageNumber;
console.log("Waiting for the anchoring using rolling hash...");
logger.info("Waiting for the anchoring using rolling hash...");
const [rollingHashUpdatedEvent] = await waitForEvents(
l2MessageService,
l2MessageService.filters.RollingHashUpdated(),
@@ -82,7 +82,7 @@ describe("Submission and finalization test suite", () => {
expect(lastNewMessageRollingHash).toEqual(rollingHashUpdatedEvent.args.rollingHash);
expect(lastAnchoredL1MessageNumber).toEqual(rollingHashUpdatedEvent.args.messageNumber);
console.log("New anchoring using rolling hash done.");
logger.info("New anchoring using rolling hash done.");
},
150_000,
);
@@ -94,10 +94,10 @@ describe("Submission and finalization test suite", () => {
const currentL2BlockNumber = await lineaRollupV6.currentL2BlockNumber();
console.log("Waiting for DataSubmittedV3 used to finalize with proof...");
logger.info("Waiting for DataSubmittedV3 used to finalize with proof...");
await waitForEvents(lineaRollupV6, lineaRollupV6.filters.DataSubmittedV3(), 1_000);
console.log("Waiting for the first DataFinalizedV3 event with proof...");
logger.info("Waiting for the first DataFinalizedV3 event with proof...");
const [dataFinalizedEvent] = await waitForEvents(
lineaRollupV6,
lineaRollupV6.filters.DataFinalizedV3(currentL2BlockNumber + 1n),
@@ -112,7 +112,7 @@ describe("Submission and finalization test suite", () => {
expect(lastBlockFinalized).toBeGreaterThanOrEqual(dataFinalizedEvent.args.endBlockNumber);
expect(newStateRootHash).toEqual(dataFinalizedEvent.args.finalStateRootHash);
console.log("Finalization with proof done.");
logger.info("Finalization with proof done.");
},
150_000,
);
@@ -122,12 +122,12 @@ describe("Submission and finalization test suite", () => {
async () => {
const sequencerEndpoint = config.getSequencerEndpoint();
if (!sequencerEndpoint) {
console.log('Skipped the "Check L2 safe/finalized tag update on sequencer" test');
logger.info('Skipped the "Check L2 safe/finalized tag update on sequencer" test');
return;
}
const lastFinalizedL2BlockNumberOnL1 = 0;
console.log(`lastFinalizedL2BlockNumberOnL1=${lastFinalizedL2BlockNumberOnL1}`);
logger.debug(`lastFinalizedL2BlockNumberOnL1=${lastFinalizedL2BlockNumberOnL1}`);
let safeL2BlockNumber = -1,
finalizedL2BlockNumber = -1;
@@ -142,12 +142,12 @@ describe("Submission and finalization test suite", () => {
await wait(1_000);
}
console.log(`safeL2BlockNumber=${safeL2BlockNumber} finalizedL2BlockNumber=${finalizedL2BlockNumber}`);
logger.debug(`safeL2BlockNumber=${safeL2BlockNumber} finalizedL2BlockNumber=${finalizedL2BlockNumber}`);
expect(safeL2BlockNumber).toBeGreaterThanOrEqual(lastFinalizedL2BlockNumberOnL1);
expect(finalizedL2BlockNumber).toBeGreaterThanOrEqual(lastFinalizedL2BlockNumberOnL1);
console.log("L2 safe/finalized tag update on sequencer done.");
logger.info("L2 safe/finalized tag update on sequencer done.");
},
150_000,
);

View File

@@ -30,11 +30,11 @@ describe("Transaction exclusion test suite", () => {
await l2AccountLocal.sendTransaction(txRequest);
} catch (err) {
// This shall return error with traces limit overflow
console.debug(`sendTransaction expected err: ${JSON.stringify(err)}`);
logger.debug(`sendTransaction expected err: ${JSON.stringify(err)}`);
}
expect(rejectedTxHash).toBeDefined();
console.log(`rejectedTxHash (RPC): ${rejectedTxHash}`);
logger.debug(`Transaction rejected as expected (RPC). transactionHash=${rejectedTxHash}`);
let getResponse;
do {
@@ -60,7 +60,7 @@ describe("Transaction exclusion test suite", () => {
// This shall be rejected by sequencer due to traces module limit overflow
const tx = await testContract!.connect(l2AccountLocal).testAddmod(13000, 31);
const rejectedTxHash = tx.hash;
console.log(`rejectedTxHash (SEQUENCER): ${rejectedTxHash}`);
logger.debug(`Transaction rejected as expected (SEQUENCER). transactionHash=${rejectedTxHash}`);
let getResponse;
do {

View File

@@ -18,5 +18,6 @@
"path": "../sdk"
}
],
"include": ["**/*.ts"],
"exclude": ["node_modules", "dist"],
}

112
pnpm-lock.yaml generated
View File

@@ -46,7 +46,7 @@ importers:
dependencies:
'@consensys/linea-sdk':
specifier: 0.3.0
version: 0.3.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10)
version: 0.3.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(utf-8-validate@5.0.10)
'@headlessui/react':
specifier: 2.1.9
version: 2.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -134,7 +134,7 @@ importers:
version: 8.1.0(typescript@5.4.5)
'@synthetixio/synpress':
specifier: 4.0.0-alpha.7
version: 4.0.0-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.22.4)
version: 4.0.0-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.22.4)
'@types/fs-extra':
specifier: 11.0.4
version: 11.0.4
@@ -158,16 +158,16 @@ importers:
version: 14.2.15(eslint@8.57.0)(typescript@5.4.5)
eslint-plugin-tailwindcss:
specifier: 3.17.4
version: 3.17.4(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)))
version: 3.17.4(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5)))
postcss:
specifier: 8.4.47
version: 8.4.47
tailwind-scrollbar:
specifier: 3.1.0
version: 3.1.0(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)))
version: 3.1.0(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5)))
tailwindcss:
specifier: 3.4.13
version: 3.4.13(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))
version: 3.4.13(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))
contracts:
dependencies:
@@ -263,8 +263,6 @@ importers:
specifier: 17.7.2
version: 17.7.2
contracts/lib/forge-std: {}
e2e:
devDependencies:
'@jest/globals':
@@ -300,6 +298,9 @@ importers:
typechain:
specifier: 8.3.2
version: 8.3.2(typescript@5.4.5)
winston:
specifier: 3.17.0
version: 3.17.0
operations:
dependencies:
@@ -6647,10 +6648,6 @@ packages:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
logform@2.6.1:
resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==}
engines: {node: '>= 12.0.0'}
logform@2.7.0:
resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==}
engines: {node: '>= 12.0.0'}
@@ -9475,18 +9472,10 @@ packages:
resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==}
engines: {node: '>=8'}
winston-transport@4.8.0:
resolution: {integrity: sha512-qxSTKswC6llEMZKgCQdaWgDuMJQnhuvF5f2Nk3SNXc4byfQ+voo2mX1Px9dkNOuR8p0KAjfPG29PuYUSIb+vSA==}
engines: {node: '>= 12.0.0'}
winston-transport@4.9.0:
resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==}
engines: {node: '>= 12.0.0'}
winston@3.13.0:
resolution: {integrity: sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==}
engines: {node: '>= 12.0.0'}
winston@3.17.0:
resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==}
engines: {node: '>= 12.0.0'}
@@ -10728,7 +10717,7 @@ snapshots:
'@colors/colors@1.6.0': {}
'@consensys/linea-sdk@0.3.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10)':
'@consensys/linea-sdk@0.3.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(utf-8-validate@5.0.10)':
dependencies:
better-sqlite3: 9.6.0
class-validator: 0.14.1
@@ -10736,9 +10725,9 @@ snapshots:
ethers: 6.13.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)
lru-cache: 10.2.2
pg: 8.11.3
typeorm: 0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))
typeorm-naming-strategies: 4.1.0(typeorm@0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)))
winston: 3.13.0
typeorm: 0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))
typeorm-naming-strategies: 4.1.0(typeorm@0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5)))
winston: 3.17.0
transitivePeerDependencies:
- '@google-cloud/spanner'
- '@sap/hana-client'
@@ -13040,7 +13029,7 @@ snapshots:
- utf-8-validate
- zod
'@synthetixio/synpress-cache@0.0.1-alpha.7(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5)':
'@synthetixio/synpress-cache@0.0.1-alpha.7(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5)':
dependencies:
axios: 1.6.7
chalk: 5.3.0
@@ -13051,7 +13040,7 @@ snapshots:
gradient-string: 2.0.2
playwright-core: 1.45.3
progress: 2.0.3
tsup: 8.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5)
tsup: 8.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5)
unzipper: 0.10.14
zod: 3.22.4
transitivePeerDependencies:
@@ -13067,10 +13056,10 @@ snapshots:
dependencies:
'@playwright/test': 1.45.3
'@synthetixio/synpress-metamask@0.0.1-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)':
'@synthetixio/synpress-metamask@0.0.1-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)':
dependencies:
'@playwright/test': 1.45.3
'@synthetixio/synpress-cache': 0.0.1-alpha.7(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5)
'@synthetixio/synpress-cache': 0.0.1-alpha.7(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5)
'@synthetixio/synpress-core': 0.0.1-alpha.7(@playwright/test@1.45.3)
'@viem/anvil': 0.0.7(bufferutil@4.0.8)(utf-8-validate@5.0.10)
fs-extra: 11.2.0
@@ -13087,13 +13076,13 @@ snapshots:
- typescript
- utf-8-validate
'@synthetixio/synpress@4.0.0-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.22.4)':
'@synthetixio/synpress@4.0.0-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.22.4)':
dependencies:
'@playwright/test': 1.45.3
'@synthetixio/ethereum-wallet-mock': 0.0.1-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.22.4)
'@synthetixio/synpress-cache': 0.0.1-alpha.7(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5)
'@synthetixio/synpress-cache': 0.0.1-alpha.7(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5)
'@synthetixio/synpress-core': 0.0.1-alpha.7(@playwright/test@1.45.3)
'@synthetixio/synpress-metamask': 0.0.1-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)
'@synthetixio/synpress-metamask': 0.0.1-alpha.7(@playwright/test@1.45.3)(bufferutil@4.0.8)(playwright-core@1.45.3)(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)
transitivePeerDependencies:
- '@microsoft/api-extractor'
- '@swc/core'
@@ -15973,7 +15962,7 @@ snapshots:
debug: 4.3.7(supports-color@8.1.1)
enhanced-resolve: 5.17.1
eslint: 8.57.0
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0)
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
fast-glob: 3.3.2
get-tsconfig: 4.8.1
is-bun-module: 1.2.1
@@ -15986,7 +15975,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
eslint-module-utils@2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0):
eslint-module-utils@2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0):
dependencies:
debug: 3.2.7
optionalDependencies:
@@ -16008,7 +15997,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0)
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -16081,11 +16070,11 @@ snapshots:
string.prototype.matchall: 4.0.11
string.prototype.repeat: 1.0.0
eslint-plugin-tailwindcss@3.17.4(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))):
eslint-plugin-tailwindcss@3.17.4(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))):
dependencies:
fast-glob: 3.3.2
postcss: 8.4.47
tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))
tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))
eslint-scope@7.2.2:
dependencies:
@@ -18336,15 +18325,6 @@ snapshots:
chalk: 4.1.2
is-unicode-supported: 0.1.0
logform@2.6.1:
dependencies:
'@colors/colors': 1.6.0
'@types/triple-beam': 1.3.5
fecha: 4.2.3
ms: 2.1.3
safe-stable-stringify: 2.5.0
triple-beam: 1.4.1
logform@2.7.0:
dependencies:
'@colors/colors': 1.6.0
@@ -19407,13 +19387,13 @@ snapshots:
camelcase-css: 2.0.1
postcss: 8.4.47
postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)):
postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5)):
dependencies:
lilconfig: 3.1.2
yaml: 2.5.1
optionalDependencies:
postcss: 8.4.47
ts-node: 10.9.2(@types/node@20.12.7)(typescript@5.4.5)
ts-node: 10.9.2(@types/node@22.7.5)(typescript@5.4.5)
postcss-nested@6.2.0(postcss@8.4.47):
dependencies:
@@ -20662,11 +20642,11 @@ snapshots:
tailwind-merge@2.5.3: {}
tailwind-scrollbar@3.1.0(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))):
tailwind-scrollbar@3.1.0(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))):
dependencies:
tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))
tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))
tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)):
tailwindcss@3.4.13(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5)):
dependencies:
'@alloc/quick-lru': 5.2.0
arg: 5.0.2
@@ -20685,7 +20665,7 @@ snapshots:
postcss: 8.4.47
postcss-import: 15.1.0(postcss@8.4.47)
postcss-js: 4.0.1(postcss@8.4.47)
postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))
postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))
postcss-nested: 6.2.0(postcss@8.4.47)
postcss-selector-parser: 6.1.2
resolve: 1.22.8
@@ -20937,7 +20917,7 @@ snapshots:
tsort@0.0.1: {}
tsup@8.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5):
tsup@8.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))(typescript@5.4.5):
dependencies:
bundle-require: 4.2.1(esbuild@0.19.12)
cac: 6.7.14
@@ -20947,7 +20927,7 @@ snapshots:
execa: 5.1.1
globby: 11.1.0
joycon: 3.1.1
postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))
postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))
resolve-from: 5.0.0
rollup: 4.24.0
source-map: 0.8.0-beta.0
@@ -21055,9 +21035,9 @@ snapshots:
dependencies:
typeorm: 0.3.20(better-sqlite3@11.6.0)(pg@8.13.1)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))
typeorm-naming-strategies@4.1.0(typeorm@0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))):
typeorm-naming-strategies@4.1.0(typeorm@0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))):
dependencies:
typeorm: 0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))
typeorm: 0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5))
typeorm@0.3.20(better-sqlite3@11.6.0)(pg@8.13.1)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5)):
dependencies:
@@ -21083,7 +21063,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
typeorm@0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)):
typeorm@0.3.20(better-sqlite3@9.6.0)(pg@8.11.3)(ts-node@10.9.2(@types/node@22.7.5)(typescript@5.4.5)):
dependencies:
'@sqltools/formatter': 1.2.5
app-root-path: 3.1.0
@@ -21103,7 +21083,7 @@ snapshots:
optionalDependencies:
better-sqlite3: 9.6.0
pg: 8.11.3
ts-node: 10.9.2(@types/node@20.12.7)(typescript@5.4.5)
ts-node: 10.9.2(@types/node@22.7.5)(typescript@5.4.5)
transitivePeerDependencies:
- supports-color
@@ -21675,32 +21655,12 @@ snapshots:
dependencies:
string-width: 4.2.3
winston-transport@4.8.0:
dependencies:
logform: 2.6.1
readable-stream: 4.5.2
triple-beam: 1.4.1
winston-transport@4.9.0:
dependencies:
logform: 2.7.0
readable-stream: 3.6.2
triple-beam: 1.4.1
winston@3.13.0:
dependencies:
'@colors/colors': 1.6.0
'@dabh/diagnostics': 2.0.3
async: 3.2.6
is-stream: 2.0.1
logform: 2.6.1
one-time: 1.0.0
readable-stream: 3.6.2
safe-stable-stringify: 2.5.0
stack-trace: 0.0.10
triple-beam: 1.4.1
winston-transport: 4.8.0
winston@3.17.0:
dependencies:
'@colors/colors': 1.6.0