mirror of
https://github.com/vacp2p/linea-monorepo.git
synced 2026-01-06 22:23:55 -05:00
Feat/272 split sdk and postman (#381)
* feat: split postman and sdk * fix: update postman client and sendMessage script * fix: clean the sdk * fix: update sdk dependencies * fix: remove .env.sample file * fix: remove testing helpers from the build * fix: update gas provider in linea sdk and update postman client * fix: update postman dependencies * fix: update postman dockerfile and fix tests imports and types * fix: remove unused code in the sdk + move typechain folder * fix: remove unused code + fix imports in postman * fix: pnpm lock file issue * fix: import issue * fix: case sensitive file issue * fix: update sdk fees options and update exports * fix: remove postman unused code and adjust imports and tests * fix: update contracts abis + clean error parsing * fix: update postman based on new SDk changes * add readme + remove unused interface in postman * fix: rename Base.ts file to BaseError.ts * fix: rename Base.ts file to BaseError.ts in postman * chore: update readme for the postman * fix: rename maxFeePerGas to maxFeePerGasCap * fix: update DefaultGasProvider fees check * fix: default gas provider test issue * fix: update main ci filter * fix: issue in default gas provider
This commit is contained in:
5
.dockerignore
Normal file
5
.dockerignore
Normal file
@@ -0,0 +1,5 @@
|
||||
**/node_modules
|
||||
**/typechain
|
||||
**/tsconfig.build.tsbuildinfo
|
||||
**/coverage
|
||||
**/dist
|
||||
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@@ -52,7 +52,9 @@ jobs:
|
||||
- 'docker/compose-local-dev.overrides.yml'
|
||||
- 'docker/compose-local-dev-traces-v2.overrides.yml'
|
||||
postman:
|
||||
- 'postman/**'
|
||||
- 'sdk/**'
|
||||
- 'ts-libs/linea-native-libs/**'
|
||||
- '.github/workflows/postman-*.yml'
|
||||
- '.github/workflows/build-and-publish.yml'
|
||||
- '.github/workflows/main.yml'
|
||||
@@ -193,7 +195,7 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
run-e2e-tests-geth-tracing:
|
||||
needs: [ store-image-name-and-tags, docker-build, manual-docker-build-and-e2e-tests ]
|
||||
needs: [ store-image-name-and-tags, docker-build, manual-docker-build-and-e2e-tests, filter-commit-changes ]
|
||||
# Make this execute for has-changes-requiring-build == 'false' so that we can get to the required job @ which is in reuse-run-e2e-tests.yml
|
||||
if: ${{ always() && needs.filter-commit-changes.outputs.has-changes-requiring-build == 'false' || needs.docker-build.result == 'success' }}
|
||||
concurrency:
|
||||
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
if: ${{ env.PUSH_IMAGE == 'false' }}
|
||||
with:
|
||||
context: ./
|
||||
file: ./sdk/Dockerfile
|
||||
file: ./postman/Dockerfile
|
||||
platforms: linux/amd64
|
||||
load: true
|
||||
push: false
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
if: ${{ env.PUSH_IMAGE == 'true' || github.event_name == 'workflow_dispatch' }}
|
||||
with:
|
||||
context: ./
|
||||
file: ./sdk/Dockerfile
|
||||
file: ./postman/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ env.TAGS }}
|
||||
|
||||
1
.github/workflows/postman-testing.yml
vendored
1
.github/workflows/postman-testing.yml
vendored
@@ -24,4 +24,5 @@ jobs:
|
||||
run: |
|
||||
pnpm run -F ./ts-libs/linea-native-libs build;
|
||||
pnpm run -F ./sdk build;
|
||||
pnpm run -F ./postman test;
|
||||
pnpm run -F ./sdk test;
|
||||
|
||||
632
pnpm-lock.yaml
generated
632
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@ packages:
|
||||
- 'contracts/**'
|
||||
- 'e2e/**'
|
||||
- 'sdk/**'
|
||||
- 'postman/**'
|
||||
- 'operations/**'
|
||||
- 'bridge-ui/**'
|
||||
- 'ts-libs/**'
|
||||
|
||||
44
postman/.env.sample
Normal file
44
postman/.env.sample
Normal file
@@ -0,0 +1,44 @@
|
||||
L1_RPC_URL=http://localhost:8445
|
||||
L1_CONTRACT_ADDRESS=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
|
||||
# Only use the following PRIVATE KEY for testing
|
||||
L1_SIGNER_PRIVATE_KEY=0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba
|
||||
L1_LISTENER_INTERVAL=2000
|
||||
# L1_LISTENER_INITIAL_FROM_BLOCK=0
|
||||
L1_LISTENER_BLOCK_CONFIRMATION=1
|
||||
L1_MAX_BLOCKS_TO_FETCH_LOGS=1000
|
||||
L1_MAX_GAS_FEE_ENFORCED=false
|
||||
L2_RPC_URL=http://localhost:8845
|
||||
L2_CONTRACT_ADDRESS=0xe537D669CA013d86EBeF1D64e40fC74CADC91987
|
||||
# Only use the following PRIVATE KEY for testing
|
||||
L2_SIGNER_PRIVATE_KEY=0xfcf854e0a0bc6fd7e97d7050e61a362c915cecd6767a32267b22e8b7af572e58
|
||||
L2_LISTENER_INTERVAL=2000
|
||||
# L2_LISTENER_INITIAL_FROM_BLOCK=0
|
||||
L2_LISTENER_BLOCK_CONFIRMATION=0
|
||||
L2_MAX_BLOCKS_TO_FETCH_LOGS=1000
|
||||
L2_MESSAGE_TREE_DEPTH=5
|
||||
L2_MAX_GAS_FEE_ENFORCED=false
|
||||
MESSAGE_SUBMISSION_TIMEOUT=300000
|
||||
MAX_FETCH_MESSAGES_FROM_DB=1000
|
||||
MAX_NONCE_DIFF=10000
|
||||
MAX_FEE_PER_GAS_CAP=100000000000
|
||||
GAS_ESTIMATION_PERCENTILE=50
|
||||
PROFIT_MARGIN=0.0
|
||||
MAX_NUMBER_OF_RETRIES=100
|
||||
RETRY_DELAY_IN_SECONDS=30
|
||||
MAX_CLAIM_GAS_LIMIT=2560000
|
||||
MAX_TX_RETRIES=20
|
||||
L1_L2_EOA_ENABLED=true
|
||||
L1_L2_CALLDATA_ENABLED=true
|
||||
L1_L2_AUTO_CLAIM_ENABLED=true
|
||||
L2_L1_EOA_ENABLED=true
|
||||
L2_L1_CALLDATA_ENABLED=true
|
||||
L2_L1_AUTO_CLAIM_ENABLED=true
|
||||
POSTGRES_HOST=127.0.0.1
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=postgres
|
||||
POSTGRES_DB=postman_db
|
||||
DB_CLEANER_ENABLED=false
|
||||
DB_CLEANING_INTERVAL=10000
|
||||
DB_DAYS_BEFORE_NOW_TO_DELETE=1
|
||||
ENABLE_LINEA_ESTIMATE_GAS=false
|
||||
3
postman/.eslintignore
Normal file
3
postman/.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
||||
dist
|
||||
node_modules
|
||||
typechain
|
||||
15
postman/.eslintrc.js
Normal file
15
postman/.eslintrc.js
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
extends: "../.eslintrc.js",
|
||||
env: {
|
||||
commonjs: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
jest: true,
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: "module",
|
||||
},
|
||||
rules: {
|
||||
"prettier/prettier": "error",
|
||||
},
|
||||
};
|
||||
3
postman/.prettierignore
Normal file
3
postman/.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
||||
dist
|
||||
node_modules
|
||||
typechain
|
||||
3
postman/.prettierrc.js
Normal file
3
postman/.prettierrc.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
...require('../.prettierrc.js'),
|
||||
};
|
||||
@@ -18,16 +18,19 @@ ARG NATIVE_LIBS_RELEASE_TAG
|
||||
ENV NATIVE_LIBS_RELEASE_TAG=${NATIVE_LIBS_RELEASE_TAG}
|
||||
|
||||
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml tsconfig.json ./
|
||||
|
||||
COPY ./postman/package.json ./postman/package.json
|
||||
COPY ./sdk/package.json ./sdk/package.json
|
||||
COPY ./ts-libs/linea-native-libs/package.json ./ts-libs/linea-native-libs/package.json
|
||||
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
|
||||
|
||||
COPY ./postman ./postman
|
||||
COPY ./sdk ./sdk
|
||||
COPY ts-libs/linea-native-libs ./ts-libs/linea-native-libs
|
||||
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm run build \
|
||||
&& pnpm deploy --filter=./sdk --prod ./prod/sdk
|
||||
&& pnpm deploy --filter=./postman --prod ./prod/postman
|
||||
|
||||
FROM node:lts-slim AS production
|
||||
|
||||
@@ -37,6 +40,6 @@ WORKDIR /usr/src/app
|
||||
|
||||
USER node
|
||||
|
||||
COPY --from=builder /usr/src/app/prod/sdk ./sdk
|
||||
COPY --from=builder /usr/src/app/prod/postman ./postman
|
||||
|
||||
CMD [ "node", "./sdk/dist/scripts/runPostman.js" ]
|
||||
CMD [ "node", "./postman/dist/scripts/runPostman.js" ]
|
||||
13
postman/LICENSE
Normal file
13
postman/LICENSE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2023 Consensys Software Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
115
postman/README.md
Normal file
115
postman/README.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Linea Postman Service
|
||||
|
||||
The Linea Postman service is a component of the Linea blockchain infrastructure that facilitates cross-chain message delivery between Layer 1 (Ethereum) and Layer 2 (Linea).
|
||||
|
||||
## Overview
|
||||
|
||||
The Postman service monitors and processes messages between L1 and L2 chains, handling message submission, verification, and claiming. It operates as a Docker container and integrates with both L1 and L2 nodes.
|
||||
|
||||
It offers the following key features:
|
||||
|
||||
- Feature 1: Listening for message sent events on Ethereum and Linea
|
||||
- Feature 2: Listening for message hash anchoring events to check if a message is ready to be claimed
|
||||
- Feature 3: Automatic claiming of messages with a configurable retry mechanism
|
||||
- Feature 4: Checking receipt status for each transaction
|
||||
|
||||
All messages are stored in a configurable Postgres DB.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
#### L1 Configuration
|
||||
- `L1_RPC_URL`: Ethereum node RPC endpoint
|
||||
- `L1_CONTRACT_ADDRESS`: Address of the LineaRollup contract on L1
|
||||
- `L1_SIGNER_PRIVATE_KEY`: Private key for L1 transactions
|
||||
- `L1_LISTENER_INTERVAL`: Block listening interval (ms)
|
||||
- `L1_LISTENER_INITIAL_FROM_BLOCK`: Starting block for event listening (optional)
|
||||
- `L1_LISTENER_BLOCK_CONFIRMATION`: Required block confirmations
|
||||
- `L1_MAX_BLOCKS_TO_FETCH_LOGS`: Maximum blocks to fetch in one request
|
||||
- `L1_MAX_GAS_FEE_ENFORCED`: Enable/disable gas fee enforcement
|
||||
|
||||
#### L2 Configuration
|
||||
- `L2_RPC_URL`: Linea node RPC endpoint
|
||||
- `L2_CONTRACT_ADDRESS`: Address of the L2MessageService contract on L2
|
||||
- `L2_SIGNER_PRIVATE_KEY`: Private key for L2 transactions
|
||||
- `L2_LISTENER_INTERVAL`: Block listening interval (ms)
|
||||
- `L2_LISTENER_INITIAL_FROM_BLOCK`: Starting block for event listening (optional)
|
||||
- `L2_LISTENER_BLOCK_CONFIRMATION`: Required block confirmations
|
||||
- `L2_MAX_BLOCKS_TO_FETCH_LOGS`: Maximum blocks to fetch in one request
|
||||
- `L2_MAX_GAS_FEE_ENFORCED`: Enable/disable gas fee enforcement
|
||||
- `L2_MESSAGE_TREE_DEPTH`: Depth of the message Merkle tree
|
||||
|
||||
#### Message Processing
|
||||
- `MESSAGE_SUBMISSION_TIMEOUT`: Timeout for message submission (ms)
|
||||
- `MAX_FETCH_MESSAGES_FROM_DB`: Maximum messages to fetch from database
|
||||
- `MAX_NONCE_DIFF`: Maximum allowed nonce difference between the DB and the chain
|
||||
- `MAX_FEE_PER_GAS_CAP`: Maximum gas fee cap
|
||||
- `GAS_ESTIMATION_PERCENTILE`: Gas estimation percentile
|
||||
- `PROFIT_MARGIN`: Profit margin for gas fees
|
||||
- `MAX_NUMBER_OF_RETRIES`: Maximum retry attempts
|
||||
- `RETRY_DELAY_IN_SECONDS`: Delay between retries
|
||||
- `MAX_CLAIM_GAS_LIMIT`: Maximum gas limit for claim transactions
|
||||
|
||||
#### Feature Flags
|
||||
- `L1_L2_EOA_ENABLED`: Enable L1->L2 EOA messages
|
||||
- `L1_L2_CALLDATA_ENABLED`: Enable L1->L2 calldata messages
|
||||
- `L1_L2_AUTO_CLAIM_ENABLED`: Enable auto-claiming for L1->L2 messages
|
||||
- `L2_L1_EOA_ENABLED`: Enable L2->L1 EOA messages
|
||||
- `L2_L1_CALLDATA_ENABLED`: Enable L2->L1 calldata messages
|
||||
- `L2_L1_AUTO_CLAIM_ENABLED`: Enable auto-claiming for L2->L1 messages
|
||||
- `ENABLE_LINEA_ESTIMATE_GAS`: Enable `linea_estimateGas`endpoint usage for L2 chain gas fees estimation
|
||||
- `DB_CLEANER_ENABLED`: Enable DB cleaning to delete old claimed messages
|
||||
|
||||
#### DB cleaning
|
||||
- `DB_CLEANING_INTERVAL`: DB cleaning polling interval (ms)
|
||||
- `DB_DAYS_BEFORE_NOW_TO_DELETE`: Number of days to retain messages in the database before deletion. Messages older than this number of days will be automatically cleaned up if they are in a final state (CLAIMED_SUCCESS, CLAIMED_REVERTED, EXCLUDED, or ZERO_FEE)
|
||||
|
||||
#### Database Configuration
|
||||
- `POSTGRES_HOST`: PostgreSQL host
|
||||
- `POSTGRES_PORT`: PostgreSQL port
|
||||
- `POSTGRES_USER`: Database user
|
||||
- `POSTGRES_PASSWORD`: Database password
|
||||
- `POSTGRES_DB`: Database name
|
||||
|
||||
## Development
|
||||
|
||||
### Running
|
||||
|
||||
#### Start the docker local stack
|
||||
|
||||
From the root folder, run the following command:
|
||||
```bash
|
||||
make fresh-start-all
|
||||
```
|
||||
|
||||
Stop the postman docker container manually.
|
||||
|
||||
#### Run the postman locally:
|
||||
|
||||
From the postman folder run the following commands:
|
||||
|
||||
```bash
|
||||
# Create a new .env file
|
||||
cp .env.sample .env
|
||||
|
||||
# Run the postman
|
||||
ts-node scripts/runPostman.ts
|
||||
```
|
||||
|
||||
### Building
|
||||
```bash
|
||||
# Build the Postman service
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run unit tests
|
||||
pnpm run test
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This package is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for more information.
|
||||
25
postman/jest.config.js
Normal file
25
postman/jest.config.js
Normal file
@@ -0,0 +1,25 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
rootDir: ".",
|
||||
testRegex: "test.ts$",
|
||||
verbose: true,
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ["src/**/*.ts"],
|
||||
coverageReporters: ["html", "lcov", "text"],
|
||||
testPathIgnorePatterns: [
|
||||
"src/clients/blockchain/typechain",
|
||||
"src/application/postman/persistence/migrations/",
|
||||
"src/application/postman/persistence/repositories/",
|
||||
"src/index.ts",
|
||||
"src/utils/WinstonLogger.ts",
|
||||
],
|
||||
coveragePathIgnorePatterns: [
|
||||
"src/clients/blockchain/typechain",
|
||||
"src/application/postman/persistence/migrations/",
|
||||
"src/application/postman/persistence/repositories/",
|
||||
"src/index.ts",
|
||||
"src/utils/WinstonLogger.ts",
|
||||
"src/utils/testing/",
|
||||
],
|
||||
};
|
||||
44
postman/package.json
Normal file
44
postman/package.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@consensys/linea-postman",
|
||||
"version": "1.0.0",
|
||||
"author": "Consensys Software Inc.",
|
||||
"license": "Apache-2.0",
|
||||
"description": "",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
"scripts": {
|
||||
"lint:ts": "npx eslint '**/*.ts'",
|
||||
"lint:ts:fix": "npx eslint --fix '**/*.ts'",
|
||||
"prettier": "prettier -c '**/*.ts'",
|
||||
"prettier:fix": "prettier -w '**/*.ts'",
|
||||
"clean": "rimraf dist node_modules coverage tsconfig.build.tsbuildinfo",
|
||||
"build": "tsc -p tsconfig.build.json",
|
||||
"build:runSdk": "tsc ./scripts/runSdk.ts",
|
||||
"test": "npx jest --bail --detectOpenHandles --forceExit",
|
||||
"lint:fix": "pnpm run lint:ts:fix && pnpm run prettier:fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@consensys/linea-native-libs": "workspace:*",
|
||||
"@consensys/linea-sdk": "workspace:*",
|
||||
"better-sqlite3": "11.6.0",
|
||||
"class-validator": "0.14.1",
|
||||
"dotenv": "16.4.5",
|
||||
"ethers": "6.13.4",
|
||||
"pg": "8.13.1",
|
||||
"typeorm": "0.3.20",
|
||||
"typeorm-naming-strategies": "4.1.0",
|
||||
"winston": "3.17.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/globals": "29.7.0",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/yargs": "17.0.33",
|
||||
"jest": "29.7.0",
|
||||
"jest-mock-extended": "3.0.5",
|
||||
"ts-jest": "29.2.5",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
]
|
||||
}
|
||||
@@ -32,7 +32,7 @@ async function main() {
|
||||
? parseInt(process.env.MESSAGE_SUBMISSION_TIMEOUT)
|
||||
: undefined,
|
||||
maxNonceDiff: process.env.MAX_NONCE_DIFF ? parseInt(process.env.MAX_NONCE_DIFF) : undefined,
|
||||
maxFeePerGas: process.env.MAX_FEE_PER_GAS ? BigInt(process.env.MAX_FEE_PER_GAS) : undefined,
|
||||
maxFeePerGasCap: process.env.MAX_FEE_PER_GAS_CAP ? BigInt(process.env.MAX_FEE_PER_GAS_CAP) : undefined,
|
||||
gasEstimationPercentile: process.env.GAS_ESTIMATION_PERCENTILE
|
||||
? parseInt(process.env.GAS_ESTIMATION_PERCENTILE)
|
||||
: undefined,
|
||||
@@ -72,7 +72,7 @@ async function main() {
|
||||
? parseInt(process.env.MESSAGE_SUBMISSION_TIMEOUT)
|
||||
: undefined,
|
||||
maxNonceDiff: process.env.MAX_NONCE_DIFF ? parseInt(process.env.MAX_NONCE_DIFF) : undefined,
|
||||
maxFeePerGas: process.env.MAX_FEE_PER_GAS ? BigInt(process.env.MAX_FEE_PER_GAS) : undefined,
|
||||
maxFeePerGasCap: process.env.MAX_FEE_PER_GAS_CAP ? BigInt(process.env.MAX_FEE_PER_GAS_CAP) : undefined,
|
||||
gasEstimationPercentile: process.env.GAS_ESTIMATION_PERCENTILE
|
||||
? parseInt(process.env.GAS_ESTIMATION_PERCENTILE)
|
||||
: undefined,
|
||||
@@ -1,17 +1,10 @@
|
||||
import { BytesLike, ContractTransactionReceipt, Overrides, Wallet, JsonRpcProvider } from "ethers";
|
||||
import { config } from "dotenv";
|
||||
import { L2MessageService, L2MessageService__factory, LineaRollup, LineaRollup__factory } from "@consensys/linea-sdk";
|
||||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import { SendMessageArgs } from "./types";
|
||||
import { sanitizeAddress, sanitizePrivKey } from "./cli";
|
||||
import {
|
||||
L2MessageService,
|
||||
L2MessageService__factory,
|
||||
ZkEvmV2__factory,
|
||||
ZkEvmV2,
|
||||
LineaRollup,
|
||||
LineaRollup__factory,
|
||||
} from "../src/clients/blockchain/typechain";
|
||||
import { encodeSendMessage } from "./helpers";
|
||||
|
||||
config();
|
||||
@@ -86,7 +79,7 @@ const argv = yargs(hideBin(process.argv))
|
||||
.parseSync();
|
||||
|
||||
const sendMessage = async (
|
||||
contract: ZkEvmV2,
|
||||
contract: LineaRollup,
|
||||
args: SendMessageArgs,
|
||||
overrides: Overrides = {},
|
||||
): Promise<ContractTransactionReceipt | null> => {
|
||||
@@ -95,7 +88,7 @@ const sendMessage = async (
|
||||
};
|
||||
|
||||
const sendMessages = async (
|
||||
contract: ZkEvmV2,
|
||||
contract: LineaRollup,
|
||||
signer: Wallet,
|
||||
numberOfMessages: number,
|
||||
args: SendMessageArgs,
|
||||
@@ -118,7 +111,7 @@ const sendMessages = async (
|
||||
};
|
||||
|
||||
const getMessageCounter = async (contractAddress: string, signer: Wallet) => {
|
||||
const lineaRollup = ZkEvmV2__factory.connect(contractAddress, signer) as ZkEvmV2;
|
||||
const lineaRollup = LineaRollup__factory.connect(contractAddress, signer) as LineaRollup;
|
||||
return lineaRollup.nextMessageNumber();
|
||||
};
|
||||
|
||||
@@ -158,11 +151,15 @@ const main = async (args: typeof argv) => {
|
||||
calldata: args.calldata,
|
||||
};
|
||||
|
||||
const zkEvmV2 = ZkEvmV2__factory.connect(args.l1ContractAddress, l1Signer) as ZkEvmV2;
|
||||
const lineaRollup = LineaRollup__factory.connect(args.l1ContractAddress, l1Signer) as LineaRollup;
|
||||
|
||||
await sendMessages(zkEvmV2, l1Signer, args.numberOfMessage, functionArgs, { value: BigInt(args.value.toString()) });
|
||||
await sendMessages(lineaRollup, l1Signer, args.numberOfMessage, functionArgs, {
|
||||
value: BigInt(args.value.toString()),
|
||||
});
|
||||
|
||||
// Anchor messages hash on L2
|
||||
if (!args.autoAnchoring) return;
|
||||
|
||||
const nextMessageCounter = await getMessageCounter(args.l1ContractAddress, l1Signer);
|
||||
const startCounter = nextMessageCounter - BigInt(args.numberOfMessage);
|
||||
|
||||
@@ -180,10 +177,7 @@ const main = async (args: typeof argv) => {
|
||||
messageHashesToAnchor.push(messageHash);
|
||||
}
|
||||
|
||||
if (!args.autoAnchoring) return;
|
||||
|
||||
const l2Signer = new Wallet(args.l2PrivKey!, l2Provider);
|
||||
const lineaRollup = LineaRollup__factory.connect(args.l1ContractAddress, l1Signer) as LineaRollup;
|
||||
const l2MessageService = L2MessageService__factory.connect(args.l2ContractAddress, l2Signer) as L2MessageService;
|
||||
const startingMessageNumber = startCounter;
|
||||
await anchorMessageHashesOnL2(lineaRollup, l2MessageService, messageHashesToAnchor, startingMessageNumber);
|
||||
@@ -2,9 +2,9 @@ import { ContractTransactionReceipt, Overrides, JsonRpcProvider, Wallet } from "
|
||||
import { config } from "dotenv";
|
||||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import { L2MessageService, L2MessageService__factory } from "@consensys/linea-sdk";
|
||||
import { SendMessageArgs } from "./types";
|
||||
import { sanitizeAddress, sanitizePrivKey } from "./cli";
|
||||
import { L2MessageService, L2MessageService__factory } from "../src/clients/blockchain/typechain";
|
||||
|
||||
config();
|
||||
|
||||
@@ -1,38 +1,28 @@
|
||||
import { Wallet, JsonRpcProvider } from "ethers";
|
||||
import { DataSource } from "typeorm";
|
||||
import { LineaSDK, Direction } from "@consensys/linea-sdk";
|
||||
import { ILogger } from "../../../core/utils/logging/ILogger";
|
||||
import { DatabaseCleaner } from "../../../services/persistence/DatabaseCleaner";
|
||||
import { TypeOrmMessageRepository } from "../persistence/repositories/TypeOrmMessageRepository";
|
||||
import { LineaRollupClient } from "../../../clients/blockchain/ethereum/LineaRollupClient";
|
||||
import { L2MessageServiceClient } from "../../../clients/blockchain/linea/L2MessageServiceClient";
|
||||
import { EthersLineaRollupLogClient } from "../../../clients/blockchain/ethereum/EthersLineaRollupLogClient";
|
||||
import { ChainQuerier } from "../../../clients/blockchain/ChainQuerier";
|
||||
import { WinstonLogger } from "../../../utils/WinstonLogger";
|
||||
import { EthersL2MessageServiceLogClient } from "../../../clients/blockchain/linea/EthersL2MessageServiceLogClient";
|
||||
import { MessageSentEventPoller } from "../../../services/pollers/MessageSentEventPoller";
|
||||
import { IPoller } from "../../../core/services/pollers/IPoller";
|
||||
import { MessageAnchoringPoller } from "../../../services/pollers/MessageAnchoringPoller";
|
||||
import { MessageAnchoringProcessor } from "../../../services/processors/MessageAnchoringProcessor";
|
||||
import {
|
||||
MessageAnchoringProcessor,
|
||||
MessageClaimingProcessor,
|
||||
MessageClaimingPersister,
|
||||
MessageSentEventProcessor,
|
||||
L2ClaimMessageTransactionSizeProcessor,
|
||||
} from "../../../services/processors";
|
||||
import { PostmanOptions } from "./config/config";
|
||||
import { DB } from "../persistence/dataSource";
|
||||
import { Direction } from "../../../core/enums/MessageEnums";
|
||||
import { MessageClaimingProcessor } from "../../../services/processors/MessageClaimingProcessor";
|
||||
import { MessageClaimingPoller } from "../../../services/pollers/MessageClaimingPoller";
|
||||
import { MessageClaimingPersister } from "../../../services/processors/MessageClaimingPersister";
|
||||
import { MessagePersistingPoller } from "../../../services/pollers/MessagePersistingPoller";
|
||||
import { MessageSentEventProcessor } from "../../../services/processors/MessageSentEventProcessor";
|
||||
import { DatabaseCleaningPoller } from "../../../services/pollers/DatabaseCleaningPoller";
|
||||
import { BaseError } from "../../../core/errors/Base";
|
||||
import { LineaRollupMessageRetriever } from "../../../clients/blockchain/ethereum/LineaRollupMessageRetriever";
|
||||
import { L2MessageServiceMessageRetriever } from "../../../clients/blockchain/linea/L2MessageServiceMessageRetriever";
|
||||
import { MerkleTreeService } from "../../../clients/blockchain/ethereum/MerkleTreeService";
|
||||
import { LineaMessageDBService } from "../../../services/persistence/LineaMessageDBService";
|
||||
import { L2ChainQuerier } from "../../../clients/blockchain/linea/L2ChainQuerier";
|
||||
import { EthereumMessageDBService } from "../../../services/persistence/EthereumMessageDBService";
|
||||
import { L2ClaimMessageTransactionSizePoller } from "../../../services/pollers/L2ClaimMessageTransactionSizePoller";
|
||||
import { L2ClaimMessageTransactionSizeProcessor } from "../../../services/processors/L2ClaimMessageTransactionSizeProcessor";
|
||||
import {
|
||||
MessageSentEventPoller,
|
||||
MessageAnchoringPoller,
|
||||
MessageClaimingPoller,
|
||||
MessagePersistingPoller,
|
||||
DatabaseCleaningPoller,
|
||||
L2ClaimMessageTransactionSizePoller,
|
||||
} from "../../../services/pollers";
|
||||
import { DatabaseCleaner, LineaMessageDBService, EthereumMessageDBService } from "../../../services/persistence";
|
||||
import { L2ClaimTransactionSizeCalculator } from "../../../services/L2ClaimTransactionSizeCalculator";
|
||||
import { GasProvider } from "../../../clients/blockchain/gas/GasProvider";
|
||||
import { LineaTransactionValidationService } from "../../../services/LineaTransactionValidationService";
|
||||
import { EthereumTransactionValidationService } from "../../../services/EthereumTransactionValidationService";
|
||||
import { getConfig } from "./config/utils";
|
||||
@@ -72,85 +62,50 @@ export class PostmanServiceClient {
|
||||
this.l1L2AutoClaimEnabled = config.l1L2AutoClaimEnabled;
|
||||
this.l2L1AutoClaimEnabled = config.l2L1AutoClaimEnabled;
|
||||
|
||||
const l1Provider = new JsonRpcProvider(config.l1Config.rpcUrl);
|
||||
const l2Provider = new JsonRpcProvider(config.l2Config.rpcUrl);
|
||||
|
||||
const l1Signer = this.getSigner(config.l1Config.claiming.signerPrivateKey, l1Provider);
|
||||
const l2Signer = this.getSigner(config.l2Config.claiming.signerPrivateKey, l2Provider);
|
||||
|
||||
const l1Querier = new ChainQuerier(l1Provider, l1Signer);
|
||||
const l2Querier = new L2ChainQuerier(l2Provider, l2Signer);
|
||||
|
||||
const lineaRollupLogClient = new EthersLineaRollupLogClient(
|
||||
l1Provider,
|
||||
config.l1Config.messageServiceContractAddress,
|
||||
);
|
||||
const l2MessageServiceLogClient = new EthersL2MessageServiceLogClient(
|
||||
l2Provider,
|
||||
config.l2Config.messageServiceContractAddress,
|
||||
);
|
||||
|
||||
const l1GasProvider = new GasProvider(l1Querier, {
|
||||
maxFeePerGas: config.l1Config.claiming.maxFeePerGas,
|
||||
gasEstimationPercentile: config.l1Config.claiming.gasEstimationPercentile,
|
||||
enforceMaxGasFee: config.l1Config.claiming.isMaxGasFeeEnforced,
|
||||
enableLineaEstimateGas: false,
|
||||
direction: Direction.L2_TO_L1,
|
||||
const lineaSdk = new LineaSDK({
|
||||
l1RpcUrlOrProvider: config.l1Config.rpcUrl,
|
||||
l2RpcUrlOrProvider: config.l2Config.rpcUrl,
|
||||
l1SignerPrivateKeyOrWallet: config.l1Config.claiming.signerPrivateKey,
|
||||
l2SignerPrivateKeyOrWallet: config.l2Config.claiming.signerPrivateKey,
|
||||
network: "custom",
|
||||
mode: "read-write",
|
||||
l1FeeEstimatorOptions: {
|
||||
gasFeeEstimationPercentile: config.l1Config.claiming.gasEstimationPercentile,
|
||||
maxFeePerGasCap: config.l1Config.claiming.maxFeePerGasCap,
|
||||
enforceMaxGasFee: config.l1Config.claiming.isMaxGasFeeEnforced,
|
||||
},
|
||||
l2FeeEstimatorOptions: {
|
||||
gasFeeEstimationPercentile: config.l2Config.claiming.gasEstimationPercentile,
|
||||
maxFeePerGasCap: config.l2Config.claiming.maxFeePerGasCap,
|
||||
enforceMaxGasFee: config.l2Config.claiming.isMaxGasFeeEnforced,
|
||||
enableLineaEstimateGas: config.l2Config.enableLineaEstimateGas,
|
||||
},
|
||||
});
|
||||
|
||||
const l2GasProvider = new GasProvider(l2Querier, {
|
||||
maxFeePerGas: config.l2Config.claiming.maxFeePerGas,
|
||||
gasEstimationPercentile: config.l2Config.claiming.gasEstimationPercentile,
|
||||
enforceMaxGasFee: config.l2Config.claiming.isMaxGasFeeEnforced,
|
||||
enableLineaEstimateGas: config.l2Config.enableLineaEstimateGas,
|
||||
direction: Direction.L1_TO_L2,
|
||||
});
|
||||
const l1Provider = lineaSdk.getL1Provider(config.l1Config.rpcUrl);
|
||||
const l2Provider = lineaSdk.getL2Provider(config.l2Config.rpcUrl);
|
||||
|
||||
const lineaRollupMessageRetriever = new LineaRollupMessageRetriever(
|
||||
l1Querier,
|
||||
lineaRollupLogClient,
|
||||
const l1Signer = lineaSdk.getL1Signer();
|
||||
const l2Signer = lineaSdk.getL2Signer();
|
||||
|
||||
const lineaRollupClient = lineaSdk.getL1Contract(
|
||||
config.l1Config.messageServiceContractAddress,
|
||||
);
|
||||
|
||||
const l1MerkleTreeService = new MerkleTreeService(
|
||||
l1Querier,
|
||||
config.l1Config.messageServiceContractAddress,
|
||||
lineaRollupLogClient,
|
||||
l2MessageServiceLogClient,
|
||||
config.l2Config.l2MessageTreeDepth,
|
||||
);
|
||||
|
||||
const l2MessageServiceMessageRetriever = new L2MessageServiceMessageRetriever(
|
||||
l2Querier,
|
||||
l2MessageServiceLogClient,
|
||||
config.l2Config.messageServiceContractAddress,
|
||||
);
|
||||
|
||||
const l1MessageServiceContract = new LineaRollupClient(
|
||||
l1Querier,
|
||||
config.l1Config.messageServiceContractAddress,
|
||||
lineaRollupLogClient,
|
||||
l2MessageServiceLogClient,
|
||||
l1GasProvider,
|
||||
lineaRollupMessageRetriever,
|
||||
l1MerkleTreeService,
|
||||
"read-write",
|
||||
l1Signer,
|
||||
const l2MessageServiceClient = lineaSdk.getL2Contract(config.l2Config.messageServiceContractAddress);
|
||||
|
||||
const lineaRollupLogClient = lineaSdk.getL1ContractEventLogClient(config.l1Config.messageServiceContractAddress);
|
||||
const l2MessageServiceLogClient = lineaSdk.getL2ContractEventLogClient(
|
||||
config.l2Config.messageServiceContractAddress,
|
||||
);
|
||||
|
||||
const l2MessageServiceContract = new L2MessageServiceClient(
|
||||
l2Querier,
|
||||
config.l2Config.messageServiceContractAddress,
|
||||
l2MessageServiceMessageRetriever,
|
||||
l2GasProvider,
|
||||
"read-write",
|
||||
l2Signer,
|
||||
);
|
||||
const l1GasProvider = lineaSdk.getL1GasProvider();
|
||||
|
||||
this.db = DB.create(config.databaseOptions);
|
||||
|
||||
const messageRepository = new TypeOrmMessageRepository(this.db);
|
||||
const lineaMessageDBService = new LineaMessageDBService(l2Querier, messageRepository);
|
||||
const lineaMessageDBService = new LineaMessageDBService(l2Provider, messageRepository);
|
||||
const ethereumMessageDBService = new EthereumMessageDBService(l1GasProvider, messageRepository);
|
||||
|
||||
// L1 -> L2 flow
|
||||
@@ -158,7 +113,7 @@ export class PostmanServiceClient {
|
||||
const l1MessageSentEventProcessor = new MessageSentEventProcessor(
|
||||
lineaMessageDBService,
|
||||
lineaRollupLogClient,
|
||||
l1Querier,
|
||||
l1Provider,
|
||||
{
|
||||
direction: Direction.L1_TO_L2,
|
||||
maxBlocksToFetchLogs: config.l1Config.listener.maxBlocksToFetchLogs,
|
||||
@@ -171,7 +126,7 @@ export class PostmanServiceClient {
|
||||
|
||||
this.l1MessageSentEventPoller = new MessageSentEventPoller(
|
||||
l1MessageSentEventProcessor,
|
||||
l1Querier,
|
||||
l1Provider,
|
||||
lineaMessageDBService,
|
||||
{
|
||||
direction: Direction.L1_TO_L2,
|
||||
@@ -183,8 +138,8 @@ export class PostmanServiceClient {
|
||||
);
|
||||
|
||||
const l2MessageAnchoringProcessor = new MessageAnchoringProcessor(
|
||||
l2MessageServiceContract,
|
||||
l2Querier,
|
||||
l2MessageServiceClient,
|
||||
l2Provider,
|
||||
lineaMessageDBService,
|
||||
{
|
||||
maxFetchMessagesFromDb: config.l1Config.listener.maxFetchMessagesFromDb,
|
||||
@@ -207,13 +162,13 @@ export class PostmanServiceClient {
|
||||
profitMargin: config.l2Config.claiming.profitMargin,
|
||||
maxClaimGasLimit: BigInt(config.l2Config.claiming.maxClaimGasLimit),
|
||||
},
|
||||
l2Querier,
|
||||
l2MessageServiceContract,
|
||||
l2Provider,
|
||||
l2MessageServiceClient,
|
||||
);
|
||||
|
||||
const l2MessageClaimingProcessor = new MessageClaimingProcessor(
|
||||
l2MessageServiceContract,
|
||||
l2Querier,
|
||||
l2MessageServiceClient,
|
||||
l2Signer,
|
||||
lineaMessageDBService,
|
||||
l2TransactionValidationService,
|
||||
{
|
||||
@@ -240,8 +195,8 @@ export class PostmanServiceClient {
|
||||
|
||||
const l2MessageClaimingPersister = new MessageClaimingPersister(
|
||||
lineaMessageDBService,
|
||||
l2MessageServiceContract,
|
||||
l2Querier,
|
||||
l2MessageServiceClient,
|
||||
l2Provider,
|
||||
{
|
||||
direction: Direction.L1_TO_L2,
|
||||
messageSubmissionTimeout: config.l2Config.claiming.messageSubmissionTimeout,
|
||||
@@ -259,10 +214,10 @@ export class PostmanServiceClient {
|
||||
new WinstonLogger(`L2${MessagePersistingPoller.name}`, config.loggerOptions),
|
||||
);
|
||||
|
||||
const transactionSizeCalculator = new L2ClaimTransactionSizeCalculator(l2MessageServiceContract);
|
||||
const transactionSizeCalculator = new L2ClaimTransactionSizeCalculator(l2MessageServiceClient);
|
||||
const transactionSizeCompressor = new L2ClaimMessageTransactionSizeProcessor(
|
||||
lineaMessageDBService,
|
||||
l2MessageServiceContract,
|
||||
l2MessageServiceClient,
|
||||
transactionSizeCalculator,
|
||||
{
|
||||
direction: Direction.L1_TO_L2,
|
||||
@@ -283,7 +238,7 @@ export class PostmanServiceClient {
|
||||
const l2MessageSentEventProcessor = new MessageSentEventProcessor(
|
||||
ethereumMessageDBService,
|
||||
l2MessageServiceLogClient,
|
||||
l2Querier,
|
||||
l2Provider,
|
||||
{
|
||||
direction: Direction.L2_TO_L1,
|
||||
maxBlocksToFetchLogs: config.l2Config.listener.maxBlocksToFetchLogs,
|
||||
@@ -296,7 +251,7 @@ export class PostmanServiceClient {
|
||||
|
||||
this.l2MessageSentEventPoller = new MessageSentEventPoller(
|
||||
l2MessageSentEventProcessor,
|
||||
l2Querier,
|
||||
l2Provider,
|
||||
ethereumMessageDBService,
|
||||
{
|
||||
direction: Direction.L2_TO_L1,
|
||||
@@ -308,8 +263,8 @@ export class PostmanServiceClient {
|
||||
);
|
||||
|
||||
const l1MessageAnchoringProcessor = new MessageAnchoringProcessor(
|
||||
l1MessageServiceContract,
|
||||
l1Querier,
|
||||
lineaRollupClient,
|
||||
l1Provider,
|
||||
ethereumMessageDBService,
|
||||
{
|
||||
maxFetchMessagesFromDb: config.l1Config.listener.maxFetchMessagesFromDb,
|
||||
@@ -327,18 +282,14 @@ export class PostmanServiceClient {
|
||||
new WinstonLogger(`L1${MessageAnchoringPoller.name}`, config.loggerOptions),
|
||||
);
|
||||
|
||||
const l1TransactionValidationService = new EthereumTransactionValidationService(
|
||||
l1MessageServiceContract,
|
||||
l1GasProvider,
|
||||
{
|
||||
profitMargin: config.l1Config.claiming.profitMargin,
|
||||
maxClaimGasLimit: BigInt(config.l1Config.claiming.maxClaimGasLimit),
|
||||
},
|
||||
);
|
||||
const l1TransactionValidationService = new EthereumTransactionValidationService(lineaRollupClient, l1GasProvider, {
|
||||
profitMargin: config.l1Config.claiming.profitMargin,
|
||||
maxClaimGasLimit: BigInt(config.l1Config.claiming.maxClaimGasLimit),
|
||||
});
|
||||
|
||||
const l1MessageClaimingProcessor = new MessageClaimingProcessor(
|
||||
l1MessageServiceContract,
|
||||
l1Querier,
|
||||
lineaRollupClient,
|
||||
l1Signer,
|
||||
ethereumMessageDBService,
|
||||
l1TransactionValidationService,
|
||||
{
|
||||
@@ -365,8 +316,8 @@ export class PostmanServiceClient {
|
||||
|
||||
const l1MessageClaimingPersister = new MessageClaimingPersister(
|
||||
ethereumMessageDBService,
|
||||
l1MessageServiceContract,
|
||||
l1Querier,
|
||||
lineaRollupClient,
|
||||
l1Provider,
|
||||
{
|
||||
direction: Direction.L2_TO_L1,
|
||||
messageSubmissionTimeout: config.l1Config.claiming.messageSubmissionTimeout,
|
||||
@@ -401,23 +352,6 @@ export class PostmanServiceClient {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Wallet instance as a signer using the provided private key and JSON RPC provider.
|
||||
*
|
||||
* @param {string} privateKey - The private key to use for the signer.
|
||||
* @param {JsonRpcProvider} provider - The JSON RPC provider associated with the network.
|
||||
* @returns {Wallet} A Wallet instance configured with the provided private key and provider.
|
||||
*/
|
||||
private getSigner(privateKey: string, provider: JsonRpcProvider): Wallet {
|
||||
try {
|
||||
return new Wallet(privateKey, provider);
|
||||
} catch (e) {
|
||||
throw new BaseError(
|
||||
"Something went wrong when trying to generate Wallet. Please check your private key and the provider url.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the database connection using the configuration provided.
|
||||
*/
|
||||
@@ -54,7 +54,7 @@ const postmanServiceClientOptions: PostmanOptions = {
|
||||
signerPrivateKey: TEST_L1_SIGNER_PRIVATE_KEY,
|
||||
messageSubmissionTimeout: 300000,
|
||||
maxNonceDiff: 10000,
|
||||
maxFeePerGas: 100000000000n,
|
||||
maxFeePerGasCap: 100000000000n,
|
||||
gasEstimationPercentile: 50,
|
||||
profitMargin: 1.0,
|
||||
maxNumberOfRetries: 100,
|
||||
@@ -75,7 +75,7 @@ const postmanServiceClientOptions: PostmanOptions = {
|
||||
signerPrivateKey: TEST_L2_SIGNER_PRIVATE_KEY,
|
||||
messageSubmissionTimeout: 300000,
|
||||
maxNonceDiff: 10000,
|
||||
maxFeePerGas: 100000000000n,
|
||||
maxFeePerGasCap: 100000000000n,
|
||||
gasEstimationPercentile: 50,
|
||||
profitMargin: 1.0,
|
||||
maxNumberOfRetries: 100,
|
||||
@@ -119,15 +119,20 @@ describe("PostmanServiceClient", () => {
|
||||
...postmanServiceClientOptions.l1Options,
|
||||
claiming: {
|
||||
...postmanServiceClientOptions.l1Options.claiming,
|
||||
signerPrivateKey: "",
|
||||
signerPrivateKey: "0x",
|
||||
},
|
||||
},
|
||||
l2Options: {
|
||||
...postmanServiceClientOptions.l2Options,
|
||||
claiming: {
|
||||
...postmanServiceClientOptions.l2Options.claiming,
|
||||
signerPrivateKey: "0x",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(() => new PostmanServiceClient(postmanServiceClientOptionsWithInvalidPrivateKey)).toThrow(
|
||||
new Error(
|
||||
"Something went wrong when trying to generate Wallet. Please check your private key and the provider url.",
|
||||
),
|
||||
new Error("Something went wrong when trying to generate Wallet. Please check your private key."),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
DEFAULT_LISTENER_INTERVAL,
|
||||
DEFAULT_MAX_BLOCKS_TO_FETCH_LOGS,
|
||||
DEFAULT_MAX_CLAIM_GAS_LIMIT,
|
||||
DEFAULT_MAX_FEE_PER_GAS,
|
||||
DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
DEFAULT_MAX_FETCH_MESSAGES_FROM_DB,
|
||||
DEFAULT_MAX_NONCE_DIFF,
|
||||
DEFAULT_MAX_NUMBER_OF_RETRIES,
|
||||
@@ -74,7 +74,7 @@ describe("Config utils", () => {
|
||||
gasEstimationPercentile: DEFAULT_GAS_ESTIMATION_PERCENTILE,
|
||||
isMaxGasFeeEnforced: DEFAULT_ENFORCE_MAX_GAS_FEE,
|
||||
maxClaimGasLimit: DEFAULT_MAX_CLAIM_GAS_LIMIT,
|
||||
maxFeePerGas: DEFAULT_MAX_FEE_PER_GAS,
|
||||
maxFeePerGasCap: DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
maxNonceDiff: DEFAULT_MAX_NONCE_DIFF,
|
||||
maxNumberOfRetries: DEFAULT_MAX_NUMBER_OF_RETRIES,
|
||||
maxTxRetries: DEFAULT_MAX_TX_RETRIES,
|
||||
@@ -102,7 +102,7 @@ describe("Config utils", () => {
|
||||
gasEstimationPercentile: DEFAULT_GAS_ESTIMATION_PERCENTILE,
|
||||
isMaxGasFeeEnforced: DEFAULT_ENFORCE_MAX_GAS_FEE,
|
||||
maxClaimGasLimit: DEFAULT_MAX_CLAIM_GAS_LIMIT,
|
||||
maxFeePerGas: DEFAULT_MAX_FEE_PER_GAS,
|
||||
maxFeePerGasCap: DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
maxNonceDiff: DEFAULT_MAX_NONCE_DIFF,
|
||||
maxNumberOfRetries: DEFAULT_MAX_NUMBER_OF_RETRIES,
|
||||
maxTxRetries: DEFAULT_MAX_TX_RETRIES,
|
||||
@@ -179,7 +179,7 @@ describe("Config utils", () => {
|
||||
gasEstimationPercentile: DEFAULT_GAS_ESTIMATION_PERCENTILE,
|
||||
isMaxGasFeeEnforced: DEFAULT_ENFORCE_MAX_GAS_FEE,
|
||||
maxClaimGasLimit: DEFAULT_MAX_CLAIM_GAS_LIMIT,
|
||||
maxFeePerGas: DEFAULT_MAX_FEE_PER_GAS,
|
||||
maxFeePerGasCap: DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
maxNonceDiff: DEFAULT_MAX_NONCE_DIFF,
|
||||
maxNumberOfRetries: DEFAULT_MAX_NUMBER_OF_RETRIES,
|
||||
maxTxRetries: DEFAULT_MAX_TX_RETRIES,
|
||||
@@ -207,7 +207,7 @@ describe("Config utils", () => {
|
||||
gasEstimationPercentile: DEFAULT_GAS_ESTIMATION_PERCENTILE,
|
||||
isMaxGasFeeEnforced: DEFAULT_ENFORCE_MAX_GAS_FEE,
|
||||
maxClaimGasLimit: DEFAULT_MAX_CLAIM_GAS_LIMIT,
|
||||
maxFeePerGas: DEFAULT_MAX_FEE_PER_GAS,
|
||||
maxFeePerGasCap: DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
maxNonceDiff: DEFAULT_MAX_NONCE_DIFF,
|
||||
maxNumberOfRetries: DEFAULT_MAX_NUMBER_OF_RETRIES,
|
||||
maxTxRetries: DEFAULT_MAX_TX_RETRIES,
|
||||
@@ -76,7 +76,7 @@ export type ClaimingOptions = {
|
||||
messageSubmissionTimeout?: number;
|
||||
feeRecipientAddress?: string;
|
||||
maxNonceDiff?: number;
|
||||
maxFeePerGas?: bigint;
|
||||
maxFeePerGasCap?: bigint;
|
||||
gasEstimationPercentile?: number;
|
||||
isMaxGasFeeEnforced?: boolean;
|
||||
profitMargin?: number;
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
DEFAULT_LISTENER_INTERVAL,
|
||||
DEFAULT_MAX_BLOCKS_TO_FETCH_LOGS,
|
||||
DEFAULT_MAX_CLAIM_GAS_LIMIT,
|
||||
DEFAULT_MAX_FEE_PER_GAS,
|
||||
DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
DEFAULT_MAX_FETCH_MESSAGES_FROM_DB,
|
||||
DEFAULT_MAX_NONCE_DIFF,
|
||||
DEFAULT_MAX_NUMBER_OF_RETRIES,
|
||||
@@ -54,7 +54,7 @@ export function getConfig(postmanOptions: PostmanOptions): PostmanConfig {
|
||||
messageSubmissionTimeout: l1Options.claiming.messageSubmissionTimeout ?? DEFAULT_MESSAGE_SUBMISSION_TIMEOUT,
|
||||
feeRecipientAddress: l1Options.claiming.feeRecipientAddress,
|
||||
maxNonceDiff: l1Options.claiming.maxNonceDiff ?? DEFAULT_MAX_NONCE_DIFF,
|
||||
maxFeePerGas: l1Options.claiming.maxFeePerGas ?? DEFAULT_MAX_FEE_PER_GAS,
|
||||
maxFeePerGasCap: l1Options.claiming.maxFeePerGasCap ?? DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
gasEstimationPercentile: l1Options.claiming.gasEstimationPercentile ?? DEFAULT_GAS_ESTIMATION_PERCENTILE,
|
||||
isMaxGasFeeEnforced: l1Options.claiming.isMaxGasFeeEnforced ?? false,
|
||||
profitMargin: l1Options.claiming.profitMargin ?? DEFAULT_PROFIT_MARGIN,
|
||||
@@ -83,7 +83,7 @@ export function getConfig(postmanOptions: PostmanOptions): PostmanConfig {
|
||||
messageSubmissionTimeout: l2Options.claiming.messageSubmissionTimeout ?? DEFAULT_MESSAGE_SUBMISSION_TIMEOUT,
|
||||
feeRecipientAddress: l2Options.claiming.feeRecipientAddress,
|
||||
maxNonceDiff: l2Options.claiming.maxNonceDiff ?? DEFAULT_MAX_NONCE_DIFF,
|
||||
maxFeePerGas: l2Options.claiming.maxFeePerGas ?? DEFAULT_MAX_FEE_PER_GAS,
|
||||
maxFeePerGasCap: l2Options.claiming.maxFeePerGasCap ?? DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
gasEstimationPercentile: l2Options.claiming.gasEstimationPercentile ?? DEFAULT_GAS_ESTIMATION_PERCENTILE,
|
||||
isMaxGasFeeEnforced: l2Options.claiming.isMaxGasFeeEnforced ?? false,
|
||||
profitMargin: l2Options.claiming.profitMargin ?? DEFAULT_PROFIT_MARGIN,
|
||||
@@ -1,6 +1,7 @@
|
||||
import { IsDate, IsDecimal, IsEnum, IsNumber, IsString } from "class-validator";
|
||||
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm";
|
||||
import { Direction, MessageStatus } from "../../../../core/enums/MessageEnums";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { MessageStatus } from "../../../../core/enums";
|
||||
|
||||
@Entity({ name: "message" })
|
||||
export class MessageEntity {
|
||||
@@ -1,4 +1,5 @@
|
||||
import { describe, it, expect } from "@jest/globals";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { generateMessage, generateMessageEntity } from "../../../../../utils/testing/helpers";
|
||||
import { mapMessageEntityToMessage, mapMessageToMessageEntity } from "../messageMappers";
|
||||
import {
|
||||
@@ -7,7 +8,7 @@ import {
|
||||
TEST_CONTRACT_ADDRESS_2,
|
||||
TEST_MESSAGE_HASH,
|
||||
} from "../../../../../utils/testing/constants";
|
||||
import { Direction, MessageStatus } from "../../../../../core/enums/MessageEnums";
|
||||
import { MessageStatus } from "../../../../../core/enums";
|
||||
import { Message } from "../../../../../core/entities/Message";
|
||||
|
||||
describe("Message Mappers", () => {
|
||||
@@ -1,13 +1,13 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { Brackets, DataSource, Repository } from "typeorm";
|
||||
import { ContractTransactionResponse } from "ethers";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { Message } from "../../../../core/entities/Message";
|
||||
import { mapMessageEntityToMessage, mapMessageToMessageEntity } from "../mappers/messageMappers";
|
||||
import { Direction, MessageStatus } from "../../../../core/enums/MessageEnums";
|
||||
import { DatabaseErrorType, DatabaseRepoName } from "../../../../core/enums/DatabaseEnums";
|
||||
import { DatabaseAccessError } from "../../../../core/errors/DatabaseErrors";
|
||||
import { DatabaseErrorType, DatabaseRepoName, MessageStatus } from "../../../../core/enums";
|
||||
import { DatabaseAccessError } from "../../../../core/errors";
|
||||
import { MessageEntity } from "../entities/Message.entity";
|
||||
import { subtractSeconds } from "../../../../core/utils/shared";
|
||||
import { ContractTransactionResponse } from "ethers";
|
||||
import { IMessageRepository } from "../../../../core/persistence/IMessageRepository";
|
||||
|
||||
export class TypeOrmMessageRepository<TransactionResponse extends ContractTransactionResponse>
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Direction } from "../../enums/MessageEnums";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
|
||||
export type GasFees = {
|
||||
maxFeePerGas: bigint;
|
||||
@@ -23,7 +23,7 @@ export type LineaEstimateGasResponse = {
|
||||
};
|
||||
|
||||
type BaseGasProviderConfig = {
|
||||
maxFeePerGas: bigint;
|
||||
maxFeePerGasCap: bigint;
|
||||
enforceMaxGasFee: boolean;
|
||||
};
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { GasFees } from "./IGasProvider";
|
||||
|
||||
export interface IChainQuerier<TransactionReceipt, Block, TransactionRequest, TransactionResponse, JsonRpcProvider> {
|
||||
getCurrentNonce(accountAddress?: string): Promise<number>;
|
||||
getCurrentBlockNumber(): Promise<number>;
|
||||
export interface IProvider<TransactionReceipt, Block, TransactionRequest, TransactionResponse, Provider> {
|
||||
getTransactionCount(address: string, blockTag: string | number | bigint): Promise<number>;
|
||||
getBlockNumber(): Promise<number>;
|
||||
getTransactionReceipt(txHash: string): Promise<TransactionReceipt | null>;
|
||||
getBlock(blockNumber: number | bigint | string): Promise<Block | null>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
sendRequest(methodName: string, params: any[]): Promise<any>;
|
||||
send(methodName: string, params: Array<any> | Record<string, any>): Promise<any>;
|
||||
estimateGas(transactionRequest: TransactionRequest): Promise<bigint>;
|
||||
getProvider(): JsonRpcProvider;
|
||||
getTransaction(transactionHash: string): Promise<TransactionResponse | null>;
|
||||
broadcastTransaction(signedTx: string): Promise<TransactionResponse>;
|
||||
ethCall(transactionRequest: TransactionRequest): Promise<string>;
|
||||
call(transactionRequest: TransactionRequest): Promise<string>;
|
||||
getFees(): Promise<GasFees>;
|
||||
get provider(): Provider;
|
||||
}
|
||||
@@ -1,11 +1,21 @@
|
||||
import { MessageProps } from "../../../entities/Message";
|
||||
import { OnChainMessageStatus } from "../../../enums/MessageEnums";
|
||||
import { MessageSent, OnChainMessageStatus } from "@consensys/linea-sdk";
|
||||
import { IMessageServiceContract } from "../../../services/contracts/IMessageServiceContract";
|
||||
import { MessageSent } from "../../../types/Events";
|
||||
import { FinalizationMessagingInfo, Proof } from "./IMerkleTreeService";
|
||||
|
||||
export interface ILineaRollupClient<Overrides, TransactionReceipt, TransactionResponse, ContractTransactionResponse>
|
||||
extends IMessageServiceContract<Overrides, TransactionReceipt, TransactionResponse, ContractTransactionResponse> {
|
||||
export interface ILineaRollupClient<
|
||||
Overrides,
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription,
|
||||
> extends IMessageServiceContract<
|
||||
Overrides,
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription
|
||||
> {
|
||||
getFinalizationMessagingInfo(transactionHash: string): Promise<FinalizationMessagingInfo>;
|
||||
getL2MessageHashesInBlockRange(fromBlock: number, toBlock: number): Promise<string[]>;
|
||||
getMessageSiblings(messageHash: string, messageHashes: string[], treeDepth: number): string[];
|
||||
@@ -1,4 +1,4 @@
|
||||
import { L2MessagingBlockAnchored, MessageClaimed, MessageSent } from "../../../types/Events";
|
||||
import { L2MessagingBlockAnchored, MessageClaimed, MessageSent } from "@consensys/linea-sdk";
|
||||
|
||||
export type MessageSentEventFilters = {
|
||||
from?: string;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MessageSent } from "sdk/src/core/types/Events";
|
||||
import { MessageProps } from "../../../../core/entities/Message";
|
||||
import { MessageSent } from "@consensys/linea-sdk";
|
||||
import { MessageProps } from "../../../entities/Message";
|
||||
import { IMessageServiceContract } from "../../../services/contracts/IMessageServiceContract";
|
||||
import { LineaGasFees } from "../IGasProvider";
|
||||
|
||||
@@ -9,7 +9,14 @@ export interface IL2MessageServiceClient<
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse,
|
||||
Signer,
|
||||
> extends IMessageServiceContract<Overrides, TransactionReceipt, TransactionResponse, ContractTransactionResponse> {
|
||||
ErrorDescription,
|
||||
> extends IMessageServiceContract<
|
||||
Overrides,
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription
|
||||
> {
|
||||
encodeClaimMessageTransactionData(message: MessageProps & { feeRecipient?: string }): string;
|
||||
estimateClaimGasFees(
|
||||
message: (MessageSent | MessageProps) & { feeRecipient?: string },
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MessageSent, ServiceVersionMigrated } from "../../../types/Events";
|
||||
import { MessageSent, ServiceVersionMigrated } from "@consensys/linea-sdk";
|
||||
|
||||
export type MessageSentEventFilters = {
|
||||
from?: string;
|
||||
13
postman/src/core/clients/blockchain/linea/ILineaProvider.ts
Normal file
13
postman/src/core/clients/blockchain/linea/ILineaProvider.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { IProvider } from "../IProvider";
|
||||
|
||||
export type BlockExtraData = {
|
||||
version: number;
|
||||
fixedCost: number;
|
||||
variableCost: number;
|
||||
ethGasPrice: number;
|
||||
};
|
||||
|
||||
export interface ILineaProvider<TransactionReceipt, Block, TransactionRequest, TransactionResponse, Provider>
|
||||
extends IProvider<TransactionReceipt, Block, TransactionRequest, TransactionResponse, Provider> {
|
||||
getBlockExtraData(blockNumber: number | bigint | string): Promise<BlockExtraData | null>;
|
||||
}
|
||||
4
postman/src/core/constants/blockchain.ts
Normal file
4
postman/src/core/constants/blockchain.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const ZERO_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
||||
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
||||
|
||||
export const MINIMUM_MARGIN = 1.2;
|
||||
25
postman/src/core/constants/common.ts
Normal file
25
postman/src/core/constants/common.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export const DEFAULT_MESSAGE_SUBMISSION_TIMEOUT = 300000;
|
||||
export const DEFAULT_LISTENER_INTERVAL = 4000;
|
||||
export const DEFAULT_DB_CLEANER_ENABLED = false;
|
||||
export const DEFAULT_DB_CLEANING_INTERVAL = 43200000;
|
||||
export const DEFAULT_DB_DAYS_BEFORE_NOW_TO_DELETE = 14;
|
||||
export const DEFAULT_MAX_BLOCKS_TO_FETCH_LOGS = 1000;
|
||||
export const DEFAULT_MAX_FETCH_MESSAGES_FROM_DB = 1000;
|
||||
export const DEFAULT_MAX_NONCE_DIFF = 10000;
|
||||
export const DEFAULT_MAX_FEE_PER_GAS_CAP = 100000000000n;
|
||||
export const DEFAULT_ENFORCE_MAX_GAS_FEE = false;
|
||||
export const DEFAULT_GAS_ESTIMATION_PERCENTILE = 20;
|
||||
export const DEFAULT_GAS_LIMIT = 0;
|
||||
export const DEFAULT_LISTENER_BLOCK_CONFIRMATIONS = 4;
|
||||
export const DEFAULT_PROFIT_MARGIN = 1.0;
|
||||
export const DEFAULT_MAX_NUMBER_OF_RETRIES = 100;
|
||||
export const DEFAULT_RETRY_DELAY_IN_SECONDS = 30;
|
||||
export const DEFAULT_EOA_ENABLED = false;
|
||||
export const DEFAULT_CALLDATA_ENABLED = false;
|
||||
export const DEFAULT_RATE_LIMIT_MARGIN = 0.95;
|
||||
export const DEFAULT_MAX_CLAIM_GAS_LIMIT = 100_000n;
|
||||
export const DEFAULT_MAX_TX_RETRIES = 20;
|
||||
export const DEFAULT_L2_MESSAGE_TREE_DEPTH = 5;
|
||||
export const DEFAULT_INITIAL_FROM_BLOCK = -1;
|
||||
|
||||
export const PROFIT_MARGIN_MULTIPLIER = 100;
|
||||
2
postman/src/core/constants/index.ts
Normal file
2
postman/src/core/constants/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./common";
|
||||
export * from "./blockchain";
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Direction, MessageStatus } from "../enums/MessageEnums";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { MessageStatus } from "../enums";
|
||||
|
||||
export type MessageProps = {
|
||||
id?: number;
|
||||
@@ -1,8 +1,3 @@
|
||||
export enum Direction {
|
||||
L1_TO_L2 = "L1_TO_L2",
|
||||
L2_TO_L1 = "L2_TO_L1",
|
||||
}
|
||||
|
||||
export enum MessageStatus {
|
||||
SENT = "SENT",
|
||||
TRANSACTION_SIZE_COMPUTED = "TRANSACTION_SIZE_COMPUTED",
|
||||
@@ -15,9 +10,3 @@ export enum MessageStatus {
|
||||
FEE_UNDERPRICED = "FEE_UNDERPRICED",
|
||||
EXCLUDED = "EXCLUDED",
|
||||
}
|
||||
|
||||
export enum OnChainMessageStatus {
|
||||
UNKNOWN = "UNKNOWN",
|
||||
CLAIMABLE = "CLAIMABLE",
|
||||
CLAIMED = "CLAIMED",
|
||||
}
|
||||
2
postman/src/core/enums/index.ts
Normal file
2
postman/src/core/enums/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { DatabaseErrorType, DatabaseRepoName } from "./DatabaseEnums";
|
||||
export { MessageStatus } from "./MessageEnums";
|
||||
11
postman/src/core/errors/BaseError.ts
Normal file
11
postman/src/core/errors/BaseError.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export class BaseError extends Error {
|
||||
reason?: BaseError | Error | string;
|
||||
|
||||
override name = "PostmanCoreError";
|
||||
|
||||
constructor(message?: string) {
|
||||
super();
|
||||
this.message = message || "An error occurred.";
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BaseError } from "./BaseError";
|
||||
import { MessageProps } from "../entities/Message";
|
||||
import { DatabaseErrorType, DatabaseRepoName } from "../enums/DatabaseEnums";
|
||||
import { BaseError } from "./Base";
|
||||
import { DatabaseErrorType, DatabaseRepoName } from "../enums";
|
||||
|
||||
export class DatabaseAccessError<T extends MessageProps> extends BaseError {
|
||||
override name = DatabaseAccessError.name;
|
||||
14
postman/src/core/errors/__tests__/BaseError.test.ts
Normal file
14
postman/src/core/errors/__tests__/BaseError.test.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { describe, it } from "@jest/globals";
|
||||
import { serialize } from "@consensys/linea-sdk";
|
||||
import { BaseError } from "../BaseError";
|
||||
|
||||
describe("BaseError", () => {
|
||||
it("Should log error message when we only pass a short message", () => {
|
||||
expect(serialize(new BaseError("An error message."))).toStrictEqual(
|
||||
serialize({
|
||||
name: "PostmanCoreError",
|
||||
message: "An error message.",
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,8 @@
|
||||
import { describe, it } from "@jest/globals";
|
||||
import { describe, it, expect } from "@jest/globals";
|
||||
import { Direction, serialize } from "@consensys/linea-sdk";
|
||||
import { DatabaseAccessError } from "../DatabaseErrors";
|
||||
import { DatabaseErrorType, DatabaseRepoName } from "../../enums/DatabaseEnums";
|
||||
import { DatabaseErrorType, DatabaseRepoName, MessageStatus } from "../../enums";
|
||||
import { MessageProps } from "../../entities/Message";
|
||||
import { Direction, MessageStatus } from "../../enums/MessageEnums";
|
||||
import { serialize } from "../../utils/serialize";
|
||||
import { ZERO_ADDRESS, ZERO_HASH } from "../../constants";
|
||||
|
||||
describe("DatabaseAccessError", () => {
|
||||
2
postman/src/core/errors/index.ts
Normal file
2
postman/src/core/errors/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { BaseError } from "./BaseError";
|
||||
export { DatabaseAccessError } from "./DatabaseErrors";
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { Message } from "../entities/Message";
|
||||
import { Direction, MessageStatus } from "../enums/MessageEnums";
|
||||
import { MessageStatus } from "../enums";
|
||||
|
||||
export interface IMessageDBService<TransactionResponse> {
|
||||
insertMessage(message: Message): Promise<void>;
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { Message } from "../entities/Message";
|
||||
import { Direction, MessageStatus } from "../enums/MessageEnums";
|
||||
import { MessageStatus } from "../enums";
|
||||
|
||||
export interface IMessageRepository<ContractTransactionResponse> {
|
||||
insertMessage(message: Message): Promise<void>;
|
||||
@@ -1,12 +1,12 @@
|
||||
import { OnChainMessageStatus } from "../../../core/enums/MessageEnums";
|
||||
import { OnChainMessageStatus, MessageSent } from "@consensys/linea-sdk";
|
||||
import { MessageProps } from "../../entities/Message";
|
||||
import { MessageSent } from "../../types/Events";
|
||||
|
||||
export interface IMessageServiceContract<
|
||||
Overrides,
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription,
|
||||
> {
|
||||
getMessageStatus(messageHash: string, overrides?: Overrides): Promise<OnChainMessageStatus>;
|
||||
getMessageByMessageHash(messageHash: string): Promise<MessageSent | null>;
|
||||
@@ -19,4 +19,5 @@ export interface IMessageServiceContract<
|
||||
retryTransactionWithHigherFee(transactionHash: string, priceBumpPercent?: number): Promise<TransactionResponse>;
|
||||
isRateLimitExceeded(messageFee: bigint, messageValue: bigint): Promise<boolean>;
|
||||
isRateLimitExceededError(transactionHash: string): Promise<boolean>;
|
||||
parseTransactionError(transactionHash: string): Promise<ErrorDescription | string>;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Direction } from "../../enums/MessageEnums";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
|
||||
export interface IL2ClaimMessageTransactionSizeProcessor {
|
||||
process(): Promise<void>;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Direction } from "../../enums/MessageEnums";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
|
||||
export interface IMessageClaimingPersister {
|
||||
process(): Promise<void>;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Direction } from "../../enums/MessageEnums";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
|
||||
export interface IMessageClaimingProcessor {
|
||||
process(): Promise<void>;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Direction } from "../../enums/MessageEnums";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
|
||||
export interface IMessageSentEventProcessor {
|
||||
process(
|
||||
11
postman/src/core/utils/__tests__/shared.test.ts
Normal file
11
postman/src/core/utils/__tests__/shared.test.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { describe, it, expect } from "@jest/globals";
|
||||
import { subtractSeconds } from "../shared";
|
||||
|
||||
describe("Shared utils", () => {
|
||||
describe("subtractSeconds", () => {
|
||||
it("should substract X seconds to the current date", () => {
|
||||
const currentDate = new Date("2024-04-08T00:12:10.000Z");
|
||||
expect(subtractSeconds(currentDate, 10)).toStrictEqual(new Date("2024-04-08T00:12:00.000Z"));
|
||||
});
|
||||
});
|
||||
});
|
||||
12
postman/src/core/utils/shared.ts
Normal file
12
postman/src/core/utils/shared.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Subtracts a specified number of seconds from a given date.
|
||||
*
|
||||
* @param {Date} date - The original date.
|
||||
* @param {number} seconds - The number of seconds to subtract from the date.
|
||||
* @returns {Date} A new date object representing the time after subtracting the specified seconds.
|
||||
*/
|
||||
export const subtractSeconds = (date: Date, seconds: number): Date => {
|
||||
const dateCopy = new Date(date);
|
||||
dateCopy.setSeconds(date.getSeconds() - seconds);
|
||||
return dateCopy;
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription,
|
||||
Overrides,
|
||||
TransactionReceipt,
|
||||
TransactionRequest,
|
||||
@@ -27,7 +28,8 @@ export class EthereumTransactionValidationService implements ITransactionValidat
|
||||
Overrides,
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription
|
||||
>,
|
||||
private readonly gasProvider: IEthereumGasProvider<TransactionRequest>,
|
||||
private readonly config: TransactionValidationServiceConfig,
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription,
|
||||
ethers,
|
||||
Overrides,
|
||||
Signer,
|
||||
@@ -8,11 +9,11 @@ import {
|
||||
TransactionResponse,
|
||||
} from "ethers";
|
||||
import { GoNativeCompressor } from "@consensys/linea-native-libs";
|
||||
import { serialize } from "@consensys/linea-sdk";
|
||||
import { BaseError } from "../core/errors";
|
||||
import { MessageProps } from "../core/entities/Message";
|
||||
import { IL2MessageServiceClient } from "../core/clients/blockchain/linea/IL2MessageServiceClient";
|
||||
import { BaseError } from "../core/errors/Base";
|
||||
import { LineaGasFees } from "../core/clients/blockchain/IGasProvider";
|
||||
import { serialize } from "../core/utils/serialize";
|
||||
import { IL2ClaimTransactionSizeCalculator } from "../core/services/processors/IL2ClaimTransactionSizeCalculator";
|
||||
|
||||
export class L2ClaimTransactionSizeCalculator implements IL2ClaimTransactionSizeCalculator {
|
||||
@@ -29,7 +30,8 @@ export class L2ClaimTransactionSizeCalculator implements IL2ClaimTransactionSize
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse,
|
||||
Signer
|
||||
Signer,
|
||||
ErrorDescription
|
||||
>,
|
||||
) {
|
||||
this.compressor = new GoNativeCompressor(800_000);
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
Block,
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription,
|
||||
JsonRpcProvider,
|
||||
Overrides,
|
||||
Signer,
|
||||
@@ -8,6 +9,7 @@ import {
|
||||
TransactionRequest,
|
||||
TransactionResponse,
|
||||
} from "ethers";
|
||||
import { BaseError } from "../core/errors";
|
||||
import { Message } from "../core/entities/Message";
|
||||
import {
|
||||
ITransactionValidationService,
|
||||
@@ -15,20 +17,19 @@ import {
|
||||
} from "../core/services/ITransactionValidationService";
|
||||
import { MINIMUM_MARGIN, PROFIT_MARGIN_MULTIPLIER } from "../core/constants";
|
||||
import { IL2MessageServiceClient } from "../core/clients/blockchain/linea/IL2MessageServiceClient";
|
||||
import { IL2ChainQuerier } from "../core/clients/blockchain/linea/IL2ChainQuerier";
|
||||
import { BaseError } from "../core/errors/Base";
|
||||
import { ILineaProvider } from "../core/clients/blockchain/linea/ILineaProvider";
|
||||
|
||||
export class LineaTransactionValidationService implements ITransactionValidationService {
|
||||
/**
|
||||
* Constructs a new instance of the `LineaTransactionValidationService`.
|
||||
*
|
||||
* @param {TransactionValidationServiceConfig} config - Configuration settings for the transaction validation service, including profit margin and maximum gas limit.
|
||||
* @param {IL2ChainQuerier} chainQuerier - An instance of a class implementing the `IL2ChainQuerier` interface, used to interact with the blockchain.
|
||||
* @param {ILineaProvider} provider - An instance of a class implementing the `ILineaProvider` interface, used to interact with the blockchain.
|
||||
* @param {IL2MessageServiceClient} l2MessageServiceClient - An instance of a class implementing the `IL2MessageServiceClient` interface, used to interact with the L2 message service.
|
||||
*/
|
||||
constructor(
|
||||
private readonly config: TransactionValidationServiceConfig,
|
||||
private readonly chainQuerier: IL2ChainQuerier<
|
||||
private readonly provider: ILineaProvider<
|
||||
TransactionReceipt,
|
||||
Block,
|
||||
TransactionRequest,
|
||||
@@ -40,7 +41,8 @@ export class LineaTransactionValidationService implements ITransactionValidation
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse,
|
||||
Signer
|
||||
Signer,
|
||||
ErrorDescription
|
||||
>,
|
||||
) {}
|
||||
|
||||
@@ -116,7 +118,7 @@ export class LineaTransactionValidationService implements ITransactionValidation
|
||||
messageFee: bigint,
|
||||
messageCompressedTransactionSize: number,
|
||||
): Promise<boolean> {
|
||||
const extraData = await this.chainQuerier.getBlockExtraData("latest");
|
||||
const extraData = await this.provider.getBlockExtraData("latest");
|
||||
|
||||
if (!extraData) {
|
||||
throw new BaseError("No extra data.");
|
||||
@@ -7,7 +7,7 @@ export class DatabaseCleaner implements IDatabaseCleaner {
|
||||
/**
|
||||
* Constructs a new instance of the `DatabaseCleaner`.
|
||||
*
|
||||
* @param {IMessageRepository<unknown>} messageRepository - An instance of a message repository that provides access to message storage and operations.
|
||||
* @param {IMessageDBService<ContractTransactionResponse>} databaseService - An instance of a MessageDBService that provides access to message storage and operations.
|
||||
* @param {ILogger} logger - An instance of a logger for logging information and errors during the cleanup process.
|
||||
*/
|
||||
constructor(
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ContractTransactionResponse, TransactionRequest } from "ethers";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { Message } from "../../core/entities/Message";
|
||||
import { Direction, MessageStatus } from "../../core/enums/MessageEnums";
|
||||
import { MessageStatus } from "../../core/enums";
|
||||
import { IMessageRepository } from "../../core/persistence/IMessageRepository";
|
||||
import { IMessageDBService } from "../../core/persistence/IMessageDBService";
|
||||
import { IGasProvider } from "../../core/clients/blockchain/IGasProvider";
|
||||
@@ -6,11 +6,12 @@ import {
|
||||
TransactionRequest,
|
||||
TransactionResponse,
|
||||
} from "ethers";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { Message } from "../../core/entities/Message";
|
||||
import { Direction, MessageStatus } from "../../core/enums/MessageEnums";
|
||||
import { MessageStatus } from "../../core/enums";
|
||||
import { IMessageRepository } from "../../core/persistence/IMessageRepository";
|
||||
import { IL2ChainQuerier } from "../../core/clients/blockchain/linea/IL2ChainQuerier";
|
||||
import { BaseError } from "../../core/errors/Base";
|
||||
import { ILineaProvider } from "../../core/clients/blockchain/linea/ILineaProvider";
|
||||
import { BaseError } from "../../core/errors";
|
||||
import { IMessageDBService } from "../../core/persistence/IMessageDBService";
|
||||
import { MessageDBService } from "./MessageDBService";
|
||||
import { MINIMUM_MARGIN } from "../../core/constants";
|
||||
@@ -19,11 +20,11 @@ export class LineaMessageDBService extends MessageDBService implements IMessageD
|
||||
/**
|
||||
* Creates an instance of `LineaMessageDBService`.
|
||||
*
|
||||
* @param {IL2ChainQuerier} chainQuerier - The chain querier for interacting with the blockchain.
|
||||
* @param {ILineaProvider} provider - The provider for interacting with the blockchain.
|
||||
* @param {IMessageRepository} messageRepository - The message repository for interacting with the message database.
|
||||
*/
|
||||
constructor(
|
||||
private readonly chainQuerier: IL2ChainQuerier<
|
||||
private readonly provider: ILineaProvider<
|
||||
TransactionReceipt,
|
||||
Block,
|
||||
TransactionRequest,
|
||||
@@ -90,8 +91,8 @@ export class LineaMessageDBService extends MessageDBService implements IMessageD
|
||||
extraDataFixedCost: number;
|
||||
}> {
|
||||
const minimumMargin = MINIMUM_MARGIN;
|
||||
const blockNumber = await this.chainQuerier.getCurrentBlockNumber();
|
||||
const extraData = await this.chainQuerier.getBlockExtraData(blockNumber);
|
||||
const blockNumber = await this.provider.getBlockNumber();
|
||||
const extraData = await this.provider.getBlockExtraData(blockNumber);
|
||||
|
||||
if (!extraData) {
|
||||
throw new BaseError("no extra data.");
|
||||
@@ -1,7 +1,8 @@
|
||||
import { ContractTransactionResponse } from "ethers";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { Message } from "../../core/entities/Message";
|
||||
import { IMessageRepository } from "../../core/persistence/IMessageRepository";
|
||||
import { Direction, MessageStatus } from "../../core/enums/MessageEnums";
|
||||
import { MessageStatus } from "../../core/enums";
|
||||
|
||||
export abstract class MessageDBService {
|
||||
/**
|
||||
@@ -4,7 +4,7 @@ import { ContractTransactionResponse } from "ethers";
|
||||
import { DatabaseCleaner } from "../DatabaseCleaner";
|
||||
import { ILogger } from "../../../core/utils/logging/ILogger";
|
||||
import { DatabaseAccessError } from "../../../core/errors/DatabaseErrors";
|
||||
import { DatabaseErrorType, DatabaseRepoName } from "../../../core/enums/DatabaseEnums";
|
||||
import { DatabaseErrorType, DatabaseRepoName } from "../../../core/enums";
|
||||
import { IMessageDBService } from "../../../core/persistence/IMessageDBService";
|
||||
|
||||
describe("TestDatabaseCleaner", () => {
|
||||
4
postman/src/services/persistence/index.ts
Normal file
4
postman/src/services/persistence/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { DatabaseCleaner } from "./DatabaseCleaner";
|
||||
export { EthereumMessageDBService } from "./EthereumMessageDBService";
|
||||
export { LineaMessageDBService } from "./LineaMessageDBService";
|
||||
export { MessageDBService } from "./MessageDBService";
|
||||
@@ -1,8 +1,8 @@
|
||||
import { wait } from "@consensys/linea-sdk";
|
||||
import { ILogger } from "../../core/utils/logging/ILogger";
|
||||
import { IPoller } from "../../core/services/pollers/IPoller";
|
||||
import { IDatabaseCleaner } from "../../core/persistence/IDatabaseCleaner";
|
||||
import { DBCleanerConfig } from "../../application/postman/persistence/config/types";
|
||||
import { wait } from "../../core/utils/shared";
|
||||
|
||||
export class DatabaseCleaningPoller implements IPoller {
|
||||
private isPolling = false;
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Direction } from "../../core/enums/MessageEnums";
|
||||
import { Direction, wait } from "@consensys/linea-sdk";
|
||||
import { ILogger } from "../../core/utils/logging/ILogger";
|
||||
import { IPoller } from "../../core/services/pollers/IPoller";
|
||||
import { wait } from "../../core/utils/shared";
|
||||
import { L2ClaimMessageTransactionSizeProcessor } from "../processors/L2ClaimMessageTransactionSizeProcessor";
|
||||
|
||||
type L2ClaimMessageTransactionSizePollerConfig = {
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Direction } from "../../core/enums/MessageEnums";
|
||||
import { Direction, wait } from "@consensys/linea-sdk";
|
||||
import { ILogger } from "../../core/utils/logging/ILogger";
|
||||
import { IPoller } from "../../core/services/pollers/IPoller";
|
||||
import { IMessageAnchoringProcessor } from "../../core/services/processors/IMessageAnchoringProcessor";
|
||||
import { wait } from "../../core/utils/shared";
|
||||
|
||||
type MessageAnchoringPollerConfig = {
|
||||
direction: Direction;
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Direction } from "../../core/enums/MessageEnums";
|
||||
import { Direction, wait } from "@consensys/linea-sdk";
|
||||
import { ILogger } from "../../core/utils/logging/ILogger";
|
||||
import { IPoller } from "../../core/services/pollers/IPoller";
|
||||
import { IMessageClaimingProcessor } from "../../core/services/processors/IMessageClaimingProcessor";
|
||||
import { wait } from "../../core/utils/shared";
|
||||
|
||||
type MessageClaimingPollerConfig = {
|
||||
direction: Direction;
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Direction } from "../../core/enums/MessageEnums";
|
||||
import { Direction, wait } from "@consensys/linea-sdk";
|
||||
import { ILogger } from "../../core/utils/logging/ILogger";
|
||||
import { IPoller } from "../../core/services/pollers/IPoller";
|
||||
import { wait } from "../../core/utils/shared";
|
||||
import { IMessageClaimingPersister } from "../../core/services/processors/IMessageClaimingPersister";
|
||||
|
||||
type MessagePersistingPollerConfig = {
|
||||
@@ -6,15 +6,14 @@ import {
|
||||
TransactionRequest,
|
||||
TransactionResponse,
|
||||
} from "ethers";
|
||||
import { Direction } from "../../core/enums/MessageEnums";
|
||||
import { Direction, wait } from "@consensys/linea-sdk";
|
||||
import { ILogger } from "../../core/utils/logging/ILogger";
|
||||
import { DEFAULT_INITIAL_FROM_BLOCK } from "../../core/constants";
|
||||
import { IMessageSentEventProcessor } from "../../core/services/processors/IMessageSentEventProcessor";
|
||||
import { Message } from "../../core/entities/Message";
|
||||
import { DatabaseAccessError } from "../../core/errors/DatabaseErrors";
|
||||
import { IChainQuerier } from "../../core/clients/blockchain/IChainQuerier";
|
||||
import { IProvider } from "../../core/clients/blockchain/IProvider";
|
||||
import { IPoller } from "../../core/services/pollers/IPoller";
|
||||
import { wait } from "../../core/utils/shared";
|
||||
import { IMessageDBService } from "../../core/persistence/IMessageDBService";
|
||||
|
||||
type MessageSentEventPollerConfig = {
|
||||
@@ -31,14 +30,14 @@ export class MessageSentEventPoller implements IPoller {
|
||||
* Constructs a new instance of the `MessageSentEventPoller`.
|
||||
*
|
||||
* @param {IMessageSentEventProcessor} eventProcessor - An instance of a class implementing the `IMessageSentEventProcessor` interface, responsible for processing message sent events.
|
||||
* @param {IChainQuerier} chainQuerier - An instance of a class implementing the `IChainQuerier` interface, used to query blockchain data.
|
||||
* @param {IProvider} provider - An instance of a class implementing the `IProvider` interface, used to query blockchain data.
|
||||
* @param {IMessageDBService} databaseService - An instance of a class implementing the `IMessageDBService` interface, used for storing and retrieving message data.
|
||||
* @param {MessageSentEventPollerConfig} config - Configuration settings for the poller, including the direction of message flow, the polling interval, and the initial block number to start listening from.
|
||||
* @param {ILogger} logger - An instance of a class implementing the `ILogger` interface, used for logging messages related to the polling process.
|
||||
*/
|
||||
constructor(
|
||||
private readonly eventProcessor: IMessageSentEventProcessor,
|
||||
private readonly chainQuerier: IChainQuerier<
|
||||
private readonly provider: IProvider<
|
||||
TransactionReceipt,
|
||||
Block,
|
||||
TransactionRequest,
|
||||
@@ -136,7 +135,7 @@ export class MessageSentEventPoller implements IPoller {
|
||||
* @returns {Promise<{ fromBlock: number; fromBlockLogIndex: number }>} An object containing the determined starting block number and log index.
|
||||
*/
|
||||
private async getInitialFromBlock(): Promise<{ fromBlock: number; fromBlockLogIndex: number }> {
|
||||
let fromBlock = await this.chainQuerier.getCurrentBlockNumber();
|
||||
let fromBlock = await this.provider.getBlockNumber();
|
||||
|
||||
const fromBlockLogIndex = 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, it, beforeEach } from "@jest/globals";
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { TestLogger } from "../../../utils/testing/helpers";
|
||||
import { Direction } from "../../../core/enums/MessageEnums";
|
||||
import { testL2NetworkConfig } from "../../../utils/testing/constants";
|
||||
import { IPoller } from "../../../core/services/pollers/IPoller";
|
||||
import { L2ClaimMessageTransactionSizePoller } from "../L2ClaimMessageTransactionSizePoller";
|
||||
@@ -1,9 +1,9 @@
|
||||
import { describe, it, beforeEach } from "@jest/globals";
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { MessageAnchoringPoller } from "../MessageAnchoringPoller";
|
||||
import { TestLogger } from "../../../utils/testing/helpers";
|
||||
import { IMessageAnchoringProcessor } from "../../../core/services/processors/IMessageAnchoringProcessor";
|
||||
import { Direction } from "../../../core/enums/MessageEnums";
|
||||
import { testL2NetworkConfig } from "../../../utils/testing/constants";
|
||||
import { IPoller } from "../../../core/services/pollers/IPoller";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { describe, it, beforeEach } from "@jest/globals";
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { MessageClaimingPoller } from "../MessageClaimingPoller";
|
||||
import { TestLogger } from "../../../utils/testing/helpers";
|
||||
import { IMessageClaimingProcessor } from "../../../core/services/processors/IMessageClaimingProcessor";
|
||||
import { Direction } from "../../../core/enums/MessageEnums";
|
||||
import { testL2NetworkConfig } from "../../../utils/testing/constants";
|
||||
import { IPoller } from "../../../core/services/pollers/IPoller";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { describe, it, beforeEach } from "@jest/globals";
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { Direction } from "@consensys/linea-sdk";
|
||||
import { MessagePersistingPoller } from "../MessagePersistingPoller";
|
||||
import { TestLogger } from "../../../utils/testing/helpers";
|
||||
import { IMessageClaimingPersister } from "../../../core/services/processors/IMessageClaimingPersister";
|
||||
import { Direction } from "../../../core/enums/MessageEnums";
|
||||
import { testL2NetworkConfig } from "../../../utils/testing/constants";
|
||||
import { IPoller } from "../../../core/services/pollers/IPoller";
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
import { describe, it, beforeEach } from "@jest/globals";
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { Block, TransactionReceipt, TransactionRequest, TransactionResponse } from "ethers";
|
||||
import { Provider, DefaultGasProvider, Direction, wait } from "@consensys/linea-sdk";
|
||||
import { TestLogger } from "../../../utils/testing/helpers";
|
||||
import { Direction } from "../../../core/enums/MessageEnums";
|
||||
import { rejectedMessageProps, testL1NetworkConfig, testMessage } from "../../../utils/testing/constants";
|
||||
import { IPoller } from "../../../core/services/pollers/IPoller";
|
||||
import { MessageSentEventPoller } from "../MessageSentEventPoller";
|
||||
import { IMessageSentEventProcessor } from "../../../core/services/processors/IMessageSentEventProcessor";
|
||||
import { IChainQuerier } from "../../../core/clients/blockchain/IChainQuerier";
|
||||
import { IProvider } from "../../../core/clients/blockchain/IProvider";
|
||||
import { IMessageRepository } from "../../../core/persistence/IMessageRepository";
|
||||
import { wait } from "../../../core/utils/shared";
|
||||
import { DatabaseAccessError } from "../../../core/errors/DatabaseErrors";
|
||||
import { DatabaseErrorType, DatabaseRepoName } from "../../../core/enums/DatabaseEnums";
|
||||
import { Block, JsonRpcProvider, TransactionReceipt, TransactionRequest, TransactionResponse } from "ethers";
|
||||
import { DatabaseAccessError } from "../../../core/errors";
|
||||
import { DatabaseErrorType, DatabaseRepoName } from "../../../core/enums";
|
||||
import { EthereumMessageDBService } from "../../persistence/EthereumMessageDBService";
|
||||
import { DefaultGasProvider } from "../../../clients/blockchain/gas/DefaultGasProvider";
|
||||
import {
|
||||
DEFAULT_GAS_ESTIMATION_PERCENTILE,
|
||||
DEFAULT_INITIAL_FROM_BLOCK,
|
||||
DEFAULT_LISTENER_INTERVAL,
|
||||
DEFAULT_MAX_FEE_PER_GAS,
|
||||
DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
} from "../../../core/constants";
|
||||
|
||||
describe("TestMessageSentEventPoller", () => {
|
||||
@@ -26,20 +24,19 @@ describe("TestMessageSentEventPoller", () => {
|
||||
let databaseService: EthereumMessageDBService;
|
||||
|
||||
const eventProcessorMock = mock<IMessageSentEventProcessor>();
|
||||
const l1QuerierMock =
|
||||
mock<IChainQuerier<TransactionReceipt, Block, TransactionRequest, TransactionResponse, JsonRpcProvider>>();
|
||||
const provider = mock<IProvider<TransactionReceipt, Block, TransactionRequest, TransactionResponse, Provider>>();
|
||||
const logger = new TestLogger(MessageSentEventPoller.name);
|
||||
|
||||
beforeEach(() => {
|
||||
const gasProvider = new DefaultGasProvider(l1QuerierMock, {
|
||||
maxFeePerGas: DEFAULT_MAX_FEE_PER_GAS,
|
||||
const gasProvider = new DefaultGasProvider(provider, {
|
||||
maxFeePerGasCap: DEFAULT_MAX_FEE_PER_GAS_CAP,
|
||||
gasEstimationPercentile: DEFAULT_GAS_ESTIMATION_PERCENTILE,
|
||||
enforceMaxGasFee: false,
|
||||
});
|
||||
databaseService = new EthereumMessageDBService(gasProvider, mock<IMessageRepository<unknown>>());
|
||||
testMessageSentEventPoller = new MessageSentEventPoller(
|
||||
eventProcessorMock,
|
||||
l1QuerierMock,
|
||||
provider,
|
||||
databaseService,
|
||||
{
|
||||
direction: Direction.L1_TO_L2,
|
||||
@@ -58,7 +55,7 @@ describe("TestMessageSentEventPoller", () => {
|
||||
describe("start", () => {
|
||||
it("Should return and log as warning if it has been started", async () => {
|
||||
const loggerWarnSpy = jest.spyOn(logger, "warn");
|
||||
jest.spyOn(l1QuerierMock, "getCurrentBlockNumber").mockResolvedValue(10);
|
||||
jest.spyOn(provider, "getBlockNumber").mockResolvedValue(10);
|
||||
jest.spyOn(databaseService, "getLatestMessageSent").mockResolvedValue(null);
|
||||
jest.spyOn(eventProcessorMock, "process").mockResolvedValue({
|
||||
nextFromBlock: 20,
|
||||
@@ -76,7 +73,7 @@ describe("TestMessageSentEventPoller", () => {
|
||||
});
|
||||
|
||||
it("Should call process and log as info if it started successfully", async () => {
|
||||
const l1QuerierMockSpy = jest.spyOn(l1QuerierMock, "getCurrentBlockNumber").mockResolvedValue(10);
|
||||
const l1QuerierMockSpy = jest.spyOn(provider, "getBlockNumber").mockResolvedValue(10);
|
||||
const messageRepositoryMockSpy = jest
|
||||
.spyOn(databaseService, "getLatestMessageSent")
|
||||
.mockResolvedValue(testMessage);
|
||||
@@ -105,7 +102,7 @@ describe("TestMessageSentEventPoller", () => {
|
||||
|
||||
it("Should log as warning if getCurrentBlockNumber throws error", async () => {
|
||||
const error = new Error("Other error for testing");
|
||||
const l1QuerierMockSpy = jest.spyOn(l1QuerierMock, "getCurrentBlockNumber").mockRejectedValue(error);
|
||||
const l1QuerierMockSpy = jest.spyOn(provider, "getBlockNumber").mockRejectedValue(error);
|
||||
const loggerErrorSpy = jest.spyOn(logger, "error");
|
||||
|
||||
await testMessageSentEventPoller.start();
|
||||
@@ -119,7 +116,7 @@ describe("TestMessageSentEventPoller", () => {
|
||||
});
|
||||
|
||||
it("Should log as warning if process throws DatabaseAccessError", async () => {
|
||||
const l1QuerierMockSpy = jest.spyOn(l1QuerierMock, "getCurrentBlockNumber").mockResolvedValue(10);
|
||||
const l1QuerierMockSpy = jest.spyOn(provider, "getBlockNumber").mockResolvedValue(10);
|
||||
const messageRepositoryMockSpy = jest
|
||||
.spyOn(databaseService, "getLatestMessageSent")
|
||||
.mockResolvedValue(testMessage);
|
||||
@@ -162,7 +159,7 @@ describe("TestMessageSentEventPoller", () => {
|
||||
});
|
||||
|
||||
it("Should log as warning or error if process throws Error", async () => {
|
||||
const l1QuerierMockSpy = jest.spyOn(l1QuerierMock, "getCurrentBlockNumber").mockResolvedValue(10);
|
||||
const l1QuerierMockSpy = jest.spyOn(provider, "getBlockNumber").mockResolvedValue(10);
|
||||
const messageRepositoryMockSpy = jest
|
||||
.spyOn(databaseService, "getLatestMessageSent")
|
||||
.mockResolvedValue(testMessage);
|
||||
@@ -193,7 +190,7 @@ describe("TestMessageSentEventPoller", () => {
|
||||
const loggerInfoSpy = jest.spyOn(logger, "info");
|
||||
testMessageSentEventPoller = new MessageSentEventPoller(
|
||||
eventProcessorMock,
|
||||
l1QuerierMock,
|
||||
provider,
|
||||
databaseService,
|
||||
{
|
||||
direction: Direction.L1_TO_L2,
|
||||
6
postman/src/services/pollers/index.ts
Normal file
6
postman/src/services/pollers/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export { DatabaseCleaningPoller } from "./DatabaseCleaningPoller";
|
||||
export { L2ClaimMessageTransactionSizePoller } from "./L2ClaimMessageTransactionSizePoller";
|
||||
export { MessageAnchoringPoller } from "./MessageAnchoringPoller";
|
||||
export { MessageClaimingPoller } from "./MessageClaimingPoller";
|
||||
export { MessagePersistingPoller } from "./MessagePersistingPoller";
|
||||
export { MessageSentEventPoller } from "./MessageSentEventPoller";
|
||||
@@ -1,5 +1,12 @@
|
||||
import { ContractTransactionResponse, Overrides, Signer, TransactionReceipt, TransactionResponse } from "ethers";
|
||||
import { MessageStatus } from "../../core/enums/MessageEnums";
|
||||
import {
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription,
|
||||
Overrides,
|
||||
Signer,
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
} from "ethers";
|
||||
import { MessageStatus } from "../../core/enums";
|
||||
import { ILogger } from "../../core/utils/logging/ILogger";
|
||||
import { IMessageDBService } from "../../core/persistence/IMessageDBService";
|
||||
import { IL2MessageServiceClient } from "../../core/clients/blockchain/linea/IL2MessageServiceClient";
|
||||
@@ -26,7 +33,8 @@ export class L2ClaimMessageTransactionSizeProcessor implements IL2ClaimMessageTr
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse,
|
||||
Signer
|
||||
Signer,
|
||||
ErrorDescription
|
||||
>,
|
||||
private readonly transactionSizeCalculator: IL2ClaimTransactionSizeCalculator,
|
||||
private readonly config: L2ClaimMessageTransactionSizeProcessorConfig,
|
||||
@@ -6,13 +6,15 @@ import {
|
||||
Block,
|
||||
TransactionRequest,
|
||||
JsonRpcProvider,
|
||||
ErrorDescription,
|
||||
} from "ethers";
|
||||
import { OnChainMessageStatus } from "@consensys/linea-sdk";
|
||||
import {
|
||||
IMessageAnchoringProcessor,
|
||||
MessageAnchoringProcessorConfig,
|
||||
} from "../../core/services/processors/IMessageAnchoringProcessor";
|
||||
import { IChainQuerier } from "../../core/clients/blockchain/IChainQuerier";
|
||||
import { MessageStatus, OnChainMessageStatus } from "../../core/enums/MessageEnums";
|
||||
import { IProvider } from "../../core/clients/blockchain/IProvider";
|
||||
import { MessageStatus } from "../../core/enums";
|
||||
import { ILogger } from "../../core/utils/logging/ILogger";
|
||||
import { IMessageServiceContract } from "../../core/services/contracts/IMessageServiceContract";
|
||||
import { IMessageDBService } from "../../core/persistence/IMessageDBService";
|
||||
@@ -24,7 +26,7 @@ export class MessageAnchoringProcessor implements IMessageAnchoringProcessor {
|
||||
* Constructs a new instance of the `MessageAnchoringProcessor`.
|
||||
*
|
||||
* @param {IMessageServiceContract<Overrides, TransactionReceipt, TransactionResponse, ContractTransactionResponse>} contractClient - An instance of a class implementing the `IMessageServiceContract` interface, used to interact with the blockchain contract.
|
||||
* @param {IChainQuerier<TransactionReceipt, Block, TransactionRequest, TransactionResponse, JsonRpcProvider>} chainQuerier - An instance of a class implementing the `IChainQuerier` interface, used to query blockchain data.
|
||||
* @param {IProvider<TransactionReceipt, Block, TransactionRequest, TransactionResponse, JsonRpcProvider>} provider - An instance of a class implementing the `IProvider` interface, used to query blockchain data.
|
||||
* @param {IMessageDBService<ContractTransactionResponse>} databaseService - An instance of a class implementing the `IMessageDBService` interface, used for storing and retrieving message data.
|
||||
* @param {MessageAnchoringProcessorConfig} config - Configuration settings for the processor, including the maximum number of messages to fetch from the database for processing.
|
||||
* @param {ILogger} logger - An instance of a class implementing the `ILogger` interface, used for logging messages.
|
||||
@@ -34,9 +36,10 @@ export class MessageAnchoringProcessor implements IMessageAnchoringProcessor {
|
||||
Overrides,
|
||||
TransactionReceipt,
|
||||
TransactionResponse,
|
||||
ContractTransactionResponse
|
||||
ContractTransactionResponse,
|
||||
ErrorDescription
|
||||
>,
|
||||
private readonly chainQuerier: IChainQuerier<
|
||||
private readonly provider: IProvider<
|
||||
TransactionReceipt,
|
||||
Block,
|
||||
TransactionRequest,
|
||||
@@ -70,7 +73,7 @@ export class MessageAnchoringProcessor implements IMessageAnchoringProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
const latestBlockNumber = await this.chainQuerier.getCurrentBlockNumber();
|
||||
const latestBlockNumber = await this.provider.getBlockNumber();
|
||||
|
||||
for (const message of messages) {
|
||||
const messageStatus = await this.contractClient.getMessageStatus(message.messageHash, {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user