diff --git a/.github/workflows/sparta.yml b/.github/workflows/sparta.yml index 1a1833e..77c8925 100644 --- a/.github/workflows/sparta.yml +++ b/.github/workflows/sparta.yml @@ -7,6 +7,11 @@ permissions: contents: read pull-requests: write +env: + TF_LOG: DEBUG + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + jobs: terraform-sparta: name: Terraform Sparta Bot @@ -15,29 +20,61 @@ jobs: run: working-directory: tooling/sparta/terraform - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - TF_VAR_bot_token: ${{ secrets.BOT_TOKEN }} - TF_VAR_passport_api_key: ${{ secrets.PASSPORT_API_KEY }} - TF_VAR_ethereum_host: ${{ secrets.ETHEREUM_HOST }} - TF_VAR_backend_api_key: ${{ secrets.BACKEND_API_KEY }} - TF_VAR_aws_region: "eu-west-2" - TF_VAR_environment: "production" - TF_VAR_bot_client_id: "1329079356785688616" - TF_VAR_guild_id: "1144692727120937080" - TF_VAR_passport_verified_role_id: "1364982673604345886" - TF_VAR_minimum_score: "10" - TF_VAR_passport_scorer_id: "11493" - TF_VAR_vite_reown_project_id: "d037e9da5c5c9b24cfcd94c509d88dce" - TF_VAR_staking_asset_handler_address: "0xF739D03e98e23A7B65940848aBA8921fF3bAc4b2" - TF_VAR_l1_chain_id: "11155111" - TF_VAR_local_dynamo_db: "false" - TF_VAR_dynamodb_local_endpoint: "http://localhost:8000" - TF_VAR_log_level: "info" - TF_VAR_log_pretty_print: "false" - TF_VAR_api_port: "3000" steps: - name: Checkout uses: actions/checkout@v4 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.5.7 + + - name: Terraform Init + run: terraform init + + - name: Terraform Format + run: terraform fmt -check + continue-on-error: true + + - name: Terraform Validate + run: terraform validate + + - name: Generate terraform.production.tfvars + run: | + cat > terraform.production.tfvars << EOF + # ============================================================================= + # AWS Configuration + # ============================================================================= + aws_region = "eu-west-2" + environment = "production" + + # ============================================================================= + # Application Secrets & Configuration + # ============================================================================= + + # --- Discord --- + bot_token = "${{ secrets.BOT_TOKEN }}" + bot_client_id = "1329079356785688616" + guild_id = "1144692727120937080" + + # --- Ethereum --- + ethereum_host = "${{ secrets.ETHEREUM_HOST }}" + staking_asset_handler_address = "0xF739D03e98e23A7B65940848aBA8921fF3bAc4b2" + l1_chain_id = "11155111" + + # --- DynamoDB --- + local_dynamo_db = false + dynamodb_local_endpoint = "http://localhost:8000" + + # --- Logging --- + log_level = "debug" + log_pretty_print = false + + # --- API Configuration --- + api_port = 3000 + backend_api_key = "${{ secrets.BACKEND_API_KEY }}" + EOF + + - name: Terraform Apply + run: terraform apply -var-file="terraform.production.tfvars" -auto-approve -input=false diff --git a/.gitignore b/.gitignore index 19dfa3f..cd7260e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ proofs debug_*.json crs yarn-error.log +.env* \ No newline at end of file diff --git a/tooling/sparta/.dockerignore b/tooling/sparta/.dockerignore index 64d19ff..d670621 100644 --- a/tooling/sparta/.dockerignore +++ b/tooling/sparta/.dockerignore @@ -1,3 +1,34 @@ -.env -.env* +# Git files +.git +.gitignore + +# Node.js dependencies +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs (adjust if your build output is different) dist +build +.next + +# Terraform state and plugins +terraform/.terraform +*.tfstate +*.tfstate.backup + +# Environment files +.env* +!.env.example + +# IDE/Editor folders +.vscode +.idea + +# OS generated files +.DS_Store +Thumbs.db + +# Other potential artifacts (add more as needed) +*.log diff --git a/tooling/sparta/.env.example b/tooling/sparta/.env.example new file mode 100644 index 0000000..38ea246 --- /dev/null +++ b/tooling/sparta/.env.example @@ -0,0 +1,53 @@ +# ------------------------------------- +# Express Server Configuration +# ------------------------------------- +# Port for the API server +API_PORT=3000 + +# ------------------------------------- +# Discord Bot Configuration +# ------------------------------------- +# Discord Bot Token (from Discord Developer Portal) +BOT_TOKEN=your_discord_bot_token_here +# Discord Application/Client ID (from Discord Developer Portal) +BOT_CLIENT_ID=your_discord_client_id_here +# ID of the Discord Server (Guild) where the bot operates +GUILD_ID=your_discord_guild_id_here + +# ------------------------------------- +# Verification Web App (Vite Frontend) +# ------------------------------------- +# Base URL of the verification web app (e.g., http://localhost:5173 or your deployed URL) +# Used to generate the verification link sent to the user. +API_URL=http://localhost:3000 # for vite frontend + +# ------------------------------------- +# DynamoDB Configuration +# ------------------------------------- +# Set to "true" to use a local DynamoDB instance (e.g., Docker container) +LOCAL_DYNAMO_DB=true +# Endpoint URL for local DynamoDB (only used if LOCAL_DYNAMO_DB is true) +DYNAMODB_LOCAL_ENDPOINT=http://localhost:8000 + +# --- AWS Credentials (Required if LOCAL_DYNAMO_DB=false and not using IAM roles/profiles) --- +AWS_REGION=us-east-1 +# AWS_ACCESS_KEY_ID=your_aws_access_key_here +# AWS_SECRET_ACCESS_KEY=your_aws_secret_key_here + +# ------------------------------------- +# Logging Configuration +# ------------------------------------- +# Log level: 'debug', 'info', 'warn', 'error' +LOG_LEVEL=info +# Set to "false" to disable pretty printing of logs (JSON output) +LOG_PRETTY_PRINT=true + +# ------------------------------------- +# Ethereum Configuration (Used by Moderator/NodeOperator commands) +# ------------------------------------- +# RPC URL for the Ethereum network (e.g., Sepolia) +ETHEREUM_HOST=your_ethereum_rpc_url_here +# Chain ID for the Ethereum network (e.g., 11155111 for Sepolia) +L1_CHAIN_ID=11155111 +# Staking asset handler contract address +STAKING_ASSET_HANDLER_ADDRESS=your_staking_asset_handler_address_here diff --git a/tooling/sparta/.github/workflows/terraform-deploy.yml b/tooling/sparta/.github/workflows/terraform-deploy.yml new file mode 100644 index 0000000..b36141f --- /dev/null +++ b/tooling/sparta/.github/workflows/terraform-deploy.yml @@ -0,0 +1,61 @@ +name: Terraform Deploy + +on: + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + +jobs: + terraform: + name: Terraform + runs-on: ubuntu-latest + + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + TF_VAR_bot_token: ${{ secrets.BOT_TOKEN }} + TF_VAR_ethereum_host: ${{ secrets.ETHEREUM_HOST }} + TF_VAR_backend_api_key: ${{ secrets.BACKEND_API_KEY }} + TF_VAR_aws_region: "eu-west-2" + TF_VAR_environment: "production" + TF_VAR_bot_client_id: "1329079356785688616" + TF_VAR_guild_id: "1144692727120937080" + TF_VAR_staking_asset_handler_address: "0xF739D03e98e23A7B65940848aBA8921fF3bAc4b2" + TF_VAR_l1_chain_id: "11155111" + TF_VAR_local_dynamo_db: "false" + TF_VAR_dynamodb_local_endpoint: "http://localhost:8000" + TF_VAR_log_level: "info" + TF_VAR_log_pretty_print: "false" + TF_VAR_api_port: "3000" + + defaults: + run: + working-directory: tooling/sparta/terraform + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.5.7 + + - name: Terraform Init + id: init + run: terraform init + + - name: Terraform Format + id: fmt + run: terraform fmt -check + continue-on-error: true + + - name: Terraform Validate + id: validate + run: terraform validate + + - name: Terraform Apply + run: | + terraform apply -auto-approve diff --git a/tooling/sparta/.gitignore b/tooling/sparta/.gitignore index 2e9690e..23773d3 100644 --- a/tooling/sparta/.gitignore +++ b/tooling/sparta/.gitignore @@ -38,3 +38,5 @@ Thumbs.db bun.lockb yarn.lock package-lock.json +.cursor/ +out.txt \ No newline at end of file diff --git a/tooling/sparta/Dockerfile b/tooling/sparta/Dockerfile index 4ccbf1d..0f725bd 100644 --- a/tooling/sparta/Dockerfile +++ b/tooling/sparta/Dockerfile @@ -1,5 +1,5 @@ -# Sparta Discord Bot Dockerfile -# This Dockerfile builds the Sparta Discord bot for deployment +# Sparta API & Frontend Dockerfile +# This Dockerfile builds the Sparta API (Express) and Frontend (Vite) for deployment # Start with the official Bun image FROM oven/bun:latest @@ -10,30 +10,51 @@ ENV PATH="/root/.foundry/bin:${PATH}" # Install required dependencies # - curl: For downloading tools # - apt-utils: For better apt functionality -RUN apt update && apt install -y curl apt-utils +RUN apt update && apt install -y curl apt-utils git -# Install Docker within the container for potential nested container operations -RUN curl -fsSL https://get.docker.com | bash +# Install Docker within the container (If needed for runtime operations, otherwise remove) +# RUN curl -fsSL https://get.docker.com | bash -# Install Foundry toolkit for Ethereum development (cast, anvil, forge) +# Install Foundry toolkit for Ethereum development (If needed for runtime operations, otherwise remove) RUN curl -L https://foundry.paradigm.xyz | bash RUN foundryup # Verify Foundry installation by checking cast version -RUN cast --version +# RUN cast --version # Optional: remove if not needed for runtime verification # Set the working directory WORKDIR /app -# Copy package files first to leverage Docker layer caching -# This way, dependencies are only re-installed when package files change -COPY src/package.json src/bun.lockb ./ -RUN bun install +# Copy the root package.json and lockfile +COPY package.json bun.lock ./ -# Then copy the rest of the source code -# This step is separate to avoid reinstalling dependencies when only code changes -COPY src ./ +# Copy package.json files from workspaces to ensure dependencies are captured +# Create the packages directory first +RUN mkdir packages +COPY packages/express/package.json ./packages/express/ +COPY packages/utils/package.json ./packages/utils/ +COPY packages/discord/package.json ./packages/discord/ +COPY packages/ethereum/package.json ./packages/ethereum/ +COPY packages/scheduler/package.json ./packages/scheduler/ +# Add other packages if they exist and are needed -# Start the bot -# Uses the production start command from package.json -CMD ["bun", "run", "start"] +# Install all dependencies for the monorepo using the lockfile +RUN bun install --frozen-lockfile + +# Copy the entire monorepo source code +# This includes Express, Vite, Utils, etc. +COPY . . + +# Declare the build argument for the Vite frontend URL +ARG API_URL + +ENV API_URL=$API_URL + +# Expose the port the Express server will listen on +# Make sure this matches the PORT environment variable passed in Terraform (var.api_port) +EXPOSE 3000 + +# Start ONLY the Express API server using its own start script +# Assumes a "start" script exists in packages/express/package.json (or the relevant API package) +# This avoids running the root build/swagger scripts at runtime. +CMD ["bun", "--filter=@sparta/api", "--filter=@sparta/discord", "run", "start"] diff --git a/tooling/sparta/README.md b/tooling/sparta/README.md index 82e491a..c0117c8 100644 --- a/tooling/sparta/README.md +++ b/tooling/sparta/README.md @@ -1,272 +1,154 @@ # Sparta Discord Bot -A Discord bot for managing Aztec validators and community roles, built with Bun/TypeScript and deployed on AWS Elastic Beanstalk. +A Discord bot for managing Aztec validators and community roles, built with Bun/TypeScript and deployed on AWS. -## Overview +## Project Overview -Sparta is a Discord bot designed to manage and monitor Aztec validators and community roles within the Discord server. It provides: +Sparta is a Discord bot designed to manage and monitor Aztec validators and community roles within a Discord server: -- **Role Management**: Automatically assigns roles based on user scores from Google Sheets -- **Validator Management**: Commands to add, remove, and check validators -- **Chain Information**: Retrieves blockchain data like pending blocks, proven blocks, epochs, slots -- **Discord Integration**: Full integration with Discord slash commands +- **Validator Management**: Commands to register, remove, and monitor validators +- **Role Management**: Assigns roles based on user scores +- **Chain Monitoring**: Retrieves and displays blockchain data like blocks, epochs, slots +- **API Integration**: RESTful API for integration with other services -## Prerequisites +## Architecture -- [Bun](https://bun.sh) v1.0 or higher (used as runtime and package manager) -- Node.js v18 or higher (for development tools) -- AWS CLI configured with appropriate credentials -- Terraform v1.0 or higher -- Discord Bot Token and Application ID from [Discord Developer Portal](https://discord.com/developers/applications) -- Ethereum node access (local or remote) -- Google Sheets API access (for role management) - -## Security Notice - -⚠️ **Important**: This project uses sensitive credentials that should never be committed to version control: -- Discord bot tokens -- Ethereum private keys -- AWS credentials -- Google Sheets API credentials -- Environment variables - -Always use: -- `.env` files for local development (never commit these) -- AWS Secrets Manager for production secrets -- `terraform.tfvars` for Terraform variables (never commit this) -- Ensure `.gitignore` includes all sensitive files -- Use environment-specific configuration files - -## Project Structure +The project follows a modular structure with several packages: ``` sparta/ -├── src/ # Source code -│ ├── clients/ # External API clients (Discord, Ethereum, Google) -│ ├── roles/ # Role-specific Discord commands -│ │ ├── nodeOperators/ # Commands for Node Operator role -│ │ └── admins/ # Admin-only commands -│ ├── services/ # Business logic services -│ │ ├── chaininfo-service.ts # Chain information retrieval -│ │ ├── discord-service.ts # Discord role management -│ │ ├── googlesheet-service.ts # Google Sheets integration -│ │ ├── validator-service.ts # Validator management -│ │ └── index.ts # Service exports -│ └── utils/ # Utility functions -├── terraform/ # Infrastructure as Code -└── Dockerfile # Docker configuration +├── packages/ +│ ├── discord/ # Discord bot and command handling +│ ├── ethereum/ # Ethereum blockchain integration +│ ├── utils/ # Shared utilities +│ ├── api/ # Express API server (package.json: @sparta/api) +│ └── scheduler/ # Lambda-based validator monitoring +├── terraform/ # Infrastructure as code +└── scripts/ # Utility scripts ``` +### Key Components + +- **Discord Bot** (@sparta/discord): Core Discord integration for slash commands and messaging +- **Ethereum Client** (@sparta/ethereum): Blockchain interaction for validator management +- **API Server** (@sparta/api): RESTful API for integration and validator management +- **Scheduler** (@sparta/scheduler): AWS Lambda for automated validator monitoring +- **Utils** (@sparta/utils): Shared utilities for logging, DynamoDB, and constants + ## Local Development -1. Clone the repository: -```bash -git clone -cd sparta -``` +### Prerequisites -2. Install dependencies using Bun: -```bash -cd src -bun install -``` +- [Bun](https://bun.sh) v1.0+ (package manager and runtime) +- Node.js v18+ +- AWS CLI configured +- Discord Bot Token from [Discord Developer Portal](https://discord.com/developers/applications) -3. Create a `.env` file in the `src` directory using `.env.example` as a template: +### Setup + +1. Clone the repository +2. Install dependencies: ```bash -cp .env.example .env +cd sparta +bun install ``` -4. Fill in the required environment variables in `.env`. Required variables include: +3. Create a `.env` file with required environment variables: ``` # Discord Bot Configuration -BOT_TOKEN=your_bot_token -BOT_CLIENT_ID=your_client_id -GUILD_ID=your_guild_id +BOT_TOKEN=your_discord_bot_token +BOT_CLIENT_ID=your_discord_client_id +GUILD_ID=your_discord_server_id + +# API Configuration +API_PORT=3000 +API_URL=http://localhost:3000 # Ethereum Configuration -ETHEREUM_HOST=http://localhost:8545 -MINTER_PRIVATE_KEY=your_private_key -ETHEREUM_REGISTRY_ADDRESS=your_registry_address -WITHDRAWER_ADDRESS=address_to_withdraw_funds_to -ETHEREUM_CHAIN_ID=1337 -ETHEREUM_VALUE=20ether -MINIMUM_STAKE=100000000000000000000 -APPROVAL_AMOUNT=10000000000000000000000 - -# Google Sheets Configuration -GOOGLE_API_KEY=your_api_key -SPREADSHEET_ID=your_spreadsheet_id -``` +ETHEREUM_HOST=your_ethereum_rpc_url +L1_CHAIN_ID=11155111 +STAKING_ASSET_HANDLER_ADDRESS=your_contract_address -5. Start the bot in development mode with hot reloading: -```bash -bun run dev +# DynamoDB Configuration +LOCAL_DYNAMO_DB=true +DYNAMODB_LOCAL_ENDPOINT=http://localhost:8000 + +# Logging +LOG_LEVEL=debug +LOG_PRETTY_PRINT=true ``` -6. For building a production version: +4. Start local DynamoDB: ```bash -bun run build +bun run scripts/start-local-dynamodb.sh ``` -7. To start the production version: +5. Run the project: ```bash -bun run start -``` +# Run API and Discord bot +bun run dev -## Building with Docker +# Run only API +bun run dev:api -1. Build the Docker image: -```bash -docker build -t sparta-bot . +# Run only scheduler +bun run dev:scheduler ``` -2. Run the container: -```bash -docker run -d --name sparta-bot --env-file ./src/.env sparta-bot -``` +## Deployment -## Deployment with Terraform +The project is deployed using Terraform to AWS services: -The bot is deployed using Terraform to AWS Elastic Container Service (ECS). Follow these steps: +- **Discord Bot & API**: AWS Elastic Container Service (ECS) +- **Validator Monitor**: AWS Lambda + EventBridge +- **Database**: DynamoDB +- **Infrastructure**: Load Balancer, IAM roles, Security Groups -1. Navigate to the terraform directory: -```bash -cd terraform -``` +### Deployment Process -2. Create `terraform.tfvars` using the example file: -```bash -cp terraform.tfvars.example terraform.tfvars -``` - -3. Fill in the required variables in `terraform.tfvars`. +1. Configure AWS credentials +2. Update Terraform variables in `terraform/terraform.tfvars` +3. Deploy using: -4. Initialize Terraform: ```bash +cd terraform terraform init -``` - -5. Deploy: -```bash terraform apply ``` -## Bot Functionality - -### Role Management -- Monitors Google Sheets for user scores -- Assigns Discord roles based on score thresholds: - - Node Operator (base role): Default role - - Defender (middle role): Score > 5 - - Sentinel (highest role): Score > 10 - -### Validator Management -- Add validators to the blockchain -- Remove validators from the blockchain -- Check validator status and information - -### Chain Information -- Get pending block number -- Get proven block number -- Check current epoch and slot -- View committee members - -## Available Commands - -### Node Operator Commands -- `/get-info`: Get chain information including pending block, proven block, current epoch, current slot, and proposer -- `/validator check`: Check if an address is a validator -- `/validator register`: Register a validator address -- `/validator help`: Get help for validator commands - -### Admin Commands -(More details in the admin command section) - -## Environment Variables - -### Development -- Uses `.env` file for local configuration -- Supports hot reloading through `bun run dev` -- Environment-specific configurations (.env.local, .env.staging) +Alternatively, use the GitHub Actions workflow: -### Production -- Uses AWS Secrets Manager for secure configuration -- Automatically loads secrets in production environment -- Supports staging and production environments +1. Configure GitHub repository secrets +2. Trigger the "Terraform Deploy" workflow -## Security Best Practices +## Configuration -1. **Environment Variables** - - Never commit .env files - - Use different env files for different environments - - Rotate secrets regularly +The application can be configured through environment variables and Terraform variables. See individual package READMEs for specific configuration options. -2. **AWS Security** - - Use IAM roles with least privilege - - Enable CloudWatch logging - - Use security groups to restrict access +## Development Workflow -3. **Discord Security** - - Implement command permissions - - Use ephemeral messages for sensitive info - - Validate user inputs +1. Make changes to source code +2. Run tests locally +3. Create a pull request +4. Upon approval, merge to main branch +5. Deploy using Terraform -4. **Ethereum Security** - - Never expose private keys - - Use secure RPC endpoints - - Implement transaction signing safeguards +## Terraform Workflow Details -## Monitoring and Logging - -- AWS CloudWatch for container logs -- Discord command execution logging -- Error tracking and reporting -- Performance monitoring - -## Logging - -The application uses Pino for structured logging with the following features: - -- **Multiple log levels**: trace, debug, info, warn, error, fatal -- **Colorful output**: Different colors for different log levels when pretty printing is enabled -- **Timestamps**: Each log includes an ISO timestamp -- **Request logging**: HTTP requests can be logged at the debug level -- **Structured logging**: Logs are output in JSON format for easy parsing - -### Configuration - -Logging can be configured through environment variables: - -- `LOG_LEVEL`: Set the minimum log level (trace, debug, info, warn, error, fatal) -- `LOG_PRETTY_PRINT`: Enable/disable colorful, human-readable logs (true/false) - -#### Example - -```sh -# Set log level to debug and enable pretty printing -export LOG_LEVEL=debug -export LOG_PRETTY_PRINT=true -npm run dev -``` - -### Terraform Configuration - -Logging can also be configured through Terraform variables: - -```hcl -module "sparta" { - # ... - log_level = "debug" - log_pretty_print = true -} -``` +The GitHub Actions workflow located in `.github/workflows/terraform-deploy.yml` handles automated deployment: -## Contributing +1. Checks out code +2. Sets up Terraform +3. Initializes Terraform +4. Validates configuration +5. Deploys infrastructure -1. Create a feature branch -2. Make your changes -3. Submit a pull request +The workflow uses repository secrets for sensitive information. -## Support +## Packages -For support, please open an issue in the repository or contact the maintainers. +- **@sparta/utils**: Common utilities for logging, DynamoDB, constants, and OpenAPI +- **@sparta/ethereum**: Ethereum blockchain connectivity and validator management +- **@sparta/discord**: Discord bot integration and command handling +- **@sparta/api**: Express API server for RESTful endpoints +- **@sparta/scheduler**: AWS Lambda for scheduled validator monitoring diff --git a/tooling/sparta/bun.lock b/tooling/sparta/bun.lock new file mode 100644 index 0000000..00bbe59 --- /dev/null +++ b/tooling/sparta/bun.lock @@ -0,0 +1,1445 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "sparta", + "dependencies": { + "@aws-sdk/client-dynamodb": "^3.788.0", + "@aws-sdk/lib-dynamodb": "^3.789.0", + "@aztec/aztec.js": "^0.86.0", + "@graphprotocol/graph-ts": "^0.38.0", + "dotenv": "^16.4.0", + "node-fetch": "^3.3.0", + "viem": "^2.7.0", + }, + "devDependencies": { + "@types/bun": "latest", + "@types/swagger-jsdoc": "^6.0.4", + "@types/swagger-ui-express": "^4.1.8", + "http-proxy-middleware": "^3.0.5", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.1", + }, + "peerDependencies": { + "typescript": "^5.8.3", + }, + }, + "packages/discord": { + "name": "@sparta/discord", + "version": "0.0.1", + "dependencies": { + "@discordjs/rest": "^2.0.1", + "@sparta/ethereum": "workspace:*", + "@sparta/utils": "workspace:*", + "axios": "^1.6.2", + "discord-api-types": "^0.37.67", + "discord.js": "^14.12.1", + "openapi-client-axios": "^7.5.1", + }, + "devDependencies": { + "typescript": "^5.0.4", + }, + }, + "packages/ethereum": { + "name": "@sparta/ethereum", + "version": "0.1.0", + "dependencies": { + "@sparta/utils": "^0.1.0", + "pino": "^8.16.0", + "viem": "^2.0.0", + }, + "devDependencies": { + "@types/bun": "latest", + "typescript": "^5.3.3", + }, + "peerDependencies": { + "typescript": "^5.0.0", + }, + }, + "packages/express": { + "name": "@sparta/api", + "dependencies": { + "@sparta/discord": "workspace:*", + "@sparta/ethereum": "workspace:*", + "@sparta/utils": "workspace:*", + "axios": "^1.6.7", + "cors": "^2.8.5", + "discord.js": "^14.14.1", + "dotenv": "^16.5.0", + "express": "^4.18.2", + "openapi-client-axios": "^7.6.0", + "swagger-autogen": "^2.23.7", + "swagger2openapi": "^7.0.8", + "viem": "^2.9.15", + }, + "devDependencies": { + "@types/bun": "latest", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/node": "^20.11.0", + "@types/uuid": "^9.0.8", + "openapi-client-axios-typegen": "^7.7.0", + "ts-node-dev": "^2.0.0", + "typescript": "^5.3.3", + }, + }, + "packages/scheduler": { + "name": "@sparta/scheduler", + "version": "0.1.0", + "dependencies": { + "@sparta/discord": "workspace:*", + "@sparta/ethereum": "workspace:*", + "@sparta/utils": "workspace:*", + "openapi-client-axios": "^7.5.1", + }, + "devDependencies": { + "aws-sdk": "^2.1499.0", + }, + }, + "packages/utils": { + "name": "@sparta/utils", + "version": "0.1.0", + "dependencies": { + "@aws-sdk/client-dynamodb": "^3.427.0", + "@aws-sdk/lib-dynamodb": "^3.427.0", + "pino": "^8.16.0", + }, + "devDependencies": { + "@types/bun": "latest", + "typescript": "^5.3.3", + }, + "peerDependencies": { + "typescript": "^5.0.0", + }, + }, + }, + "packages": { + "@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.0", "", {}, "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg=="], + + "@anttiviljami/dtsgenerator": ["@anttiviljami/dtsgenerator@3.20.0", "", { "dependencies": { "commander": "^11.1.0", "cross-fetch": "^4.0.0", "debug": "^4.3.4", "glob": "^10.3.10", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "js-yaml": "^4.1.0", "tslib": "^2.6.2", "typescript": "^5.2.2" }, "bin": { "dtsgen": "bin/dtsgen" } }, "sha512-b90uOx7/dC53mo8fHfXXz3Iy20nLkIaZXBZt6RwPzxMll9MZTG5rVkJdy74vxw9ngmnrtC8Z4elmGgNA2aeTIA=="], + + "@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@11.9.3", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0" } }, "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ=="], + + "@apidevtools/openapi-schemas": ["@apidevtools/openapi-schemas@2.1.0", "", {}, "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ=="], + + "@apidevtools/swagger-methods": ["@apidevtools/swagger-methods@3.0.2", "", {}, "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg=="], + + "@apidevtools/swagger-parser": ["@apidevtools/swagger-parser@10.0.3", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.6", "@apidevtools/openapi-schemas": "^2.0.4", "@apidevtools/swagger-methods": "^3.0.2", "@jsdevtools/ono": "^7.1.3", "call-me-maybe": "^1.0.1", "z-schema": "^5.0.1" }, "peerDependencies": { "openapi-types": ">=7" } }, "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g=="], + + "@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="], + + "@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="], + + "@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="], + + "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], + + "@aws-sdk/client-dynamodb": ["@aws-sdk/client-dynamodb@3.810.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.810.0", "@aws-sdk/credential-provider-node": "3.810.0", "@aws-sdk/middleware-endpoint-discovery": "3.808.0", "@aws-sdk/middleware-host-header": "3.804.0", "@aws-sdk/middleware-logger": "3.804.0", "@aws-sdk/middleware-recursion-detection": "3.804.0", "@aws-sdk/middleware-user-agent": "3.810.0", "@aws-sdk/region-config-resolver": "3.808.0", "@aws-sdk/types": "3.804.0", "@aws-sdk/util-endpoints": "3.808.0", "@aws-sdk/util-user-agent-browser": "3.804.0", "@aws-sdk/util-user-agent-node": "3.810.0", "@smithy/config-resolver": "^4.1.2", "@smithy/core": "^3.3.3", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.6", "@smithy/middleware-retry": "^4.1.7", "@smithy/middleware-serde": "^4.0.5", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.1.1", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.14", "@smithy/util-defaults-mode-node": "^4.0.14", "@smithy/util-endpoints": "^3.0.4", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.3", "@smithy/util-utf8": "^4.0.0", "@smithy/util-waiter": "^4.0.3", "@types/uuid": "^9.0.1", "tslib": "^2.6.2", "uuid": "^9.0.1" } }, "sha512-AU492ZqySeFjbaBMhtVKx8DJNCENWyY0VUbaK7bQQjsskIHDecfqkXCBaWe5QjHdV/KXkbgGHYJReiBDyxjQ0A=="], + + "@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.810.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.810.0", "@aws-sdk/middleware-host-header": "3.804.0", "@aws-sdk/middleware-logger": "3.804.0", "@aws-sdk/middleware-recursion-detection": "3.804.0", "@aws-sdk/middleware-user-agent": "3.810.0", "@aws-sdk/region-config-resolver": "3.808.0", "@aws-sdk/types": "3.804.0", "@aws-sdk/util-endpoints": "3.808.0", "@aws-sdk/util-user-agent-browser": "3.804.0", "@aws-sdk/util-user-agent-node": "3.810.0", "@smithy/config-resolver": "^4.1.2", "@smithy/core": "^3.3.3", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.6", "@smithy/middleware-retry": "^4.1.7", "@smithy/middleware-serde": "^4.0.5", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.1.1", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.14", "@smithy/util-defaults-mode-node": "^4.0.14", "@smithy/util-endpoints": "^3.0.4", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.3", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-Txp/3jHqkfA4BTklQEOGiZ1yTUxg+hITislfaWEzJ904vlDt4DvAljTlhfaz7pceCLA2+LhRlYZYSv7t5b0Ltw=="], + + "@aws-sdk/core": ["@aws-sdk/core@3.810.0", "", { "dependencies": { "@aws-sdk/types": "3.804.0", "@smithy/core": "^3.3.3", "@smithy/node-config-provider": "^4.1.1", "@smithy/property-provider": "^4.0.2", "@smithy/protocol-http": "^5.1.0", "@smithy/signature-v4": "^5.1.0", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "@smithy/util-middleware": "^4.0.2", "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" } }, "sha512-s2IJk+qa/15YZcv3pbdQNATDR+YdYnHf94MrAeVAWubtRLnzD8JciC+gh4LSPp7JzrWSvVOg2Ut1S+0y89xqCg=="], + + "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.810.0", "", { "dependencies": { "@aws-sdk/core": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-iwHqF+KryKONfbdFk3iKhhPk4fHxh5QP5fXXR//jhYwmszaLOwc7CLCE9AxhgiMzAs+kV8nBFQZvdjFpPzVGOA=="], + + "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.810.0", "", { "dependencies": { "@aws-sdk/core": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/property-provider": "^4.0.2", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "@smithy/util-stream": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-SKzjLd+8ugif7yy9sOAAdnPE1vCBHQe6jKgs2AadMpCmWm34DiHz/KuulHdvURUGMIi7CvmaC8aH77twDPYbtg=="], + + "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.810.0", "", { "dependencies": { "@aws-sdk/core": "3.810.0", "@aws-sdk/credential-provider-env": "3.810.0", "@aws-sdk/credential-provider-http": "3.810.0", "@aws-sdk/credential-provider-process": "3.810.0", "@aws-sdk/credential-provider-sso": "3.810.0", "@aws-sdk/credential-provider-web-identity": "3.810.0", "@aws-sdk/nested-clients": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/credential-provider-imds": "^4.0.4", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-H2QCSnxWJ/mj8HTcyHmCmyQ5bO/+imRi4mlBIpUyKjiYKro52WD3gXlGgPIDo2q3UFIHq37kmYvS00i+qIY9tw=="], + + "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.810.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.810.0", "@aws-sdk/credential-provider-http": "3.810.0", "@aws-sdk/credential-provider-ini": "3.810.0", "@aws-sdk/credential-provider-process": "3.810.0", "@aws-sdk/credential-provider-sso": "3.810.0", "@aws-sdk/credential-provider-web-identity": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/credential-provider-imds": "^4.0.4", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-9E3Chv3x+RBM3N1bwLCyvXxoiPAckCI74wG7ePN4F3b/7ieIkbEl/3Hd67j1fnt62Xa1cjUHRu2tz5pdEv5G1Q=="], + + "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.810.0", "", { "dependencies": { "@aws-sdk/core": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-42kE6MLdsmMGp1id3Gisal4MbMiF7PIc0tAznTeIuE8r7cIF8yeQWw/PBOIvjyI57DxbyKzLUAMEJuigUpApCw=="], + + "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.810.0", "", { "dependencies": { "@aws-sdk/client-sso": "3.810.0", "@aws-sdk/core": "3.810.0", "@aws-sdk/token-providers": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-8WjX6tz+FCvM93Y33gsr13p/HiiTJmVn5AK1O8PTkvHBclQDzmtAW5FdPqTpAJGswLW2FB0xRqdsSMN2dQEjNw=="], + + "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.810.0", "", { "dependencies": { "@aws-sdk/core": "3.810.0", "@aws-sdk/nested-clients": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-uKQJY0AcPyrvMmfGLo36semgjqJ4vmLTqOSW9u40qQDspRnG73/P09lAO2ntqKlhwvMBt3XfcNnOpyyhKRcOfA=="], + + "@aws-sdk/endpoint-cache": ["@aws-sdk/endpoint-cache@3.804.0", "", { "dependencies": { "mnemonist": "0.38.3", "tslib": "^2.6.2" } }, "sha512-TQVDkA/lV6ua75ELZaichMzlp6x7tDa1bqdy/+0ZftmODPtKXuOOEcJxmdN7Ui/YRo1gkRz2D9txYy7IlNg1Og=="], + + "@aws-sdk/lib-dynamodb": ["@aws-sdk/lib-dynamodb@3.810.0", "", { "dependencies": { "@aws-sdk/core": "3.810.0", "@aws-sdk/util-dynamodb": "3.810.0", "@smithy/core": "^3.3.3", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "peerDependencies": { "@aws-sdk/client-dynamodb": "^3.810.0" } }, "sha512-3GmNCn6/wW0EUP54FfKywFmLIrd5w+aPY9vvSFLrRc2bZLKpLD8ZxLkEyjVDoIDeQqQ951gRv2dp3scPnpC1yA=="], + + "@aws-sdk/middleware-endpoint-discovery": ["@aws-sdk/middleware-endpoint-discovery@3.808.0", "", { "dependencies": { "@aws-sdk/endpoint-cache": "3.804.0", "@aws-sdk/types": "3.804.0", "@smithy/node-config-provider": "^4.1.1", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-h8LAIO6tuA0JAahrg+oSIVZpb6rhJOFVDDqYNQVp6ZdawlIzpZcc1sa+XVZvarBnThNKqvLTSGK7boSRmaLAwg=="], + + "@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.804.0", "", { "dependencies": { "@aws-sdk/types": "3.804.0", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-bum1hLVBrn2lJCi423Z2fMUYtsbkGI2s4N+2RI2WSjvbaVyMSv/WcejIrjkqiiMR+2Y7m5exgoKeg4/TODLDPQ=="], + + "@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.804.0", "", { "dependencies": { "@aws-sdk/types": "3.804.0", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-w/qLwL3iq0KOPQNat0Kb7sKndl9BtceigINwBU7SpkYWX9L/Lem6f8NPEKrC9Tl4wDBht3Yztub4oRTy/horJA=="], + + "@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.804.0", "", { "dependencies": { "@aws-sdk/types": "3.804.0", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zqHOrvLRdsUdN/ehYfZ9Tf8svhbiLLz5VaWUz22YndFv6m9qaAcijkpAOlKexsv3nLBMJdSdJ6GUTAeIy3BZzw=="], + + "@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.810.0", "", { "dependencies": { "@aws-sdk/core": "3.810.0", "@aws-sdk/types": "3.804.0", "@aws-sdk/util-endpoints": "3.808.0", "@smithy/core": "^3.3.3", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-gLMJcqgIq7k9skX8u0Yyi+jil4elbsmLf3TuDuqNdlqiZ44/AKdDFfU3mU5tRUtMfP42a3gvb2U3elP0BIeybQ=="], + + "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.810.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.810.0", "@aws-sdk/middleware-host-header": "3.804.0", "@aws-sdk/middleware-logger": "3.804.0", "@aws-sdk/middleware-recursion-detection": "3.804.0", "@aws-sdk/middleware-user-agent": "3.810.0", "@aws-sdk/region-config-resolver": "3.808.0", "@aws-sdk/types": "3.804.0", "@aws-sdk/util-endpoints": "3.808.0", "@aws-sdk/util-user-agent-browser": "3.804.0", "@aws-sdk/util-user-agent-node": "3.810.0", "@smithy/config-resolver": "^4.1.2", "@smithy/core": "^3.3.3", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.6", "@smithy/middleware-retry": "^4.1.7", "@smithy/middleware-serde": "^4.0.5", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.1.1", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.14", "@smithy/util-defaults-mode-node": "^4.0.14", "@smithy/util-endpoints": "^3.0.4", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.3", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-w+tGXFSQjzvJ3j2sQ4GJRdD+YXLTgwLd9eG/A+7pjrv2yLLV70M4HqRrFqH06JBjqT5rsOxonc/QSjROyxk+IA=="], + + "@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.808.0", "", { "dependencies": { "@aws-sdk/types": "3.804.0", "@smithy/node-config-provider": "^4.1.1", "@smithy/types": "^4.2.0", "@smithy/util-config-provider": "^4.0.0", "@smithy/util-middleware": "^4.0.2", "tslib": "^2.6.2" } }, "sha512-9x2QWfphkARZY5OGkl9dJxZlSlYM2l5inFeo2bKntGuwg4A4YUe5h7d5yJ6sZbam9h43eBrkOdumx03DAkQF9A=="], + + "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.810.0", "", { "dependencies": { "@aws-sdk/nested-clients": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-fdgHRCDpnzsD+0km7zuRbHRysJECfS8o9T9/pZ6XAr1z2FNV/UveHtnUYq0j6XpDMrIm0/suvXbshIjQU+a+sw=="], + + "@aws-sdk/types": ["@aws-sdk/types@3.804.0", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg=="], + + "@aws-sdk/util-dynamodb": ["@aws-sdk/util-dynamodb@3.810.0", "", { "dependencies": { "tslib": "^2.6.2" }, "peerDependencies": { "@aws-sdk/client-dynamodb": "^3.810.0" } }, "sha512-0oPFhzYz15z8FI7wuaXjPUqVP3cQjehblBaQ98M6iLcdTIpZTkRyJNQkqFJsEmSeAjdw9b3LvLcJ9yDwj6NBjA=="], + + "@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.808.0", "", { "dependencies": { "@aws-sdk/types": "3.804.0", "@smithy/types": "^4.2.0", "@smithy/util-endpoints": "^3.0.4", "tslib": "^2.6.2" } }, "sha512-N6Lic98uc4ADB7fLWlzx+1uVnq04VgVjngZvwHoujcRg9YDhIg9dUDiTzD5VZv13g1BrPYmvYP1HhsildpGV6w=="], + + "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.804.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A=="], + + "@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.804.0", "", { "dependencies": { "@aws-sdk/types": "3.804.0", "@smithy/types": "^4.2.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-KfW6T6nQHHM/vZBBdGn6fMyG/MgX5lq82TDdX4HRQRRuHKLgBWGpKXqqvBwqIaCdXwWHgDrg2VQups6GqOWW2A=="], + + "@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.810.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.810.0", "@aws-sdk/types": "3.804.0", "@smithy/node-config-provider": "^4.1.1", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-T56/ANEGNuvhqVoWZdr+0ZY2hjV93cH2OfGHIlVTVSAMACWG54XehDPESEso1CJNhJGYZPsE+FE42HGCk/XDMg=="], + + "@aztec/aztec.js": ["@aztec/aztec.js@0.86.0", "", { "dependencies": { "@aztec/constants": "0.86.0", "@aztec/entrypoints": "0.86.0", "@aztec/ethereum": "0.86.0", "@aztec/foundation": "0.86.0", "@aztec/l1-artifacts": "0.86.0", "@aztec/protocol-contracts": "0.86.0", "@aztec/stdlib": "0.86.0", "axios": "^1.8.2", "tslib": "^2.4.0", "viem": "2.23.7" } }, "sha512-nUfT31+7W+hEdOMpx2K62WZPtN9vVNr96FPJ2psBKdTx4fzXtuX2NE/ZrgHFtEenycDWEgjlEcYG9aR5LI51Bw=="], + + "@aztec/bb.js": ["@aztec/bb.js@0.86.0", "", { "dependencies": { "comlink": "^4.4.1", "commander": "^12.1.0", "debug": "^4.3.4", "fflate": "^0.8.0", "pako": "^2.1.0", "tslib": "^2.4.0" }, "bin": { "bb.js": "dest/node/main.js" } }, "sha512-9XcEltM0qRJpNvowZ0w2TY1YCDXlktxupBG+HHi6P+snF/wBhAXPzJb5mdqEkVcVqcwXskVoBdj4XqTLNiPZKg=="], + + "@aztec/blob-lib": ["@aztec/blob-lib@0.86.0", "", { "dependencies": { "@aztec/constants": "0.86.0", "@aztec/foundation": "0.86.0", "c-kzg": "4.0.0-alpha.1", "tslib": "^2.4.0" } }, "sha512-GyTnqC3nCkfUKayQRk8RBy/MftejTgcrqGn5tryK3Vo21LJSPzo6MGe/tZ/glqxX2CpwI8YkFtPCbBaOPvZQTg=="], + + "@aztec/constants": ["@aztec/constants@0.86.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-xNlaNkBGodgEeSfwee7yevPNgMvNCMl9jZ2j+gBAR+SrbGtMkdTo1aNg732gcQNFjW+3MN/rUNMqPodWD0KN4A=="], + + "@aztec/entrypoints": ["@aztec/entrypoints@0.86.0", "", { "dependencies": { "@aztec/constants": "0.86.0", "@aztec/foundation": "0.86.0", "@aztec/protocol-contracts": "0.86.0", "@aztec/stdlib": "0.86.0", "tslib": "^2.4.0" } }, "sha512-V9st4p1+EaDNk7srix6nMCgPXVodBpIm+uMEhtoUUSXWWrCJIaioywHOAkqeLR6Roq0epDT849yWgcvUIrQOhA=="], + + "@aztec/ethereum": ["@aztec/ethereum@0.86.0", "", { "dependencies": { "@aztec/blob-lib": "0.86.0", "@aztec/foundation": "0.86.0", "@aztec/l1-artifacts": "0.86.0", "@viem/anvil": "^0.0.10", "dotenv": "^16.0.3", "tslib": "^2.4.0", "viem": "2.23.7", "zod": "^3.23.8" } }, "sha512-ApBl27p4Sr19IH5XJUruKSLV1CkR2NDkh7Km39PCdbtJ086KL4yG/Zs8IFAq9Irwx2JwLFSoGGeOuporKf+QPA=="], + + "@aztec/foundation": ["@aztec/foundation@0.86.0", "", { "dependencies": { "@aztec/bb.js": "0.86.0", "@koa/cors": "^5.0.0", "@noble/curves": "^1.2.0", "bn.js": "^5.2.1", "c-kzg": "4.0.0-alpha.1", "colorette": "^2.0.20", "debug": "^4.3.4", "detect-node": "^2.1.0", "hash.js": "^1.1.7", "koa": "^2.16.1", "koa-bodyparser": "^4.4.0", "koa-compress": "^5.1.0", "koa-router": "^12.0.0", "leveldown": "^6.1.1", "lodash.chunk": "^4.2.0", "lodash.clonedeepwith": "^4.5.0", "pako": "^2.1.0", "pino": "^9.5.0", "pino-pretty": "^13.0.0", "sha3": "^2.1.4", "undici": "^5.28.5", "zod": "^3.23.8" } }, "sha512-7jWbH4oZrMPMLuKEKPyu7fMa5wk2eLZVaKZR2TtLPUQKlJdtgA/UuLvRirmFEDlsIF22AkorHfQmFxBSxzogoQ=="], + + "@aztec/l1-artifacts": ["@aztec/l1-artifacts@0.86.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-qvEzljtfH7Z6EYwp8m/Enzl2bhYZap8TgEM8AKzYVjo3Mi9OW9jFLhQwUzQ6o6X1PzTDb1/k4GYQSR1dxVGsmg=="], + + "@aztec/noir-noirc_abi": ["@aztec/noir-noirc_abi@0.86.0", "", { "dependencies": { "@aztec/noir-types": "0.86.0" } }, "sha512-HgCm2slJHguMNQmBJfFlkrJ66k9hv5uj+GOY+E2OfqCMCVPV+ORdAXxE+gZq+u5CFxT7jhk05i5g8hYHc6+Ziw=="], + + "@aztec/noir-types": ["@aztec/noir-types@0.86.0", "", {}, "sha512-+Q7Ql8SFklbtG1oIN8+6BNLEvXQRji9kmmgT2pARQwMNa3tfU3ybPUHTPMpapcB58Hbn1Sv84TpZvr9cweycEA=="], + + "@aztec/protocol-contracts": ["@aztec/protocol-contracts@0.86.0", "", { "dependencies": { "@aztec/constants": "0.86.0", "@aztec/foundation": "0.86.0", "@aztec/stdlib": "0.86.0", "lodash.chunk": "^4.2.0", "lodash.omit": "^4.5.0", "tslib": "^2.4.0" } }, "sha512-dAUlqROtbjb/yvL6IzaDb43WigdUuZ4+Yx2tY6I1NWcy41S7BO4ClH49zjIemozcClyn9qKIpEGokJFej7lMLg=="], + + "@aztec/stdlib": ["@aztec/stdlib@0.86.0", "", { "dependencies": { "@aztec/bb.js": "0.86.0", "@aztec/blob-lib": "0.86.0", "@aztec/constants": "0.86.0", "@aztec/ethereum": "0.86.0", "@aztec/foundation": "0.86.0", "@aztec/noir-noirc_abi": "0.86.0", "@google-cloud/storage": "^7.15.0", "lodash.chunk": "^4.2.0", "lodash.isequal": "^4.5.0", "lodash.omit": "^4.5.0", "lodash.times": "^4.3.2", "msgpackr": "^1.11.2", "pako": "^2.1.0", "tslib": "^2.4.0", "viem": "2.23.7", "zod": "^3.23.8" } }, "sha512-8oeGazLUGx6rtKAIz8GOUgSwZg4uRAYhVbRREYd79JGiwu96hVQ3suTlKdHK4gc1EYOugvuUpKS+8eAKC3rv9g=="], + + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], + + "@discordjs/builders": ["@discordjs/builders@1.11.2", "", { "dependencies": { "@discordjs/formatters": "^0.6.1", "@discordjs/util": "^1.1.1", "@sapphire/shapeshift": "^4.0.0", "discord-api-types": "^0.38.1", "fast-deep-equal": "^3.1.3", "ts-mixer": "^6.0.4", "tslib": "^2.6.3" } }, "sha512-F1WTABdd8/R9D1icJzajC4IuLyyS8f3rTOz66JsSI3pKvpCAtsMBweu8cyNYsIyvcrKAVn9EPK+Psoymq+XC0A=="], + + "@discordjs/collection": ["@discordjs/collection@1.5.3", "", {}, "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ=="], + + "@discordjs/formatters": ["@discordjs/formatters@0.6.1", "", { "dependencies": { "discord-api-types": "^0.38.1" } }, "sha512-5cnX+tASiPCqCWtFcFslxBVUaCetB0thvM/JyavhbXInP1HJIEU+Qv/zMrnuwSsX3yWH2lVXNJZeDK3EiP4HHg=="], + + "@discordjs/rest": ["@discordjs/rest@2.5.0", "", { "dependencies": { "@discordjs/collection": "^2.1.1", "@discordjs/util": "^1.1.1", "@sapphire/async-queue": "^1.5.3", "@sapphire/snowflake": "^3.5.3", "@vladfrangu/async_event_emitter": "^2.4.6", "discord-api-types": "^0.38.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.1" } }, "sha512-PWhchxTzpn9EV3vvPRpwS0EE2rNYB9pvzDU/eLLW3mByJl0ZHZjHI2/wA8EbH2gRMQV7nu+0FoDF84oiPl8VAQ=="], + + "@discordjs/util": ["@discordjs/util@1.1.1", "", {}, "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g=="], + + "@discordjs/ws": ["@discordjs/ws@1.2.2", "", { "dependencies": { "@discordjs/collection": "^2.1.0", "@discordjs/rest": "^2.5.0", "@discordjs/util": "^1.1.0", "@sapphire/async-queue": "^1.5.2", "@types/ws": "^8.5.10", "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "^0.38.1", "tslib": "^2.6.2", "ws": "^8.17.0" } }, "sha512-dyfq7yn0wO0IYeYOs3z79I6/HumhmKISzFL0Z+007zQJMtAFGtt3AEoq1nuLXtcunUE5YYYQqgKvybXukAK8/w=="], + + "@exodus/schemasafe": ["@exodus/schemasafe@1.3.0", "", {}, "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw=="], + + "@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="], + + "@google-cloud/paginator": ["@google-cloud/paginator@5.0.2", "", { "dependencies": { "arrify": "^2.0.0", "extend": "^3.0.2" } }, "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg=="], + + "@google-cloud/projectify": ["@google-cloud/projectify@4.0.0", "", {}, "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA=="], + + "@google-cloud/promisify": ["@google-cloud/promisify@4.0.0", "", {}, "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g=="], + + "@google-cloud/storage": ["@google-cloud/storage@7.16.0", "", { "dependencies": { "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "<4.1.0", "abort-controller": "^3.0.0", "async-retry": "^1.3.3", "duplexify": "^4.1.3", "fast-xml-parser": "^4.4.1", "gaxios": "^6.0.2", "google-auth-library": "^9.6.3", "html-entities": "^2.5.2", "mime": "^3.0.0", "p-limit": "^3.0.1", "retry-request": "^7.0.0", "teeny-request": "^9.0.0", "uuid": "^8.0.0" } }, "sha512-7/5LRgykyOfQENcm6hDKP8SX/u9XxE5YOiWOkgkwcoO+cG8xT/cyOvp9wwN3IxfdYgpHs8CE7Nq2PKX2lNaEXw=="], + + "@graphprotocol/graph-ts": ["@graphprotocol/graph-ts@0.38.0", "", { "dependencies": { "assemblyscript": "0.27.31" } }, "sha512-fx9IpqbXHWMskl6wLDstKLy0VeszTQg6K5xsUEHXPkpOtceDkWAiDE8FyqsGF0IVTmE2Pxafw4t6+rEG8lVfyw=="], + + "@hapi/bourne": ["@hapi/bourne@3.0.0", "", {}, "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], + + "@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="], + + "@koa/cors": ["@koa/cors@5.0.0", "", { "dependencies": { "vary": "^1.1.2" } }, "sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw=="], + + "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="], + + "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="], + + "@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3", "", { "os": "linux", "cpu": "arm" }, "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw=="], + + "@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg=="], + + "@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg=="], + + "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="], + + "@noble/curves": ["@noble/curves@1.8.2", "", { "dependencies": { "@noble/hashes": "1.7.2" } }, "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g=="], + + "@noble/hashes": ["@noble/hashes@1.7.2", "", {}, "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ=="], + + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + + "@sapphire/async-queue": ["@sapphire/async-queue@1.5.5", "", {}, "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="], + + "@sapphire/shapeshift": ["@sapphire/shapeshift@4.0.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" } }, "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg=="], + + "@sapphire/snowflake": ["@sapphire/snowflake@3.5.3", "", {}, "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ=="], + + "@scarf/scarf": ["@scarf/scarf@1.4.0", "", {}, "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ=="], + + "@scure/base": ["@scure/base@1.2.5", "", {}, "sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw=="], + + "@scure/bip32": ["@scure/bip32@1.6.2", "", { "dependencies": { "@noble/curves": "~1.8.1", "@noble/hashes": "~1.7.1", "@scure/base": "~1.2.2" } }, "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw=="], + + "@scure/bip39": ["@scure/bip39@1.5.4", "", { "dependencies": { "@noble/hashes": "~1.7.1", "@scure/base": "~1.2.4" } }, "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA=="], + + "@smithy/abort-controller": ["@smithy/abort-controller@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Sl/78VDtgqKxN2+1qduaVE140XF+Xg+TafkncspwM4jFP/LHr76ZHmIY/y3V1M0mMLNk+Je6IGbzxy23RSToMw=="], + + "@smithy/config-resolver": ["@smithy/config-resolver@4.1.2", "", { "dependencies": { "@smithy/node-config-provider": "^4.1.1", "@smithy/types": "^4.2.0", "@smithy/util-config-provider": "^4.0.0", "@smithy/util-middleware": "^4.0.2", "tslib": "^2.6.2" } }, "sha512-7r6mZGwb5LmLJ+zPtkLoznf2EtwEuSWdtid10pjGl/7HefCE4mueOkrfki8JCUm99W6UfP47/r3tbxx9CfBN5A=="], + + "@smithy/core": ["@smithy/core@3.3.3", "", { "dependencies": { "@smithy/middleware-serde": "^4.0.5", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.2", "@smithy/util-stream": "^4.2.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-CiJNc0b/WdnttAfQ6uMkxPQ3Z8hG/ba8wF89x9KtBBLDdZk6CX52K4F8hbe94uNbc8LDUuZFtbqfdhM3T21naw=="], + + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.0.4", "", { "dependencies": { "@smithy/node-config-provider": "^4.1.1", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "tslib": "^2.6.2" } }, "sha512-jN6M6zaGVyB8FmNGG+xOPQB4N89M1x97MMdMnm1ESjljLS3Qju/IegQizKujaNcy2vXAvrz0en8bobe6E55FEA=="], + + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.0.2", "", { "dependencies": { "@smithy/protocol-http": "^5.1.0", "@smithy/querystring-builder": "^4.0.2", "@smithy/types": "^4.2.0", "@smithy/util-base64": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-+9Dz8sakS9pe7f2cBocpJXdeVjMopUDLgZs1yWeu7h++WqSbjUYv/JAJwKwXw1HV6gq1jyWjxuyn24E2GhoEcQ=="], + + "@smithy/hash-node": ["@smithy/hash-node@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-VnTpYPnRUE7yVhWozFdlxcYknv9UN7CeOqSrMH+V877v4oqtVYuoqhIhtSjmGPvYrYnAkaM61sLMKHvxL138yg=="], + + "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GatB4+2DTpgWPday+mnUkoumP54u/MDM/5u44KF9hIu8jF0uafZtQLcdfIKkIcUNuF/fBojpLEHZS/56JqPeXQ=="], + + "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw=="], + + "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.0.2", "", { "dependencies": { "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-hAfEXm1zU+ELvucxqQ7I8SszwQ4znWMbNv6PLMndN83JJN41EPuS93AIyh2N+gJ6x8QFhzSO6b7q2e6oClDI8A=="], + + "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.1.6", "", { "dependencies": { "@smithy/core": "^3.3.3", "@smithy/middleware-serde": "^4.0.5", "@smithy/node-config-provider": "^4.1.1", "@smithy/shared-ini-file-loader": "^4.0.2", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-middleware": "^4.0.2", "tslib": "^2.6.2" } }, "sha512-Zdieg07c3ua3ap5ungdcyNnY1OsxmsXXtKDTk28+/YbwIPju0Z1ZX9X5AnkjmDE3+AbqgvhtC/ZuCMSr6VSfPw=="], + + "@smithy/middleware-retry": ["@smithy/middleware-retry@4.1.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.1.1", "@smithy/protocol-http": "^5.1.0", "@smithy/service-error-classification": "^4.0.3", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.3", "tslib": "^2.6.2", "uuid": "^9.0.1" } }, "sha512-lFIFUJ0E/4I0UaIDY5usNUzNKAghhxO0lDH4TZktXMmE+e4ActD9F154Si0Unc01aCPzcwd+NcOwQw6AfXXRRQ=="], + + "@smithy/middleware-serde": ["@smithy/middleware-serde@4.0.5", "", { "dependencies": { "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-yREC3q/HXqQigq29xX3hiy6tFi+kjPKXoYUQmwQdgPORLbQ0n6V2Z/Iw9Nnlu66da9fM/WhDtGvYvqwecrCljQ=="], + + "@smithy/middleware-stack": ["@smithy/middleware-stack@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-eSPVcuJJGVYrFYu2hEq8g8WWdJav3sdrI4o2c6z/rjnYDd3xH9j9E7deZQCzFn4QvGPouLngH3dQ+QVTxv5bOQ=="], + + "@smithy/node-config-provider": ["@smithy/node-config-provider@4.1.1", "", { "dependencies": { "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-1slS5jf5icHETwl5hxEVBj+mh6B+LbVW4yRINsGtUKH+nxM5Pw2H59+qf+JqYFCHp9jssG4vX81f5WKnjMN3Vw=="], + + "@smithy/node-http-handler": ["@smithy/node-http-handler@4.0.4", "", { "dependencies": { "@smithy/abort-controller": "^4.0.2", "@smithy/protocol-http": "^5.1.0", "@smithy/querystring-builder": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-/mdqabuAT3o/ihBGjL94PUbTSPSRJ0eeVTdgADzow0wRJ0rN4A27EOrtlK56MYiO1fDvlO3jVTCxQtQmK9dZ1g=="], + + "@smithy/property-provider": ["@smithy/property-provider@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-wNRoQC1uISOuNc2s4hkOYwYllmiyrvVXWMtq+TysNRVQaHm4yoafYQyjN/goYZS+QbYlPIbb/QRjaUZMuzwQ7A=="], + + "@smithy/protocol-http": ["@smithy/protocol-http@5.1.0", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-KxAOL1nUNw2JTYrtviRRjEnykIDhxc84qMBzxvu1MUfQfHTuBlCG7PA6EdVwqpJjH7glw7FqQoFxUJSyBQgu7g=="], + + "@smithy/querystring-builder": ["@smithy/querystring-builder@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-NTOs0FwHw1vimmQM4ebh+wFQvOwkEf/kQL6bSM1Lock+Bv4I89B3hGYoUEPkmvYPkDKyp5UdXJYu+PoTQ3T31Q=="], + + "@smithy/querystring-parser": ["@smithy/querystring-parser@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-v6w8wnmZcVXjfVLjxw8qF7OwESD9wnpjp0Dqry/Pod0/5vcEA3qxCr+BhbOHlxS8O+29eLpT3aagxXGwIoEk7Q=="], + + "@smithy/service-error-classification": ["@smithy/service-error-classification@4.0.3", "", { "dependencies": { "@smithy/types": "^4.2.0" } }, "sha512-FTbcajmltovWMjj3tksDQdD23b2w6gH+A0DYA1Yz3iSpjDj8fmkwy62UnXcWMy4d5YoMoSyLFHMfkEVEzbiN8Q=="], + + "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-J9/gTWBGVuFZ01oVA6vdb4DAjf1XbDhK6sLsu3OS9qmLrS6KB5ygpeHiM3miIbj1qgSJ96GYszXFWv6ErJ8QEw=="], + + "@smithy/signature-v4": ["@smithy/signature-v4@5.1.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.0.0", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "@smithy/util-hex-encoding": "^4.0.0", "@smithy/util-middleware": "^4.0.2", "@smithy/util-uri-escape": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-4t5WX60sL3zGJF/CtZsUQTs3UrZEDO2P7pEaElrekbLqkWPYkgqNW1oeiNYC6xXifBnT9dVBOnNQRvOE9riU9w=="], + + "@smithy/smithy-client": ["@smithy/smithy-client@4.2.6", "", { "dependencies": { "@smithy/core": "^3.3.3", "@smithy/middleware-endpoint": "^4.1.6", "@smithy/middleware-stack": "^4.0.2", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", "@smithy/util-stream": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-WEqP0wQ1N/lVS4pwNK1Vk+0i6QIr66cq/xbu1dVy1tM0A0qYwAYyz0JhbquzM5pMa8s89lyDBtoGKxo7iG74GA=="], + + "@smithy/types": ["@smithy/types@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-7eMk09zQKCO+E/ivsjQv+fDlOupcFUCSC/L2YUPgwhvowVGWbPQHjEFcmjt7QQ4ra5lyowS92SV53Zc6XD4+fg=="], + + "@smithy/url-parser": ["@smithy/url-parser@4.0.2", "", { "dependencies": { "@smithy/querystring-parser": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Bm8n3j2ScqnT+kJaClSVCMeiSenK6jVAzZCNewsYWuZtnBehEz4r2qP0riZySZVfzB+03XZHJeqfmJDkeeSLiQ=="], + + "@smithy/util-base64": ["@smithy/util-base64@4.0.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg=="], + + "@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA=="], + + "@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg=="], + + "@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.0.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug=="], + + "@smithy/util-config-provider": ["@smithy/util-config-provider@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w=="], + + "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.0.14", "", { "dependencies": { "@smithy/property-provider": "^4.0.2", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-l7QnMX8VcDOH6n/fBRu4zqguSlOBZxFzWqp58dXFSARFBjNlmEDk5G/z4T7BMGr+rI0Pg8MkhmMUfEtHFgpy2g=="], + + "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.0.14", "", { "dependencies": { "@smithy/config-resolver": "^4.1.2", "@smithy/credential-provider-imds": "^4.0.4", "@smithy/node-config-provider": "^4.1.1", "@smithy/property-provider": "^4.0.2", "@smithy/smithy-client": "^4.2.6", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Ujs1gsWDo3m/T63VWBTBmHLTD2UlU6J6FEokLCEp7OZQv45jcjLHoxTwgWsi8ULpsYozvH4MTWkRP+bhwr0vDg=="], + + "@smithy/util-endpoints": ["@smithy/util-endpoints@3.0.4", "", { "dependencies": { "@smithy/node-config-provider": "^4.1.1", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-VfFATC1bmZLV2858B/O1NpMcL32wYo8DPPhHxYxDCodDl3f3mSZ5oJheW1IF91A0EeAADz2WsakM/hGGPGNKLg=="], + + "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw=="], + + "@smithy/util-middleware": ["@smithy/util-middleware@4.0.2", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6GDamTGLuBQVAEuQ4yDQ+ti/YINf/MEmIegrEeg7DdB/sld8BX1lqt9RRuIcABOhAGTA50bRbPzErez7SlDtDQ=="], + + "@smithy/util-retry": ["@smithy/util-retry@4.0.3", "", { "dependencies": { "@smithy/service-error-classification": "^4.0.3", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-DPuYjZQDXmKr/sNvy9Spu8R/ESa2e22wXZzSAY6NkjOLj6spbIje/Aq8rT97iUMdDj0qHMRIe+bTxvlU74d9Ng=="], + + "@smithy/util-stream": ["@smithy/util-stream@4.2.0", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/types": "^4.2.0", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-hex-encoding": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-Vj1TtwWnuWqdgQI6YTUF5hQ/0jmFiOYsc51CSMgj7QfyO+RF4EnT2HNjoviNlOOmgzgvf3f5yno+EiC4vrnaWQ=="], + + "@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="], + + "@smithy/util-utf8": ["@smithy/util-utf8@4.0.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow=="], + + "@smithy/util-waiter": ["@smithy/util-waiter@4.0.3", "", { "dependencies": { "@smithy/abort-controller": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-JtaY3FxmD+te+KSI2FJuEcfNC9T/DGGVf551babM7fAaXhjJUt7oSYurH1Devxd2+BOSUACCgt3buinx4UnmEA=="], + + "@sparta/api": ["@sparta/api@workspace:packages/express"], + + "@sparta/discord": ["@sparta/discord@workspace:packages/discord"], + + "@sparta/ethereum": ["@sparta/ethereum@workspace:packages/ethereum"], + + "@sparta/scheduler": ["@sparta/scheduler@workspace:packages/scheduler"], + + "@sparta/utils": ["@sparta/utils@workspace:packages/utils"], + + "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], + + "@tsconfig/node10": ["@tsconfig/node10@1.0.11", "", {}, "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw=="], + + "@tsconfig/node12": ["@tsconfig/node12@1.0.11", "", {}, "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="], + + "@tsconfig/node14": ["@tsconfig/node14@1.0.3", "", {}, "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="], + + "@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="], + + "@types/body-parser": ["@types/body-parser@1.19.5", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg=="], + + "@types/bun": ["@types/bun@1.2.13", "", { "dependencies": { "bun-types": "1.2.13" } }, "sha512-u6vXep/i9VBxoJl3GjZsl/BFIsvML8DfVDO0RYLEwtSZSp981kEO1V5NwRcO1CPJ7AmvpbnDCiMKo3JvbDEjAg=="], + + "@types/caseless": ["@types/caseless@0.12.5", "", {}, "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg=="], + + "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], + + "@types/cors": ["@types/cors@2.8.18", "", { "dependencies": { "@types/node": "*" } }, "sha512-nX3d0sxJW41CqQvfOzVG1NCTXfFDrDWIghCZncpHeWlVFd81zxB/DLhg7avFg6eHLCRX7ckBmoIIcqa++upvJA=="], + + "@types/express": ["@types/express@4.17.21", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } }, "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ=="], + + "@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.6", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A=="], + + "@types/http-errors": ["@types/http-errors@2.0.4", "", {}, "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA=="], + + "@types/http-proxy": ["@types/http-proxy@1.17.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/mime": ["@types/mime@1.3.5", "", {}, "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="], + + "@types/node": ["@types/node@20.17.47", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-3dLX0Upo1v7RvUimvxLeXqwrfyKxUINk0EAM83swP2mlSUcwV73sZy8XhNz8bcZ3VbsfQyC/y6jRdL5tgCNpDQ=="], + + "@types/qs": ["@types/qs@6.9.18", "", {}, "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA=="], + + "@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="], + + "@types/request": ["@types/request@2.48.12", "", { "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", "form-data": "^2.5.0" } }, "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw=="], + + "@types/send": ["@types/send@0.17.4", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA=="], + + "@types/serve-static": ["@types/serve-static@1.15.7", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "*" } }, "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw=="], + + "@types/strip-bom": ["@types/strip-bom@3.0.0", "", {}, "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ=="], + + "@types/strip-json-comments": ["@types/strip-json-comments@0.0.30", "", {}, "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ=="], + + "@types/swagger-jsdoc": ["@types/swagger-jsdoc@6.0.4", "", {}, "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ=="], + + "@types/swagger-ui-express": ["@types/swagger-ui-express@4.1.8", "", { "dependencies": { "@types/express": "*", "@types/serve-static": "*" } }, "sha512-AhZV8/EIreHFmBV5wAs0gzJUNq9JbbSXgJLQubCC0jtIo6prnI9MIRRxnU4MZX9RB9yXxF1V4R7jtLl/Wcj31g=="], + + "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="], + + "@types/uuid": ["@types/uuid@9.0.8", "", {}, "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="], + + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + + "@viem/anvil": ["@viem/anvil@0.0.10", "", { "dependencies": { "execa": "^7.1.1", "get-port": "^6.1.2", "http-proxy": "^1.18.1", "ws": "^8.13.0" } }, "sha512-9PzYXBRikfSUhhm8Bd0avv07agwcbMJ5FaSu2D2vbE0cxkvXGtolL3fW5nz2yefMqOqVQL4XzfM5nwY81x3ytw=="], + + "@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.6", "", {}, "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA=="], + + "abitype": ["abitype@1.0.8", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3 >=3.22.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg=="], + + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], + + "abstract-leveldown": ["abstract-leveldown@7.2.0", "", { "dependencies": { "buffer": "^6.0.3", "catering": "^2.0.0", "is-buffer": "^2.0.5", "level-concat-iterator": "^3.0.0", "level-supports": "^2.0.1", "queue-microtask": "^1.2.3" } }, "sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ=="], + + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + + "acorn": ["acorn@7.4.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="], + + "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], + + "agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], + + "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], + + "assemblyscript": ["assemblyscript@0.27.31", "", { "dependencies": { "binaryen": "116.0.0-nightly.20240114", "long": "^5.2.1" }, "bin": { "asc": "bin/asc.js", "asinit": "bin/asinit.js" } }, "sha512-Ra8kiGhgJQGZcBxjtMcyVRxOEJZX64kd+XGpjWzjcjgxWJVv+CAQO0aDBk4GQVhjYbOkATarC83mHjAVGtwPBQ=="], + + "async-retry": ["async-retry@1.3.3", "", { "dependencies": { "retry": "0.13.1" } }, "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + + "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], + + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], + + "aws-sdk": ["aws-sdk@2.1692.0", "", { "dependencies": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", "xml2js": "0.6.2" } }, "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw=="], + + "axios": ["axios@1.9.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "bath-es5": ["bath-es5@3.0.3", "", {}, "sha512-PdCioDToH3t84lP40kUFCKWCOCH389Dl1kbC8FGoqOwamxsmqxxnJSXdkTOsPoNHXjem4+sJ+bbNoQm5zeCqxg=="], + + "bignumber.js": ["bignumber.js@9.3.0", "", {}, "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "binaryen": ["binaryen@116.0.0-nightly.20240114", "", { "bin": { "wasm2js": "bin/wasm2js", "wasm-opt": "bin/wasm-opt" } }, "sha512-0GZrojJnuhoe+hiwji7QFaL3tBlJoA+KFUN7ouYSDGZLSo9CKM8swQX8n/UcbR0d1VuZKU+nhogNzv423JEu5A=="], + + "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="], + + "bn.js": ["bn.js@5.2.2", "", {}, "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw=="], + + "body-parser": ["body-parser@1.20.3", "", { "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } }, "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g=="], + + "bowser": ["bowser@2.11.0", "", {}, "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="], + + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="], + + "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], + + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + + "bun-types": ["bun-types@1.2.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-rRjA1T6n7wto4gxhAO/ErZEtOXyEZEmnIHQfl0Dt1QQSB4QV0iP6BZ9/YB5fZaHFQ2dwHFrmPaRQ9GGMX01k9Q=="], + + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + + "c-kzg": ["c-kzg@4.0.0-alpha.1", "", { "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^5.0.0" } }, "sha512-I8S9+c6OEaF6mD5OQJ/PylPk8C3TENQqvMomzV4u+NyOTdVOwF/VFj/z2o5OOPt930qkms0AbzXZ+Qu4qQCYxg=="], + + "cache-content-type": ["cache-content-type@1.0.1", "", { "dependencies": { "mime-types": "^2.1.18", "ylru": "^1.2.0" } }, "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA=="], + + "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "call-me-maybe": ["call-me-maybe@1.0.2", "", {}, "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="], + + "catering": ["catering@2.1.1", "", {}, "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w=="], + + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "co": ["co@4.6.0", "", {}, "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ=="], + + "co-body": ["co-body@6.2.0", "", { "dependencies": { "@hapi/bourne": "^3.0.0", "inflation": "^2.0.0", "qs": "^6.5.2", "raw-body": "^2.3.3", "type-is": "^1.6.16" } }, "sha512-Kbpv2Yd1NdL1V/V4cwLVxraHDV6K8ayohr2rmH0J87Er8+zJjcTa6dAn9QMPC9CRgU8+aNajKbSf1TzDB1yKPA=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], + + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + + "comlink": ["comlink@4.4.2", "", {}, "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g=="], + + "commander": ["commander@6.2.0", "", {}, "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q=="], + + "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + + "cookie": ["cookie@0.7.1", "", {}, "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w=="], + + "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="], + + "cookies": ["cookies@0.9.1", "", { "dependencies": { "depd": "~2.0.0", "keygrip": "~1.1.0" } }, "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw=="], + + "copy-to": ["copy-to@2.0.1", "", {}, "sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w=="], + + "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], + + "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], + + "cross-fetch": ["cross-fetch@4.1.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], + + "dateformat": ["dateformat@4.6.3", "", {}, "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA=="], + + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "deep-equal": ["deep-equal@1.0.1", "", {}, "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw=="], + + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + + "delegates": ["delegates@1.0.0", "", {}, "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="], + + "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], + + "dereference-json-schema": ["dereference-json-schema@0.2.1", "", {}, "sha512-uzJsrg225owJyRQ8FNTPHIuBOdSzIZlHhss9u6W8mp7jJldHqGuLv9cULagP/E26QVJDnjtG8U7Dw139mM1ydA=="], + + "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], + + "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], + + "detect-node": ["detect-node@2.1.0", "", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="], + + "diff": ["diff@4.0.2", "", {}, "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="], + + "discord-api-types": ["discord-api-types@0.37.120", "", {}, "sha512-7xpNK0EiWjjDFp2nAhHXezE4OUWm7s1zhc/UXXN6hnFFU8dfoPHgV0Hx0RPiCa3ILRpdeh152icc68DGCyXYIw=="], + + "discord.js": ["discord.js@14.19.3", "", { "dependencies": { "@discordjs/builders": "^1.11.2", "@discordjs/collection": "1.5.3", "@discordjs/formatters": "^0.6.1", "@discordjs/rest": "^2.5.0", "@discordjs/util": "^1.1.1", "@discordjs/ws": "^1.2.2", "@sapphire/snowflake": "3.5.3", "discord-api-types": "^0.38.1", "fast-deep-equal": "3.1.3", "lodash.snakecase": "4.1.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.1" } }, "sha512-lncTRk0k+8Q5D3nThnODBR8fR8x2fM798o8Vsr40Krx0DjPwpZCuxxTcFMrXMQVOqM1QB9wqWgaXPg3TbmlHqA=="], + + "doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="], + + "dotenv": ["dotenv@16.5.0", "", {}, "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "duplexify": ["duplexify@4.1.3", "", { "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", "stream-shift": "^1.0.2" } }, "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA=="], + + "dynamic-dedupe": ["dynamic-dedupe@0.3.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], + + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + + "end-of-stream": ["end-of-stream@1.4.4", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "es6-promise": ["es6-promise@3.3.1", "", {}, "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + + "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + + "eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], + + "events": ["events@1.1.1", "", {}, "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="], + + "execa": ["execa@7.2.0", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", "human-signals": "^4.3.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^3.0.7", "strip-final-newline": "^3.0.0" } }, "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA=="], + + "express": ["express@4.21.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "fast-copy": ["fast-copy@3.0.2", "", {}, "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-redact": ["fast-redact@3.5.0", "", {}, "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A=="], + + "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="], + + "fast-xml-parser": ["fast-xml-parser@4.4.1", "", { "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw=="], + + "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], + + "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], + + "file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "finalhandler": ["finalhandler@1.3.1", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", "statuses": "2.0.1", "unpipe": "~1.0.0" } }, "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ=="], + + "follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="], + + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], + + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + + "form-data": ["form-data@4.0.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" } }, "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w=="], + + "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], + + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + + "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], + + "gcp-metadata": ["gcp-metadata@6.1.1", "", { "dependencies": { "gaxios": "^6.1.1", "google-logging-utils": "^0.0.2", "json-bigint": "^1.0.0" } }, "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-port": ["get-port@6.1.2", "", {}, "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], + + "glob": ["glob@7.1.6", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "google-auth-library": ["google-auth-library@9.15.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^6.1.1", "gcp-metadata": "^6.1.0", "gtoken": "^7.0.0", "jws": "^4.0.0" } }, "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng=="], + + "google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "gtoken": ["gtoken@7.1.0", "", { "dependencies": { "gaxios": "^6.0.0", "jws": "^4.0.0" } }, "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw=="], + + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hash.js": ["hash.js@1.1.7", "", { "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], + + "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="], + + "http-assert": ["http-assert@1.5.0", "", { "dependencies": { "deep-equal": "~1.0.1", "http-errors": "~1.8.0" } }, "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w=="], + + "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], + + "http-proxy": ["http-proxy@1.18.1", "", { "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ=="], + + "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], + + "http-proxy-middleware": ["http-proxy-middleware@3.0.5", "", { "dependencies": { "@types/http-proxy": "^1.17.15", "debug": "^4.3.6", "http-proxy": "^1.18.1", "is-glob": "^4.0.3", "is-plain-object": "^5.0.0", "micromatch": "^4.0.8" } }, "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg=="], + + "http2-client": ["http2-client@1.3.5", "", {}, "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA=="], + + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + + "human-signals": ["human-signals@4.3.1", "", {}, "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ=="], + + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + + "ieee754": ["ieee754@1.1.13", "", {}, "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="], + + "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + + "inflation": ["inflation@2.1.0", "", {}, "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ=="], + + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + + "is-arguments": ["is-arguments@1.2.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA=="], + + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + + "is-buffer": ["is-buffer@2.0.5", "", {}, "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="], + + "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], + + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-generator-function": ["is-generator-function@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-plain-object": ["is-plain-object@5.0.0", "", {}, "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="], + + "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], + + "is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="], + + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + + "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "isows": ["isows@1.0.6", "", { "peerDependencies": { "ws": "*" } }, "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "jmespath": ["jmespath@0.16.0", "", {}, "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="], + + "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], + + "jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], + + "keygrip": ["keygrip@1.1.0", "", { "dependencies": { "tsscmp": "1.0.6" } }, "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ=="], + + "koa": ["koa@2.16.1", "", { "dependencies": { "accepts": "^1.3.5", "cache-content-type": "^1.0.0", "content-disposition": "~0.5.2", "content-type": "^1.0.4", "cookies": "~0.9.0", "debug": "^4.3.2", "delegates": "^1.0.0", "depd": "^2.0.0", "destroy": "^1.0.4", "encodeurl": "^1.0.2", "escape-html": "^1.0.3", "fresh": "~0.5.2", "http-assert": "^1.3.0", "http-errors": "^1.6.3", "is-generator-function": "^1.0.7", "koa-compose": "^4.1.0", "koa-convert": "^2.0.0", "on-finished": "^2.3.0", "only": "~0.0.2", "parseurl": "^1.3.2", "statuses": "^1.5.0", "type-is": "^1.6.16", "vary": "^1.1.2" } }, "sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA=="], + + "koa-bodyparser": ["koa-bodyparser@4.4.1", "", { "dependencies": { "co-body": "^6.0.0", "copy-to": "^2.0.1", "type-is": "^1.6.18" } }, "sha512-kBH3IYPMb+iAXnrxIhXnW+gXV8OTzCu8VPDqvcDHW9SQrbkHmqPQtiZwrltNmSq6/lpipHnT7k7PsjlVD7kK0w=="], + + "koa-compose": ["koa-compose@4.1.0", "", {}, "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="], + + "koa-compress": ["koa-compress@5.1.1", "", { "dependencies": { "bytes": "^3.1.2", "compressible": "^2.0.18", "http-errors": "^1.8.1", "koa-is-json": "^1.0.0" } }, "sha512-UgMIN7ZoEP2DuoSQmD6CYvFSLt0NReGlc2qSY4bO4Oq0L56OiD9pDG41Kj/zFmVY/A3Wvmn4BqKcfq5H30LGIg=="], + + "koa-convert": ["koa-convert@2.0.0", "", { "dependencies": { "co": "^4.6.0", "koa-compose": "^4.1.0" } }, "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA=="], + + "koa-is-json": ["koa-is-json@1.0.0", "", {}, "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw=="], + + "koa-router": ["koa-router@12.0.1", "", { "dependencies": { "debug": "^4.3.4", "http-errors": "^2.0.0", "koa-compose": "^4.1.0", "methods": "^1.1.2", "path-to-regexp": "^6.2.1" } }, "sha512-gaDdj3GtzoLoeosacd50kBBTnnh3B9AYxDThQUo4sfUyXdOhY6ku1qyZKW88tQCRgc3Sw6ChXYXWZwwgjOxE0w=="], + + "level-concat-iterator": ["level-concat-iterator@3.1.0", "", { "dependencies": { "catering": "^2.1.0" } }, "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ=="], + + "level-supports": ["level-supports@2.1.0", "", {}, "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA=="], + + "leveldown": ["leveldown@6.1.1", "", { "dependencies": { "abstract-leveldown": "^7.2.0", "napi-macros": "~2.0.0", "node-gyp-build": "^4.3.0" } }, "sha512-88c+E+Eizn4CkQOBHwqlCJaTNEjGpaEIikn1S+cINc5E9HEvJ77bqY4JY/HxT5u0caWqsc3P3DcFIKBI1vHt+A=="], + + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "lodash.chunk": ["lodash.chunk@4.2.0", "", {}, "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="], + + "lodash.clonedeepwith": ["lodash.clonedeepwith@4.5.0", "", {}, "sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA=="], + + "lodash.get": ["lodash.get@4.4.2", "", {}, "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="], + + "lodash.isequal": ["lodash.isequal@4.5.0", "", {}, "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="], + + "lodash.mergewith": ["lodash.mergewith@4.6.2", "", {}, "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="], + + "lodash.omit": ["lodash.omit@4.5.0", "", {}, "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg=="], + + "lodash.snakecase": ["lodash.snakecase@4.1.1", "", {}, "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="], + + "lodash.times": ["lodash.times@4.3.2", "", {}, "sha512-FfaJzl0SA35CRPDh5SWe2BTght6y5KSK7yJv166qIp/8q7qOwBDCvuDZE2RUSMRpBkLF6rZKbLEUoTmaP3qg6A=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "magic-bytes.js": ["magic-bytes.js@1.12.1", "", {}, "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA=="], + + "make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], + + "merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="], + + "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], + + "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="], + + "minimalistic-assert": ["minimalistic-assert@1.0.1", "", {}, "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "mnemonist": ["mnemonist@0.38.3", "", { "dependencies": { "obliterator": "^1.6.1" } }, "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "msgpackr": ["msgpackr@1.11.2", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g=="], + + "msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="], + + "napi-macros": ["napi-macros@2.0.0", "", {}, "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg=="], + + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + + "node-addon-api": ["node-addon-api@5.1.0", "", {}, "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="], + + "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], + + "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + + "node-fetch-h2": ["node-fetch-h2@2.3.0", "", { "dependencies": { "http2-client": "^1.2.5" } }, "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg=="], + + "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], + + "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], + + "node-readfiles": ["node-readfiles@0.2.0", "", { "dependencies": { "es6-promise": "^3.2.1" } }, "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="], + + "oas-kit-common": ["oas-kit-common@1.0.8", "", { "dependencies": { "fast-safe-stringify": "^2.0.7" } }, "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ=="], + + "oas-linter": ["oas-linter@3.2.2", "", { "dependencies": { "@exodus/schemasafe": "^1.0.0-rc.2", "should": "^13.2.1", "yaml": "^1.10.0" } }, "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ=="], + + "oas-resolver": ["oas-resolver@2.5.6", "", { "dependencies": { "node-fetch-h2": "^2.3.0", "oas-kit-common": "^1.0.8", "reftools": "^1.1.9", "yaml": "^1.10.0", "yargs": "^17.0.1" }, "bin": { "resolve": "resolve.js" } }, "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ=="], + + "oas-schema-walker": ["oas-schema-walker@1.1.5", "", {}, "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ=="], + + "oas-validator": ["oas-validator@5.0.8", "", { "dependencies": { "call-me-maybe": "^1.0.1", "oas-kit-common": "^1.0.8", "oas-linter": "^3.2.2", "oas-resolver": "^2.5.6", "oas-schema-walker": "^1.1.5", "reftools": "^1.1.9", "should": "^13.2.1", "yaml": "^1.10.0" } }, "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "obliterator": ["obliterator@1.6.1", "", {}, "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig=="], + + "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], + + "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="], + + "only": ["only@0.0.2", "", {}, "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ=="], + + "openapi-client-axios": ["openapi-client-axios@7.6.0", "", { "dependencies": { "bath-es5": "^3.0.3", "dereference-json-schema": "^0.2.1", "openapi-types": "^12.1.3" }, "peerDependencies": { "axios": ">=0.25.0", "js-yaml": "^4.1.0" } }, "sha512-WfOjOtGaYDKCtf7mbLD4AH1HcJRo6VRFdHNNZClgihloYGkNyD/E/34l1LH0Vx2XHLGqP9phIid2rUFmVfbG7A=="], + + "openapi-client-axios-typegen": ["openapi-client-axios-typegen@7.7.0", "", { "dependencies": { "@anttiviljami/dtsgenerator": "^3.20.0", "@apidevtools/json-schema-ref-parser": "^11.2.0", "axios": ">=0.25.0", "indent-string": "^4.0.0", "lodash": "^4.17.21", "openapi-client-axios": "^7.5.5", "openapi-types": "^12.1.0", "yargs": "^17.3.0" }, "bin": { "typegen": "typegen" } }, "sha512-V659GvUazWxLoc1dJJEqhZFxP1GdKUCkpSHlj5Vg05P1LoN947x8ElGg9VNCmiTNTq/5e6BDXiWYy1XpGTCwvw=="], + + "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], + + "ox": ["ox@0.6.9", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "pako": ["pako@2.1.0", "", {}, "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="], + + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + + "path-to-regexp": ["path-to-regexp@0.1.12", "", {}, "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "pino": ["pino@8.21.0", "", { "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^1.2.0", "pino-std-serializers": "^6.0.0", "process-warning": "^3.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^3.7.0", "thread-stream": "^2.6.0" }, "bin": { "pino": "bin.js" } }, "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q=="], + + "pino-abstract-transport": ["pino-abstract-transport@1.2.0", "", { "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q=="], + + "pino-pretty": ["pino-pretty@13.0.0", "", { "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^3.0.2", "fast-safe-stringify": "^2.1.1", "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pump": "^3.0.0", "secure-json-parse": "^2.4.0", "sonic-boom": "^4.0.1", "strip-json-comments": "^3.1.1" }, "bin": { "pino-pretty": "bin.js" } }, "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA=="], + + "pino-std-serializers": ["pino-std-serializers@6.2.2", "", {}, "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="], + + "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], + + "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], + + "process-warning": ["process-warning@3.0.0", "", {}, "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="], + + "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], + + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "pump": ["pump@3.0.2", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw=="], + + "punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="], + + "qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="], + + "querystring": ["querystring@0.2.0", "", {}, "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], + + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + + "raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="], + + "readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], + + "reftools": ["reftools@1.1.9", "", {}, "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w=="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="], + + "resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="], + + "retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + + "retry-request": ["retry-request@7.0.2", "", { "dependencies": { "@types/request": "^2.48.8", "extend": "^3.0.2", "teeny-request": "^9.0.0" } }, "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w=="], + + "rimraf": ["rimraf@2.7.1", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], + + "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "sax": ["sax@1.2.1", "", {}, "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="], + + "secure-json-parse": ["secure-json-parse@2.7.0", "", {}, "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="], + + "send": ["send@0.19.0", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "2.4.1", "range-parser": "~1.2.1", "statuses": "2.0.1" } }, "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw=="], + + "serve-static": ["serve-static@1.16.2", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.19.0" } }, "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw=="], + + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], + + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + + "sha3": ["sha3@2.1.4", "", { "dependencies": { "buffer": "6.0.3" } }, "sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "should": ["should@13.2.3", "", { "dependencies": { "should-equal": "^2.0.0", "should-format": "^3.0.3", "should-type": "^1.4.0", "should-type-adaptors": "^1.0.1", "should-util": "^1.0.0" } }, "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ=="], + + "should-equal": ["should-equal@2.0.0", "", { "dependencies": { "should-type": "^1.4.0" } }, "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA=="], + + "should-format": ["should-format@3.0.3", "", { "dependencies": { "should-type": "^1.3.0", "should-type-adaptors": "^1.0.1" } }, "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q=="], + + "should-type": ["should-type@1.4.0", "", {}, "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ=="], + + "should-type-adaptors": ["should-type-adaptors@1.1.0", "", { "dependencies": { "should-type": "^1.3.0", "should-util": "^1.0.0" } }, "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA=="], + + "should-util": ["should-util@1.0.1", "", {}, "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g=="], + + "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + + "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "sonic-boom": ["sonic-boom@3.8.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg=="], + + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + + "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], + + "statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], + + "stream-events": ["stream-events@1.0.5", "", { "dependencies": { "stubs": "^3.0.0" } }, "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg=="], + + "stream-shift": ["stream-shift@1.0.3", "", {}, "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="], + + "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], + + "strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="], + + "stubs": ["stubs@3.0.0", "", {}, "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "swagger-autogen": ["swagger-autogen@2.23.7", "", { "dependencies": { "acorn": "^7.4.1", "deepmerge": "^4.2.2", "glob": "^7.1.7", "json5": "^2.2.3" } }, "sha512-vr7uRmuV0DCxWc0wokLJAwX3GwQFJ0jwN+AWk0hKxre2EZwusnkGSGdVFd82u7fQLgwSTnbWkxUL7HXuz5LTZQ=="], + + "swagger-jsdoc": ["swagger-jsdoc@6.2.8", "", { "dependencies": { "commander": "6.2.0", "doctrine": "3.0.0", "glob": "7.1.6", "lodash.mergewith": "^4.6.2", "swagger-parser": "^10.0.3", "yaml": "2.0.0-1" }, "bin": { "swagger-jsdoc": "bin/swagger-jsdoc.js" } }, "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ=="], + + "swagger-parser": ["swagger-parser@10.0.3", "", { "dependencies": { "@apidevtools/swagger-parser": "10.0.3" } }, "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg=="], + + "swagger-ui-dist": ["swagger-ui-dist@5.21.0", "", { "dependencies": { "@scarf/scarf": "=1.4.0" } }, "sha512-E0K3AB6HvQd8yQNSMR7eE5bk+323AUxjtCz/4ZNKiahOlPhPJxqn3UPIGs00cyY/dhrTDJ61L7C/a8u6zhGrZg=="], + + "swagger-ui-express": ["swagger-ui-express@5.0.1", "", { "dependencies": { "swagger-ui-dist": ">=5.0.0" }, "peerDependencies": { "express": ">=4.0.0 || >=5.0.0-beta" } }, "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA=="], + + "swagger2openapi": ["swagger2openapi@7.0.8", "", { "dependencies": { "call-me-maybe": "^1.0.1", "node-fetch": "^2.6.1", "node-fetch-h2": "^2.3.0", "node-readfiles": "^0.2.0", "oas-kit-common": "^1.0.8", "oas-resolver": "^2.5.6", "oas-schema-walker": "^1.1.5", "oas-validator": "^5.0.8", "reftools": "^1.1.9", "yaml": "^1.10.0", "yargs": "^17.0.1" }, "bin": { "swagger2openapi": "swagger2openapi.js", "oas-validate": "oas-validate.js", "boast": "boast.js" } }, "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g=="], + + "teeny-request": ["teeny-request@9.0.0", "", { "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.9", "stream-events": "^1.0.5", "uuid": "^9.0.0" } }, "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g=="], + + "thread-stream": ["thread-stream@2.7.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + + "ts-mixer": ["ts-mixer@6.0.4", "", {}, "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="], + + "ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-script": "dist/bin-script-deprecated.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="], + + "ts-node-dev": ["ts-node-dev@2.0.0", "", { "dependencies": { "chokidar": "^3.5.1", "dynamic-dedupe": "^0.3.0", "minimist": "^1.2.6", "mkdirp": "^1.0.4", "resolve": "^1.0.0", "rimraf": "^2.6.1", "source-map-support": "^0.5.12", "tree-kill": "^1.2.2", "ts-node": "^10.4.0", "tsconfig": "^7.0.0" }, "peerDependencies": { "node-notifier": "*", "typescript": "*" }, "optionalPeers": ["node-notifier"], "bin": { "ts-node-dev": "lib/bin.js", "tsnd": "lib/bin.js" } }, "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w=="], + + "tsconfig": ["tsconfig@7.0.0", "", { "dependencies": { "@types/strip-bom": "^3.0.0", "@types/strip-json-comments": "0.0.30", "strip-bom": "^3.0.0", "strip-json-comments": "^2.0.0" } }, "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tsscmp": ["tsscmp@1.0.6", "", {}, "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="], + + "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], + + "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + + "undici": ["undici@6.21.1", "", {}, "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ=="], + + "undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], + + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], + + "url": ["url@0.10.3", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ=="], + + "util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], + + "uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + + "v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="], + + "validator": ["validator@13.15.0", "", {}, "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + + "viem": ["viem@2.29.3", "", { "dependencies": { "@noble/curves": "1.8.2", "@noble/hashes": "1.7.2", "@scure/bip32": "1.6.2", "@scure/bip39": "1.5.4", "abitype": "1.0.8", "isows": "1.0.6", "ox": "0.6.9", "ws": "8.18.1" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-9D/nO+4S3Kk0P8vh6yXUA8OJ0mli9nzoY22qyh8iYHf1Q0GIejUnyq0QGjoDbkTcVzCVD5iA9KBkSxw9Tp3vUg=="], + + "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], + + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], + + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], + + "xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="], + + "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], + + "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yaml": ["yaml@2.0.0-1", "", {}, "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ=="], + + "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "ylru": ["ylru@1.4.0", "", {}, "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA=="], + + "yn": ["yn@3.1.1", "", {}, "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "z-schema": ["z-schema@5.0.6", "", { "dependencies": { "lodash.get": "^4.4.2", "lodash.isequal": "^4.5.0", "validator": "^13.7.0" }, "optionalDependencies": { "commander": "^10.0.0" }, "bin": { "z-schema": "bin/z-schema" } }, "sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg=="], + + "zod": ["zod@3.24.4", "", {}, "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg=="], + + "@anttiviljami/dtsgenerator/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "@anttiviljami/dtsgenerator/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + + "@apidevtools/swagger-parser/@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@9.1.2", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.6", "call-me-maybe": "^1.0.1", "js-yaml": "^4.1.0" } }, "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg=="], + + "@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + + "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + + "@aztec/aztec.js/viem": ["viem@2.23.7", "", { "dependencies": { "@noble/curves": "1.8.1", "@noble/hashes": "1.7.1", "@scure/bip32": "1.6.2", "@scure/bip39": "1.5.4", "abitype": "1.0.8", "isows": "1.0.6", "ox": "0.6.7", "ws": "8.18.0" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-Gbyz0uE3biWDPxECrEyzILWPsnIgDREgfRMuLSWHSSnM6ktefSC/lqQNImnxESdDEixa8/6EWXjmf2H6L9VV0A=="], + + "@aztec/bb.js/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "@aztec/ethereum/viem": ["viem@2.23.7", "", { "dependencies": { "@noble/curves": "1.8.1", "@noble/hashes": "1.7.1", "@scure/bip32": "1.6.2", "@scure/bip39": "1.5.4", "abitype": "1.0.8", "isows": "1.0.6", "ox": "0.6.7", "ws": "8.18.0" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-Gbyz0uE3biWDPxECrEyzILWPsnIgDREgfRMuLSWHSSnM6ktefSC/lqQNImnxESdDEixa8/6EWXjmf2H6L9VV0A=="], + + "@aztec/foundation/pino": ["pino@9.6.0", "", { "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^4.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg=="], + + "@aztec/foundation/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], + + "@aztec/stdlib/viem": ["viem@2.23.7", "", { "dependencies": { "@noble/curves": "1.8.1", "@noble/hashes": "1.7.1", "@scure/bip32": "1.6.2", "@scure/bip39": "1.5.4", "abitype": "1.0.8", "isows": "1.0.6", "ox": "0.6.7", "ws": "8.18.0" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-Gbyz0uE3biWDPxECrEyzILWPsnIgDREgfRMuLSWHSSnM6ktefSC/lqQNImnxESdDEixa8/6EWXjmf2H6L9VV0A=="], + + "@discordjs/builders/discord-api-types": ["discord-api-types@0.38.5", "", {}, "sha512-2sRkDRid39myMMeRzVTWLc2PyafSxu6k3LHpkB1Lx6IVzqycRnIhOedCbXg3IYpbJhKvA7ErNAh0DA/nXG/1Uw=="], + + "@discordjs/formatters/discord-api-types": ["discord-api-types@0.38.5", "", {}, "sha512-2sRkDRid39myMMeRzVTWLc2PyafSxu6k3LHpkB1Lx6IVzqycRnIhOedCbXg3IYpbJhKvA7ErNAh0DA/nXG/1Uw=="], + + "@discordjs/rest/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], + + "@discordjs/rest/discord-api-types": ["discord-api-types@0.38.5", "", {}, "sha512-2sRkDRid39myMMeRzVTWLc2PyafSxu6k3LHpkB1Lx6IVzqycRnIhOedCbXg3IYpbJhKvA7ErNAh0DA/nXG/1Uw=="], + + "@discordjs/ws/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], + + "@discordjs/ws/discord-api-types": ["discord-api-types@0.38.5", "", {}, "sha512-2sRkDRid39myMMeRzVTWLc2PyafSxu6k3LHpkB1Lx6IVzqycRnIhOedCbXg3IYpbJhKvA7ErNAh0DA/nXG/1Uw=="], + + "@google-cloud/storage/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], + + "@google-cloud/storage/uuid": ["uuid@8.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="], + + "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "@types/request/form-data": ["form-data@2.5.3", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ=="], + + "abstract-leveldown/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + + "acorn-walk/acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + + "aws-sdk/uuid": ["uuid@8.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="], + + "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "discord.js/discord-api-types": ["discord-api-types@0.38.5", "", {}, "sha512-2sRkDRid39myMMeRzVTWLc2PyafSxu6k3LHpkB1Lx6IVzqycRnIhOedCbXg3IYpbJhKvA7ErNAh0DA/nXG/1Uw=="], + + "duplexify/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "gaxios/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + + "gaxios/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "http-assert/http-errors": ["http-errors@1.8.1", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.1" } }, "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g=="], + + "koa/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], + + "koa/http-errors": ["http-errors@1.8.1", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.1" } }, "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g=="], + + "koa/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], + + "koa-compress/http-errors": ["http-errors@1.8.1", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.1" } }, "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g=="], + + "koa-router/path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], + + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + + "oas-linter/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + + "oas-resolver/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + + "oas-validator/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + + "ox/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "pino-pretty/pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="], + + "pino-pretty/sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="], + + "pino-pretty/strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + + "readable-stream/events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + + "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], + + "sha3/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + + "swagger-autogen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "swagger2openapi/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "swagger2openapi/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + + "teeny-request/http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="], + + "teeny-request/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "teeny-request/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "ts-node/acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + + "z-schema/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + + "@anttiviljami/dtsgenerator/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], + + "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], + + "@aztec/aztec.js/viem/@noble/curves": ["@noble/curves@1.8.1", "", { "dependencies": { "@noble/hashes": "1.7.1" } }, "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ=="], + + "@aztec/aztec.js/viem/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], + + "@aztec/aztec.js/viem/ox": ["ox@0.6.7", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA=="], + + "@aztec/aztec.js/viem/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + + "@aztec/ethereum/viem/@noble/curves": ["@noble/curves@1.8.1", "", { "dependencies": { "@noble/hashes": "1.7.1" } }, "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ=="], + + "@aztec/ethereum/viem/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], + + "@aztec/ethereum/viem/ox": ["ox@0.6.7", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA=="], + + "@aztec/ethereum/viem/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + + "@aztec/foundation/pino/pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="], + + "@aztec/foundation/pino/pino-std-serializers": ["pino-std-serializers@7.0.0", "", {}, "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA=="], + + "@aztec/foundation/pino/process-warning": ["process-warning@4.0.1", "", {}, "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q=="], + + "@aztec/foundation/pino/sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="], + + "@aztec/foundation/pino/thread-stream": ["thread-stream@3.1.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A=="], + + "@aztec/stdlib/viem/@noble/curves": ["@noble/curves@1.8.1", "", { "dependencies": { "@noble/hashes": "1.7.1" } }, "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ=="], + + "@aztec/stdlib/viem/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], + + "@aztec/stdlib/viem/ox": ["ox@0.6.7", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA=="], + + "@aztec/stdlib/viem/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + + "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "abstract-leveldown/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "http-assert/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], + + "http-assert/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], + + "koa-compress/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], + + "koa-compress/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], + + "koa/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], + + "readable-stream/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "sha3/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "teeny-request/http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "teeny-request/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "@anttiviljami/dtsgenerator/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], + + "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], + + "@aztec/aztec.js/viem/ox/@noble/curves": ["@noble/curves@1.8.2", "", { "dependencies": { "@noble/hashes": "1.7.2" } }, "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g=="], + + "@aztec/aztec.js/viem/ox/@noble/hashes": ["@noble/hashes@1.7.2", "", {}, "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ=="], + + "@aztec/aztec.js/viem/ox/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "@aztec/ethereum/viem/ox/@noble/curves": ["@noble/curves@1.8.2", "", { "dependencies": { "@noble/hashes": "1.7.2" } }, "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g=="], + + "@aztec/ethereum/viem/ox/@noble/hashes": ["@noble/hashes@1.7.2", "", {}, "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ=="], + + "@aztec/ethereum/viem/ox/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "@aztec/stdlib/viem/ox/@noble/curves": ["@noble/curves@1.8.2", "", { "dependencies": { "@noble/hashes": "1.7.2" } }, "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g=="], + + "@aztec/stdlib/viem/ox/@noble/hashes": ["@noble/hashes@1.7.2", "", {}, "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ=="], + + "@aztec/stdlib/viem/ox/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + } +} diff --git a/tooling/sparta/e2e-tests/README.md b/tooling/sparta/e2e-tests/README.md new file mode 100644 index 0000000..bc80f00 --- /dev/null +++ b/tooling/sparta/e2e-tests/README.md @@ -0,0 +1,53 @@ +# Sparta E2E Tests + +This directory contains end-to-end tests for the Sparta services using Bun's testing capabilities. + +## Available Tests + +- **API Service**: Tests for the Express API service +- **Discord Bot**: Tests for the Discord bot functionality +- **Scheduler**: Tests for the scheduler service +- **Ethereum**: Tests for Ethereum-related functionality + +## Running Tests + +To run all tests: + +```bash +bun test +``` + +To run a specific test file: + +```bash +bun test src/api.test.ts +``` + +To run tests with coverage: + +```bash +bun test --coverage +``` + +## Test Structure + +Each test file follows a similar pattern: + +1. Mock the necessary dependencies +2. Set up test data +3. Define tests for key functionality +4. Use Bun's built-in assertions to verify behavior + +## Adding New Tests + +1. Create a new test file in the `src` directory +2. Import the necessary testing utilities from `bun:test` +3. Mock any external dependencies +4. Write your tests using the `test()` and `describe()` functions +5. Run the tests to verify they pass + +## Notes + +- These tests use mocks to simulate services rather than connecting to real infrastructure +- For more complex scenarios, consider adding integration tests that connect to local test instances +- Refer to the [Bun documentation](https://bun.sh/docs/test/writing) for more details on writing tests \ No newline at end of file diff --git a/tooling/sparta/e2e-tests/package.json b/tooling/sparta/e2e-tests/package.json new file mode 100644 index 0000000..c3a261c --- /dev/null +++ b/tooling/sparta/e2e-tests/package.json @@ -0,0 +1,20 @@ +{ + "name": "@sparta/e2e-tests", + "version": "0.1.0", + "type": "module", + "scripts": { + "test": "bun test", + "test:coverage": "bun test --coverage" + }, + "dependencies": { + "@sparta/utils": "workspace:*", + "@sparta/api": "workspace:*", + "@sparta/discord": "workspace:*", + "@sparta/scheduler": "workspace:*", + "@sparta/ethereum": "workspace:*" + }, + "devDependencies": { + "bun-types": "latest", + "typescript": "^5.8.3" + } +} \ No newline at end of file diff --git a/tooling/sparta/e2e-tests/src/api.test.ts b/tooling/sparta/e2e-tests/src/api.test.ts new file mode 100644 index 0000000..e30aa1c --- /dev/null +++ b/tooling/sparta/e2e-tests/src/api.test.ts @@ -0,0 +1,75 @@ +import { test, expect, describe, beforeAll, afterAll, mock } from "bun:test"; +import { Server } from "bun"; + +// Mock the actual server module - in real e2e, you'd use the actual server or a test instance +let mockServer: Server | null = null; +const mockPort = 3456; +const baseUrl = `http://localhost:${mockPort}`; + +// Creating a simple mock for the API +const startMockServer = () => { + return Bun.serve({ + port: mockPort, + fetch(req) { + const url = new URL(req.url); + + // Mock endpoints + if (url.pathname === "/api/health") { + return new Response(JSON.stringify({ status: "ok" }), { + headers: { "Content-Type": "application/json" }, + }); + } + + if (url.pathname === "/api/users" && req.method === "GET") { + return new Response(JSON.stringify([ + { id: 1, name: "User 1" }, + { id: 2, name: "User 2" } + ]), { + headers: { "Content-Type": "application/json" }, + }); + } + + return new Response("Not found", { status: 404 }); + }, + }); +}; + +describe("API Service E2E Tests", () => { + beforeAll(() => { + // Start a mock server for testing + mockServer = startMockServer(); + console.log(`Mock API server listening at ${baseUrl}`); + }); + + afterAll(() => { + // Clean up: close the server + if (mockServer) { + mockServer.stop(); + console.log("Mock API server stopped"); + } + }); + + test("Health endpoint returns 200 OK", async () => { + const response = await fetch(`${baseUrl}/api/health`); + expect(response.status).toBe(200); + + const data = await response.json(); + expect(data).toEqual({ status: "ok" }); + }); + + test("Users endpoint returns list of users", async () => { + const response = await fetch(`${baseUrl}/api/users`); + expect(response.status).toBe(200); + + const users = await response.json(); + expect(users).toBeArray(); + expect(users.length).toBe(2); + expect(users[0]).toHaveProperty("id"); + expect(users[0]).toHaveProperty("name"); + }); + + test("Non-existent endpoint returns 404", async () => { + const response = await fetch(`${baseUrl}/api/non-existent`); + expect(response.status).toBe(404); + }); +}); \ No newline at end of file diff --git a/tooling/sparta/e2e-tests/src/discord.test.ts b/tooling/sparta/e2e-tests/src/discord.test.ts new file mode 100644 index 0000000..a88c101 --- /dev/null +++ b/tooling/sparta/e2e-tests/src/discord.test.ts @@ -0,0 +1,87 @@ +import { test, expect, describe, beforeAll, afterAll, mock } from "bun:test"; + +// Mock Discord.js client and its methods +const mockDiscordClient = { + login: mock(() => Promise.resolve("mock-token")), + destroy: mock(() => Promise.resolve()), + on: mock((event, callback) => { + // Simulate events if needed in tests + if (event === "ready") { + setTimeout(() => callback(), 10); + } + return mockDiscordClient; + }), + user: { + setActivity: mock(() => Promise.resolve()) + }, + application: { + commands: { + set: mock(() => Promise.resolve()) + } + } +}; + +// Mock the slash commands +const mockCommands = [ + { + name: "help", + description: "Show help information" + }, + { + name: "status", + description: "Check status of services" + } +]; + +describe("Discord Bot E2E Tests", () => { + beforeAll(() => { + // Reset mocks before each test + mockDiscordClient.login.mockReset(); + mockDiscordClient.destroy.mockReset(); + mockDiscordClient.on.mockReset(); + }); + + test("Bot initializes and logs in successfully", async () => { + // Simulate bot initialization + const result = await mockDiscordClient.login(); + + // Assert login was called + expect(mockDiscordClient.login).toHaveBeenCalled(); + expect(result).toBe("mock-token"); + }); + + test("Bot registers slash commands", async () => { + // Simulate registering commands + await mockDiscordClient.application.commands.set(); + + // Assert commands were set + expect(mockDiscordClient.application.commands.set).toHaveBeenCalled(); + }); + + test("Bot sets activity status", async () => { + // Simulate setting activity + await mockDiscordClient.user.setActivity(); + + // Assert activity was set + expect(mockDiscordClient.user.setActivity).toHaveBeenCalled(); + }); + + test("Bot handles ready event", async () => { + let readyEventFired = false; + + // Create a promise that resolves when the ready event fires + const readyPromise = new Promise(resolve => { + mockDiscordClient.on("ready", () => { + readyEventFired = true; + resolve(); + }); + }); + + // Wait for the ready event + await readyPromise; + + // Assert event listener was registered and event was handled + expect(mockDiscordClient.on).toHaveBeenCalledWith("ready", expect.any(Function)); + expect(readyEventFired).toBe(true); + }); +}); \ No newline at end of file diff --git a/tooling/sparta/e2e-tests/src/ethereum.test.ts b/tooling/sparta/e2e-tests/src/ethereum.test.ts new file mode 100644 index 0000000..3d4d69b --- /dev/null +++ b/tooling/sparta/e2e-tests/src/ethereum.test.ts @@ -0,0 +1,95 @@ +import { test, expect, describe, beforeAll, afterAll, mock } from "bun:test"; + +// Mock contract data +const mockContract = { + address: "0x123456789abcdef", + abi: [{ type: "function", name: "getValue", inputs: [], outputs: [{ type: "uint256" }] }] +}; + +// Mock blockchain provider +const mockProvider = { + getBalance: mock(() => Promise.resolve(BigInt(1000000000000000000))), // 1 ETH + getBlockNumber: mock(() => Promise.resolve(12345678)), + getTransactionCount: mock(() => Promise.resolve(42)) +}; + +// Mock wallet +const mockWallet = { + address: "0xWalletAddress123", + signMessage: mock(() => Promise.resolve("0xSignature123")), + signTransaction: mock(() => Promise.resolve("0xSignedTx123")) +}; + +// Mock contract interactions +const mockContractCalls = { + read: mock(() => Promise.resolve(BigInt(42))), + write: mock(() => Promise.resolve({ hash: "0xTxHash123" })) +}; + +describe("Ethereum Service E2E Tests", () => { + beforeAll(() => { + // Reset mocks before tests + mockProvider.getBalance.mockReset(); + mockProvider.getBlockNumber.mockReset(); + mockProvider.getTransactionCount.mockReset(); + mockWallet.signMessage.mockReset(); + mockWallet.signTransaction.mockReset(); + mockContractCalls.read.mockReset(); + mockContractCalls.write.mockReset(); + }); + + test("Can get ETH balance", async () => { + // Get wallet balance + const balance = await mockProvider.getBalance(); + + // Assert balance call was made and returns expected value + expect(mockProvider.getBalance).toHaveBeenCalled(); + expect(balance).toBe(BigInt(1000000000000000000)); // 1 ETH + }); + + test("Can get current block number", async () => { + // Get current block number + const blockNumber = await mockProvider.getBlockNumber(); + + // Assert block number call was made and returns expected value + expect(mockProvider.getBlockNumber).toHaveBeenCalled(); + expect(blockNumber).toBe(12345678); + }); + + test("Can sign messages", async () => { + // Sign a message + const signature = await mockWallet.signMessage(); + + // Assert sign message was called and returns expected signature + expect(mockWallet.signMessage).toHaveBeenCalled(); + expect(signature).toBe("0xSignature123"); + }); + + test("Can read from smart contracts", async () => { + // Read from contract + const value = await mockContractCalls.read(); + + // Assert contract read was called and returns expected value + expect(mockContractCalls.read).toHaveBeenCalled(); + expect(value).toBe(BigInt(42)); + }); + + test("Can write to smart contracts", async () => { + // Write to contract + const tx = await mockContractCalls.write(); + + // Assert contract write was called and returns expected transaction + expect(mockContractCalls.write).toHaveBeenCalled(); + expect(tx).toHaveProperty("hash"); + expect(tx.hash).toBe("0xTxHash123"); + }); + + test("Can get transaction count", async () => { + // Get transaction count + const count = await mockProvider.getTransactionCount(); + + // Assert get transaction count was called and returns expected value + expect(mockProvider.getTransactionCount).toHaveBeenCalled(); + expect(count).toBe(42); + }); +}); \ No newline at end of file diff --git a/tooling/sparta/e2e-tests/src/integration.test.ts b/tooling/sparta/e2e-tests/src/integration.test.ts new file mode 100644 index 0000000..3b88129 --- /dev/null +++ b/tooling/sparta/e2e-tests/src/integration.test.ts @@ -0,0 +1,189 @@ +import { test, expect, describe, beforeAll, afterAll, mock } from "bun:test"; +import { Server } from "bun"; + +// Creating mock servers and clients for different services +let mockApiServer: Server | null = null; +const apiPort = 3456; +const apiBaseUrl = `http://localhost:${apiPort}`; + +// Mock event data for integration tests +const mockEvent = { + id: "event-123", + name: "Contract Deployment", + timestamp: Date.now(), + details: { + contractAddress: "0x123456789abcdef", + network: "testnet", + deployer: "0xUser123" + } +}; + +// Mock handlers for API server +const mockApiHandlers = { + getEvents: mock(() => [mockEvent]), + createEvent: mock((event) => ({ id: "event-" + Date.now(), ...event })), + notifyDiscord: mock(() => ({ success: true })) +}; + +// Mock Discord client +const mockDiscordClient = { + login: mock(() => Promise.resolve("mock-token")), + channels: { + cache: { + get: mock(() => ({ + send: mock(() => Promise.resolve({ id: "message-123" })) + })) + } + } +}; + +// Mock Ethereum provider +const mockEthProvider = { + getBlockNumber: mock(() => Promise.resolve(12345678)), + getBalance: mock(() => Promise.resolve(BigInt(1000000000000000000))) +}; + +// Start mock API server +const startMockApiServer = () => { + return Bun.serve({ + port: apiPort, + websocket: { message() {} }, // Required property + fetch(req, server) { + const url = new URL(req.url); + + // GET /api/events + if (url.pathname === "/api/events" && req.method === "GET") { + return new Response(JSON.stringify(mockApiHandlers.getEvents()), { + headers: { "Content-Type": "application/json" }, + }); + } + + // POST /api/events + if (url.pathname === "/api/events" && req.method === "POST") { + return req.json().then(body => { + const newEvent = mockApiHandlers.createEvent(body); + return new Response(JSON.stringify(newEvent), { + status: 201, + headers: { "Content-Type": "application/json" }, + }); + }); + } + + // POST /api/discord/notify + if (url.pathname === "/api/discord/notify" && req.method === "POST") { + return req.json().then(() => { + const result = mockApiHandlers.notifyDiscord(); + return new Response(JSON.stringify(result), { + headers: { "Content-Type": "application/json" }, + }); + }); + } + + return new Response("Not found", { status: 404 }); + }, + }); +}; + +describe("Integration E2E Tests", () => { + beforeAll(() => { + // Start mock API server + mockApiServer = startMockApiServer(); + console.log(`Mock API server listening at ${apiBaseUrl}`); + + // Reset all mocks + mockApiHandlers.getEvents.mockReset(); + mockApiHandlers.createEvent.mockReset(); + mockApiHandlers.notifyDiscord.mockReset(); + mockDiscordClient.login.mockReset(); + mockDiscordClient.channels.cache.get.mockReset(); + mockEthProvider.getBlockNumber.mockReset(); + mockEthProvider.getBalance.mockReset(); + }); + + afterAll(() => { + // Clean up: close the server + if (mockApiServer) { + mockApiServer.stop(); + console.log("Mock API server stopped"); + } + }); + + test("Full event flow from creation to Discord notification", async () => { + // 1. Create a new event through the API + const eventPayload = { + name: "New Contract Deployment", + timestamp: Date.now(), + details: { + contractAddress: "0xNewContract123", + network: "mainnet", + deployer: "0xDeployer456" + } + }; + + const createResponse = await fetch(`${apiBaseUrl}/api/events`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(eventPayload) + }); + + expect(createResponse.status).toBe(201); + const createdEvent = await createResponse.json(); + expect(createdEvent).toHaveProperty("id"); + expect(createdEvent.name).toBe(eventPayload.name); + + // 2. Get all events to verify our event was added + const getEventsResponse = await fetch(`${apiBaseUrl}/api/events`); + expect(getEventsResponse.status).toBe(200); + + // 3. Send a Discord notification about the event + const notifyResponse = await fetch(`${apiBaseUrl}/api/discord/notify`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ eventId: createdEvent.id }) + }); + + expect(notifyResponse.status).toBe(200); + const notifyResult = await notifyResponse.json(); + expect(notifyResult).toHaveProperty("success"); + expect(notifyResult.success).toBe(true); + + // Verify the notifications were sent properly + expect(mockApiHandlers.notifyDiscord).toHaveBeenCalled(); + }); + + test("Blockchain integration flow", async () => { + // Simulate checking contract deployment on blockchain + const blockNumber = await mockEthProvider.getBlockNumber(); + expect(mockEthProvider.getBlockNumber).toHaveBeenCalled(); + expect(blockNumber).toBe(12345678); + + // Simulate checking wallet balance + const balance = await mockEthProvider.getBalance(); + expect(mockEthProvider.getBalance).toHaveBeenCalled(); + expect(balance).toBe(BigInt(1000000000000000000)); + + // Simulate posting contract deployment event + const eventPayload = { + name: "Contract Verified", + timestamp: Date.now(), + details: { + contractAddress: "0xVerifiedContract456", + network: "mainnet", + blockNumber: blockNumber + } + }; + + const createResponse = await fetch(`${apiBaseUrl}/api/events`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(eventPayload) + }); + + expect(createResponse.status).toBe(201); + const createdEvent = await createResponse.json(); + expect(createdEvent).toHaveProperty("id"); + + // Check integration between blockchain data and event system + expect(createdEvent.details.blockNumber).toBe(blockNumber); + }); +}); \ No newline at end of file diff --git a/tooling/sparta/e2e-tests/src/scheduler.test.ts b/tooling/sparta/e2e-tests/src/scheduler.test.ts new file mode 100644 index 0000000..c67b7fe --- /dev/null +++ b/tooling/sparta/e2e-tests/src/scheduler.test.ts @@ -0,0 +1,96 @@ +import { test, expect, describe, beforeAll, afterAll, mock } from "bun:test"; + +// Mock event data +const mockEvent = { + name: "Deploy Contract", + timestamp: Date.now(), + details: { + contractAddress: "0x123456789abcdef", + network: "testnet", + deployer: "0xUser123" + } +}; + +// Mock API client that the scheduler might use +const mockApiClient = { + getEvents: mock(() => Promise.resolve([mockEvent])), + scheduleEvent: mock(() => Promise.resolve({ id: "event-1", ...mockEvent })), + cancelEvent: mock(() => Promise.resolve(true)) +}; + +// Mock scheduler functions +const mockScheduler = { + processEvents: mock(() => Promise.resolve(true)), + handleEvent: mock(() => Promise.resolve({ success: true })), + initialize: mock(() => Promise.resolve()) +}; + +describe("Scheduler Service E2E Tests", () => { + beforeAll(() => { + // Reset mocks before tests + mockApiClient.getEvents.mockReset(); + mockApiClient.scheduleEvent.mockReset(); + mockApiClient.cancelEvent.mockReset(); + mockScheduler.processEvents.mockReset(); + mockScheduler.handleEvent.mockReset(); + mockScheduler.initialize.mockReset(); + }); + + test("Scheduler initializes successfully", async () => { + // Simulate initialization + await mockScheduler.initialize(); + + // Assert initialization was called + expect(mockScheduler.initialize).toHaveBeenCalled(); + }); + + test("Scheduler retrieves events from API", async () => { + // Simulate getting events from API + const events = await mockApiClient.getEvents(); + + // Assert get events was called and returns expected data + expect(mockApiClient.getEvents).toHaveBeenCalled(); + expect(events).toBeArray(); + expect(events.length).toBe(1); + expect(events[0].name).toBe(mockEvent.name); + }); + + test("Scheduler processes events", async () => { + // Simulate processing events + const result = await mockScheduler.processEvents(); + + // Assert process events was called and succeeded + expect(mockScheduler.processEvents).toHaveBeenCalled(); + expect(result).toBe(true); + }); + + test("Scheduler handles individual events", async () => { + // Simulate handling a specific event + const result = await mockScheduler.handleEvent(); + + // Assert handle event was called and returns expected result + expect(mockScheduler.handleEvent).toHaveBeenCalled(); + expect(result).toHaveProperty("success"); + expect(result.success).toBe(true); + }); + + test("Scheduler can schedule new events", async () => { + // Simulate scheduling a new event + const createdEvent = await mockApiClient.scheduleEvent(); + + // Assert schedule event was called and returns expected data + expect(mockApiClient.scheduleEvent).toHaveBeenCalled(); + expect(createdEvent).toHaveProperty("id"); + expect(createdEvent).toHaveProperty("name"); + expect(createdEvent.name).toBe(mockEvent.name); + }); + + test("Scheduler can cancel events", async () => { + // Simulate canceling an event + const result = await mockApiClient.cancelEvent(); + + // Assert cancel event was called and succeeded + expect(mockApiClient.cancelEvent).toHaveBeenCalled(); + expect(result).toBe(true); + }); +}); \ No newline at end of file diff --git a/tooling/sparta/e2e-tests/tsconfig.json b/tooling/sparta/e2e-tests/tsconfig.json new file mode 100644 index 0000000..4d27dbf --- /dev/null +++ b/tooling/sparta/e2e-tests/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "types": ["bun-types"] + }, + "include": ["src/**/*"], + "references": [ + { "path": "../packages/utils" }, + { "path": "../packages/api" }, + { "path": "../packages/discord" }, + { "path": "../packages/scheduler" }, + { "path": "../packages/ethereum" } + ] +} \ No newline at end of file diff --git a/tooling/sparta/package.json b/tooling/sparta/package.json new file mode 100644 index 0000000..4d9ef35 --- /dev/null +++ b/tooling/sparta/package.json @@ -0,0 +1,40 @@ +{ + "name": "sparta", + "type": "module", + "workspaces": [ + "packages/*" + ], + "devDependencies": { + "@types/bun": "latest", + "@types/swagger-jsdoc": "^6.0.4", + "@types/swagger-ui-express": "^4.1.8", + "http-proxy-middleware": "^3.0.5", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.1" + }, + "peerDependencies": { + "typescript": "^5.8.3" + }, + "scripts": { + "types": "tsc --noEmit", + "swagger": "bun run scripts/swagger.js", + "openapi": "bunx openapi-client-axios-typegen packages/utils/openapi/api-docs.json > packages/utils/openapi/types.d.ts", + "prep": "bun run swagger && bun run openapi", + "build": "bun run prep && bun --filter='@sparta/utils' --filter='@sparta/discord' run types && bun --filter='@sparta/scheduler' run build", + "start": "bun run prep && bun run build && NODE_ENV='production' bun --filter='@sparta/api' --filter='@sparta/discord' run start", + "dev": "bun run prep && bun run build && NODE_ENV='development' bun --env-file=.env --elide-lines=0 --filter='@sparta/api' --filter='@sparta/discord' run dev", + "dev:webapp": "bun --env-file=.env --elide-lines=0 --filter='@sparta/webapp' run dev", + "dev:api": "bun --env-file=.env --elide-lines=0 --filter='@sparta/api' run dev", + "dev:scheduler": "bun run build && bun --env-file=.env --elide-lines=0 --filter='@sparta/scheduler' run dev" + }, + "dependencies": { + "@aws-sdk/client-dynamodb": "^3.788.0", + "@aws-sdk/lib-dynamodb": "^3.789.0", + "@aztec/aztec.js": "^0.86.0", + "@graphprotocol/graph-ts": "^0.38.0", + "dotenv": "^16.4.0", + "node-fetch": "^3.3.0", + "viem": "^2.7.0" + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" +} diff --git a/tooling/sparta/packages/discord/README.md b/tooling/sparta/packages/discord/README.md new file mode 100644 index 0000000..c2fb6e5 --- /dev/null +++ b/tooling/sparta/packages/discord/README.md @@ -0,0 +1,149 @@ +# @sparta/discord + +Discord bot package for the Sparta project, providing Discord integration and command handling. + +## Overview + +This package provides the core Discord bot functionality for the Sparta project: + +- Discord client setup and configuration +- Slash command registration and handling +- Role management and assignment +- User interaction through Discord channels +- Webhook message delivery + +## Features + +- Discord client setup and event handling +- API integration via OpenAPI-generated client +- Role management commands +- Human verification via Passport +- Chain information queries +- Node operator registration and monitoring + +## Available Commands + +The bot supports the following slash commands: + +| Command | Subcommand | Description | Parameters | +| ----------- | -------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| `/operator` | `chain-info` | Get current chain information including pending/proven blocks, epoch, slot, and current proposer | None | +| `/operator` | `my-stats` | Check validator statistics | `address` (required): The validator address to check | +| `/operator` | `register` | Register as a validator and get the Apprentice role | `address` (optional): Your validator address
`block-number` (optional): Block number for verification
`proof` (optional): Your sync proof | +| `/operator` | `help` | Display operator commands and instructions | None | +| `/mod` | `info` | Get comprehensive information about a node operator | `username` (required): The Discord username of the operator | +| `/mod` | `approve` | Approve a user to join the validator set | `user` (required): The Discord username of the user to approve | +| `/mod` | `help` | Display all moderator commands and their descriptions in a table | None | + +## Command Restrictions + +### Moderator Commands + +Moderator commands (`/mod`) have the following restrictions: + +- **Role-based access**: Only users with one of these roles can use moderator commands: + - Aztec Labs Team (ID: 1144693819015700620) + - AzMod (ID: 1362901049803018513) + - Admin (ID: 1146246812299165817) + +- **Channel restrictions**: + - In production: Commands can only be used in `#mod-bot` or `#bot-test` channels + - In development: Commands can only be used in the `#bot-test` channel + +### User Roles + +- **Verified+**: Assigned to users who have successfully verified with Human Passport +- **Apprentice**: Assigned to users who successfully register as validators + +## Usage + +```typescript +import { getDiscordInstance, discordService } from '@sparta/discord'; + +// Get Discord instance +const discord = await getDiscordInstance(); + +// Send a message to a channel +await discordService.sendMessage('channel-id', 'Hello from Sparta bot!'); + +// Get Discord client for advanced usage +const client = discord.getClient(); +``` + +## Components + +### Discord Client + +Main Discord client for interacting with the Discord API: + +```typescript +import { getDiscordInstance } from '@sparta/discord'; + +// Initialize Discord client +const discord = await getDiscordInstance(); + +// Get the underlying Discord.js client +const client = discord.getClient(); + +// Check if the client is ready +if (client.isReady()) { + console.log(`Logged in as ${client.user.tag}`); +} +``` + +### Discord Service + +Service for common Discord operations: + +```typescript +import { discordService } from '@sparta/discord'; + +// Send a message to a channel +await discordService.sendMessage('channel-id', 'Hello world!'); + +// Send an embed message +await discordService.sendEmbed('channel-id', { + title: 'Validator Status', + description: 'All validators are operational', + color: 0x00ff00 +}); + +// Assign a role to a user +await discordService.assignRole('guild-id', 'user-id', 'role-id'); +``` + +### Discord Webhook Service + +Service for sending messages via Discord webhooks: + +```typescript +import { discordWebhookService } from '@sparta/discord'; + +// Send a webhook message +await discordWebhookService.sendMessage({ + webhookUrl: 'https://discord.com/api/webhooks/...', + content: 'Alert: Validator offline!', + username: 'Sparta Monitoring' +}); +``` + +## Configuration + +The Discord client is configured through environment variables: + +- `BOT_TOKEN`: Discord bot token +- `BOT_CLIENT_ID`: Discord application client ID +- `GUILD_ID`: Discord server (guild) ID + +## Development + +```bash +# Build types +bun run types + +# Run in development mode with hot reloading +bun run dev + +# Run in production mode +bun run start +``` diff --git a/tooling/sparta/packages/discord/package.json b/tooling/sparta/packages/discord/package.json new file mode 100644 index 0000000..6fb9b36 --- /dev/null +++ b/tooling/sparta/packages/discord/package.json @@ -0,0 +1,33 @@ +{ + "name": "@sparta/discord", + "version": "0.0.1", + "description": "Discord package for Sparta project", + "type": "module", + "files": [ + "src" + ], + "exports": { + ".": { + "import": "./src/index.ts", + "require": "./src/index.ts" + } + }, + "scripts": { + "types": "tsc", + "dev": "bun --watch run src/index.ts", + "start": "bun run src/index.ts", + "clean": "rm -rf dist" + }, + "dependencies": { + "@discordjs/rest": "^2.0.1", + "@sparta/utils": "workspace:*", + "@sparta/ethereum": "workspace:*", + "discord-api-types": "^0.37.67", + "discord.js": "^14.12.1", + "openapi-client-axios": "^7.5.1", + "axios": "^1.6.2" + }, + "devDependencies": { + "typescript": "^5.0.4" + } +} diff --git a/tooling/sparta/packages/discord/src/clients/discord.ts b/tooling/sparta/packages/discord/src/clients/discord.ts new file mode 100644 index 0000000..acfe50b --- /dev/null +++ b/tooling/sparta/packages/discord/src/clients/discord.ts @@ -0,0 +1,288 @@ +/** + * @fileoverview Discord client and utilities + * @description Provides Discord client configuration and event handling + * @module sparta/discord/clients + */ + +import { + Client, + GatewayIntentBits, + Collection, + type Interaction, + MessageFlags, + TextChannel, + REST, + Routes, +} from "discord.js"; +import { logger } from "@sparta/utils"; +import { ApiProvider } from "@sparta/utils/openapi/api/apiProvider"; +import commands from "../slashCommands/index"; + +// Command interface +interface Command { + data: { + toJSON: () => any; + name: string; + }; + execute: (interaction: Interaction) => Promise; +} + +// Extended Discord client interface with commands collection +export interface ExtendedClient extends Client { + commands: Collection; +} + +export class Discord { + private client: ExtendedClient; + private apiProvider: ApiProvider; + + constructor(client: ExtendedClient, apiProvider: ApiProvider) { + this.client = client; + this.apiProvider = apiProvider; + } + + /** + * Creates a new Discord instance with initialized client + */ + static new = async () => { + try { + logger.info("Initializing Discord client"); + + // Initialize Discord client with required intents + const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + ], + }) as ExtendedClient; + + // Initialize commands collection + client.commands = new Collection(); + + // Initialize API provider + const apiProvider = ApiProvider.getInstance(); + await apiProvider.init(); + + if (!apiProvider.isInitialized()) { + const error = apiProvider.getError(); + logger.error({ error }, "Failed to initialize API provider"); + throw error || new Error("Failed to initialize API provider"); + } + + // Set up event handlers + Discord.setupEventHandlers(client); + + // Log in to Discord + await client.login(process.env.BOT_TOKEN); + + return new Discord(client, apiProvider); + } catch (error) { + logger.error({ error }, "Error initializing Discord client"); + throw error; + } + }; + + /** + * Sets up the event handlers for the Discord client + * @param client The Discord client + */ + private static setupEventHandlers(client: ExtendedClient): void { + /** + * Error event handler + */ + client.once("error", (error) => { + logger.error({ error }, "Discord client error"); + }); + + /** + * Ready event handler - called when bot is initialized + */ + client.once("ready", async () => { + logger.info("Sparta bot is ready!"); + logger.info( + { clientId: process.env.BOT_CLIENT_ID }, + "Bot connected with Client ID" + ); + Discord.deployCommands(client); + }); + + /** + * Interaction event handler - processes all slash commands + * @param {Interaction} interaction - The interaction object from Discord + */ + client.on("interactionCreate", async (interaction: Interaction) => { + if (!interaction.isChatInputCommand()) return; + + const command = client.commands.get(interaction.commandName); + if (!command) return; + + logger.debug( + { + command: interaction.commandName, + subcommand: interaction.options.getSubcommand(), + }, + "Command" + ); + try { + const channel = interaction.channel as TextChannel; + + logger.debug( + { + channel: channel.name, + user: interaction.user.username, + date: interaction.createdAt, + }, + "Command info" + ); + const reply = await command.execute(interaction); + logger.debug( + { + reply, + }, + "Command reply" + ); + } catch (error) { + logger.error({ error }, "Error executing command"); + await interaction.reply({ + content: "There was an error executing this command!", + flags: MessageFlags.Ephemeral, + }); + } + }); + } + + /** + * Deploys all slash commands to the Discord server + * @param client The Discord client + */ + private static async deployCommands(client: ExtendedClient): Promise { + const rest = new REST({ version: "10" }).setToken( + process.env.BOT_TOKEN as string + ); + + try { + logger.info( + { + clientId: process.env.BOT_CLIENT_ID, + guildId: process.env.GUILD_ID, + }, + "Started refreshing application (/) commands" + ); + + // Import all commands + const commandsObj = { + ...commands, + }; + + const commandsData = Object.values(commandsObj) + .filter((cmd) => cmd && typeof cmd.data?.toJSON === "function") + .map((command) => command.data.toJSON()); + + try { + const response = await rest.put( + Routes.applicationGuildCommands( + process.env.BOT_CLIENT_ID as string, + process.env.GUILD_ID as string + ), + { + body: commandsData, + } + ); + + logger.debug( + { + commandCount: commandsData.length, + responseStatus: response ? "success" : "unknown", + }, + "Command registration response" + ); + + // Register commands in client + for (const [_, command] of Object.entries(commandsObj)) { + if (command && command.data && command.data.name) { + client.commands.set( + command.data.name, + command as Command + ); + logger.debug( + `Registered command: ${command.data.name}` + ); + } + } + + logger.info("Successfully reloaded application (/) commands"); + } catch (putError: any) { + // More detailed error logging for the REST call + logger.error( + { + error: putError, + code: putError.code, + status: putError.status, + message: putError.message, + clientId: process.env.BOT_CLIENT_ID, + guildId: process.env.GUILD_ID, + tokenPresent: !!process.env.BOT_TOKEN, + tokenLength: process.env.BOT_TOKEN?.length, + }, + "Error during Discord REST API call to register commands" + ); + + // Check for common issues + if (putError.status === 403) { + logger.error( + "Permission denied (403) - The bot token may be invalid or the bot doesn't have the required permissions" + ); + } + if (putError.code === 50001) { + logger.error( + "Missing Access - Bot doesn't have required permissions in this guild" + ); + } + if (putError.code === 50035) { + logger.error( + "Invalid Form Body - Command structure might be invalid" + ); + } + } + } catch (error: any) { + logger.error( + { + error: error.message, + stack: error.stack, + }, + "Error deploying commands" + ); + } + } + + /** + * Gets the Discord client + */ + getClient = () => { + return this.client; + }; + + /** + * Gets the API provider + */ + getApiProvider = () => { + return this.apiProvider; + }; + + /** + * Finds a guild by ID + */ + getGuild = async (guildId: string) => { + return await this.client.guilds.fetch(guildId); + }; +} + +// --- Lazy Initialization --- +let discordInstance: Discord | null = null; + +export async function getDiscordInstance(): Promise { + if (!discordInstance) { + discordInstance = await Discord.new(); + } + return discordInstance; +} diff --git a/tooling/sparta/packages/discord/src/debug.ts b/tooling/sparta/packages/discord/src/debug.ts new file mode 100644 index 0000000..10f4fac --- /dev/null +++ b/tooling/sparta/packages/discord/src/debug.ts @@ -0,0 +1,2 @@ +// Debug utilities can be added here as needed +export {}; \ No newline at end of file diff --git a/tooling/sparta/packages/discord/src/index.ts b/tooling/sparta/packages/discord/src/index.ts new file mode 100644 index 0000000..672ca94 --- /dev/null +++ b/tooling/sparta/packages/discord/src/index.ts @@ -0,0 +1,19 @@ +/** + * @fileoverview Main Discord package entry point + * @description Exports all Discord package components + * @module sparta/discord + */ + +// Export API-related components +export { ApiProvider } from "@sparta/utils/openapi/api/apiProvider"; +export { clientPromise } from "@sparta/utils/openapi/api/axios"; + +// Export clients +export { Discord, getDiscordInstance } from "./clients/discord"; + +// Export services +export { DiscordService, discordService } from "./services"; +export { DiscordWebhookService, discordWebhookService } from "./services/discord-webhook"; + +// Export utils +export { _handleUserRolesAssignment } from "./utils/roleAssigner"; \ No newline at end of file diff --git a/tooling/sparta/packages/discord/src/services/discord-service.ts b/tooling/sparta/packages/discord/src/services/discord-service.ts new file mode 100644 index 0000000..59b9de1 --- /dev/null +++ b/tooling/sparta/packages/discord/src/services/discord-service.ts @@ -0,0 +1,394 @@ +/** + * @fileoverview Discord service for role management + * @description Provides methods for managing Discord roles and finding users + * @module sparta/discord/services + */ + +import { getDiscordInstance } from "../clients/discord"; +import { logger } from "@sparta/utils"; +import type { Guild, GuildMember, Role as DiscordRole, TextChannel } from "discord.js"; +import { REST } from "@discordjs/rest"; +import { Routes } from "discord-api-types/v10"; +import type { ApiProvider } from "@sparta/utils/openapi/api/apiProvider"; +import type { Client as ApiClient } from "@sparta/utils/openapi/types"; +import type { Role } from "@sparta/utils/const/roles"; + +/** + * Discord service class for role management and user operations + * + * This service provides methods to: + * - Assign roles to Discord users + * - Find Discord users by username or tag + * - Manage role hierarchies + * - Send direct messages to users + */ +export class DiscordService { + private static instance: DiscordService; + private apiProvider: ApiProvider | null = null; + private apiClient: ApiClient | null = null; + + private constructor() { + // Private constructor for singleton pattern + } + + /** + * Gets the singleton instance of DiscordService + */ + public static getInstance(): DiscordService { + if (!DiscordService.instance) { + DiscordService.instance = new DiscordService(); + } + return DiscordService.instance; + } + + /** + * Initialize the service with API provider + */ + public async init(): Promise { + if (this.apiClient) return; // Already initialized + + try { + const discord = await getDiscordInstance(); + this.apiProvider = discord.getApiProvider(); + this.apiClient = this.apiProvider.getClient(); + logger.info("Discord service initialized with API client"); + } catch (error) { + logger.error({ error }, "Failed to initialize Discord service"); + throw error; + } + } + + /** + * Shutdown the Discord client and clean up resources + * This prevents unhandled promise rejections when the Lambda function exits + */ + public async shutdown(): Promise { + try { + // Get the Discord instance + const discord = await getDiscordInstance(); + const client = discord.getClient(); + + // Destroy the client connection + if (client) { + logger.debug("Destroying Discord client connection"); + await client.destroy(); + } + + // Clear the singleton instance + DiscordService.instance = null as any; + this.apiProvider = null; + this.apiClient = null; + + logger.debug("Discord client resources released"); + } catch (error) { + logger.error({ error }, "Error shutting down Discord client"); + } + } + + /** + * Validates that a role can be assigned to a user + */ + public async validateRoleAssignment( + userId: string, + roleName: string + ): Promise<{ + isValid: boolean; + message: string; + guild?: Guild; + role?: DiscordRole; + member?: GuildMember; + }> { + try { + // Get the guild (server) + const guildId = process.env.GUILD_ID; + if (!guildId) { + return { + isValid: false, + message: "GUILD_ID not set in environment variables", + }; + } + + // Get the instance + const discord = await getDiscordInstance(); + const guild = await discord.getGuild(guildId); + if (!guild) { + return { + isValid: false, + message: `Guild not found with ID: ${guildId}`, + }; + } + + // Find the role + const role: DiscordRole | undefined = guild.roles.cache.find( + (r) => r.name === roleName + ); + if (!role) { + return { + isValid: false, + message: `Role '${roleName}' not found in guild '${guild.name}'`, + }; + } + + // Get the member + try { + if (!userId) { + return { + isValid: false, + message: "Missing userId for role assignment", + }; + } + + const member = await guild.members.fetch(userId); + if (!member) { + return { + isValid: false, + message: `User with ID '${userId}' not found in guild '${guild.name}'`, + }; + } + + return { + isValid: true, + message: "Validation successful", + guild, + role, + member, + }; + } catch (memberError) { + return { + isValid: false, + message: `User with ID '${userId}' not found in guild '${guild.name}'`, + }; + } + } catch (error) { + const errorMessage = + error instanceof Error ? error.message : String(error); + return { + isValid: false, + message: `Validation error: ${errorMessage}`, + }; + } + } + + public async assignRoles(userId: string, roles: Role[]): Promise { + for (const role of roles) { + await this.assignRole(userId, role.name); + } + return true; + } + + /** + * Assigns a role to a Discord user + * @param userId The Discord user ID + * @param roleName The name of the role to assign + */ + public async assignRole( + userId: string, + roleName: string + ): Promise { + // Ensure API client is initialized + if (!this.apiClient) { + await this.init(); + if (!this.apiClient) { + logger.error("API client not initialized"); + return false; + } + } + + const validationResult = await this.validateRoleAssignment( + userId, + roleName + ); + + if (!validationResult.isValid) { + logger.error( + { userId, roleName, error: validationResult.message }, + "Role assignment validation failed" + ); + return false; + } + + const { member, role } = validationResult; + await member!.roles.add(role!); + logger.info({ userId, roleName }, "Role assigned successfully"); + + return true; + } + + /** + * Edits the reply to an interaction using the interaction token + */ + public async editInteractionReply( + interactionToken: string, + content: any + ): Promise { + if (!interactionToken) { + logger.error("No interaction token provided for edit"); + return false; + } + + try { + const rest = new REST({ version: "10" }).setToken( + process.env.BOT_TOKEN as string + ); + + await rest.patch( + Routes.webhookMessage( + process.env.BOT_CLIENT_ID as string, + interactionToken + ), + { body: content } + ); + return true; + } catch (error) { + logger.error( + { + error, + interactionToken: interactionToken.substring(0, 10) + "...", + }, + "Error updating interaction reply" + ); + return false; + } + } + + /** + * Sends a direct message to a Discord user + * @param userId The Discord user ID + * @param message The message content to send + * @returns Promise indicating success or failure + */ + public async sendDirectMessage( + userId: string, + message: string + ): Promise { + try { + // Validate userId parameter + if (!userId) { + logger.error( + "Cannot send direct message - userId is null, undefined, or empty" + ); + return false; + } + + // Ensure API client is initialized + if (!this.apiClient) { + await this.init(); + if (!this.apiClient) { + logger.error("API client not initialized"); + return false; + } + } + + const discord = await getDiscordInstance(); + const client = discord.getClient(); + + try { + // Get the user + const user = await client.users.fetch(userId); + if (!user) { + logger.error( + { userId }, + "Failed to find Discord user for direct message" + ); + return false; + } + + // Send DM + await user.send(message); + logger.info( + { userId, messageLength: message.length }, + "Direct message sent successfully" + ); + return true; + } catch (error) { + logger.error( + { error, userId }, + "Error sending direct message to Discord user" + ); + return false; + } + } catch (error) { + logger.error( + { error, userId }, + "Error in sendDirectMessage method" + ); + return false; + } + } + + /** + * Sends a message to a Discord channel + * @param channelId The Discord channel ID + * @param message The message content to send + * @returns Promise indicating success or failure + */ + public async sendChannelMessage( + channelId: string, + message: string + ): Promise { + try { + // Ensure API client is initialized + if (!this.apiClient) { + await this.init(); + if (!this.apiClient) { + logger.error("API client not initialized"); + return false; + } + } + + const discord = await getDiscordInstance(); + const client = discord.getClient(); + + try { + // Get the guild + const guildId = process.env.GUILD_ID; + if (!guildId) { + logger.error("GUILD_ID not set in environment variables"); + return false; + } + + const guild = await client.guilds.fetch(guildId); + if (!guild) { + logger.error( + { guildId }, + "Failed to find Discord guild" + ); + return false; + } + + // Get the channel from the guild + const channel = await guild.channels.fetch(channelId) as TextChannel; + if (!channel || !channel.isTextBased()) { + logger.error( + { channelId }, + "Failed to find Discord text channel for message" + ); + return false; + } + + // Send channel message + await channel.send(message); + logger.info( + { channelId, messageLength: message.length }, + "Channel message sent successfully" + ); + return true; + } catch (error) { + logger.error( + { error, channelId }, + "Error sending message to Discord channel" + ); + return false; + } + } catch (error) { + logger.error( + { error, channelId }, + "Error in sendChannelMessage method" + ); + return false; + } + } +} + +// Export a singleton instance +export const discordService = DiscordService.getInstance(); diff --git a/tooling/sparta/packages/discord/src/services/discord-webhook.ts b/tooling/sparta/packages/discord/src/services/discord-webhook.ts new file mode 100644 index 0000000..f92cf98 --- /dev/null +++ b/tooling/sparta/packages/discord/src/services/discord-webhook.ts @@ -0,0 +1,129 @@ +/** + * @fileoverview Lightweight Discord webhook service + * @description Provides methods for sending Discord messages via webhooks without initializing the full client + * @module sparta/discord/services + */ + +import { logger } from "@sparta/utils"; +import { REST } from "@discordjs/rest"; +import { Routes } from "discord-api-types/v10"; + +/** + * Lightweight service for sending Discord messages via REST API + * Designed for serverless environments like AWS Lambda + */ +export class DiscordWebhookService { + private static instance: DiscordWebhookService; + private botToken: string; + private clientId: string; + private rest: REST; + + /** + * Initialize with bot token and client ID + */ + private constructor() { + this.botToken = process.env.BOT_TOKEN || ""; + this.clientId = process.env.BOT_CLIENT_ID || ""; + this.rest = new REST({ version: "10" }).setToken(this.botToken); + } + + /** + * Get the singleton instance + */ + public static getInstance(): DiscordWebhookService { + if (!DiscordWebhookService.instance) { + DiscordWebhookService.instance = new DiscordWebhookService(); + } + return DiscordWebhookService.instance; + } + + /** + * Send a direct message to a user via the REST API + * @param userId Discord user ID + * @param content Message content + */ + public async sendDirectMessage(userId: string, content: string): Promise { + try { + if (!userId || !content) { + logger.warn("Missing userId or content for direct message"); + return false; + } + + if (!this.botToken || !this.clientId) { + logger.error("Missing BOT_TOKEN or BOT_CLIENT_ID environment variables"); + return false; + } + + // Create a DM channel first + const dmChannelData = await this.rest.post( + Routes.userChannels(), + { + body: { + recipient_id: userId + } + } + ) as { id: string }; + + // Get the DM channel ID + const channelId = dmChannelData.id; + if (!channelId) { + logger.error(`Failed to create DM channel for user ${userId}`); + return false; + } + + // Send message to the DM channel + await this.rest.post( + Routes.channelMessages(channelId), + { + body: { + content + } + } + ); + + logger.info(`Direct message sent to user ${userId}`); + return true; + } catch (error) { + logger.error({ error }, `Failed to send direct message to user ${userId}`); + return false; + } + } + + /** + * Send a message to a channel via the REST API + * @param channelId Discord channel ID + * @param content Message content + */ + public async sendChannelMessage(channelId: string, content: string): Promise { + try { + if (!channelId || !content) { + logger.warn("Missing channelId or content for channel message"); + return false; + } + + if (!this.botToken) { + logger.error("Missing BOT_TOKEN environment variable"); + return false; + } + + // Send message to the channel + await this.rest.post( + Routes.channelMessages(channelId), + { + body: { + content + } + } + ); + + logger.info(`Channel message sent to channel ${channelId}`); + return true; + } catch (error) { + logger.error({ error }, `Failed to send channel message to channel ${channelId}`); + return false; + } + } +} + +// Export a singleton instance +export const discordWebhookService = DiscordWebhookService.getInstance(); \ No newline at end of file diff --git a/tooling/sparta/packages/discord/src/services/index.ts b/tooling/sparta/packages/discord/src/services/index.ts new file mode 100644 index 0000000..01e7572 --- /dev/null +++ b/tooling/sparta/packages/discord/src/services/index.ts @@ -0,0 +1,15 @@ +/** + * @fileoverview Service module exports + * @description Centralizes exports for all Sparta Discord service modules + * @module sparta/discord/services + */ + +import { DiscordService, discordService } from "./discord-service.js"; + +/** + * Export all service classes and instances + * + * - DiscordService: Manages Discord roles and user interactions + * - discordService: Singleton instance of DiscordService + */ +export { DiscordService, discordService }; diff --git a/tooling/sparta/packages/discord/src/slashCommands/index.ts b/tooling/sparta/packages/discord/src/slashCommands/index.ts new file mode 100644 index 0000000..ab177e1 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/index.ts @@ -0,0 +1,12 @@ +/** + * @fileoverview Roles module exports + * @description Centralizes exports for all Discord role-related commands + * @module sparta/discord/roles + */ + +import operatorsCommands from "./operators/index"; +import moderatorsCommands from "./moderators/index"; +export * from "../types"; + +// Export roles commands +export default { operatorsCommands, moderatorsCommands }; diff --git a/tooling/sparta/packages/discord/src/slashCommands/moderators/help.ts b/tooling/sparta/packages/discord/src/slashCommands/moderators/help.ts new file mode 100644 index 0000000..f731f97 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/moderators/help.ts @@ -0,0 +1,80 @@ +/** + * @fileoverview Moderator help command handler + * @description Handles Discord command for displaying moderator command documentation + * @module sparta/discord/roles/moderators/help + */ + +import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js"; +import { logger } from "@sparta/utils"; +import { ModeratorSubcommands } from "../../types.js"; +import { getAllowedChannelsText } from "@sparta/utils"; +import { MODERATOR_ROLES } from "@sparta/utils/const/roles.js"; +/** + * Display help information for all moderator commands + */ +export async function showModeratorHelp( + interaction: ChatInputCommandInteraction +): Promise { + try { + // No need to defer reply here since it's already deferred in the parent command + + // Create a formatted embed for the command help + const embed = new EmbedBuilder() + .setTitle("Moderator Commands Help") + .setDescription( + "List of available moderator commands and their usage" + ) + .setColor(0x2b65ec) // Blue color for help message + .addFields([ + { + name: "Moderator Permissions", + value: + "These commands are restricted to users with the following roles:\n" + + Object.values(MODERATOR_ROLES) + .map((role) => `• \`${role.name}\``) + .join("\n"), + inline: false, + }, + { + name: "Channel Restrictions", + value: `Moderator commands can only be used in ${getAllowedChannelsText()} ${ + process.env.NODE_ENV === "production" + ? "channels" + : "channel" + }.`, + inline: false, + }, + { + name: `/mod ${ModeratorSubcommands.Help}`, + value: "Display this help message listing all moderator commands", + inline: false, + }, + { + name: `/mod ${ModeratorSubcommands.Info}`, + value: "Get comprehensive information about a node operator\n`username` - The Discord username of the operator (required)\n\nThis command shows:\n• Operator details (wallet, approval status)\n• Validator information (in set, attesting status, miss percentage)", + inline: false, + }, + { + name: `/mod ${ModeratorSubcommands.Approve}`, + value: "Approve a user to join the validator set\n`user` - The Discord username of the user to approve (required)", + inline: false, + }, + ]) + .setFooter({ + text: "Use these commands to manage and monitor validator operations", + }) + .setTimestamp(); + + await interaction.editReply({ + embeds: [embed], + }); + + return "Moderator help displayed successfully"; + } catch (error) { + logger.error("Error displaying moderator help:", error); + await interaction.editReply({ + content: "Error displaying moderator help information.", + }); + throw error; + } +} diff --git a/tooling/sparta/packages/discord/src/slashCommands/moderators/index.ts b/tooling/sparta/packages/discord/src/slashCommands/moderators/index.ts new file mode 100644 index 0000000..e9de4a0 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/moderators/index.ts @@ -0,0 +1,104 @@ +import { + SlashCommandBuilder, + ChatInputCommandInteraction, + MessageFlags, +} from "discord.js"; +// import { getValidatorStats } from "./get-operator-stats.js"; +import { logger } from "@sparta/utils"; +import { + ModeratorSubcommandGroups, + ModeratorSubcommands, +} from "../../types.js"; +import { showModeratorHelp } from "./help.js"; +import { checkModeratorPermissions } from "../../utils/index.js"; +import { approveUser } from "./operator-approve.js"; +import { getOperatorInfo } from "./operator-info.js"; + +export default { + data: new SlashCommandBuilder() + .setName(ModeratorSubcommandGroups.Moderator) + .setDescription("Moderator commands") + .addSubcommand((subcommand) => + subcommand + .setName(ModeratorSubcommands.Info) + .setDescription("Get comprehensive information about a node operator") + .addStringOption((option) => + option + .setName("username") + .setDescription("The Discord username of the operator") + .setRequired(true) + ) + ) + .addSubcommand((subcommand) => + subcommand + .setName(ModeratorSubcommands.Approve) + .setDescription("Approve a user to join the validator set") + .addStringOption((option) => + option + .setName("user") + .setDescription("The Discord username of the user to approve") + .setRequired(true) + ) + ) + .addSubcommand((subcommand) => + subcommand + .setName(ModeratorSubcommands.Help) + .setDescription("Display help for moderator commands") + ), + execute: async (interaction: ChatInputCommandInteraction) => { + try { + // Check if the user has permission to use moderator commands + // This checks against the defined moderator roles and provides appropriate error messages + if (!(await checkModeratorPermissions(interaction))) { + // The checkModeratorPermissions function already sent a reply if the user doesn't have permission + return "Insufficient permissions"; + } + + // Defer the reply after permission check to avoid timeout issues + // For commands that might take longer to process + await interaction.deferReply({ + flags: MessageFlags.Ephemeral, + }); + + const subcommand = interaction.options.getSubcommand(); + switch (subcommand) { + case ModeratorSubcommands.Info: + await getOperatorInfo(interaction); + break; + case ModeratorSubcommands.Approve: + await approveUser(interaction); + break; + case ModeratorSubcommands.Help: + await showModeratorHelp(interaction); + break; + default: + await interaction.editReply({ + content: `Invalid subcommand: ${subcommand}`, + }); + return "Invalid subcommand"; + } + // Add explicit return after successful command execution + return; + } catch (error) { + console.log(error); + logger.error("Failed to get info:", { error }); + try { + // Check if the reply has been deferred + await interaction.editReply({ + content: "Something went wrong while fetching info.", + }); + } catch (replyError) { + // If editReply fails (e.g., not deferred), use reply instead + try { + await interaction.reply({ + content: "Something went wrong while fetching info.", + flags: MessageFlags.Ephemeral, + }); + } catch (finalError) { + logger.error("Failed to send error response:", finalError); + } + } + return "Error executing command"; // Keep explicit return + } + }, +}; diff --git a/tooling/sparta/packages/discord/src/slashCommands/moderators/operator-approve.ts b/tooling/sparta/packages/discord/src/slashCommands/moderators/operator-approve.ts new file mode 100644 index 0000000..71fb9d0 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/moderators/operator-approve.ts @@ -0,0 +1,111 @@ +import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js"; +import { logger } from "@sparta/utils"; +import * as dotenv from "dotenv"; +import { clientPromise } from "@sparta/utils/openapi/api/axios"; + +// Load environment variables +dotenv.config(); + +/** + * Approves a node operator by setting their isApproved flag to true + */ +export async function approveUser( + interaction: ChatInputCommandInteraction +) { + try { + // Get Discord username from options + const discordUsername = interaction.options.getString("user"); + + if (!discordUsername) { + await interaction.editReply("Please provide a Discord username."); + return; + } + + try { + const client = await clientPromise; + + // Call the approve endpoint with the Discord username as query parameter + try { + // The OpenAPI client is correctly configured to handle query parameters + // The endpoint is documented in the OpenAPI spec as /api/operator/approve + // The approveOperator operation expects query parameters, not body + await client.approveOperator( + { + discordUsername: discordUsername + }, + null // No body data + ); + + const embed = new EmbedBuilder() + .setTitle("✅ OPERATOR APPROVED") + .setColor(0x00ff00) // Green for success + .setDescription(`Discord Username: \`${discordUsername}\``) + .addFields([ + { + name: "Status", + value: "Operator has been successfully approved.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return "APPROVED"; + } catch (approvalError: any) { + console.log(approvalError); + logger.error("Error approving operator:", approvalError); + + // If 404, operator not found + if (approvalError.response && approvalError.response.status === 404) { + const embed = new EmbedBuilder() + .setTitle("❌ APPROVAL FAILED") + .setColor(0xff0000) // Red for failure + .setDescription(`No node operator found with Discord username: \`${discordUsername}\``) + .addFields([ + { + name: "Error", + value: "This Discord username is not registered in our database.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return "NOT_FOUND"; + } + + // Other errors + const embed = new EmbedBuilder() + .setTitle("❌ APPROVAL FAILED") + .setColor(0xff0000) // Red for failure + .setDescription(`Error approving operator with Discord username: \`${discordUsername}\``) + .addFields([ + { + name: "Error", + value: "There was an error with the approval process.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return "APPROVAL_ERROR"; + } + + } catch (apiError) { + logger.error("Error with operator API:", apiError); + + const embed = new EmbedBuilder() + .setTitle("❌ APPROVAL FAILED") + .setColor(0xff0000) // Red for failure + .setDescription(`API service error when approving Discord username: \`${discordUsername}\``) + .addFields([ + { + name: "Error", + value: "The operator service is currently unavailable.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return "API_ERROR"; + } + } catch (error) { + logger.error("Error executing approve user command:", error); + await interaction.editReply("Error approving operator."); + throw error; + } +} diff --git a/tooling/sparta/packages/discord/src/slashCommands/moderators/operator-info.ts b/tooling/sparta/packages/discord/src/slashCommands/moderators/operator-info.ts new file mode 100644 index 0000000..1f565c6 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/moderators/operator-info.ts @@ -0,0 +1,245 @@ +import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js"; +import { logger } from "@sparta/utils"; +import * as dotenv from "dotenv"; +import { clientPromise } from "@sparta/utils/openapi/api/axios"; +import { getEthereumInstance, l2InfoService } from "@sparta/ethereum"; + +// Load environment variables +dotenv.config(); + +// Define types based on API responses +interface Validator { + validatorAddress: string; + nodeOperatorId: string; +} + +interface NodeOperator { + discordId: string; + walletAddress: string; + discordUsername?: string; + isApproved?: boolean; + createdAt: number; + updatedAt: number; + validators?: Validator[]; +} + +interface ValidatorDetail { + address: string; + inSet: boolean; + attesting: boolean; + missPercentage: string; +} + +/** + * Gets comprehensive information about a node operator by their Discord username + * Combines the functionality of operator-attesting and operator-in-set + */ +export async function getOperatorInfo( + interaction: ChatInputCommandInteraction +) { + try { + // Get Discord username from options + const discordUsername = interaction.options.getString("username"); + + if (!discordUsername) { + await interaction.editReply("Please provide a Discord username."); + return; + } + + try { + const client = await clientPromise; + + // Fetch operator info by Discord username + try { + // Call the operator API with the Discord username as query parameter + const response = await client.getOperator({ + discordUsername: discordUsername + }); + + const operator = response.data as NodeOperator; + + if (!operator) { + const embed = new EmbedBuilder() + .setTitle("❌ OPERATOR NOT FOUND") + .setColor(0xff0000) // Red for error + .setDescription(`No node operator found with Discord username: \`${discordUsername}\``); + + await interaction.editReply({ embeds: [embed] }); + return; + } + + // Get Ethereum instance for validator set check + const ethereum = await getEthereumInstance(); + const chainInfo = await ethereum.getRollupInfo(); + + // Initialize variables for reporting + let hasValidators = false; + let validatorsInSet = 0; + let validatorsAttesting = 0; + let totalValidators = 0; + const validatorDetails: ValidatorDetail[] = []; + + // Process validator information if the operator has any + if (operator.validators && operator.validators.length > 0) { + hasValidators = true; + totalValidators = operator.validators.length; + + // Process each validator + for (const validator of operator.validators) { + if (validator && validator.validatorAddress) { + const validatorAddress = validator.validatorAddress; + + // Check if validator is in set + const isInValidatorSet = chainInfo.validators.some( + (v: string) => v.toLowerCase() === validatorAddress.toLowerCase() + ); + + // Check if validator is attesting (if in set) + let isAttesting = false; + let missPercentage = "N/A"; + + if (isInValidatorSet) { + validatorsInSet++; + + // Fetch attestation stats + const validatorStats = await l2InfoService.fetchValidatorStats(validatorAddress); + + if (validatorStats.totalSlots && validatorStats.missedAttestationsCount !== undefined) { + const missed = (validatorStats.missedAttestationsCount / validatorStats.totalSlots) * 100; + missPercentage = missed.toFixed(2) + "%"; + + // Active if missed less than 20% of attestations + isAttesting = missed < 20; + if (isAttesting) { + validatorsAttesting++; + } + } + } + + // Add to validator details + validatorDetails.push({ + address: validatorAddress, + inSet: isInValidatorSet, + attesting: isAttesting, + missPercentage: missPercentage + }); + } + } + } + + // Create embed with all operator information + const embed = new EmbedBuilder() + .setTitle(`${operator.isApproved ? "✅" : "⚠️"} OPERATOR INFO: ${discordUsername}`) + .setColor(operator.isApproved ? 0x00ff00 : 0xffcc00) // Green if approved, yellow if not + .setDescription(`Comprehensive information about node operator: \`${discordUsername}\``) + .addFields([ + { + name: "Discord ID", + value: `\`${operator.discordId}\``, + inline: true + }, + { + name: "Wallet Address", + value: `\`${operator.walletAddress}\``, + inline: true + }, + { + name: "Approval Status", + value: operator.isApproved ? "Approved ✅" : "Not Approved ⚠️", + inline: true + }, + { + name: "Validators", + value: hasValidators ? + `Total: ${totalValidators} | In Set: ${validatorsInSet} | Attesting: ${validatorsAttesting}` : + "No validators found", + } + ]); + + // Add details for each validator if there are any + if (hasValidators && validatorDetails.length > 0) { + for (let i = 0; i < validatorDetails.length; i++) { + const v = validatorDetails[i]; + if (v) { + embed.addFields([ + { + name: `Validator ${i+1}: ${v.address.substring(0, 10)}...`, + value: `In Set: ${v.inSet ? "✅" : "❌"} | ` + + `Attesting: ${v.attesting ? "✅" : "❌"} | ` + + `Miss %: ${v.missPercentage}`, + inline: false + } + ]); + } + } + } + + // Add registration timestamps + embed.addFields([ + { + name: "Registered", + value: new Date(operator.createdAt).toISOString(), + inline: true + }, + { + name: "Last Updated", + value: new Date(operator.updatedAt).toISOString(), + inline: true + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return; + + } catch (apiError: any) { + logger.error("Error fetching operator:", apiError); + + if (apiError.response && apiError.response.status === 404) { + const embed = new EmbedBuilder() + .setTitle("❌ OPERATOR NOT FOUND") + .setColor(0xff0000) // Red for error + .setDescription(`No node operator found with Discord username: \`${discordUsername}\``); + + await interaction.editReply({ embeds: [embed] }); + return; + } + + // Other errors + const embed = new EmbedBuilder() + .setTitle("❌ ERROR FETCHING OPERATOR INFO") + .setColor(0xff0000) // Red for error + .setDescription(`Error retrieving information for: \`${discordUsername}\``) + .addFields([ + { + name: "Error", + value: "There was an error fetching operator information.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return; + } + + } catch (error) { + logger.error("Error with operator API service:", error); + + const embed = new EmbedBuilder() + .setTitle("❌ SERVICE ERROR") + .setColor(0xff0000) // Red for error + .setDescription(`API service error when fetching info for: \`${discordUsername}\``) + .addFields([ + { + name: "Error", + value: "The operator service is currently unavailable.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return; + } + } catch (error) { + logger.error("Error executing operator info command:", error); + await interaction.editReply("Error retrieving operator information."); + throw error; + } +} \ No newline at end of file diff --git a/tooling/sparta/packages/discord/src/slashCommands/operators/add-validator.ts b/tooling/sparta/packages/discord/src/slashCommands/operators/add-validator.ts new file mode 100644 index 0000000..0e5c598 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/operators/add-validator.ts @@ -0,0 +1,156 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + MessageFlags, + GuildMember, +} from "discord.js"; +import { logger } from "@sparta/utils"; +import { clientPromise } from "@sparta/utils/openapi/api/axios"; +import { hasGuardianRole } from "../../utils/roles"; + +/** + * Handle the "add-validator" subcommand to add a new validator + */ +export async function addValidator( + interaction: ChatInputCommandInteraction +): Promise { + await interaction.deferReply({ + flags: MessageFlags.Ephemeral, + }); + + // Check if the user has the Guardian role + const member = interaction.member as GuildMember; + if (!member) { + await interaction.editReply({ + content: "Could not verify your server membership. Please try again.", + }); + return "Failed to verify server membership"; + } + + if (!hasGuardianRole(member)) { + await interaction.editReply({ + content: "You don't have permission to use this command", + }); + return "Permission denied - Guardian role required"; + } + + try { + // Get parameters from the command options + const validatorAddress = interaction.options.getString("validator-address"); + + // Validate address format + if (!validatorAddress || !/^0x[a-fA-F0-9]{40}$/.test(validatorAddress)) { + await interaction.editReply("Invalid Ethereum address format."); + return "Invalid address format"; + } + + // Get Discord user ID from interaction + const discordId = interaction.user.id; + const discordUsername = interaction.user.username; + + try { + // Get API client + const client = await clientPromise; + + // First, get the node operator to check if they already have validators + const operatorResponse = await client.getOperator({ + discordId + }); + + // Check if the operator already has validators + const operatorData = operatorResponse.data; + if (operatorData && operatorData.validators && operatorData.validators.length > 0) { + // Create error embed for the case when operator already has validators + const errorEmbed = new EmbedBuilder() + .setTitle(`Validator Addition Failed`) + .setColor(0xff0000) // Red for failure + .setTimestamp() + .setFooter({ text: "Sparta Validator Registration" }) + .setDescription("You already have one or more validators registered. Only one validator is allowed per operator."); + + await interaction.editReply({ embeds: [errorEmbed] }); + return "Error: Operator already has validators"; + } + + // Call the POST /api/operator/validator endpoint + await client.addValidator( + { + discordId, + discordUsername, + }, + { + validatorAddress, + } + ); + + // Create a Discord embed for the result + const embed = new EmbedBuilder() + .setTitle(`Validator Added`) + .setColor(0x00ff00) // Green for success + .setTimestamp() + .setFooter({ text: "Sparta Validator Registration" }); + + const displayAddress = `${validatorAddress.slice(0, 6)}...${validatorAddress.slice(-4)}`; // Shortened address + + embed.setDescription( + `✅ **New validator ${displayAddress} added successfully!**` + ); + embed.addFields( + { + name: "Validator Address", + value: validatorAddress, + inline: false, + }, + { + name: "Status", + value: "Validator added", + inline: true, + } + ); + + await interaction.editReply({ embeds: [embed] }); + return "Validator added successfully"; + + } catch (apiError: any) { + logger.error("Error with operator API:", apiError); + + // Create error embed + const errorEmbed = new EmbedBuilder() + .setTitle(`Validator Addition Failed`) + .setColor(0xff0000) // Red for failure + .setTimestamp() + .setFooter({ text: "Sparta Validator Registration" }); + + // Add appropriate error message based on error status + if (apiError.response) { + switch (apiError.response.status) { + case 400: + errorEmbed.setDescription("Invalid validator address format."); + break; + case 403: + errorEmbed.setDescription("Your account requires approval before adding validators."); + break; + case 404: + errorEmbed.setDescription("Node operator not found. Please register as an operator first."); + break; + case 401: + errorEmbed.setDescription("Authentication error. Please try again later."); + break; + default: + errorEmbed.setDescription("An error occurred while adding the validator. Please try again later."); + } + } else { + errorEmbed.setDescription("Connection error. Please try again later."); + } + + await interaction.editReply({ embeds: [errorEmbed] }); + return "Error adding validator"; + } + } catch (error) { + logger.error("Failed to add validator:", error); + await interaction.editReply({ + content: "An unexpected error occurred. Please try again later.", + }); + return "Unexpected error adding validator"; + } +} \ No newline at end of file diff --git a/tooling/sparta/packages/discord/src/slashCommands/operators/chain-info.ts b/tooling/sparta/packages/discord/src/slashCommands/operators/chain-info.ts new file mode 100644 index 0000000..408ce19 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/operators/chain-info.ts @@ -0,0 +1,37 @@ +import { ChatInputCommandInteraction, MessageFlags } from "discord.js"; +import { getEthereumInstance } from "@sparta/ethereum"; +import { logger } from "@sparta/utils"; + +export const get = async ( + interaction: ChatInputCommandInteraction +): Promise => { + try { + await interaction.deferReply(); + + // Get Ethereum instance + const ethereum = await getEthereumInstance(); + + // Get chain info directly + const { + pendingBlockNum, + provenBlockNum, + currentEpoch, + currentSlot, + proposerNow, + } = await ethereum.getRollupInfo(); + + await interaction.editReply({ + content: ` +Pending block: [${pendingBlockNum}](https://aztecscan.xyz/blocks/${pendingBlockNum}) +Proven block: [${provenBlockNum}](https://aztecscan.xyz/blocks/${provenBlockNum}) +Current epoch: ${currentEpoch} +Current slot: ${currentSlot} +Proposer now: [${proposerNow}](https://sepolia.etherscan.io/address/${proposerNow})`, + flags: MessageFlags.SuppressEmbeds, + }); + return `Pending block: ${pendingBlockNum}\nProven block: ${provenBlockNum}\nCurrent epoch: ${currentEpoch}\nCurrent slot: ${currentSlot}\nProposer now: ${proposerNow}`; + } catch (error) { + logger.error(error, "Error getting chain info"); + throw error; + } +}; diff --git a/tooling/sparta/packages/discord/src/slashCommands/operators/help.ts b/tooling/sparta/packages/discord/src/slashCommands/operators/help.ts new file mode 100644 index 0000000..b8e33c7 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/operators/help.ts @@ -0,0 +1,132 @@ +/** + * @fileoverview Operator help command handler + * @description Handles Discord command for displaying node operator command documentation and registration instructions + * @module sparta/discord/roles/operators/help + */ + +import { + ChatInputCommandInteraction, + EmbedBuilder, + MessageFlags, +} from "discord.js"; +import { logger } from "@sparta/utils"; +import { NodeOperatorSubcommands } from "../../types.js"; + +/** + * Display help information for all operator commands with reference to registration + */ +export async function showOperatorHelp( + interaction: ChatInputCommandInteraction +): Promise { + try { + await interaction.deferReply({ + flags: MessageFlags.Ephemeral, + }); + + // Create a formatted embed for the command help + const helpEmbed = new EmbedBuilder() + .setTitle("🔧 Node Operator Commands") + .setDescription( + "Available commands and tools for Sparta Network node operators" + ) + .setColor(0x4bb543) // Green color for operator commands + .addFields([ + { + name: `/operator ${NodeOperatorSubcommands.Help}`, + value: "Display this help message with available commands", + inline: false, + }, + { + name: `/operator ${NodeOperatorSubcommands.ChainInfo}`, + value: "Get current information about the Sparta Network chain status", + inline: false, + }, + { + name: `/operator ${NodeOperatorSubcommands.MyStats}`, + value: "Check your node operator status and validator statistics", + inline: false, + }, + { + name: `/operator ${NodeOperatorSubcommands.Start}`, + value: "Register your validator node on the discord server\n• Run without parameters for detailed registration instructions\n• Or use with:\n`address` - Your validator address\n`block-number` - Block number for verification\n`proof` - Your sync proof", + inline: false, + }, + ]) + .setFooter({ + text: "Use these commands to manage your node operations", + }) + .setTimestamp(); + + await interaction.editReply({ + embeds: [helpEmbed], + }); + + return "Operator help information displayed successfully"; + } catch (error) { + logger.error("Error displaying operator help:", error); + await interaction.editReply({ + content: "Error displaying operator help information.", + }); + throw error; + } +} + +/** + * Display detailed instructions for validator registration + */ +export async function showRegistrationHelp( + interaction: ChatInputCommandInteraction +): Promise { + try { + await interaction.deferReply({ + flags: MessageFlags.Ephemeral, + }); + + // Create a registration instructions embed + const registrationEmbed = new EmbedBuilder() + .setTitle("📝 How to Get the Apprentice Role") + .setDescription( + "Follow these simple steps to generate a sync proof and register your validator node on the Discord server" + ) + .setColor(0x4bb543) // Green color + .addFields([ + { + name: "📋 Step 1: Get the latest proven block number", + value: '```bash\ncurl -s -X POST -H \'Content-Type: application/json\' \\\n-d \'{"jsonrpc":"2.0","method":"node_getL2Tips","params":[],"id":67}\' \\\n: | jq -r ".result.proven.number"\n```\n• Replace `:` with your node\'s URL, for example `http://localhost:8080` or `https://mynode.example.com:8080`\n• Save this block number for the next steps\n• Example output: `12345`', + inline: false, + }, + { + name: "🔍 Step 2: Generate your sync proof", + value: '```bash\ncurl -s -X POST -H \'Content-Type: application/json\' \\\n-d \'{"jsonrpc":"2.0","method":"node_getArchiveSiblingPath","params":["",""],"id":67}\' \\\n: | jq -r ".result"\n```\n• Replace `:` with the same URL you used in Step 1\n• Replace both instances of `` with the number from Step 1 (example: 12345)\n• This will output a long base64-encoded string - copy it completely\n• Example command with values filled in:\n```bash\ncurl -s -X POST -H \'Content-Type: application/json\' \\\n-d \'{"jsonrpc":"2.0","method":"node_getArchiveSiblingPath","params":["12345","12345"],"id":67}\' \\\nhttp://localhost:8080 | jq -r ".result"\n```', + inline: false, + }, + { + name: "✅ Step 3: Register with Discord", + value: "Type the following command in this Discord server:\n```\n/operator start\n```\n**IMPORTANT**: After typing the command, Discord will display option fields that look like this:\n```\nOPTIONS\naddress Your validator address\nblock-number Block number for verification\nproof Your sync proof\n```\nClick on each option to fill in your information:\n• `address`: Your Ethereum validator address (must start with 0x, example: 0x1234567890abcdef1234567890abcdef12345678)\n• `block-number`: The block number from Step 1 (example: 12345)\n• `proof`: The complete base64 string from Step 2\n\n❗ **Common mistake**: Do not type all parameters in a single line. You must click on each option field separately to input your data.", + inline: false, + }, + { + name: "💡 Tips for Success", + value: "• Ensure your node is fully synced before attempting registration\n• Double-check your validator Ethereum address format (must begin with 0x followed by 40 hex characters)\n• Make sure to copy the entire proof string without missing any characters\n• If you don't have jq installed, you can omit the `| jq` part and extract the needed values manually\n• If registration fails, try generating a new proof with a more recent block\n• Common errors: incorrect URL format, node not synced, or incomplete proof string", + inline: false, + }, + { + name: "🛠️ Troubleshooting", + value: "• If you get `Connection refused`: Check that your node is running and the URL is correct\n• If your proof is invalid: Ensure your node is fully synced and try again with a newer block\n• If you can't format the commands properly: Ask for help in the support channel", + inline: false, + }, + ]); + + await interaction.editReply({ + embeds: [registrationEmbed], + }); + + return "Registration instructions displayed successfully"; + } catch (error) { + logger.error("Error displaying registration help:", error); + await interaction.editReply({ + content: "Error displaying registration instructions.", + }); + throw error; + } +} diff --git a/tooling/sparta/packages/discord/src/slashCommands/operators/index.ts b/tooling/sparta/packages/discord/src/slashCommands/operators/index.ts new file mode 100644 index 0000000..c725fc1 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/operators/index.ts @@ -0,0 +1,98 @@ +import { SlashCommandBuilder, ChatInputCommandInteraction } from "discord.js"; +import { get as getChainInfo } from "./chain-info.js"; +import { logger } from "@sparta/utils"; +import { + NodeOperatorSubcommandGroups, + NodeOperatorSubcommands, +} from "../../types.js"; +import { getNodeOperatorInfo } from "./my-stats.js"; +import { registerValidator } from "./register.js"; +import { showOperatorHelp } from "./help.js"; +import { addValidator } from "./add-validator.js"; + +export default { + data: new SlashCommandBuilder() + .setName(NodeOperatorSubcommandGroups.Operator) + .setDescription("Node operator commands") + .addSubcommand((subcommand) => + subcommand + .setName(NodeOperatorSubcommands.MyStats) + .setDescription("Check your node operator status and validator stats") + ) + .addSubcommand((subcommand) => + subcommand + .setName(NodeOperatorSubcommands.ChainInfo) + .setDescription("Get chain information") + ) + .addSubcommand((subcommand) => + subcommand + .setName(NodeOperatorSubcommands.Start) + .setDescription("Register your validator") + .addStringOption((option) => + option + .setName("address") + .setDescription("Your validator address") + .setRequired(true) + ) + .addStringOption((option) => + option + .setName("block-number") + .setDescription("Block number for verification") + .setRequired(true) + ) + .addStringOption((option) => + option + .setName("proof") + .setDescription("Your sync proof") + .setRequired(true) + ) + ) + .addSubcommand((subcommand) => + subcommand + .setName(NodeOperatorSubcommands.AddValidator) + .setDescription("Add a new validator to your account") + .addStringOption((option) => + option + .setName("validator-address") + .setDescription("The validator address to add") + .setRequired(true) + ) + ) + .addSubcommand((subcommand) => + subcommand + .setName(NodeOperatorSubcommands.Help) + .setDescription("Display help information for node operators") + ), + execute: async (interaction: ChatInputCommandInteraction) => { + try { + const subcommand = interaction.options.getSubcommand(); + switch (subcommand) { + case NodeOperatorSubcommands.MyStats: + await getNodeOperatorInfo(interaction); + break; + case NodeOperatorSubcommands.ChainInfo: + await getChainInfo(interaction); + break; + case NodeOperatorSubcommands.Start: + await registerValidator(interaction); + break; + case NodeOperatorSubcommands.Help: + await showOperatorHelp(interaction); + break; + case NodeOperatorSubcommands.AddValidator: + await addValidator(interaction); + break; + default: + await interaction.editReply({ + content: `Invalid subcommand: ${subcommand}`, + }); + return "Invalid subcommand"; + } + // Add explicit return after successful command execution + return; + } catch (error) { + logger.error("Failed to execute operator command:", error); + return; // Keep explicit return + } + }, +}; diff --git a/tooling/sparta/packages/discord/src/slashCommands/operators/my-stats.ts b/tooling/sparta/packages/discord/src/slashCommands/operators/my-stats.ts new file mode 100644 index 0000000..1bb2645 --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/operators/my-stats.ts @@ -0,0 +1,255 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + MessageFlags, +} from "discord.js"; +import { logger } from "@sparta/utils"; +import * as dotenv from "dotenv"; +import { clientPromise } from "@sparta/utils/openapi/api/axios"; +import { getEthereumInstance, l2InfoService } from "@sparta/ethereum"; + +// Load environment variables +dotenv.config(); + +// Define types based on API responses +interface Validator { + validatorAddress: string; + nodeOperatorId: string; +} + +interface NodeOperator { + discordId: string; + walletAddress: string; + discordUsername?: string; + isApproved?: boolean; + createdAt: number; + updatedAt: number; + validators?: Validator[]; +} + +interface ValidatorDetail { + address: string; + inSet: boolean; + attesting: boolean; + missPercentage: string; +} + +/** + * Handler for the operator "my-info" command + * Shows the current user's operator information and validator status + */ +export async function getNodeOperatorInfo( + interaction: ChatInputCommandInteraction +) { + try { + await interaction.deferReply({ + flags: MessageFlags.Ephemeral, // Make the response only visible to the user + }); + + // Get the user's Discord ID from the interaction + const discordId = interaction.user.id; + + try { + const client = await clientPromise; + + // Fetch operator info by Discord ID + try { + // Call the operator API with the Discord ID as query parameter + const response = await client.getOperator({ + discordId: discordId + }); + + const operator = response.data as NodeOperator; + + if (!operator) { + const embed = new EmbedBuilder() + .setTitle("❌ NOT REGISTERED") + .setColor(0xff0000) // Red for error + .setDescription("You are not registered as a node operator.") + .addFields([ + { + name: "How to Register", + value: "Use the `/operator start` command to register as a node operator.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return; + } + + // Get Ethereum instance for validator set check + const ethereum = await getEthereumInstance(); + const chainInfo = await ethereum.getRollupInfo(); + + // Initialize variables for reporting + let hasValidators = false; + let validatorsInSet = 0; + let validatorsAttesting = 0; + let totalValidators = 0; + const validatorDetails: ValidatorDetail[] = []; + + // Process validator information if the operator has any + if (operator.validators && operator.validators.length > 0) { + hasValidators = true; + totalValidators = operator.validators.length; + + // Process each validator + for (const validator of operator.validators) { + if (validator && validator.validatorAddress) { + const validatorAddress = validator.validatorAddress; + + // Check if validator is in set + const isInValidatorSet = chainInfo.validators.some( + (v: string) => v.toLowerCase() === validatorAddress.toLowerCase() + ); + + // Check if validator is attesting (if in set) + let isAttesting = false; + let missPercentage = "N/A"; + + if (isInValidatorSet) { + validatorsInSet++; + + // Fetch attestation stats + const validatorStats = await l2InfoService.fetchValidatorStats(validatorAddress); + + if (validatorStats.totalSlots && validatorStats.missedAttestationsCount !== undefined) { + const missed = (validatorStats.missedAttestationsCount / validatorStats.totalSlots) * 100; + missPercentage = missed.toFixed(2) + "%"; + + // Active if missed less than 20% of attestations + isAttesting = missed < 20; + if (isAttesting) { + validatorsAttesting++; + } + } + } + + // Add to validator details + validatorDetails.push({ + address: validatorAddress, + inSet: isInValidatorSet, + attesting: isAttesting, + missPercentage: missPercentage + }); + } + } + } + + // Create embed with all operator information + const embed = new EmbedBuilder() + .setTitle(`YOUR OPERATOR INFO`) + .setColor(0x4bb543) // Standard green color for operator info + .setDescription(`Your node operator status and validator information`) + .addFields([ + { + name: "Discord ID", + value: `\`${operator.discordId}\``, + inline: true + }, + { + name: "Wallet Address", + value: `\`${operator.walletAddress}\``, + inline: true + }, + { + name: "Validators", + value: hasValidators ? + `Total: ${totalValidators} | In Set: ${validatorsInSet} | Attesting: ${validatorsAttesting}` : + "No validators found", + } + ]); + + // Add details for each validator if there are any + if (hasValidators && validatorDetails.length > 0) { + for (let i = 0; i < validatorDetails.length; i++) { + const v = validatorDetails[i]; + if (v) { + embed.addFields([ + { + name: `Validator ${i+1}: ${v.address.substring(0, 10)}...`, + value: `In Set: ${v.inSet ? "✅" : "❌"} | ` + + `Attesting: ${v.attesting ? "✅" : "❌"} | ` + + `Miss %: ${v.missPercentage}`, + inline: false + } + ]); + } + } + } + + // Add registration timestamps + embed.addFields([ + { + name: "Registered", + value: new Date(operator.createdAt).toISOString(), + inline: true + }, + { + name: "Last Updated", + value: new Date(operator.updatedAt).toISOString(), + inline: true + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return; + + } catch (apiError: any) { + logger.error("Error fetching operator:", apiError); + + if (apiError.response && apiError.response.status === 404) { + const embed = new EmbedBuilder() + .setTitle("❌ NOT REGISTERED") + .setColor(0xff0000) // Red for error + .setDescription("You are not registered as a node operator.") + .addFields([ + { + name: "How to Register", + value: "Use the `/operator start` command to register as a node operator.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return; + } + + // Other errors + const embed = new EmbedBuilder() + .setTitle("❌ ERROR FETCHING YOUR INFO") + .setColor(0xff0000) // Red for error + .setDescription("There was an error retrieving your operator information.") + .addFields([ + { + name: "Error", + value: "The operator service returned an error.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return; + } + + } catch (error) { + logger.error("Error with operator API service:", error); + + const embed = new EmbedBuilder() + .setTitle("❌ SERVICE ERROR") + .setColor(0xff0000) // Red for error + .setDescription("API service error when fetching your operator information.") + .addFields([ + { + name: "Error", + value: "The operator service is currently unavailable.", + } + ]); + + await interaction.editReply({ embeds: [embed] }); + return; + } + } catch (error) { + logger.error("Error executing my-info command:", error); + await interaction.editReply("Error retrieving your operator information."); + throw error; + } +} diff --git a/tooling/sparta/packages/discord/src/slashCommands/operators/register.ts b/tooling/sparta/packages/discord/src/slashCommands/operators/register.ts new file mode 100644 index 0000000..5780c2f --- /dev/null +++ b/tooling/sparta/packages/discord/src/slashCommands/operators/register.ts @@ -0,0 +1,299 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + MessageFlags, +} from "discord.js"; +import { logger } from "@sparta/utils"; +import { l2InfoService } from "@sparta/ethereum"; +import { clientPromise } from "@sparta/utils/openapi/api/axios"; +import { NODE_OPERATOR_ROLES } from "@sparta/utils/const/roles"; +import { _handleNodeOperatorRoleAssignment } from "../../utils/roleAssigner"; + +/** + * Handle the "register" subcommand to verify a validator's sync proof + */ +export async function registerValidator( + interaction: ChatInputCommandInteraction +): Promise { + await interaction.deferReply({ + flags: MessageFlags.Ephemeral, + }); + + try { + // Get parameters from the command options + const address = interaction.options.getString("address"); + const blockNumber = interaction.options.getString("block-number"); + const proof = interaction.options.getString("proof"); + + // Validate address format + if (!address || !/^0x[a-fA-F0-9]{40}$/.test(address)) { + await interaction.editReply("Invalid Ethereum address format."); + return "Invalid address format"; + } + + if (!blockNumber || !/^[0-9]+$/.test(blockNumber)) { + await interaction.editReply("Invalid block number format."); + return "Invalid block number format"; + } + + if (!proof) { + await interaction.editReply("Invalid proof format."); + return "Invalid proof format"; + } + + try { + // Verify the proof using the L2InfoService + const isValid = await l2InfoService.proveSynced(blockNumber, proof); + + // Create a Discord embed for the result + const embed = new EmbedBuilder() + .setTitle(`Validator Registration`) + .setColor(isValid ? 0x00ff00 : 0xff0000) // Green for success, Red for failure + .setTimestamp() + .setFooter({ text: "Sparta Validator Registration" }); + + const displayAddress = `${address.slice(0, 6)}...${address.slice( + -4 + )}`; // Shortened address + + if (isValid) { + // Get Discord user ID from interaction + const discordId = interaction.user.id; + + try { + // Get API client + const client = await clientPromise; + + let operationResult = "created"; // Default to "created" status + + try { + // Step 1: Check if operator exists with this discordId + const { data: operatorData } = + await client.getOperator( + { + discordId, + }, + ); + + if ( + operatorData && + operatorData.walletAddress !== address + ) { + // Update wallet if it's a different address + await client.updateOperator( + { + discordId: operatorData.discordId, + walletAddress: address, + }, + {} + ); + operationResult = "updated"; + } else { + operationResult = "unchanged"; + } + } catch (error: any) { + console.log(error) + // If 404, create new operator + if (error.response && error.response.status === 404) { + await client.createOperator( + { + discordId, + walletAddress: address, + discordUsername: interaction.user.username, + }, + {} + ); + operationResult = "created"; + } else { + // Rethrow for outer catch block + throw error; + } + } + + // Add Apprentice role to the user using the Discord service + // This grants the user access to resources reserved for validated node operators + if ( + operationResult === "created" || + operationResult === "updated" + ) { + try { + const success = + await _handleNodeOperatorRoleAssignment( + discordId, + NODE_OPERATOR_ROLES.APPRENTICE! + ); + if (success) { + logger.info( + `Added Apprentice role to user ${discordId}` + ); + } else { + logger.error( + `Failed to assign Apprentice role to user ${discordId}` + ); + } + } catch (roleError) { + logger.error( + "Error adding Apprentice role:", + roleError + ); + } + } + + // Set appropriate message based on operation result + if (operationResult === "created") { + embed.setDescription( + `✅ **New validator ${displayAddress} registered successfully!**` + ); + embed.addFields( + { + name: "Address", + value: address, + inline: false, + }, + { + name: "Block Number", + value: blockNumber, + inline: true, + }, + { + name: "Proof Verified", + value: "✓", + inline: true, + }, + { + name: "Status", + value: "New operator registered", + inline: false, + } + ); + } else if (operationResult === "updated") { + embed.setDescription( + `✅ **Validator ${displayAddress} updated successfully!**` + ); + embed.addFields( + { + name: "Address", + value: address, + inline: false, + }, + { + name: "Block Number", + value: blockNumber, + inline: true, + }, + { + name: "Proof Verified", + value: "✓", + inline: true, + }, + { + name: "Status", + value: "Wallet address updated", + inline: false, + } + ); + } else { + embed.setDescription( + `✅ **Validator ${displayAddress} verification successful!**` + ); + embed.addFields( + { + name: "Address", + value: address, + inline: false, + }, + { + name: "Block Number", + value: blockNumber, + inline: true, + }, + { + name: "Proof Verified", + value: "✓", + inline: true, + }, + { + name: "Status", + value: "Already registered with this address", + inline: false, + } + ); + } + } catch (apiError) { + console.log(apiError); + logger.error("Error with operator API:", { apiError }); + + // Set fallback message when API error occurs + embed.setDescription( + `✅ **Validator ${displayAddress} proof verified, but registration service unavailable.**` + ); + embed.addFields( + { + name: "Address", + value: address, + inline: false, + }, + { + name: "Block Number", + value: blockNumber, + inline: true, + }, + { + name: "Proof Verified", + value: "✓", + inline: true, + }, + { + name: "Note", + value: "Registration service error - please try again later", + inline: false, + } + ); + } + } else { + embed.setDescription(`❌ **Validator registration failed.**`); + embed.addFields( + { name: "Address", value: address, inline: false }, + { name: "Reason", value: "Invalid proof", inline: false } + ); + } + + await interaction.editReply({ embeds: [embed] }); + + return isValid ? "Registration successful" : "Registration failed"; + } catch (error) { + logger.error("Error validating proof:", error); + + const errorMessage = + error instanceof Error ? error.message : "Unknown error"; + + const embed = new EmbedBuilder() + .setTitle(`Registration Error`) + .setColor(0xff0000) // Red for error + .setDescription( + `❌ **Validator registration failed:**\n${errorMessage}` + ) + .setTimestamp() + .setFooter({ text: "Sparta Validator Registration" }); + + await interaction.editReply({ embeds: [embed] }); + return `Registration error: ${errorMessage}`; + } + } catch (error) { + logger.error("Error executing validator registration command:", error); + + if (interaction.replied || interaction.deferred) { + await interaction.editReply({ + content: + "Something went wrong while processing your registration.", + }); + } else { + await interaction.editReply({ + content: + "Something went wrong while processing your registration.", + }); + } + + throw error; + } +} diff --git a/tooling/sparta/packages/discord/src/types.ts b/tooling/sparta/packages/discord/src/types.ts new file mode 100644 index 0000000..b7151f4 --- /dev/null +++ b/tooling/sparta/packages/discord/src/types.ts @@ -0,0 +1,34 @@ +/** + * @fileoverview Command types for Discord roles + * @description Defines types and enums for Discord command handlers + * @module sparta/discord/roles/types + */ + +// Moderator command enums +export enum ModeratorSubcommandGroups { + Moderator = "mod", +} + +export enum ModeratorSubcommands { + Info = "info", + Approve = "approve", + Help = "help", +} + +// Node Operator command enums +export enum NodeOperatorSubcommandGroups { + Operator = "operator", +} + +export enum NodeOperatorSubcommands { + ChainInfo = "chain-info", + MyStats = "my-stats", + Start = "start", + Help = "help", + AddValidator = "add-validator", +} + +// Other role-related enums +export enum PassportRoles { + Verified = "Verified+", // Base role for verification +} diff --git a/tooling/sparta/packages/discord/src/utils/index.ts b/tooling/sparta/packages/discord/src/utils/index.ts new file mode 100644 index 0000000..7bae52b --- /dev/null +++ b/tooling/sparta/packages/discord/src/utils/index.ts @@ -0,0 +1,12 @@ +/** + * @fileoverview Utility module index + * @description Exports all utility functions from the utils directory + * @module sparta/discord/utils + */ + + +// Re-export role utilities +export * from "./roles"; + +// Re-export other utilities +export * from "./roleAssigner"; diff --git a/tooling/sparta/packages/discord/src/utils/roleAssigner.ts b/tooling/sparta/packages/discord/src/utils/roleAssigner.ts new file mode 100644 index 0000000..02d2b89 --- /dev/null +++ b/tooling/sparta/packages/discord/src/utils/roleAssigner.ts @@ -0,0 +1,88 @@ +import { logger } from "@sparta/utils/logger"; +import { DiscordService } from "../services/discord-service.js"; +import type { Role } from "@sparta/utils/const/roles.js"; + +/** + * Attempts to assign Discord roles based on score. + * Returns true if successful, false otherwise (logs errors). + */ +export async function _handleNodeOperatorRoleAssignment( + discordUserId: string, + role: Role +): Promise { + const discordService = DiscordService.getInstance(); // Get instance + + logger.info( + { userId: discordUserId }, + "Attempting immediate role assignment..." + ); + try { + // Ensure the discord service is initialized + await discordService.init(); + + const success = await discordService.assignRole( + discordUserId, + role.name + ); + if (success) { + logger.info( + { userId: discordUserId, role: role.name }, + "Node operator role assignment successful." + ); + } else { + logger.error( + { userId: discordUserId, role: role.name }, + "Node operator role assignment failed (discordService returned false)." + ); + } + return success; + } catch (error: any) { + logger.error( + { error: error.message, userId: discordUserId }, + "Error during role assignment." + ); + return false; + } +} + +/** + * Attempts to assign Discord roles based on score. + * Returns true if successful, false otherwise (logs errors). + */ +export async function _handleUserRolesAssignment( + sessionId: string, + discordUserId: string, + roles: Role[] +): Promise { + logger.info( + { sessionId, userId: discordUserId, roles }, + "Attempting immediate role assignment..." + ); + + const discordService = DiscordService.getInstance(); // Get instance + + try { + // Ensure the discord service is initialized + await discordService.init(); + + const success = await discordService.assignRoles(discordUserId, roles); + if (success) { + logger.info( + { sessionId, userId: discordUserId, roles }, + "Role assignment successful." + ); + } else { + logger.error( + { sessionId, userId: discordUserId, roles }, + "Role assignment failed (discordService returned false)." + ); + } + return success; + } catch (error: any) { + logger.error( + { error: error.message, sessionId, userId: discordUserId }, + "Error during role assignment." + ); + return false; + } +} diff --git a/tooling/sparta/packages/discord/src/utils/roles.ts b/tooling/sparta/packages/discord/src/utils/roles.ts new file mode 100644 index 0000000..a438020 --- /dev/null +++ b/tooling/sparta/packages/discord/src/utils/roles.ts @@ -0,0 +1,107 @@ +/** + * @fileoverview Role-based access control utilities + * @description Provides utilities for checking user roles and permissions + * @module sparta/discord/utils/roles + */ + +import { + ChatInputCommandInteraction, + GuildMember, + MessageFlags, +} from "discord.js"; +import { MODERATOR_ROLES, NODE_OPERATOR_ROLES } from "@sparta/utils/const/roles"; + +/** + * Checks if the user has any of the specified moderator roles + * @param member The guild member to check + * @returns True if the user has any moderator role, false otherwise + */ +export function hasModeratorRole(member: GuildMember): boolean { + const moderatorRoleIds = Object.values(MODERATOR_ROLES).map( + (role) => role.id + ); + return member.roles.cache.some((role) => + moderatorRoleIds.includes(role.id) + ); +} + +/** + * Checks if the user has the Guardian role + * @param member The guild member to check + * @returns True if the user has the Guardian role, false otherwise + */ +export function hasGuardianRole(member: GuildMember): boolean { + return member.roles.cache.some((role) => + role.id === NODE_OPERATOR_ROLES.GUARDIAN!.id + ); +} + +/** + * Checks if the interaction user has moderator permissions and is in an allowed channel + * @param interaction The Discord interaction + * @returns True if the user has moderator permissions and is in an allowed channel, false otherwise + */ +export async function checkModeratorPermissions( + interaction: ChatInputCommandInteraction +): Promise { + // Get the member from the interaction + const member = interaction.member as GuildMember; + + if (!member) { + await interaction.reply({ + content: + "Could not verify your server membership. Please try again.", + flags: MessageFlags.Ephemeral, + }); + return false; + } + + // Check if the member has moderator roles + if (!hasModeratorRole(member)) { + await interaction.reply({ + content: + "You don't have permission to use moderator commands. This command requires one of these roles: " + + Object.values(MODERATOR_ROLES) + .map((role) => `\`${role.name}\``) + .join(", "), + flags: MessageFlags.Ephemeral, + }); + return false; + } + + return true; +} + +/** + * Checks if the interaction user has the Guardian role + * @param interaction The Discord interaction + * @returns True if the user has the Guardian role, false otherwise + */ +export async function checkGuardianPermissions( + interaction: ChatInputCommandInteraction +): Promise { + // Get the member from the interaction + const member = interaction.member as GuildMember; + + if (!member) { + await interaction.reply({ + content: + "Could not verify your server membership. Please try again.", + flags: MessageFlags.Ephemeral, + }); + return false; + } + + // Check if the member has the Guardian role + if (!hasGuardianRole(member)) { + await interaction.reply({ + content: + "You don't have permission to use this command. This command requires the " + + `\`${NODE_OPERATOR_ROLES.GUARDIAN!.name}\` role.`, + flags: MessageFlags.Ephemeral, + }); + return false; + } + + return true; +} diff --git a/tooling/sparta/packages/discord/tsconfig.json b/tooling/sparta/packages/discord/tsconfig.json new file mode 100644 index 0000000..d388a80 --- /dev/null +++ b/tooling/sparta/packages/discord/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "composite": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true + }, + "include": ["src/**/*", "../ethereum/src/l2-info-service.ts", "../utils/openapi/api"], + "references": [{ "path": "../utils" }, { "path": "../ethereum" }] +} diff --git a/tooling/sparta/packages/discord/tsconfig.tsbuildinfo b/tooling/sparta/packages/discord/tsconfig.tsbuildinfo new file mode 100644 index 0000000..34621c7 --- /dev/null +++ b/tooling/sparta/packages/discord/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/typescript/lib/lib.es2023.d.ts","../../node_modules/typescript/lib/lib.es2024.d.ts","../../node_modules/typescript/lib/lib.esnext.d.ts","../../node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../node_modules/typescript/lib/lib.dom.asynciterable.d.ts","../../node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../node_modules/typescript/lib/lib.scripthost.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../node_modules/typescript/lib/lib.es2023.array.d.ts","../../node_modules/typescript/lib/lib.es2023.collection.d.ts","../../node_modules/typescript/lib/lib.es2023.intl.d.ts","../../node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2024.collection.d.ts","../../node_modules/typescript/lib/lib.es2024.object.d.ts","../../node_modules/typescript/lib/lib.es2024.promise.d.ts","../../node_modules/typescript/lib/lib.es2024.regexp.d.ts","../../node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2024.string.d.ts","../../node_modules/typescript/lib/lib.esnext.array.d.ts","../../node_modules/typescript/lib/lib.esnext.collection.d.ts","../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../node_modules/typescript/lib/lib.esnext.promise.d.ts","../../node_modules/typescript/lib/lib.esnext.decorators.d.ts","../../node_modules/typescript/lib/lib.esnext.iterator.d.ts","../../node_modules/typescript/lib/lib.esnext.float16.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../node_modules/typescript/lib/lib.esnext.full.d.ts","./src/debug.ts","../../node_modules/axios/index.d.ts","../../node_modules/openapi-types/dist/index.d.ts","../../node_modules/openapi-client-axios/types/client.d.ts","../../node_modules/openapi-client-axios/client.d.ts","../../node_modules/openapi-client-axios/index.d.ts","../utils/openapi/types.d.ts","../utils/dist/openapi/api/apiProvider.d.ts","../utils/dist/openapi/api/axios.d.ts","../../node_modules/@sapphire/shapeshift/dist/esm/index.d.mts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/globals.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/utils/internals.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/common.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/common.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/permissions.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/user.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/emoji.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/oauth2.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/sticker.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/guild.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/autoModeration.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/guildScheduledEvent.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/stageInstance.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/webhook.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/auditLog.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/invite.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/monetization.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/poll.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/soundboard.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/teams.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/application.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/auditLog.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/autoModeration.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/poll.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/channel.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/emoji.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/gateway.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/guild.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/guildScheduledEvent.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/webhook.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/interactions.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/invite.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/monetization.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/oauth2.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/soundboard.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/stageInstance.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/sticker.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/template.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/user.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/voice.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/index.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/template.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/voice.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/index.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/responses.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/base.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/shared.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/base.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/attachment.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/boolean.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/channel.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/integer.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/mentionable.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/number.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/role.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/string.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommand.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommandGroup.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/user.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/internals.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/chatInput.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/contextMenu.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/entryPoint.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/permissions.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/applicationCommands.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/autocomplete.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/messageComponents.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/modalSubmit.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/ping.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/interactions.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/application.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/channel.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/gateway.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/gateway/common.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/gateway/v10.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rpc/common.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rpc/v10.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/utils/v10.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/v10.d.ts","../../node_modules/@discordjs/formatters/node_modules/discord-api-types/globals.d.ts","../../node_modules/@discordjs/formatters/dist/index.d.mts","../../node_modules/@discordjs/util/dist/index.d.mts","../../node_modules/@discordjs/builders/dist/index.d.mts","../../node_modules/@discordjs/collection/dist/index.d.ts","../../node_modules/@discordjs/rest/node_modules/discord-api-types/v10.d.ts","../../node_modules/@discordjs/rest/node_modules/@discordjs/collection/dist/index.d.mts","../../node_modules/undici/types/header.d.ts","../../node_modules/undici/types/readable.d.ts","../../node_modules/@types/node/compatibility/disposable.d.ts","../../node_modules/@types/node/compatibility/indexable.d.ts","../../node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/@types/node/compatibility/index.d.ts","../../node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/undici-types/header.d.ts","../../node_modules/undici-types/readable.d.ts","../../node_modules/undici-types/file.d.ts","../../node_modules/undici-types/fetch.d.ts","../../node_modules/undici-types/formdata.d.ts","../../node_modules/undici-types/connector.d.ts","../../node_modules/undici-types/client.d.ts","../../node_modules/undici-types/errors.d.ts","../../node_modules/undici-types/dispatcher.d.ts","../../node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/undici-types/global-origin.d.ts","../../node_modules/undici-types/pool-stats.d.ts","../../node_modules/undici-types/pool.d.ts","../../node_modules/undici-types/handlers.d.ts","../../node_modules/undici-types/balanced-pool.d.ts","../../node_modules/undici-types/agent.d.ts","../../node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/undici-types/mock-agent.d.ts","../../node_modules/undici-types/mock-client.d.ts","../../node_modules/undici-types/mock-pool.d.ts","../../node_modules/undici-types/mock-errors.d.ts","../../node_modules/undici-types/proxy-agent.d.ts","../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/undici-types/retry-handler.d.ts","../../node_modules/undici-types/retry-agent.d.ts","../../node_modules/undici-types/api.d.ts","../../node_modules/undici-types/interceptors.d.ts","../../node_modules/undici-types/util.d.ts","../../node_modules/undici-types/cookies.d.ts","../../node_modules/undici-types/patch.d.ts","../../node_modules/undici-types/websocket.d.ts","../../node_modules/undici-types/eventsource.d.ts","../../node_modules/undici-types/filereader.d.ts","../../node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/undici-types/content-type.d.ts","../../node_modules/undici-types/cache.d.ts","../../node_modules/undici-types/index.d.ts","../../node_modules/@types/node/globals.d.ts","../../node_modules/@types/node/assert.d.ts","../../node_modules/@types/node/assert/strict.d.ts","../../node_modules/@types/node/async_hooks.d.ts","../../node_modules/@types/node/buffer.d.ts","../../node_modules/@types/node/child_process.d.ts","../../node_modules/@types/node/cluster.d.ts","../../node_modules/@types/node/console.d.ts","../../node_modules/@types/node/constants.d.ts","../../node_modules/@types/node/crypto.d.ts","../../node_modules/@types/node/dgram.d.ts","../../node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/@types/node/dns.d.ts","../../node_modules/@types/node/dns/promises.d.ts","../../node_modules/@types/node/domain.d.ts","../../node_modules/@types/node/dom-events.d.ts","../../node_modules/@types/node/events.d.ts","../../node_modules/@types/node/fs.d.ts","../../node_modules/@types/node/fs/promises.d.ts","../../node_modules/@types/node/http.d.ts","../../node_modules/@types/node/http2.d.ts","../../node_modules/@types/node/https.d.ts","../../node_modules/@types/node/inspector.d.ts","../../node_modules/@types/node/module.d.ts","../../node_modules/@types/node/net.d.ts","../../node_modules/@types/node/os.d.ts","../../node_modules/@types/node/path.d.ts","../../node_modules/@types/node/perf_hooks.d.ts","../../node_modules/@types/node/process.d.ts","../../node_modules/@types/node/punycode.d.ts","../../node_modules/@types/node/querystring.d.ts","../../node_modules/@types/node/readline.d.ts","../../node_modules/@types/node/readline/promises.d.ts","../../node_modules/@types/node/repl.d.ts","../../node_modules/@types/node/sea.d.ts","../../node_modules/@types/node/stream.d.ts","../../node_modules/@types/node/stream/promises.d.ts","../../node_modules/@types/node/stream/consumers.d.ts","../../node_modules/@types/node/stream/web.d.ts","../../node_modules/@types/node/string_decoder.d.ts","../../node_modules/@types/node/test.d.ts","../../node_modules/@types/node/timers.d.ts","../../node_modules/@types/node/timers/promises.d.ts","../../node_modules/@types/node/tls.d.ts","../../node_modules/@types/node/trace_events.d.ts","../../node_modules/@types/node/tty.d.ts","../../node_modules/@types/node/url.d.ts","../../node_modules/@types/node/util.d.ts","../../node_modules/@types/node/v8.d.ts","../../node_modules/@types/node/vm.d.ts","../../node_modules/@types/node/wasi.d.ts","../../node_modules/@types/node/worker_threads.d.ts","../../node_modules/@types/node/zlib.d.ts","../../node_modules/@types/node/index.d.ts","../../node_modules/undici/types/file.d.ts","../../node_modules/undici/types/fetch.d.ts","../../node_modules/undici/types/formdata.d.ts","../../node_modules/undici/types/connector.d.ts","../../node_modules/undici/types/client.d.ts","../../node_modules/undici/types/errors.d.ts","../../node_modules/undici/types/dispatcher.d.ts","../../node_modules/undici/types/global-dispatcher.d.ts","../../node_modules/undici/types/global-origin.d.ts","../../node_modules/undici/types/pool-stats.d.ts","../../node_modules/undici/types/pool.d.ts","../../node_modules/undici/types/handlers.d.ts","../../node_modules/undici/types/balanced-pool.d.ts","../../node_modules/undici/types/agent.d.ts","../../node_modules/undici/types/mock-interceptor.d.ts","../../node_modules/undici/types/mock-agent.d.ts","../../node_modules/undici/types/mock-client.d.ts","../../node_modules/undici/types/mock-pool.d.ts","../../node_modules/undici/types/mock-errors.d.ts","../../node_modules/undici/types/proxy-agent.d.ts","../../node_modules/undici/types/env-http-proxy-agent.d.ts","../../node_modules/undici/types/retry-handler.d.ts","../../node_modules/undici/types/retry-agent.d.ts","../../node_modules/undici/types/api.d.ts","../../node_modules/undici/types/interceptors.d.ts","../../node_modules/undici/types/util.d.ts","../../node_modules/undici/types/cookies.d.ts","../../node_modules/undici/types/patch.d.ts","../../node_modules/undici/types/websocket.d.ts","../../node_modules/undici/types/eventsource.d.ts","../../node_modules/undici/types/filereader.d.ts","../../node_modules/undici/types/diagnostics-channel.d.ts","../../node_modules/undici/types/content-type.d.ts","../../node_modules/undici/types/cache.d.ts","../../node_modules/undici/types/index.d.ts","../../node_modules/undici/index.d.ts","../../node_modules/@vladfrangu/async_event_emitter/dist/index.d.mts","../../node_modules/@discordjs/rest/dist/web.d.mts","../../node_modules/@discordjs/ws/node_modules/discord-api-types/v10.d.ts","../../node_modules/@discordjs/ws/node_modules/@discordjs/collection/dist/index.d.mts","../../node_modules/@sapphire/async-queue/dist/esm/index.d.mts","../../node_modules/@discordjs/ws/dist/index.d.mts","../../node_modules/discord.js/node_modules/discord-api-types/v10.d.ts","../../node_modules/discord.js/typings/rawDataTypes.d.mts","../../node_modules/@sapphire/snowflake/dist/esm/index.d.mts","../../node_modules/discord.js/typings/index.d.mts","../utils/node_modules/pino/node_modules/pino-std-serializers/index.d.ts","../utils/node_modules/pino/node_modules/sonic-boom/types/index.d.ts","../utils/node_modules/pino/pino.d.ts","../utils/dist/logger.d.ts","../../node_modules/@smithy/types/dist-types/abort-handler.d.ts","../../node_modules/@smithy/types/dist-types/abort.d.ts","../../node_modules/@smithy/types/dist-types/auth/auth.d.ts","../../node_modules/@smithy/types/dist-types/auth/HttpApiKeyAuth.d.ts","../../node_modules/@smithy/types/dist-types/identity/identity.d.ts","../../node_modules/@smithy/types/dist-types/response.d.ts","../../node_modules/@smithy/types/dist-types/command.d.ts","../../node_modules/@smithy/types/dist-types/endpoint.d.ts","../../node_modules/@smithy/types/dist-types/feature-ids.d.ts","../../node_modules/@smithy/types/dist-types/logger.d.ts","../../node_modules/@smithy/types/dist-types/uri.d.ts","../../node_modules/@smithy/types/dist-types/http.d.ts","../../node_modules/@smithy/types/dist-types/util.d.ts","../../node_modules/@smithy/types/dist-types/middleware.d.ts","../../node_modules/@smithy/types/dist-types/auth/HttpSigner.d.ts","../../node_modules/@smithy/types/dist-types/auth/IdentityProviderConfig.d.ts","../../node_modules/@smithy/types/dist-types/auth/HttpAuthScheme.d.ts","../../node_modules/@smithy/types/dist-types/auth/HttpAuthSchemeProvider.d.ts","../../node_modules/@smithy/types/dist-types/auth/index.d.ts","../../node_modules/@smithy/types/dist-types/transform/exact.d.ts","../../node_modules/@smithy/types/dist-types/externals-check/browser-externals-check.d.ts","../../node_modules/@smithy/types/dist-types/blob/blob-payload-input-types.d.ts","../../node_modules/@smithy/types/dist-types/crypto.d.ts","../../node_modules/@smithy/types/dist-types/checksum.d.ts","../../node_modules/@smithy/types/dist-types/client.d.ts","../../node_modules/@smithy/types/dist-types/connection/config.d.ts","../../node_modules/@smithy/types/dist-types/transfer.d.ts","../../node_modules/@smithy/types/dist-types/connection/manager.d.ts","../../node_modules/@smithy/types/dist-types/connection/pool.d.ts","../../node_modules/@smithy/types/dist-types/connection/index.d.ts","../../node_modules/@smithy/types/dist-types/eventStream.d.ts","../../node_modules/@smithy/types/dist-types/encode.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/shared.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/EndpointRuleObject.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/ErrorRuleObject.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/TreeRuleObject.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/RuleSetObject.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/index.d.ts","../../node_modules/@smithy/types/dist-types/extensions/checksum.d.ts","../../node_modules/@smithy/types/dist-types/extensions/defaultClientConfiguration.d.ts","../../node_modules/@smithy/types/dist-types/shapes.d.ts","../../node_modules/@smithy/types/dist-types/retry.d.ts","../../node_modules/@smithy/types/dist-types/extensions/retry.d.ts","../../node_modules/@smithy/types/dist-types/extensions/defaultExtensionConfiguration.d.ts","../../node_modules/@smithy/types/dist-types/extensions/index.d.ts","../../node_modules/@smithy/types/dist-types/http/httpHandlerInitialization.d.ts","../../node_modules/@smithy/types/dist-types/identity/apiKeyIdentity.d.ts","../../node_modules/@smithy/types/dist-types/identity/awsCredentialIdentity.d.ts","../../node_modules/@smithy/types/dist-types/identity/tokenIdentity.d.ts","../../node_modules/@smithy/types/dist-types/identity/index.d.ts","../../node_modules/@smithy/types/dist-types/pagination.d.ts","../../node_modules/@smithy/types/dist-types/profile.d.ts","../../node_modules/@smithy/types/dist-types/serde.d.ts","../../node_modules/@smithy/types/dist-types/signature.d.ts","../../node_modules/@smithy/types/dist-types/stream.d.ts","../../node_modules/@smithy/types/dist-types/streaming-payload/streaming-blob-common-types.d.ts","../../node_modules/@smithy/types/dist-types/streaming-payload/streaming-blob-payload-input-types.d.ts","../../node_modules/@smithy/types/dist-types/streaming-payload/streaming-blob-payload-output-types.d.ts","../../node_modules/@smithy/types/dist-types/transform/type-transform.d.ts","../../node_modules/@smithy/types/dist-types/transform/client-method-transforms.d.ts","../../node_modules/@smithy/types/dist-types/transform/client-payload-blob-type-narrow.d.ts","../../node_modules/@smithy/types/dist-types/transform/no-undefined.d.ts","../../node_modules/@smithy/types/dist-types/waiter.d.ts","../../node_modules/@smithy/types/dist-types/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/account-id-endpoint/AccountIdEndpointModeConstants.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/account-id-endpoint/AccountIdEndpointModeConfigResolver.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/fromEnv.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/getHomeDir.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/getProfileName.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/getSSOTokenFilepath.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/getSSOTokenFromFile.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/loadSharedConfigFiles.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/loadSsoSessionData.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/parseKnownFiles.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/types.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/index.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/fromSharedConfigFiles.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/fromStatic.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/configLoader.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/account-id-endpoint/NodeAccountIdEndpointModeConfigOptions.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/account-id-endpoint/index.d.ts","../../node_modules/@aws-sdk/middleware-endpoint-discovery/dist-types/configurations.d.ts","../../node_modules/@aws-sdk/endpoint-cache/dist-types/Endpoint.d.ts","../../node_modules/@aws-sdk/endpoint-cache/dist-types/EndpointCache.d.ts","../../node_modules/@aws-sdk/endpoint-cache/dist-types/index.d.ts","../../node_modules/@aws-sdk/middleware-endpoint-discovery/dist-types/resolveEndpointDiscoveryConfig.d.ts","../../node_modules/@aws-sdk/middleware-endpoint-discovery/dist-types/getEndpointDiscoveryPlugin.d.ts","../../node_modules/@aws-sdk/middleware-endpoint-discovery/dist-types/index.d.ts","../../node_modules/@aws-sdk/middleware-host-header/dist-types/index.d.ts","../../node_modules/@aws-sdk/middleware-user-agent/dist-types/configurations.d.ts","../../node_modules/@aws-sdk/types/dist-types/abort.d.ts","../../node_modules/@aws-sdk/types/dist-types/auth.d.ts","../../node_modules/@aws-sdk/types/dist-types/blob/blob-types.d.ts","../../node_modules/@aws-sdk/types/dist-types/checksum.d.ts","../../node_modules/@aws-sdk/types/dist-types/client.d.ts","../../node_modules/@aws-sdk/types/dist-types/command.d.ts","../../node_modules/@aws-sdk/types/dist-types/connection.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/Identity.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/AnonymousIdentity.d.ts","../../node_modules/@aws-sdk/types/dist-types/feature-ids.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/AwsCredentialIdentity.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/LoginIdentity.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/TokenIdentity.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/index.d.ts","../../node_modules/@aws-sdk/types/dist-types/util.d.ts","../../node_modules/@aws-sdk/types/dist-types/credentials.d.ts","../../node_modules/@aws-sdk/types/dist-types/crypto.d.ts","../../node_modules/@aws-sdk/types/dist-types/dns.d.ts","../../node_modules/@aws-sdk/types/dist-types/encode.d.ts","../../node_modules/@aws-sdk/types/dist-types/endpoint.d.ts","../../node_modules/@aws-sdk/types/dist-types/eventStream.d.ts","../../node_modules/@aws-sdk/types/dist-types/extensions/index.d.ts","../../node_modules/@aws-sdk/types/dist-types/function.d.ts","../../node_modules/@aws-sdk/types/dist-types/http.d.ts","../../node_modules/@aws-sdk/types/dist-types/logger.d.ts","../../node_modules/@aws-sdk/types/dist-types/middleware.d.ts","../../node_modules/@aws-sdk/types/dist-types/pagination.d.ts","../../node_modules/@aws-sdk/types/dist-types/profile.d.ts","../../node_modules/@aws-sdk/types/dist-types/request.d.ts","../../node_modules/@aws-sdk/types/dist-types/response.d.ts","../../node_modules/@aws-sdk/types/dist-types/retry.d.ts","../../node_modules/@aws-sdk/types/dist-types/serde.d.ts","../../node_modules/@aws-sdk/types/dist-types/shapes.d.ts","../../node_modules/@aws-sdk/types/dist-types/signature.d.ts","../../node_modules/@aws-sdk/types/dist-types/stream.d.ts","../../node_modules/@aws-sdk/types/dist-types/token.d.ts","../../node_modules/@aws-sdk/types/dist-types/transfer.d.ts","../../node_modules/@aws-sdk/types/dist-types/uri.d.ts","../../node_modules/@aws-sdk/types/dist-types/waiter.d.ts","../../node_modules/@aws-sdk/types/dist-types/index.d.ts","../../node_modules/@aws-sdk/middleware-user-agent/dist-types/user-agent-middleware.d.ts","../../node_modules/@aws-sdk/middleware-user-agent/dist-types/index.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/NodeUseDualstackEndpointConfigOptions.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/NodeUseFipsEndpointConfigOptions.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/resolveEndpointsConfig.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/resolveCustomEndpointsConfig.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/index.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionConfig/config.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionConfig/resolveRegionConfig.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionConfig/index.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/EndpointVariantTag.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/EndpointVariant.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/PartitionHash.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/RegionHash.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/getRegionInfo.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/index.d.ts","../../node_modules/@smithy/config-resolver/dist-types/index.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/resolveEndpointConfig.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/types.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/adaptors/getEndpointFromInstructions.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/adaptors/toEndpointV1.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/adaptors/index.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/endpointMiddleware.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/getEndpointPlugin.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/index.d.ts","../../node_modules/@smithy/util-retry/dist-types/types.d.ts","../../node_modules/@smithy/util-retry/dist-types/AdaptiveRetryStrategy.d.ts","../../node_modules/@smithy/util-retry/dist-types/StandardRetryStrategy.d.ts","../../node_modules/@smithy/util-retry/dist-types/ConfiguredRetryStrategy.d.ts","../../node_modules/@smithy/util-retry/dist-types/DefaultRateLimiter.d.ts","../../node_modules/@smithy/util-retry/dist-types/config.d.ts","../../node_modules/@smithy/util-retry/dist-types/constants.d.ts","../../node_modules/@smithy/util-retry/dist-types/index.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/types.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/StandardRetryStrategy.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/AdaptiveRetryStrategy.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/configurations.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/delayDecider.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/omitRetryHeadersMiddleware.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/retryDecider.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/retryMiddleware.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/index.d.ts","../../node_modules/@smithy/protocol-http/dist-types/httpRequest.d.ts","../../node_modules/@smithy/protocol-http/dist-types/httpResponse.d.ts","../../node_modules/@smithy/protocol-http/dist-types/httpHandler.d.ts","../../node_modules/@smithy/protocol-http/dist-types/extensions/httpExtensionConfiguration.d.ts","../../node_modules/@smithy/protocol-http/dist-types/extensions/index.d.ts","../../node_modules/@smithy/protocol-http/dist-types/Field.d.ts","../../node_modules/@smithy/protocol-http/dist-types/Fields.d.ts","../../node_modules/@smithy/protocol-http/dist-types/isValidHostname.d.ts","../../node_modules/@smithy/protocol-http/dist-types/types.d.ts","../../node_modules/@smithy/protocol-http/dist-types/index.d.ts","../../node_modules/@smithy/smithy-client/dist-types/client.d.ts","../../node_modules/@smithy/util-stream/dist-types/blob/Uint8ArrayBlobAdapter.d.ts","../../node_modules/@smithy/util-stream/dist-types/checksum/ChecksumStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/checksum/ChecksumStream.browser.d.ts","../../node_modules/@smithy/util-stream/dist-types/checksum/createChecksumStream.browser.d.ts","../../node_modules/@smithy/util-stream/dist-types/checksum/createChecksumStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/createBufferedReadable.d.ts","../../node_modules/@smithy/util-stream/dist-types/getAwsChunkedEncodingStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/headStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/sdk-stream-mixin.d.ts","../../node_modules/@smithy/util-stream/dist-types/splitStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/stream-type-check.d.ts","../../node_modules/@smithy/util-stream/dist-types/index.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/collect-stream-body.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/extended-encode-uri-component.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/requestBuilder.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/resolve-path.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/index.d.ts","../../node_modules/@smithy/smithy-client/dist-types/collect-stream-body.d.ts","../../node_modules/@smithy/smithy-client/dist-types/command.d.ts","../../node_modules/@smithy/smithy-client/dist-types/constants.d.ts","../../node_modules/@smithy/smithy-client/dist-types/create-aggregated-client.d.ts","../../node_modules/@smithy/smithy-client/dist-types/date-utils.d.ts","../../node_modules/@smithy/smithy-client/dist-types/default-error-handler.d.ts","../../node_modules/@smithy/smithy-client/dist-types/defaults-mode.d.ts","../../node_modules/@smithy/smithy-client/dist-types/emitWarningIfUnsupportedVersion.d.ts","../../node_modules/@smithy/smithy-client/dist-types/exceptions.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extended-encode-uri-component.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extensions/checksum.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extensions/retry.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extensions/defaultExtensionConfiguration.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extensions/index.d.ts","../../node_modules/@smithy/smithy-client/dist-types/get-array-if-single-item.d.ts","../../node_modules/@smithy/smithy-client/dist-types/get-value-from-text-node.d.ts","../../node_modules/@smithy/smithy-client/dist-types/is-serializable-header-value.d.ts","../../node_modules/@smithy/smithy-client/dist-types/lazy-json.d.ts","../../node_modules/@smithy/smithy-client/dist-types/NoOpLogger.d.ts","../../node_modules/@smithy/smithy-client/dist-types/object-mapping.d.ts","../../node_modules/@smithy/smithy-client/dist-types/parse-utils.d.ts","../../node_modules/@smithy/smithy-client/dist-types/quote-header.d.ts","../../node_modules/@smithy/smithy-client/dist-types/resolve-path.d.ts","../../node_modules/@smithy/smithy-client/dist-types/ser-utils.d.ts","../../node_modules/@smithy/smithy-client/dist-types/serde-json.d.ts","../../node_modules/@smithy/smithy-client/dist-types/split-every.d.ts","../../node_modules/@smithy/smithy-client/dist-types/split-header.d.ts","../../node_modules/@smithy/smithy-client/dist-types/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/client/emitWarningIfUnsupportedVersion.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/client/setCredentialFeature.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/client/setFeature.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/client/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4AConfig.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/NODE_AUTH_SCHEME_PREFERENCE_OPTIONS.d.ts","../../node_modules/@smithy/signature-v4/dist-types/SignatureV4Base.d.ts","../../node_modules/@smithy/signature-v4/dist-types/SignatureV4.d.ts","../../node_modules/@smithy/signature-v4/dist-types/constants.d.ts","../../node_modules/@smithy/signature-v4/dist-types/getCanonicalHeaders.d.ts","../../node_modules/@smithy/signature-v4/dist-types/getCanonicalQuery.d.ts","../../node_modules/@smithy/signature-v4/dist-types/getPayloadHash.d.ts","../../node_modules/@smithy/signature-v4/dist-types/moveHeadersToQuery.d.ts","../../node_modules/@smithy/signature-v4/dist-types/prepareRequest.d.ts","../../node_modules/@smithy/signature-v4/dist-types/credentialDerivation.d.ts","../../node_modules/@smithy/signature-v4/dist-types/headerUtil.d.ts","../../node_modules/@smithy/signature-v4/dist-types/signature-v4a-container.d.ts","../../node_modules/@smithy/signature-v4/dist-types/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4Config.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/coercing-serializers.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/json/awsExpectUnion.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/json/parseJsonBody.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/xml/parseXmlBody.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/auth/httpAuthSchemeProvider.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/models/DynamoDBServiceException.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/models/models_0.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/BatchExecuteStatementCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/BatchGetItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/BatchWriteItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/CreateBackupCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/CreateGlobalTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/CreateTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DeleteBackupCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DeleteItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DeleteResourcePolicyCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DeleteTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeBackupCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeContinuousBackupsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeContributorInsightsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeEndpointsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeExportCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeGlobalTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeGlobalTableSettingsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeImportCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeKinesisStreamingDestinationCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeLimitsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeTableReplicaAutoScalingCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeTimeToLiveCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DisableKinesisStreamingDestinationCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/EnableKinesisStreamingDestinationCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ExecuteStatementCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ExecuteTransactionCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ExportTableToPointInTimeCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/GetItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/GetResourcePolicyCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ImportTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListBackupsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListContributorInsightsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListExportsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListGlobalTablesCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListImportsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListTablesCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListTagsOfResourceCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/PutItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/PutResourcePolicyCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/QueryCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/RestoreTableFromBackupCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/RestoreTableToPointInTimeCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ScanCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/TagResourceCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/TransactGetItemsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/TransactWriteItemsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UntagResourceCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateContinuousBackupsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateContributorInsightsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateGlobalTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateGlobalTableSettingsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateKinesisStreamingDestinationCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateTableReplicaAutoScalingCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateTimeToLiveCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/endpoint/EndpointParameters.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/auth/httpAuthExtensionConfiguration.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/extensionConfiguration.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/runtimeExtensions.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/DynamoDBClient.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/DynamoDB.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/Interfaces.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ListContributorInsightsPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ListExportsPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ListImportsPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ListTablesPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/QueryPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ScanPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/index.d.ts","../../node_modules/@smithy/util-waiter/dist-types/waiter.d.ts","../../node_modules/@smithy/util-waiter/dist-types/createWaiter.d.ts","../../node_modules/@smithy/util-waiter/dist-types/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/waiters/waitForTableExists.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/waiters/waitForTableNotExists.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/waiters/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/models/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/index.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/models.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/NumberValue.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/marshall.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/convertToAttr.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/unmarshall.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/convertToNative.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/index.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/utils.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/BatchGetCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/BatchWriteCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/DeleteCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/ExecuteStatementCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/ExecuteTransactionCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/GetCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/PutCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/QueryCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/ScanCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/TransactGetCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/TransactWriteCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/UpdateCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/DynamoDBDocumentClient.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/baseCommand/DynamoDBDocumentClientCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/BatchExecuteStatementCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/DynamoDBDocument.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/index.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/pagination/Interfaces.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/pagination/QueryPaginator.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/pagination/ScanPaginator.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/pagination/index.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/index.d.ts","../utils/dist/dynamo-db.d.ts","../utils/dist/const/verificationStatus.d.ts","../utils/dist/const/channels.d.ts","../utils/dist/const/index.d.ts","../utils/openapi/api-docs.json","../utils/dist/index.d.ts","../../node_modules/abitype/dist/types/register.d.ts","../../node_modules/abitype/dist/types/types.d.ts","../../node_modules/abitype/dist/types/abi.d.ts","../../node_modules/abitype/dist/types/errors.d.ts","../../node_modules/abitype/dist/types/narrow.d.ts","../../node_modules/abitype/dist/types/utils.d.ts","../../node_modules/abitype/dist/types/human-readable/types/signatures.d.ts","../../node_modules/abitype/dist/types/human-readable/formatAbiParameter.d.ts","../../node_modules/abitype/dist/types/human-readable/formatAbiParameters.d.ts","../../node_modules/abitype/dist/types/human-readable/formatAbiItem.d.ts","../../node_modules/abitype/dist/types/human-readable/formatAbi.d.ts","../../node_modules/abitype/dist/types/human-readable/types/utils.d.ts","../../node_modules/abitype/dist/types/human-readable/types/structs.d.ts","../../node_modules/abitype/dist/types/human-readable/parseAbi.d.ts","../../node_modules/abitype/dist/types/human-readable/parseAbiItem.d.ts","../../node_modules/abitype/dist/types/human-readable/parseAbiParameter.d.ts","../../node_modules/abitype/dist/types/human-readable/parseAbiParameters.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/abiItem.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/abiParameter.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/signature.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/splitParameters.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/struct.d.ts","../../node_modules/abitype/dist/types/exports/index.d.ts","../../node_modules/ox/_types/core/Errors.d.ts","../../node_modules/ox/_types/core/internal/bytes.d.ts","../../node_modules/ox/_types/core/internal/hex.d.ts","../../node_modules/ox/_types/core/Hex.d.ts","../../node_modules/ox/_types/core/Bytes.d.ts","../../node_modules/ox/_types/core/Hash.d.ts","../../node_modules/ox/_types/core/internal/types.d.ts","../../node_modules/ox/_types/core/PublicKey.d.ts","../../node_modules/ox/_types/core/Address.d.ts","../../node_modules/ox/_types/core/Withdrawal.d.ts","../../node_modules/ox/_types/core/BlockOverrides.d.ts","../../node_modules/ox/_types/core/Base64.d.ts","../../node_modules/ox/_types/core/Signature.d.ts","../../node_modules/@noble/curves/esm/abstract/utils.d.ts","../../node_modules/@noble/curves/esm/abstract/modular.d.ts","../../node_modules/@noble/curves/esm/abstract/curve.d.ts","../../node_modules/@noble/curves/esm/abstract/weierstrass.d.ts","../../node_modules/ox/_types/core/P256.d.ts","../../node_modules/ox/_types/core/internal/webauthn.d.ts","../../node_modules/ox/_types/core/WebAuthnP256.d.ts","../../node_modules/viem/_types/errors/utils.d.ts","../../node_modules/viem/_types/accounts/utils/parseAccount.d.ts","../../node_modules/viem/_types/types/utils.d.ts","../../node_modules/@scure/bip32/lib/esm/index.d.ts","../../node_modules/viem/_types/types/account.d.ts","../../node_modules/ox/_types/core/AbiItem.d.ts","../../node_modules/ox/_types/core/internal/cursor.d.ts","../../node_modules/ox/_types/core/internal/abiParameters.d.ts","../../node_modules/ox/_types/core/AbiParameters.d.ts","../../node_modules/ox/_types/core/internal/abiItem.d.ts","../../node_modules/ox/_types/core/Abi.d.ts","../../node_modules/ox/_types/core/internal/abiConstructor.d.ts","../../node_modules/ox/_types/core/AbiConstructor.d.ts","../../node_modules/ox/_types/core/internal/abiError.d.ts","../../node_modules/ox/_types/core/AbiError.d.ts","../../node_modules/ox/_types/core/AccessList.d.ts","../../node_modules/ox/_types/core/Rlp.d.ts","../../node_modules/ox/_types/core/Authorization.d.ts","../../node_modules/ox/_types/core/Transaction.d.ts","../../node_modules/ox/_types/core/Block.d.ts","../../node_modules/ox/_types/core/Filter.d.ts","../../node_modules/ox/_types/core/internal/abiEvent.d.ts","../../node_modules/ox/_types/core/AbiEvent.d.ts","../../node_modules/ox/_types/core/internal/abiFunction.d.ts","../../node_modules/ox/_types/core/AbiFunction.d.ts","../../node_modules/ox/_types/core/AccountProof.d.ts","../../node_modules/ox/_types/core/AesGcm.d.ts","../../node_modules/ox/_types/core/internal/base58.d.ts","../../node_modules/ox/_types/core/Base58.d.ts","../../node_modules/ox/_types/core/BinaryStateTree.d.ts","../../node_modules/ox/_types/core/Kzg.d.ts","../../node_modules/ox/_types/core/Blobs.d.ts","../../node_modules/ox/_types/core/Bloom.d.ts","../../node_modules/ox/_types/core/BlsPoint.d.ts","../../node_modules/@noble/curves/esm/abstract/hash-to-curve.d.ts","../../node_modules/@noble/curves/esm/abstract/tower.d.ts","../../node_modules/@noble/curves/esm/abstract/bls.d.ts","../../node_modules/ox/_types/core/Bls.d.ts","../../node_modules/ox/_types/core/internal/lru.d.ts","../../node_modules/ox/_types/core/Caches.d.ts","../../node_modules/ox/_types/core/ContractAddress.d.ts","../../node_modules/ox/_types/core/internal/ens.d.ts","../../node_modules/ox/_types/core/Ens.d.ts","../../node_modules/ox/_types/core/internal/hdKey.d.ts","../../node_modules/ox/_types/core/HdKey.d.ts","../../node_modules/ox/_types/core/Fee.d.ts","../../node_modules/ox/_types/core/Json.d.ts","../../node_modules/ox/_types/core/Log.d.ts","../../node_modules/@scure/bip39/esm/wordlists/czech.d.ts","../../node_modules/@scure/bip39/esm/wordlists/english.d.ts","../../node_modules/@scure/bip39/esm/wordlists/french.d.ts","../../node_modules/@scure/bip39/esm/wordlists/italian.d.ts","../../node_modules/@scure/bip39/esm/wordlists/japanese.d.ts","../../node_modules/@scure/bip39/esm/wordlists/korean.d.ts","../../node_modules/@scure/bip39/esm/wordlists/portuguese.d.ts","../../node_modules/@scure/bip39/esm/wordlists/simplified-chinese.d.ts","../../node_modules/@scure/bip39/esm/wordlists/spanish.d.ts","../../node_modules/@scure/bip39/esm/wordlists/traditional-chinese.d.ts","../../node_modules/ox/_types/core/internal/mnemonic/wordlists.d.ts","../../node_modules/ox/_types/core/Mnemonic.d.ts","../../node_modules/ox/_types/core/PersonalMessage.d.ts","../../node_modules/ox/node_modules/eventemitter3/index.d.ts","../../node_modules/ox/_types/core/internal/register.d.ts","../../node_modules/ox/_types/core/StateOverrides.d.ts","../../node_modules/ox/_types/core/TransactionReceipt.d.ts","../../node_modules/ox/_types/core/TransactionRequest.d.ts","../../node_modules/ox/_types/core/internal/rpcSchemas/eth.d.ts","../../node_modules/ox/_types/core/internal/rpcSchemas/wallet.d.ts","../../node_modules/ox/_types/core/RpcSchema.d.ts","../../node_modules/ox/_types/core/internal/rpcSchema.d.ts","../../node_modules/ox/_types/core/Provider.d.ts","../../node_modules/ox/_types/core/RpcRequest.d.ts","../../node_modules/ox/_types/core/internal/promise.d.ts","../../node_modules/ox/_types/core/internal/rpcTransport.d.ts","../../node_modules/ox/_types/core/RpcTransport.d.ts","../../node_modules/ox/_types/core/Secp256k1.d.ts","../../node_modules/ox/_types/core/Siwe.d.ts","../../node_modules/ox/_types/core/Solidity.d.ts","../../node_modules/ox/_types/core/TransactionEnvelope.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeLegacy.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeEip1559.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeEip2930.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeEip4844.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeEip7702.d.ts","../../node_modules/ox/_types/core/TypedData.d.ts","../../node_modules/ox/_types/core/ValidatorData.d.ts","../../node_modules/ox/_types/core/Value.d.ts","../../node_modules/ox/_types/core/WebCryptoP256.d.ts","../../node_modules/ox/_types/index.d.ts","../../node_modules/ox/_types/core/RpcResponse.d.ts","../../node_modules/viem/_types/types/misc.d.ts","../../node_modules/viem/_types/types/authorization.d.ts","../../node_modules/viem/_types/types/eip4844.d.ts","../../node_modules/viem/_types/types/fee.d.ts","../../node_modules/viem/_types/types/kzg.d.ts","../../node_modules/viem/_types/types/contract.d.ts","../../node_modules/viem/_types/types/log.d.ts","../../node_modules/viem/_types/types/transaction.d.ts","../../node_modules/viem/_types/types/withdrawal.d.ts","../../node_modules/viem/_types/types/block.d.ts","../../node_modules/viem/_types/types/proof.d.ts","../../node_modules/viem/_types/types/rpc.d.ts","../../node_modules/viem/_types/account-abstraction/types/entryPointVersion.d.ts","../../node_modules/viem/_types/account-abstraction/types/userOperation.d.ts","../../node_modules/viem/_types/account-abstraction/types/rpc.d.ts","../../node_modules/viem/_types/errors/base.d.ts","../../node_modules/viem/_types/errors/request.d.ts","../../node_modules/viem/_types/errors/rpc.d.ts","../../node_modules/viem/_types/utils/promise/createBatchScheduler.d.ts","../../node_modules/viem/_types/utils/promise/withRetry.d.ts","../../node_modules/viem/_types/utils/rpc/socket.d.ts","../../node_modules/viem/_types/utils/buildRequest.d.ts","../../node_modules/viem/_types/experimental/erc7895/actions/addSubAccount.d.ts","../../node_modules/viem/_types/utils/siwe/types.d.ts","../../node_modules/viem/_types/types/register.d.ts","../../node_modules/viem/_types/types/capabilities.d.ts","../../node_modules/viem/_types/types/eip1193.d.ts","../../node_modules/viem/_types/clients/transports/createTransport.d.ts","../../node_modules/viem/_types/errors/fee.d.ts","../../node_modules/viem/_types/types/stateOverride.d.ts","../../node_modules/viem/_types/utils/signature/recoverAddress.d.ts","../../node_modules/viem/_types/utils/data/concat.d.ts","../../node_modules/viem/_types/utils/data/isHex.d.ts","../../node_modules/viem/_types/errors/data.d.ts","../../node_modules/viem/_types/utils/data/pad.d.ts","../../node_modules/viem/_types/errors/encoding.d.ts","../../node_modules/viem/_types/utils/data/size.d.ts","../../node_modules/viem/_types/utils/data/trim.d.ts","../../node_modules/viem/_types/utils/encoding/fromHex.d.ts","../../node_modules/viem/_types/utils/encoding/toHex.d.ts","../../node_modules/viem/_types/utils/encoding/toBytes.d.ts","../../node_modules/viem/_types/errors/cursor.d.ts","../../node_modules/viem/_types/utils/cursor.d.ts","../../node_modules/viem/_types/utils/encoding/toRlp.d.ts","../../node_modules/viem/_types/utils/hash/keccak256.d.ts","../../node_modules/viem/_types/utils/authorization/hashAuthorization.d.ts","../../node_modules/viem/_types/utils/authorization/recoverAuthorizationAddress.d.ts","../../node_modules/viem/_types/errors/estimateGas.d.ts","../../node_modules/viem/_types/errors/transaction.d.ts","../../node_modules/viem/_types/utils/transaction/getTransactionType.d.ts","../../node_modules/viem/_types/utils/authorization/serializeAuthorizationList.d.ts","../../node_modules/viem/_types/utils/blob/blobsToCommitments.d.ts","../../node_modules/viem/_types/utils/blob/blobsToProofs.d.ts","../../node_modules/viem/_types/utils/hash/sha256.d.ts","../../node_modules/viem/_types/utils/blob/commitmentToVersionedHash.d.ts","../../node_modules/viem/_types/utils/blob/commitmentsToVersionedHashes.d.ts","../../node_modules/viem/_types/errors/blob.d.ts","../../node_modules/viem/_types/utils/blob/toBlobs.d.ts","../../node_modules/viem/_types/utils/blob/toBlobSidecars.d.ts","../../node_modules/viem/_types/errors/address.d.ts","../../node_modules/viem/_types/errors/chain.d.ts","../../node_modules/viem/_types/errors/node.d.ts","../../node_modules/viem/_types/utils/lru.d.ts","../../node_modules/viem/_types/utils/address/isAddress.d.ts","../../node_modules/viem/_types/utils/transaction/assertTransaction.d.ts","../../node_modules/viem/_types/utils/transaction/serializeAccessList.d.ts","../../node_modules/viem/_types/utils/transaction/serializeTransaction.d.ts","../../node_modules/viem/_types/accounts/utils/sign.d.ts","../../node_modules/viem/_types/accounts/utils/signTransaction.d.ts","../../node_modules/viem/_types/errors/account.d.ts","../../node_modules/viem/_types/utils/chain/assertCurrentChain.d.ts","../../node_modules/viem/_types/utils/errors/getTransactionError.d.ts","../../node_modules/viem/_types/utils/formatters/formatter.d.ts","../../node_modules/viem/_types/utils/formatters/transactionRequest.d.ts","../../node_modules/viem/_types/utils/transaction/assertRequest.d.ts","../../node_modules/viem/_types/actions/public/getChainId.d.ts","../../node_modules/viem/_types/actions/wallet/sendRawTransaction.d.ts","../../node_modules/viem/_types/actions/wallet/sendTransaction.d.ts","../../node_modules/viem/_types/utils/errors/getNodeError.d.ts","../../node_modules/viem/_types/utils/errors/getEstimateGasError.d.ts","../../node_modules/viem/_types/actions/public/estimateGas.d.ts","../../node_modules/viem/_types/errors/block.d.ts","../../node_modules/viem/_types/utils/formatters/transaction.d.ts","../../node_modules/viem/_types/utils/formatters/block.d.ts","../../node_modules/viem/_types/actions/public/getBlock.d.ts","../../node_modules/viem/_types/actions/public/getTransactionCount.d.ts","../../node_modules/viem/_types/utils/nonceManager.d.ts","../../node_modules/viem/_types/actions/wallet/prepareTransactionRequest.d.ts","../../node_modules/viem/_types/actions/public/getGasPrice.d.ts","../../node_modules/viem/_types/actions/public/estimateMaxPriorityFeePerGas.d.ts","../../node_modules/viem/_types/actions/public/estimateFeesPerGas.d.ts","../../node_modules/viem/_types/types/chain.d.ts","../../node_modules/viem/_types/errors/abi.d.ts","../../node_modules/viem/_types/utils/data/slice.d.ts","../../node_modules/viem/_types/utils/hash/hashSignature.d.ts","../../node_modules/viem/_types/utils/hash/normalizeSignature.d.ts","../../node_modules/viem/_types/utils/hash/toSignature.d.ts","../../node_modules/viem/_types/utils/hash/toSignatureHash.d.ts","../../node_modules/viem/_types/utils/hash/toFunctionSelector.d.ts","../../node_modules/viem/_types/utils/address/getAddress.d.ts","../../node_modules/viem/_types/utils/encoding/fromBytes.d.ts","../../node_modules/viem/_types/utils/abi/decodeAbiParameters.d.ts","../../node_modules/viem/_types/utils/abi/formatAbiItem.d.ts","../../node_modules/viem/_types/utils/abi/decodeErrorResult.d.ts","../../node_modules/viem/_types/errors/contract.d.ts","../../node_modules/viem/_types/utils/abi/getAbiItem.d.ts","../../node_modules/viem/_types/utils/abi/decodeFunctionResult.d.ts","../../node_modules/viem/_types/utils/abi/encodeAbiParameters.d.ts","../../node_modules/viem/_types/utils/abi/encodeDeployData.d.ts","../../node_modules/viem/_types/utils/abi/encodeFunctionData.d.ts","../../node_modules/viem/_types/utils/chain/getChainContractAddress.d.ts","../../node_modules/viem/_types/utils/errors/getCallError.d.ts","../../node_modules/viem/_types/errors/stateOverride.d.ts","../../node_modules/viem/_types/utils/stateOverride.d.ts","../../node_modules/viem/_types/actions/public/call.d.ts","../../node_modules/viem/_types/errors/ccip.d.ts","../../node_modules/viem/_types/utils/ccip.d.ts","../../node_modules/viem/_types/utils/ens/encodedLabelToLabelhash.d.ts","../../node_modules/viem/_types/utils/ens/namehash.d.ts","../../node_modules/viem/_types/utils/ens/encodeLabelhash.d.ts","../../node_modules/viem/_types/utils/ens/labelhash.d.ts","../../node_modules/viem/_types/utils/ens/packetToBytes.d.ts","../../node_modules/viem/_types/utils/errors/getContractError.d.ts","../../node_modules/viem/_types/actions/public/readContract.d.ts","../../node_modules/viem/_types/actions/ens/getEnsAddress.d.ts","../../node_modules/viem/_types/types/ens.d.ts","../../node_modules/viem/_types/errors/ens.d.ts","../../node_modules/viem/_types/utils/ens/avatar/utils.d.ts","../../node_modules/viem/_types/utils/ens/avatar/parseAvatarRecord.d.ts","../../node_modules/viem/_types/actions/ens/getEnsText.d.ts","../../node_modules/viem/_types/actions/ens/getEnsAvatar.d.ts","../../node_modules/viem/_types/actions/ens/getEnsName.d.ts","../../node_modules/viem/_types/actions/ens/getEnsResolver.d.ts","../../node_modules/viem/_types/actions/public/createAccessList.d.ts","../../node_modules/viem/_types/types/filter.d.ts","../../node_modules/viem/_types/actions/public/createBlockFilter.d.ts","../../node_modules/viem/_types/errors/log.d.ts","../../node_modules/viem/_types/utils/hash/toEventSelector.d.ts","../../node_modules/viem/_types/utils/abi/encodeEventTopics.d.ts","../../node_modules/viem/_types/actions/public/createContractEventFilter.d.ts","../../node_modules/viem/_types/actions/public/createEventFilter.d.ts","../../node_modules/viem/_types/actions/public/createPendingTransactionFilter.d.ts","../../node_modules/viem/_types/actions/public/estimateContractGas.d.ts","../../node_modules/viem/_types/actions/public/getBalance.d.ts","../../node_modules/viem/_types/actions/public/getBlobBaseFee.d.ts","../../node_modules/viem/_types/utils/promise/withCache.d.ts","../../node_modules/viem/_types/actions/public/getBlockNumber.d.ts","../../node_modules/viem/_types/actions/public/getBlockTransactionCount.d.ts","../../node_modules/viem/_types/actions/public/getCode.d.ts","../../node_modules/viem/_types/utils/abi/decodeEventLog.d.ts","../../node_modules/viem/_types/utils/formatters/log.d.ts","../../node_modules/viem/_types/actions/public/getLogs.d.ts","../../node_modules/viem/_types/actions/public/getContractEvents.d.ts","../../node_modules/viem/_types/errors/eip712.d.ts","../../node_modules/viem/_types/actions/public/getEip712Domain.d.ts","../../node_modules/viem/_types/utils/formatters/feeHistory.d.ts","../../node_modules/viem/_types/actions/public/getFeeHistory.d.ts","../../node_modules/viem/_types/actions/public/getFilterChanges.d.ts","../../node_modules/viem/_types/actions/public/getFilterLogs.d.ts","../../node_modules/viem/_types/utils/formatters/proof.d.ts","../../node_modules/viem/_types/actions/public/getProof.d.ts","../../node_modules/viem/_types/actions/public/getStorageAt.d.ts","../../node_modules/viem/_types/actions/public/getTransaction.d.ts","../../node_modules/viem/_types/utils/formatters/transactionReceipt.d.ts","../../node_modules/viem/_types/actions/public/getTransactionConfirmations.d.ts","../../node_modules/viem/_types/actions/public/getTransactionReceipt.d.ts","../../node_modules/viem/_types/types/multicall.d.ts","../../node_modules/viem/_types/actions/public/multicall.d.ts","../../node_modules/viem/_types/types/calls.d.ts","../../node_modules/viem/_types/actions/public/simulateBlocks.d.ts","../../node_modules/viem/_types/actions/public/simulateCalls.d.ts","../../node_modules/viem/_types/actions/wallet/writeContract.d.ts","../../node_modules/viem/_types/actions/public/simulateContract.d.ts","../../node_modules/viem/_types/actions/public/uninstallFilter.d.ts","../../node_modules/viem/_types/utils/signature/hashMessage.d.ts","../../node_modules/viem/_types/actions/public/verifyHash.d.ts","../../node_modules/viem/_types/actions/public/verifyMessage.d.ts","../../node_modules/viem/_types/types/typedData.d.ts","../../node_modules/viem/_types/utils/typedData.d.ts","../../node_modules/viem/_types/utils/signature/hashTypedData.d.ts","../../node_modules/viem/_types/actions/public/verifyTypedData.d.ts","../../node_modules/viem/_types/utils/observe.d.ts","../../node_modules/viem/_types/clients/transports/fallback.d.ts","../../node_modules/viem/_types/types/transport.d.ts","../../node_modules/viem/_types/utils/poll.d.ts","../../node_modules/viem/_types/actions/public/watchBlockNumber.d.ts","../../node_modules/viem/_types/actions/public/waitForTransactionReceipt.d.ts","../../node_modules/viem/_types/utils/stringify.d.ts","../../node_modules/viem/_types/actions/public/watchBlocks.d.ts","../../node_modules/viem/_types/actions/public/watchContractEvent.d.ts","../../node_modules/viem/_types/actions/public/watchEvent.d.ts","../../node_modules/viem/_types/actions/public/watchPendingTransactions.d.ts","../../node_modules/viem/_types/utils/siwe/validateSiweMessage.d.ts","../../node_modules/viem/_types/actions/siwe/verifySiweMessage.d.ts","../../node_modules/viem/_types/clients/decorators/public.d.ts","../../node_modules/viem/_types/actions/wallet/addChain.d.ts","../../node_modules/viem/_types/actions/wallet/deployContract.d.ts","../../node_modules/viem/_types/actions/wallet/getAddresses.d.ts","../../node_modules/viem/_types/actions/wallet/getCallsStatus.d.ts","../../node_modules/viem/_types/actions/wallet/getCapabilities.d.ts","../../node_modules/viem/_types/actions/wallet/getPermissions.d.ts","../../node_modules/viem/_types/actions/wallet/prepareAuthorization.d.ts","../../node_modules/viem/_types/actions/wallet/requestAddresses.d.ts","../../node_modules/viem/_types/actions/wallet/requestPermissions.d.ts","../../node_modules/viem/_types/actions/wallet/sendCalls.d.ts","../../node_modules/viem/_types/actions/wallet/showCallsStatus.d.ts","../../node_modules/viem/_types/accounts/utils/signAuthorization.d.ts","../../node_modules/viem/_types/actions/wallet/signAuthorization.d.ts","../../node_modules/viem/_types/accounts/utils/signMessage.d.ts","../../node_modules/viem/_types/actions/wallet/signMessage.d.ts","../../node_modules/viem/_types/actions/wallet/signTransaction.d.ts","../../node_modules/viem/_types/accounts/utils/signTypedData.d.ts","../../node_modules/viem/_types/actions/wallet/signTypedData.d.ts","../../node_modules/viem/_types/actions/wallet/switchChain.d.ts","../../node_modules/viem/_types/actions/wallet/waitForCallsStatus.d.ts","../../node_modules/viem/_types/actions/wallet/watchAsset.d.ts","../../node_modules/viem/_types/clients/decorators/wallet.d.ts","../../node_modules/viem/_types/clients/createClient.d.ts","../../node_modules/viem/_types/account-abstraction/accounts/types.d.ts","../../node_modules/viem/_types/accounts/types.d.ts","../../node_modules/viem/_types/actions/getContract.d.ts","../../node_modules/viem/_types/actions/test/dumpState.d.ts","../../node_modules/viem/_types/actions/test/getAutomine.d.ts","../../node_modules/viem/_types/actions/test/getTxpoolContent.d.ts","../../node_modules/viem/_types/actions/test/getTxpoolStatus.d.ts","../../node_modules/viem/_types/actions/test/impersonateAccount.d.ts","../../node_modules/viem/_types/actions/test/increaseTime.d.ts","../../node_modules/viem/_types/actions/test/inspectTxpool.d.ts","../../node_modules/viem/_types/actions/test/loadState.d.ts","../../node_modules/viem/_types/actions/test/mine.d.ts","../../node_modules/viem/_types/actions/test/reset.d.ts","../../node_modules/viem/_types/actions/test/revert.d.ts","../../node_modules/viem/_types/actions/test/sendUnsignedTransaction.d.ts","../../node_modules/viem/_types/actions/test/setBalance.d.ts","../../node_modules/viem/_types/actions/test/setBlockGasLimit.d.ts","../../node_modules/viem/_types/actions/test/setBlockTimestampInterval.d.ts","../../node_modules/viem/_types/actions/test/setCode.d.ts","../../node_modules/viem/_types/actions/test/setCoinbase.d.ts","../../node_modules/viem/_types/actions/test/setIntervalMining.d.ts","../../node_modules/viem/_types/actions/test/setMinGasPrice.d.ts","../../node_modules/viem/_types/actions/test/setNextBlockBaseFeePerGas.d.ts","../../node_modules/viem/_types/actions/test/setNextBlockTimestamp.d.ts","../../node_modules/viem/_types/actions/test/setNonce.d.ts","../../node_modules/viem/_types/actions/test/setStorageAt.d.ts","../../node_modules/viem/_types/actions/test/stopImpersonatingAccount.d.ts","../../node_modules/viem/_types/clients/decorators/test.d.ts","../../node_modules/viem/_types/clients/createTestClient.d.ts","../../node_modules/viem/_types/actions/test/dropTransaction.d.ts","../../node_modules/viem/_types/actions/test/snapshot.d.ts","../../node_modules/viem/_types/actions/test/removeBlockTimestampInterval.d.ts","../../node_modules/viem/_types/actions/test/setAutomine.d.ts","../../node_modules/viem/_types/actions/test/setLoggingEnabled.d.ts","../../node_modules/viem/_types/actions/test/setRpcUrl.d.ts","../../node_modules/viem/_types/clients/transports/custom.d.ts","../../node_modules/viem/_types/errors/transport.d.ts","../../node_modules/viem/_types/utils/promise/withTimeout.d.ts","../../node_modules/viem/_types/utils/rpc/http.d.ts","../../node_modules/viem/_types/clients/transports/http.d.ts","../../node_modules/viem/_types/clients/createPublicClient.d.ts","../../node_modules/viem/_types/clients/createWalletClient.d.ts","../../node_modules/viem/_types/utils/rpc/webSocket.d.ts","../../node_modules/viem/_types/clients/transports/webSocket.d.ts","../../node_modules/viem/_types/constants/abis.d.ts","../../node_modules/viem/_types/constants/address.d.ts","../../node_modules/viem/_types/constants/contracts.d.ts","../../node_modules/viem/_types/constants/unit.d.ts","../../node_modules/viem/_types/constants/number.d.ts","../../node_modules/viem/_types/constants/bytes.d.ts","../../node_modules/viem/_types/constants/strings.d.ts","../../node_modules/viem/_types/errors/unit.d.ts","../../node_modules/viem/_types/errors/typedData.d.ts","../../node_modules/viem/_types/utils/abi/decodeDeployData.d.ts","../../node_modules/viem/_types/utils/abi/decodeFunctionData.d.ts","../../node_modules/viem/_types/utils/abi/encodeErrorResult.d.ts","../../node_modules/viem/_types/utils/abi/prepareEncodeFunctionData.d.ts","../../node_modules/viem/_types/utils/abi/encodeFunctionResult.d.ts","../../node_modules/viem/_types/utils/abi/parseEventLogs.d.ts","../../node_modules/viem/_types/utils/data/isBytes.d.ts","../../node_modules/viem/_types/utils/address/getContractAddress.d.ts","../../node_modules/viem/_types/utils/transaction/getSerializedTransactionType.d.ts","../../node_modules/viem/_types/utils/signature/compactSignatureToSignature.d.ts","../../node_modules/viem/_types/utils/signature/parseCompactSignature.d.ts","../../node_modules/viem/_types/utils/signature/parseSignature.d.ts","../../node_modules/viem/_types/utils/signature/recoverMessageAddress.d.ts","../../node_modules/viem/_types/utils/signature/recoverPublicKey.d.ts","../../node_modules/viem/_types/utils/signature/serializeSignature.d.ts","../../node_modules/viem/_types/utils/signature/recoverTransactionAddress.d.ts","../../node_modules/viem/_types/utils/signature/recoverTypedDataAddress.d.ts","../../node_modules/viem/_types/utils/signature/signatureToCompactSignature.d.ts","../../node_modules/viem/_types/utils/signature/serializeCompactSignature.d.ts","../../node_modules/viem/_types/utils/address/isAddressEqual.d.ts","../../node_modules/viem/_types/utils/signature/verifyHash.d.ts","../../node_modules/viem/_types/utils/signature/verifyMessage.d.ts","../../node_modules/viem/_types/utils/signature/verifyTypedData.d.ts","../../node_modules/viem/_types/utils/signature/isErc6492Signature.d.ts","../../node_modules/viem/_types/utils/signature/parseErc6492Signature.d.ts","../../node_modules/viem/_types/utils/signature/serializeErc6492Signature.d.ts","../../node_modules/viem/_types/utils/blob/sidecarsToVersionedHashes.d.ts","../../node_modules/viem/_types/utils/blob/fromBlobs.d.ts","../../node_modules/viem/_types/utils/kzg/defineKzg.d.ts","../../node_modules/viem/_types/utils/kzg/setupKzg.d.ts","../../node_modules/viem/_types/utils/chain/defineChain.d.ts","../../node_modules/viem/_types/utils/chain/extractChain.d.ts","../../node_modules/viem/_types/utils/abi/encodePacked.d.ts","../../node_modules/viem/_types/utils/unit/formatUnits.d.ts","../../node_modules/viem/_types/utils/unit/formatEther.d.ts","../../node_modules/viem/_types/utils/unit/formatGwei.d.ts","../../node_modules/viem/_types/utils/encoding/fromRlp.d.ts","../../node_modules/viem/_types/utils/hash/toEventSignature.d.ts","../../node_modules/viem/_types/utils/hash/toFunctionSignature.d.ts","../../node_modules/viem/_types/utils/hash/toEventHash.d.ts","../../node_modules/viem/_types/utils/hash/toFunctionHash.d.ts","../../node_modules/viem/_types/utils/signature/toPrefixedMessage.d.ts","../../node_modules/viem/_types/utils/hash/isHash.d.ts","../../node_modules/viem/_types/utils/hash/ripemd160.d.ts","../../node_modules/viem/_types/utils/unit/parseUnits.d.ts","../../node_modules/viem/_types/utils/unit/parseEther.d.ts","../../node_modules/viem/_types/utils/unit/parseGwei.d.ts","../../node_modules/viem/_types/utils/transaction/parseTransaction.d.ts","../../node_modules/viem/_types/index.d.ts","../ethereum/dist/ethereum.d.ts","../ethereum/dist/l2-info-service.d.ts","../ethereum/dist/index.d.ts","./src/slashCommands/operators/chain-info.ts","./src/types.ts","../../node_modules/dotenv/lib/main.d.ts","./src/slashCommands/operators/my-stats.ts","../utils/dist/const/roles.d.ts","../../node_modules/discord-api-types/globals.d.ts","../../node_modules/discord-api-types/rest/common.d.ts","../../node_modules/discord-api-types/payloads/common.d.ts","../../node_modules/discord-api-types/payloads/v10/permissions.d.ts","../../node_modules/discord-api-types/payloads/v10/user.d.ts","../../node_modules/discord-api-types/payloads/v10/emoji.d.ts","../../node_modules/discord-api-types/payloads/v10/oauth2.d.ts","../../node_modules/discord-api-types/payloads/v10/sticker.d.ts","../../node_modules/discord-api-types/payloads/v10/guild.d.ts","../../node_modules/discord-api-types/payloads/v10/autoModeration.d.ts","../../node_modules/discord-api-types/payloads/v10/guildScheduledEvent.d.ts","../../node_modules/discord-api-types/payloads/v10/stageInstance.d.ts","../../node_modules/discord-api-types/payloads/v10/webhook.d.ts","../../node_modules/discord-api-types/payloads/v10/auditLog.d.ts","../../node_modules/discord-api-types/payloads/v10/invite.d.ts","../../node_modules/discord-api-types/payloads/v10/monetization.d.ts","../../node_modules/discord-api-types/payloads/v10/poll.d.ts","../../node_modules/discord-api-types/payloads/v10/soundboard.d.ts","../../node_modules/discord-api-types/payloads/v10/teams.d.ts","../../node_modules/discord-api-types/utils/internals.d.ts","../../node_modules/discord-api-types/rest/v10/application.d.ts","../../node_modules/discord-api-types/rest/v10/auditLog.d.ts","../../node_modules/discord-api-types/rest/v10/autoModeration.d.ts","../../node_modules/discord-api-types/rest/v10/poll.d.ts","../../node_modules/discord-api-types/rest/v10/channel.d.ts","../../node_modules/discord-api-types/rest/v10/emoji.d.ts","../../node_modules/discord-api-types/rest/v10/gateway.d.ts","../../node_modules/discord-api-types/rest/v10/guild.d.ts","../../node_modules/discord-api-types/rest/v10/guildScheduledEvent.d.ts","../../node_modules/discord-api-types/rest/v10/webhook.d.ts","../../node_modules/discord-api-types/rest/v10/interactions.d.ts","../../node_modules/discord-api-types/rest/v10/invite.d.ts","../../node_modules/discord-api-types/rest/v10/monetization.d.ts","../../node_modules/discord-api-types/rest/v10/oauth2.d.ts","../../node_modules/discord-api-types/rest/v10/soundboard.d.ts","../../node_modules/discord-api-types/rest/v10/stageInstance.d.ts","../../node_modules/discord-api-types/rest/v10/sticker.d.ts","../../node_modules/discord-api-types/rest/v10/template.d.ts","../../node_modules/discord-api-types/rest/v10/user.d.ts","../../node_modules/discord-api-types/rest/v10/voice.d.ts","../../node_modules/discord-api-types/rest/v10/index.d.ts","../../node_modules/discord-api-types/payloads/v10/template.d.ts","../../node_modules/discord-api-types/payloads/v10/voice.d.ts","../../node_modules/discord-api-types/payloads/v10/index.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/responses.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/base.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/shared.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/base.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/attachment.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/boolean.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/channel.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/integer.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/mentionable.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/number.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/role.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/string.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommand.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommandGroup.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/user.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/internals.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/chatInput.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/contextMenu.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/entryPoint.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/permissions.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/applicationCommands.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/autocomplete.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/messageComponents.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/modalSubmit.d.ts","../../node_modules/discord-api-types/payloads/v10/_interactions/ping.d.ts","../../node_modules/discord-api-types/payloads/v10/interactions.d.ts","../../node_modules/discord-api-types/payloads/v10/application.d.ts","../../node_modules/discord-api-types/payloads/v10/channel.d.ts","../../node_modules/discord-api-types/payloads/v10/gateway.d.ts","../../node_modules/discord-api-types/gateway/common.d.ts","../../node_modules/discord-api-types/gateway/v10.d.ts","../../node_modules/discord-api-types/rpc/common.d.ts","../../node_modules/discord-api-types/rpc/v10.d.ts","../../node_modules/discord-api-types/utils/v10.d.ts","../../node_modules/discord-api-types/v10.d.ts","./src/services/discord-service.ts","./src/utils/roleAssigner.ts","./src/slashCommands/operators/register.ts","./src/slashCommands/operators/help.ts","./src/utils/roles.ts","./src/slashCommands/operators/add-validator.ts","./src/slashCommands/operators/index.ts","./src/slashCommands/moderators/help.ts","./src/utils/index.ts","./src/slashCommands/moderators/operator-approve.ts","./src/slashCommands/moderators/operator-info.ts","./src/slashCommands/moderators/index.ts","./src/slashCommands/index.ts","./src/clients/discord.ts","./src/services/index.ts","./src/services/discord-webhook.ts","./src/index.ts","../../node_modules/@types/connect/index.d.ts","../../node_modules/@types/body-parser/index.d.ts","../../node_modules/bun-types/globals.d.ts","../../node_modules/bun-types/s3.d.ts","../../node_modules/bun-types/fetch.d.ts","../../node_modules/bun-types/bun.d.ts","../../node_modules/bun-types/extensions.d.ts","../../node_modules/bun-types/devserver.d.ts","../../node_modules/bun-types/ffi.d.ts","../../node_modules/bun-types/html-rewriter.d.ts","../../node_modules/bun-types/jsc.d.ts","../../node_modules/bun-types/sqlite.d.ts","../../node_modules/bun-types/test.d.ts","../../node_modules/bun-types/wasm.d.ts","../../node_modules/bun-types/overrides.d.ts","../../node_modules/bun-types/deprecated.d.ts","../../node_modules/bun-types/redis.d.ts","../../node_modules/bun-types/shell.d.ts","../../node_modules/bun-types/bun.ns.d.ts","../../node_modules/bun-types/index.d.ts","../../node_modules/@types/bun/index.d.ts","../../node_modules/@types/caseless/index.d.ts","../../node_modules/@types/cors/index.d.ts","../../node_modules/@types/mime/index.d.ts","../../node_modules/@types/send/index.d.ts","../../node_modules/@types/qs/index.d.ts","../../node_modules/@types/range-parser/index.d.ts","../../node_modules/@types/express-serve-static-core/index.d.ts","../../node_modules/@types/http-errors/index.d.ts","../../node_modules/@types/serve-static/index.d.ts","../../node_modules/@types/express/index.d.ts","../../node_modules/@types/http-proxy/index.d.ts","../../node_modules/@types/json-schema/index.d.ts","../../node_modules/@types/request/node_modules/form-data/index.d.ts","../../node_modules/@types/tough-cookie/index.d.ts","../../node_modules/@types/request/index.d.ts","../../node_modules/@types/strip-bom/index.d.ts","../../node_modules/@types/strip-json-comments/index.d.ts","../../node_modules/@types/swagger-jsdoc/index.d.ts","../../node_modules/@types/swagger-ui-express/index.d.ts","../../node_modules/@types/uuid/index.d.ts","../../node_modules/@types/ws/index.d.ts","../ethereum/src/l2-info-service.ts"],"fileIdsList":[[188,230,393,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,652,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,411,418,419,462,477,485,502,512,558,588,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,651,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,588,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,587,652,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,485,558,590,652,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,460,512,649,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,589,648,650,651,652,653,654,662,668,669,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,558,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,590,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,558,589,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,652,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,623,655,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,624,655,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,626,655,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,627,655,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,631,655,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,634,655,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,655,656,657,658,659,660,661,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,650,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,666,667,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,611,652,665,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,562,581,586,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,394,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,394,409,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,394,395,410,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,559,560,561,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,460,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,564,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,563,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,409,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,563,564,565,566,579,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,409,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,460,578,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,580,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,582,583,584,585,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,413,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,413,414,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,670,679,680,681,682,683,684,685,686,687,688,689,690,691,693,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,558,670,677,679,680,681,682,683,684,685,686,687,688,689,690,693,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,558,678,691,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,558,670,677,678,691,692,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,679,680,681,682,683,684,685,686,687,688,689,690,693,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,677,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,677,691,694,695,699,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,691,694,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,686,696,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,687,696,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,696,697,698,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,416,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,412,416,417,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,415,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,420,461,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,420,460,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,434,435,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,428,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,430,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,428,429,431,432,433,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,421,422,423,424,425,426,427,430,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,434,435,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,671,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,670,671,673,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,670,671,675,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,671,672,673,674,675,676,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,670,671,672,1266,1267,1268,1269,1271,1277,1279,1280,1281],[94,173,175,176,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,135,138,167,168,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[97,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,141,142,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[141,173,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[141,142,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,141,142,166,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[139,141,142,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[173,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[139,141,142,155,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[139,141,142,151,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[138,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,159,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,140,154,159,166,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[140,154,159,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,159,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,139,140,154,155,156,157,158,173,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[138,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,100,104,111,139,166,173,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,140,164,166,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[138,166,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[139,140,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[159,166,173,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,98,100,102,104,108,114,164,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,99,100,103,104,105,106,107,108,164,166,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,99,100,101,103,104,112,164,165,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,99,100,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,100,101,166,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,97,99,100,101,102,103,167,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,100,104,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,136,137,164,165,166,167,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[139,140,159,160,161,162,163,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[100,104,106,107,165,166,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[101,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,100,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,104,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,97,100,135,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,138,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[96,165,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,109,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,118,138,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,97,119,138,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,173,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,97,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,124,138,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,173,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[96,138,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,118,119,138,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[170,173,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,96,135,138,169,171,172,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[95,188,230,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[173,176,180,188,230,261,264,272,315,316,1266,1267,1268,1269,1271,1277,1279,1280,1281],[173,176,180,188,230,316,317,320,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,743,744,746,784,785,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,744,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,743,744,745,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,744,746,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,273,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,463,464,465,466,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,465,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,467,470,476,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,468,469,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,471,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,472,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,473,474,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,473,474,475,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,525,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,526,527,528,529,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,512,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,478,479,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,480,481,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,478,479,482,483,484,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,493,495,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,494,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,495,496,497,498,499,500,501,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,497,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,396,406,407,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,405,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,396,406,407,408,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,508,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,505,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,506,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,503,504,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,503,504,505,507,508,509,510,511,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,397,398,399,400,401,402,403,404,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,401,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,567,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,567,568,569,570,571,572,573,574,575,576,577,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,530,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,485,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,513,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,541,542,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,543,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,513,531,532,533,534,535,536,537,538,539,540,544,545,546,547,548,549,550,551,552,553,554,555,556,557,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,331,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,330,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,334,343,344,345,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,343,346,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,334,341,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,334,346,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,332,333,344,345,346,347,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,279,350,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,352,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,335,336,342,343,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,335,343,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,355,357,358,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,355,356,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,360,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,332,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,337,362,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,362,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,365,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,362,363,364,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,362,363,364,365,366,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,339,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,335,341,343,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,352,353,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,368,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,368,372,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,368,369,372,373,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,342,371,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,349,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,331,340,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,245,247,279,339,341,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,334,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,334,376,377,378,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,331,335,336,337,338,339,340,341,342,343,348,351,352,353,354,356,359,360,361,367,370,371,374,375,379,380,381,382,383,384,385,386,387,388,390,391,392,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,332,336,337,338,339,342,346,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,336,354,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,370,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,341,342,356,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,335,341,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,341,360,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,342,352,353,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,245,261,279,350,382,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,335,336,387,388,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,245,246,279,336,341,354,382,386,387,388,389,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,336,354,370,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,341,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,486,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,393,488,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,486,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,486,487,488,489,490,491,492,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,279,393,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,516,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,279,515,517,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,514,515,518,519,520,521,522,523,524,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,393,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,663,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,663,664,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,245,279,1264,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281,1283],[188,230,245,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,245,279,1266,1267,1268,1269,1271,1277,1279,1280,1281,1288,1289,1290],[188,230,1265,1266,1267,1268,1269,1271,1277,1279,1280,1281,1289,1291,1293],[188,230,242,245,247,250,261,272,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,227,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,229,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,235,264,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,231,236,242,243,250,261,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,231,232,242,250,1266,1267,1268,1269,1271,1277,1279,1280,1281],[183,184,185,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,233,273,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,234,235,243,251,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,235,261,269,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,236,238,242,250,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,229,230,237,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,238,239,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,240,242,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,229,230,242,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,243,244,261,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,243,244,257,261,264,1266,1267,1268,1269,1271,1277,1278,1279,1280,1281],[188,225,230,277,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,238,242,245,250,261,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,243,245,246,250,261,269,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,245,247,261,269,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[186,187,188,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,248,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,249,272,277,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,238,242,250,261,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,251,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,252,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,229,230,253,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,227,228,229,230,231,232,233,234,235,236,237,238,239,240,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,1266,1267,1268,1269,1271,1277,1278,1279,1280,1281],[188,230,255,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,256,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,257,258,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,257,259,273,275,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,261,262,264,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,263,264,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,262,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,264,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,265,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,227,230,261,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,267,268,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,267,268,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,235,250,261,269,1266,1267,1268,1269,1271,1277,1278,1279,1280,1281],[188,230,270,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,250,271,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,245,256,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,235,273,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,274,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,249,275,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,276,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,235,242,244,253,261,272,275,277,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,278,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,243,245,247,250,261,272,279,1266,1267,1268,1269,1271,1277,1279,1280,1281,1285,1297,1298],[188,230,245,261,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,243,261,279,1266,1267,1268,1269,1271,1277,1279,1280,1281,1287],[188,230,245,279,1266,1267,1268,1269,1271,1277,1279,1280,1281,1288,1292],[188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281,1293,1294],[188,230,242,245,247,250,261,269,272,278,279,1266,1267,1268,1269,1271,1277,1278,1279,1280,1281],[188,230,707,708,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,708,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,707,709,710,711,712,714,715,716,717,720,721,722,723,724,725,726,727,728,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,710,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,709,710,713,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,709,710,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,709,716,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,709,713,715,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,708,709,713,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,708,709,714,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,708,709,713,718,719,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,708,709,711,713,718,719,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,708,709,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,708,709,713,718,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,707,708,709,713,719,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,707,708,709,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,225,230,235,243,245,269,273,277,1266,1267,1268,1271,1272,1277,1278,1279,1280,1281],[188,230,1266,1267,1268,1269,1271,1277,1280,1281],[188,230,1266,1267,1268,1269,1277,1279,1280,1281],[188,225,230,1266,1267,1269,1271,1277,1279,1280,1281],[188,230,235,253,261,264,269,273,277,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,279,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282],[188,230,235,243,244,251,269,278,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1266,1267,1268,1269,1271,1277,1279,1281],[188,230,243,1266,1268,1269,1271,1277,1279,1280,1281],[188,230,1266,1267,1268,1269,1271,1277,1279,1280],[188,230,1266,1267,1268,1269,1271,1279,1280,1281],[188,230,1168,1187,1208,1211,1240,1241,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1169,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1214,1215,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1214,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1214,1215,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1214,1215,1239,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1212,1214,1215,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1212,1214,1215,1228,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1212,1214,1215,1224,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1211,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1232,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1213,1227,1232,1239,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1213,1227,1232,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1232,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1212,1213,1227,1228,1229,1230,1231,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1211,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1172,1176,1183,1212,1239,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1213,1237,1239,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1211,1239,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1212,1213,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1232,1239,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1170,1172,1174,1176,1180,1186,1237,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1171,1172,1175,1176,1177,1178,1179,1180,1237,1239,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1171,1172,1173,1175,1176,1184,1237,1238,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1171,1172,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1172,1173,1239,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1169,1171,1172,1173,1174,1175,1240,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1172,1176,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1209,1210,1237,1238,1239,1240,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1212,1213,1232,1233,1234,1235,1236,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1172,1176,1178,1179,1238,1239,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1173,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1172,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1176,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1169,1172,1208,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1211,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1187,1238,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1181,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1187,1191,1211,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1169,1187,1192,1211,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1187,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1169,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1187,1197,1211,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1187,1211,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1187,1191,1192,1211,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1243,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1168,1187,1208,1211,1242,1244,1245,1266,1267,1268,1269,1271,1277,1279,1280,1281],[173,175,176,177,178,188,230,231,242,261,277,317,321,323,324,1266,1267,1268,1269,1271,1277,1279,1280,1281],[173,188,230,325,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,272,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[86,88,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[86,88,89,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[86,87,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,759,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,733,736,755,758,760,761,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,733,736,755,758,759,760,763,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,733,734,735,736,738,755,758,759,760,771,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,733,736,755,757,758,759,760,773,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,733,735,736,759,760,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,733,734,757,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,736,738,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,838,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,734,735,737,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,735,736,738,742,766,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,777,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,734,736,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,736,756,780,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,736,738,739,768,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,733,738,739,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,735,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,736,783,786,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,736,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,731,732,733,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,788,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,735,736,738,766,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,735,791,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,733,736,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,736,738,769,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,737,753,793,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,731,732,734,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,734,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,794,808,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,737,742,743,744,746,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,736,738,811,818,819,839,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,736,756,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,736,818,819,838,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,736,838,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,736,812,816,817,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,736,818,819,822,823,839,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,736,737,738,742,743,744,746,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,736,738,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,733,736,738,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,736,738,742,765,767,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,735,736,738,742,765,766,828,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,735,736,742,765,766,781,828,830,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,735,736,738,742,765,766,767,828,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,735,736,738,742,766,828,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,736,738,797,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,736,738,765,767,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,733,734,735,736,738,758,796,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,735,738,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,735,736,737,741,742,747,748,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,736,737,742,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,736,759,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,733,736,759,770,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,736,755,758,760,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,730,733,734,736,738,756,758,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,792,838,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,753,794,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,798,799,800,801,802,803,804,805,806,807,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,818,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,736,818,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,733,738,740,768,769,770,775,795,797,813,814,815,818,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,733,736,738,815,818,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,736,818,821,824,839,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,737,749,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,730,733,734,735,737,738,739,740,741,742,747,749,755,758,760,762,764,765,766,767,768,769,770,772,774,775,776,778,779,780,781,782,783,787,789,790,792,794,795,796,797,809,810,812,813,814,815,818,820,821,824,825,826,827,828,829,830,831,832,833,834,835,836,837,839,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,197,201,230,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,197,230,261,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,192,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,194,197,230,269,272,1266,1267,1268,1269,1271,1277,1278,1279,1280,1281],[188,230,250,269,1266,1267,1268,1269,1271,1277,1278,1279,1280,1281],[188,230,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,192,230,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,194,197,230,250,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,189,190,193,196,230,242,261,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,197,204,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,189,195,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,197,218,219,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,193,197,230,264,272,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,218,230,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,191,192,230,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,197,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,191,192,193,194,195,196,197,198,199,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,219,220,221,222,223,224,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,197,212,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,197,204,205,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,195,197,205,206,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,196,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,189,192,197,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,197,201,205,206,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,201,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,195,197,200,230,272,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,189,194,197,204,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,192,197,218,230,277,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,314,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,272,286,290,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,261,272,286,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,281,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,269,272,283,286,1266,1267,1268,1269,1271,1277,1278,1279,1280,1281],[188,230,279,281,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,250,272,283,286,1266,1267,1268,1269,1271,1277,1279,1280,1281],[181,182,188,230,242,261,272,282,285,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,286,293,1266,1267,1268,1269,1271,1277,1279,1280,1281],[181,188,230,284,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,286,307,308,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,264,272,279,282,286,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,279,307,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,279,280,281,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,286,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,280,281,282,283,284,285,286,287,288,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,311,312,313,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,238,286,301,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,286,293,294,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,284,286,294,295,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,285,1266,1267,1268,1269,1271,1277,1279,1280,1281],[181,188,230,281,286,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,286,290,294,295,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,290,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,272,284,286,289,1266,1267,1268,1269,1271,1277,1279,1280,1281],[181,188,230,283,286,293,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,286,301,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,277,279,281,286,307,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,749,752,840,852,853,867,926,931,1017,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1058,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,840,851,852,853,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,841,846,847,852,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,754,840,841,847,889,906,926,1017,1046,1058,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,879,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,840,841,885,907,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,907,1014,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,847,884,889,906,907,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,907,1017,1019,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,867,877,879,931,946,949,950,958,961,963,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,867,931,965,968,969,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,867,879,931,950,961,963,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,867,879,931,946,949,950,958,961,963,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,845,867,931,963,979,982,992,1011,1012,1029,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,740,750,751,752,840,849,858,861,867,869,879,913,914,931,944,946,948,949,950,951,953,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,751,752,847,849,861,867,879,913,914,931,951,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,861,867,931,974,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,845,849,861,867,879,931,974,978,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,845,849,861,867,879,931,974,978,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,751,752,840,845,867,920,931,949,962,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,754,843,849,867,868,927,928,929,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,751,752,849,861,867,869,879,886,913,914,919,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,754,849,861,867,868,878,924,927,928,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,849,861,867,879,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,861,867,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,840,849,861,867,879,921,923,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,861,867,931,985,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,849,861,867,878,879,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,861,867,878,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,849,861,867,879,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,845,846,849,867,931,945,991,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,867,963,993,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,843,849,861,867,879,931,995,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,846,849,861,867,931,974,989,990,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,846,849,861,867,931,974,989,990,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,845,846,849,861,867,879,931,978,989,990,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,849,850,861,867,879,931,999,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,840,849,861,867,879,888,922,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,867,931,986,1002,1003,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,849,861,867,878,879,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,861,867,888,931,1003,1057,1159,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,845,867,931,946,949,950,954,962,963,1006,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,845,867,931,946,949,954,962,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,740,750,751,752,754,840,846,847,849,867,869,879,913,914,918,923,931,946,949,953,1006,1008,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,754,774,840,846,849,867,869,931,949,973,1006,1008,1009,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,751,752,754,840,845,847,867,931,946,949,954,962,1011,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,867,872,875,879,931,948,954,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,867,931,1014,1015,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,867,931,1015,1017,1019,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,847,859,867,888,924,931,1002,1005,1021,1025,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,867,931,986,1023,1024,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,849,867,924,931,1023,1024,1027,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,845,846,849,867,931,1021,1023,1027,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,867,931,1021,1023,1027,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,840,867,931,1014,1015,1032,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,754,840,861,867,931,1086,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,754,861,867,931,1086,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,754,851,861,867,931,1086,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,754,861,867,931,1086,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,754,851,861,867,931,1086,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,754,840,861,867,913,931,1086,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,754,840,861,867,931,1086,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,861,867,879,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,867,917,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,861,867,931,939,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,754,861,865,866,867,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,754,861,865,867,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,861,866,867,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,751,752,754,841,861,867,909,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,751,752,754,844,847,867,889,909,913,914,920,924,925,926,930,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,861,867,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,861,866,867,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,754,861,865,866,867,931,1008,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,847,861,867,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,751,752,754,840,844,861,867,886,908,909,910,911,913,914,915,916,927,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,754,861,867,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,751,867,909,931,1041,1046,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,751,754,840,861,867,879,931,1048,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,751,752,754,844,847,861,867,879,889,908,910,913,914,915,931,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,751,754,840,861,867,872,909,931,1017,1018,1027,1051,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,855,867,931,1021,1024,1038,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,751,752,754,840,845,867,909,913,917,931,949,962,1012,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,751,752,754,866,867,931,956,1034,1056,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,754,866,867,931,1034,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,754,866,867,931,1057,1059,1085,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,754,866,867,931,1056,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,754,843,845,849,867,915,916,920,924,925,927,928,929,930,931,954,963,964,969,970,971,972,973,974,975,979,980,981,982,983,984,986,987,988,991,992,994,996,997,998,1000,1001,1002,1004,1005,1007,1009,1010,1012,1013,1016,1020,1025,1026,1028,1029,1030,1031,1033,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,754,851,867,931,1057,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1086,1087,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,845,867,915,916,917,927,931,1011,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1047,1049,1050,1052,1053,1054,1055,1057,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,866,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,867,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,867,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,866,867,1094,1096,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,851,860,867,1094,1100,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,840,855,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,855,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,840,855,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,855,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,840,855,931,943,954,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,855,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,855,920,931,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,752,855,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,855,869,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,840,847,849,855,917,931,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,861,867,931,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,740,752,754,840,841,842,843,844,845,846,847,848,849,851,854,855,856,857,859,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,883,884,887,888,889,891,892,893,894,895,897,898,899,900,901,903,904,905,906,910,913,914,915,916,917,920,921,922,923,924,925,926,927,928,929,930,931,932,933,938,939,940,941,943,944,945,946,947,948,949,950,952,954,956,958,960,962,963,964,965,966,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,994,996,997,998,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1022,1023,1025,1026,1027,1028,1029,1030,1031,1034,1035,1036,1037,1038,1039,1040,1042,1043,1044,1045,1049,1050,1052,1053,1054,1055,1056,1057,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1097,1098,1099,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,753,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,840,847,848,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,1006,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,752,840,862,863,864,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,754,843,847,867,906,923,927,930,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,847,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,740,752,839,840,847,849,851,854,865,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,840,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,752,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,845,849,866,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,847,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,840,845,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,845,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,840,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,865,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,843,846,847,849,850,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,840,841,842,843,844,846,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,752,867,1022,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,876,877,879,880,882,932,933,939,940,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,845,932,941,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,932,938,941,942,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,932,941,942,977,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,932,933,938,941,942,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,932,941,945,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,871,874,876,879,899,903,932,933,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,871,932,947,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,871,938,942,945,947,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,880,884,932,942,945,947,976,977,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,871,932,938,942,945,947,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,932,945,947,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,871,874,879,899,903,932,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,845,932,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,872,903,932,938,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,845,846,851,989,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,845,871,932,938,942,945,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,880,884,903,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,871,874,880,883,884,933,939,1117,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,902,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,899,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,841,871,879,880,883,884,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,841,870,885,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,841,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,844,879,880,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,879,893,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,894,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,879,880,882,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,842,894,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,840,842,844,891,892,897,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,876,879,880,882,896,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,856,857,858,859,860,866,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,856,867,931,954,955,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,900,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,752,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,900,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,881,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,873,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,872,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,872,873,876,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,877,878,879,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,875,876,877,880,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,855,875,879,880,882,883,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,872,874,878,879,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,874,875,878,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,867,931,965,967,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,867,931,963,965,966,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,879,880,884,957,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,871,879,880,884,957,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,880,959,960,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,918,931,944,954,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,944,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,887,918,920,931,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,752,855,901,917,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,888,917,918,931,1059,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,840,849,851,912,922,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,843,851,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,846,851,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,850,851,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,847,849,851,912,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,847,851,912,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,880,884,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,872,876,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,872,879,880,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,937,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,937,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,936,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,933,937,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,935,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,934,936,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,844,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,1139,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,1057,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,851,856,1095,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,851,858,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,860,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,879,880,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,884,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,879,884,947,1017,1018,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,933,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,752,840,941,1134,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,870,1014,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,872,878,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,847,870,884,906,1125,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,870,1017,1019,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,878,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,878,879,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,871,879,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,870,939,1130,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,939,1123,1130,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,939,1017,1127,1130,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,752,863,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,851,869,873,879,899,952,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,751,752,888,899,901,917,931,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,847,855,896,899,900,901,903,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,847,878,888,933,1159,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,847,888,1159,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,840,847,872,874,878,883,888,899,903,904,1119,1147,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,840,847,883,888,899,903,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,752,840,847,871,879,883,888,889,890,891,892,895,898,904,905,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,729,750,840,876,879,903,1017,1019,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1144,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,750,1155,1266,1267,1268,1269,1271,1277,1279,1280,1281],[92,188,230,325,706,1259,1266,1267,1268,1269,1271,1277,1279,1280,1281],[92,93,188,230,1248,1260,1261,1262,1266,1267,1268,1269,1271,1277,1279,1280,1281],[91,92,188,230,317,325,706,1167,1246,1260,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,317,706,1246,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1247,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1164,1253,1258,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,325,706,1164,1167,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,325,706,1164,1254,1255,1256,1257,1266,1267,1268,1269,1271,1277,1279,1280,1281],[93,188,230,325,706,1165,1266,1267,1268,1269,1271,1277,1279,1280,1281],[93,188,230,325,706,1162,1165,1266,1267,1268,1269,1271,1277,1279,1280,1281],[93,188,230,325,706,1251,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,325,706,1162,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,325,706,1164,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,325,706,1163,1164,1166,1249,1250,1252,1266,1267,1268,1269,1271,1277,1279,1280,1281],[93,188,230,325,706,1162,1167,1248,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1248,1251,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,329,1167,1247,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,325,1167,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1159,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,1160,1161,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,702,703,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,700,1266,1267,1268,1269,1271,1277,1279,1280,1281],[87,188,230,329,701,704,705,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,328,1266,1267,1268,1269,1271,1277,1279,1280,1281],[91,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,279,1266,1267,1268,1269,1271,1277,1279,1280,1281],[188,230,242,277,326,327,1266,1267,1268,1269,1271,1277,1279,1280,1281],[90,188,230,1266,1267,1268,1269,1271,1277,1279,1280,1281]],"fileInfos":[{"version":"69684132aeb9b5642cbcd9e22dff7818ff0ee1aa831728af0ecf97d3364d5546","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"8fd575e12870e9944c7e1d62e1f5a73fcf23dd8d3a321f2a2c74c20d022283fe","impliedFormat":1},{"version":"8bf8b5e44e3c9c36f98e1007e8b7018c0f38d8adc07aecef42f5200114547c70","impliedFormat":1},{"version":"092c2bfe125ce69dbb1223c85d68d4d2397d7d8411867b5cc03cec902c233763","affectsGlobalScope":true,"impliedFormat":1},{"version":"07f073f19d67f74d732b1adea08e1dc66b1b58d77cb5b43931dee3d798a2fd53","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7a3c8b952931daebdfc7a2897c53c0a1c73624593fa070e46bd537e64dcd20a","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"b5ce7a470bc3628408429040c4e3a53a27755022a32fd05e2cb694e7015386c7","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"87dc0f382502f5bbce5129bdc0aea21e19a3abbc19259e0b43ae038a9fc4e326","affectsGlobalScope":true,"impliedFormat":1},{"version":"b1cb28af0c891c8c96b2d6b7be76bd394fddcfdb4709a20ba05a7c1605eea0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2fef54945a13095fdb9b84f705f2b5994597640c46afeb2ce78352fab4cb3279","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac77cb3e8c6d3565793eb90a8373ee8033146315a3dbead3bde8db5eaf5e5ec6","affectsGlobalScope":true,"impliedFormat":1},{"version":"56e4ed5aab5f5920980066a9409bfaf53e6d21d3f8d020c17e4de584d29600ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ece9f17b3866cc077099c73f4983bddbcb1dc7ddb943227f1ec070f529dedd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a6282c8827e4b9a95f4bf4f5c205673ada31b982f50572d27103df8ceb8013c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1c9319a09485199c1f7b0498f2988d6d2249793ef67edda49d1e584746be9032","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3a2a0cee0f03ffdde24d89660eba2685bfbdeae955a6c67e8c4c9fd28928eeb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"60037901da1a425516449b9a20073aa03386cce92f7a1fd902d7602be3a7c2e9","affectsGlobalScope":true,"impliedFormat":1},{"version":"d4b1d2c51d058fc21ec2629fff7a76249dec2e36e12960ea056e3ef89174080f","affectsGlobalScope":true,"impliedFormat":1},{"version":"22adec94ef7047a6c9d1af3cb96be87a335908bf9ef386ae9fd50eeb37f44c47","affectsGlobalScope":true,"impliedFormat":1},{"version":"4245fee526a7d1754529d19227ecbf3be066ff79ebb6a380d78e41648f2f224d","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"bde31fd423cd93b0eff97197a3f66df7c93e8c0c335cbeb113b7ff1ac35c23f4","impliedFormat":1},{"version":"abbb795d88336e6c40e373c73f0379cc9be87068d0585893fcf2f1c19b0f7347","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"c1a44418b7e3f9381e55dea86cc32b26ec3d5ccf6510102716aaa55023919f38","impliedFormat":99},{"version":"2df62cd6db7d86f765cfc05606bbd27b38ed7bae502b5c4d927996bcf3638d64","impliedFormat":1},{"version":"ead90f132d6e4b88191fdfb4f70739766d704da0fd5c213db614ff56b5c705bf","impliedFormat":1},{"version":"c7961377ceb9a0b5ff1d1026e7acf5f25bc79fa0d47b8d473012042a5697bed4","impliedFormat":1},{"version":"db97e174c3a81833da502336e85e289da5a81cc5425078b139419405e5d401cd","impliedFormat":1},"5dc28b693ee4c626dc83b68c87aceab6e77428dbac41fb047a7665a8e6b9f5f2","b730df103122cd3e3d2942e7213004baf52a50958300b2707cc8899de15127d4","cfb492d2a62bab5d583c90b48c217552cd5d50118594612c1673c6b467512409",{"version":"a2999ed84296a880c3f8ad4adc1c8c07617007cc55a2b6ad362b142a6fed9af0","impliedFormat":99},{"version":"a9f672caa1c5631a744b05f69c28b4cfdbcb35e16112b2596ad88c90d1491e90","impliedFormat":1},{"version":"8d1722eddb71400b416698dc4a4faf61d38f3c5fb191412b487877c12f92f5ce","impliedFormat":1},{"version":"8d36f5b65e38d64c7370a80cdd26d2b0eea3b200c90b4b1fa5b594de262b5adf","impliedFormat":1},{"version":"2d5094424c7e06500d51088d6182e1324704010c54e4df440cf687da6d196ca1","impliedFormat":1},{"version":"69333b916a0a4329de4fed1191ec176b476bf419d5c56b3d66c2736ce1e6a4de","impliedFormat":1},{"version":"a955a5652fac7e3f6adc1ad7f4c22774e08251f06091779d48db944c32d54b9c","impliedFormat":1},{"version":"133fd0be181d7c21fceeccfa59efeaabf949502d37288326ffe6b0383fdc0b9e","impliedFormat":1},{"version":"15eee289dbd1369243ce767502b3d48bbdf50638249df90555c0f02f5b2107b6","impliedFormat":1},{"version":"633f7c4ebb6f3a3ab186b8ad44af6b7a41355b19e4125bd378899a50ba5991e7","impliedFormat":1},{"version":"2f460be609337ac6d2dd5969d5336f8512e75bd4ec6282336a5b5f3485853c21","impliedFormat":1},{"version":"8b3449c5b0bcc0f9b82cfd611179453444576ddc31ecfa0df32b94bba23c7962","impliedFormat":1},{"version":"28f13eae6f1c2e2c0b09b3a5899695881f586050cdc5e26ea70b84d53e245c53","impliedFormat":1},{"version":"eeb3eeaf375fc738138043ecc239471c0d4c1798e5426dadda6a370a6e430313","impliedFormat":1},{"version":"75eda22ec0b6351316f9af18f9d714ac2cb708d8ede0ddd6b33d8314dbfc9fc0","impliedFormat":1},{"version":"53ae98cb8a690dcb13ff08468cd532817ceec23301cd2fbd1638a4509c75fb5a","impliedFormat":1},{"version":"716285ba259e4094d45564aa66c45a673d55cb7fa38745b35b8e0ca5b76431e8","impliedFormat":1},{"version":"5d303981e2efe7b75e303b9ba0b149f7dc52b60a716a37366d15c0ee7e06d71c","impliedFormat":1},{"version":"66f11f0455e2ddcd1d861ccb6222c9287ccdf5a4f775288ba4e84588c9f6e7d4","impliedFormat":1},{"version":"566d39c79490d7d3c0edf99528a27ddbc190a43187de9c6903c539310dc32876","impliedFormat":1},{"version":"f6d629d05333c4f6097d2e8d43622930677cfaa0d04451c19d149da012fb024e","impliedFormat":1},{"version":"37ff372218ab7f5fe97a3ea0d889aa22a9cf856f49f3c071b285bb57f61126a4","impliedFormat":1},{"version":"0697562c198ad4887ee0c6ba87c81674415bf08622c38761a35ce284f79000a6","impliedFormat":1},{"version":"ec298fb58b43841e59e9cf74e5c4da1b28211549a111361d1b814b6cf9846ba3","impliedFormat":1},{"version":"f6af127f8f33c31698e4162dc44e27faa32213c8029b01a75ec8d337e8a29d98","impliedFormat":1},{"version":"f2d25ffb9fa1ea3b6c4461d749fffb2943d89365ae492b5da914082e373ef319","impliedFormat":1},{"version":"033ff83964da431641bb12966218670b067eb875f40b867a2f13eccbd22d2ad0","impliedFormat":1},{"version":"b29fca8647befa819e15522effef648208d240212705b5eea931107f252c2cd4","impliedFormat":1},{"version":"e2c0e97358d22f3139d4a26d93c7120014171ef31993440a8b3b69f4bb877fcc","impliedFormat":1},{"version":"90efedb2afa77beb63a1df83ab098109e796e08538e8157840c0b50e1da81a09","impliedFormat":1},{"version":"f72866fd4b0f2ea1c088065c4d6445095d5d8204b5d47bcb567865ba807d0a13","impliedFormat":1},{"version":"2292b8ede5c530d2c30f5a6ea14b455612b85eaf7c817da5bf79daa245068041","impliedFormat":1},{"version":"a6f12f14dbcb3fa60e7972637c7fd2ebee8ecaa320f88e4a6ea0233c77037d98","impliedFormat":1},{"version":"9514002fe1f72b3049408f9d6ca86e3cb961652f0e537d46f9b5452d577bb8cd","impliedFormat":1},{"version":"212bf5658e5e9a5c2339c6c4ed1a9b26048de14f21869e2df1bb7edcd730c54d","impliedFormat":1},{"version":"54de542e1f492d0b9df28493e771f7967c46d0285024f053ac6d81b8e24c05cb","impliedFormat":1},{"version":"a5b04b41838cd784ac841c351ae2c626a45a4d6b7981f805f41c0f332f632e0b","impliedFormat":1},{"version":"cb11accd47db05613ce31bcf360fe9357c25df8d50c3a7f0e953b7569ea4bee5","impliedFormat":1},{"version":"17810264cbbdc018764b9cbd0125892d47245d818d595ec94ddf23079bfeb732","impliedFormat":1},{"version":"04b32b104bf086362811496726a9a761a93ef1051e56107582433eeabb05216c","impliedFormat":1},{"version":"2d2c3ff10f8825d2a7120cb43addefb64111be064e35d270f662cde6ad1c8d5c","impliedFormat":1},{"version":"4752749fa062c4b02e46a60143a0e13ef404ad6ea3282d1aacc7016a17f66369","impliedFormat":1},{"version":"89aff3abdf4a99430d0e8e90c51ee4ca7c63aa5add8c159f922f7e7e7864ca55","impliedFormat":1},{"version":"ee1c930e3da09a2296ed5518b4ee1538e9788ac34b0a60ac33e0a0a2badd76e3","impliedFormat":1},{"version":"9349ef8829763a15785c41e115eb77440570effcaff9b9482c1e6178c8c6f368","impliedFormat":1},{"version":"14affb15c4923cd38b98dda994a6338109067c6f94615ba21db4b8c20c9b2c67","impliedFormat":1},{"version":"f5b3ebeb467837dd6593e4fe8f1de9b7598fb23981e02b32b7e72b81c04164da","impliedFormat":1},{"version":"68a75a201a5d1322df462c133020e5c639809c94a6698e3cc46363e56c174b30","impliedFormat":1},{"version":"265a4739974854eb43539419a6c86faab7e161b1133496c62f8bf2725542244d","impliedFormat":1},{"version":"a1accfaac01020c1b866634f7a698fdd48612caccf305e16844665cb7ecac399","impliedFormat":1},{"version":"ec00441ae4838b8d595acfe3b2750750e4335802b06ba1f41fb03453c2c776b5","impliedFormat":1},{"version":"ac1689d264991e5f58deb5a82ee44940f091a709b8ca815b38d5a7cb1305ce9f","impliedFormat":1},{"version":"8dca1366d02c160f39732f1a9ff2a882489903cd034e9c9c3f0ebfe9fa90f7ae","impliedFormat":1},{"version":"c548226db013facd262a4bc1c32c44a13eda7e1181aa6f569f9bdd531c95b0d5","impliedFormat":1},{"version":"37db669ef9a2ff2244d8e13aa8df9237fe3135c24facf0d62e7751fd49832386","impliedFormat":1},{"version":"543f461070fbd4b33bd05a5ba3e472e1297bb1db3c3101092bd69bfdddd3b1a1","impliedFormat":1},{"version":"929540ba3980906ac3f38e8567233028233c1c7e4d8921c1ce19604357028600","impliedFormat":1},{"version":"de5512f2a4c42776474808db1a6a8f12374be84392eeb649ad306330df41d0b3","impliedFormat":1},{"version":"7e96277aa5d7be6cddfdb78db26d986e00308e63f0202fb0d9fa39c826597dd4","impliedFormat":1},{"version":"3745762b83e5d49983a4183821125e3417473f992c4bf1d6dd6cea91efb4166f","impliedFormat":1},{"version":"ade458e350eda79fa74ecb678d9c51cc17f592d56df3e47286ef28e71401a989","impliedFormat":1},{"version":"695d23d7fb1f989d4d385001d8d8029f2f1a65dd91b4e47078e2586b8cdc4999","impliedFormat":1},{"version":"d73236e868cf6537240359fc4bea5733728567444ec7d2768e78ccc06ef22088","impliedFormat":1},{"version":"279c2ed4f57d90587de8e8dbadcb58b2ce2a0f6f7466ca07de24ad2cd50b6d12","impliedFormat":1},{"version":"02a711dc0da3eb73b8fae269ea1603cceaf395a7288429fdd724986974fa0ffa","impliedFormat":1},{"version":"cec41f4ba1a759fd9913cf418f17fe6a9dd6379cffd6923bb7f7f5efdcab4dda","impliedFormat":1},{"version":"caebb18abe3f02c23f8a16a2ee40ca5e26ac77f952cb15c660ff653cbad52144","impliedFormat":1},{"version":"49bddd70b375e6ba2b0f6e8dca81608dff0e9496dc28a87b79a622b8d1d4b41f","impliedFormat":1},{"version":"fd6d1d663e9ffe474e0b340ca3960c5b1acd4a72c464a0eacfd035c4d178e10d","impliedFormat":1},{"version":"4359e8ba73374bb7d25c0d4181c4e9f9fd6174569897788596feac600ec69639","impliedFormat":1},{"version":"2b31eaeb5ecf87fb46dc532da7b187a6711eb13bd58791d0470eb8ff16281991","impliedFormat":1},{"version":"d4fe178cd599f1de33b0a18107fbaca86f23d0cee832a8b69aa76b8e991d2a94","impliedFormat":1},{"version":"888a96c2375741d846bf0cd44b233143ceca7be646780fd27c6dcb85f1f632e6","impliedFormat":1},{"version":"b21366779c846ce32d31e2af08d40f9a37961e4dfb7a20c16c37fe752047db5d","impliedFormat":1},{"version":"4130c2c57580e214060025c2df1460313ba070d3d6906c957755f10fc3b23ae0","impliedFormat":1},{"version":"5c56d077a2581c84910c8f9f0fad30ae45b2ca0a8cd78c7cf49ef6fe969bb809","impliedFormat":1},{"version":"0d81a9fdbcbe694d70175a1848a8be1c9281810a19d9c61ae197364149e4a8c0","impliedFormat":1},{"version":"2aede4f826e1717895a9b9b72afa7ace796267a37c2b36ce320366c84e3c540d","impliedFormat":1},{"version":"16f8e713001d58b9ee1bdcc52b43215c42ccd15da02fb639c32b942449244957","impliedFormat":1},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"a9f672caa1c5631a744b05f69c28b4cfdbcb35e16112b2596ad88c90d1491e90","impliedFormat":1},{"version":"64cd53feac77ca70c7ac520a67e8bd0331c64bb0faca28aa572d826f00527f98","impliedFormat":99},{"version":"ffdb36fdaa921ab5d6dd94414eb1a8bfcd71472aecd2476bce3c40a082ccaa2c","impliedFormat":99},{"version":"fe8e12d5151d3c526e5fd493757c9d3534c9b42338e7b4ac62a45c088b9a2e64","impliedFormat":99},{"version":"66181539572954871da89df777217a2feb17640a32c993fd25f9a004ff4bd1b2","impliedFormat":1},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"8e20b585eed1b1afb844f5d1f32e726b1ef00a829ac408ca118b7bfbadd2dea9","impliedFormat":99},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"a79e62f1e20467e11a904399b8b18b18c0c6eea6b50c1168bf215356d5bebfaf","affectsGlobalScope":true,"impliedFormat":1},{"version":"49a5a44f2e68241a1d2bd9ec894535797998841c09729e506a7cbfcaa40f2180","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"24bd580b5743dc56402c440dc7f9a4f5d592ad7a419f25414d37a7bfe11e342b","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"6bdc71028db658243775263e93a7db2fd2abfce3ca569c3cca5aee6ed5eb186d","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"4d2b0eb911816f66abe4970898f97a2cfc902bcd743cbfa5017fad79f7ef90d8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"e53a3c2a9f624d90f24bf4588aacd223e7bec1b9d0d479b68d2f4a9e6011147f","impliedFormat":1},{"version":"24b8685c62562f5d98615c5a0c1d05f297cf5065f15246edfe99e81ec4c0e011","impliedFormat":1},{"version":"93507c745e8f29090efb99399c3f77bec07db17acd75634249dc92f961573387","impliedFormat":1},{"version":"339dc5265ee5ed92e536a93a04c4ebbc2128f45eeec6ed29f379e0085283542c","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b08684f05523597e20de97c6d5d0bb663a8c20966d7a8ae3b006cb0583b31c1f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6b042aa5d277ad6963e2837179fd2f8fbb01968ac67115b0833c0244e93d1d50","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"9e025aa38cad40827cc30aca974fe33fe2c4652fe8c88f48dadbbbd6300c8b07","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3e58c4c18a031cbb17abec7a4ad0bd5ae9fc70c1f4ba1e7fb921ad87c504aca","impliedFormat":1},{"version":"84c1930e33d1bb12ad01bcbe11d656f9646bd21b2fb2afd96e8e10615a021aef","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4b87f767c7bc841511113c876a6b8bf1fd0cb0b718c888ad84478b372ec486b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d04e3640dd9eb67f7f1e5bd3d0bf96c784666f7aefc8ac1537af6f2d38d4c29","impliedFormat":1},{"version":"008e4cac37da1a6831aa43f6726da0073957ae89da2235082311eaf479b2ffa5","impliedFormat":1},{"version":"5a369483ac4cfbdf0331c248deeb36140e6907db5e1daed241546b4a2055f82c","impliedFormat":1},{"version":"e8f5b5cc36615c17d330eaf8eebbc0d6bdd942c25991f96ef122f246f4ff722f","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ada07543808f3b967624645a8e1ccd446f8b01ade47842acf1328aec899fed0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4c21aaa8257d7950a5b75a251d9075b6a371208fc948c9c8402f6690ef3b5b55","impliedFormat":1},{"version":"b5895e6353a5d708f55d8685c38a235c3a6d8138e374dee8ceb8ffde5aa8002a","impliedFormat":1},{"version":"b9b859f6e245c3c39ec85e65ab1b1ffe43473b75eaae16fe64f44c2d6832173e","impliedFormat":1},{"version":"93bd413918fa921c8729cef45302b24d8b6c7855d72d5bf82d3972595ae8dcbf","impliedFormat":1},{"version":"4ff41188773cbf465807dd2f7059c7494cbee5115608efc297383832a1150c43","impliedFormat":1},{"version":"dccdf1677e531e33f8ac961a68bc537418c9a414797c1ea7e91307501cdc3f5e","impliedFormat":1},{"version":"e184c4b8918ef56c8c9e68bd79f3f3780e2d0d75bf2b8a41da1509a40c2deb46","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3114a0b8ab879b52767d1225cb8420ec99a827e5f744dbeb4900afc08c3e341","impliedFormat":1},{"version":"93f437e1398a4f06a984f441f7fa7a9f0535c04399619b5c22e0b87bdee182cb","impliedFormat":1},{"version":"afbe24ab0d74694372baa632ecb28bb375be53f3be53f9b07ecd7fc994907de5","impliedFormat":1},{"version":"70731d10d5311bd4cf710ef7f6539b62660f4b0bfdbb3f9fbe1d25fe6366a7fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"6b19db3600a17af69d4f33d08cc7076a7d19fb65bb36e442cac58929ec7c9482","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"8145e07aad6da5f23f2fcd8c8e4c5c13fb26ee986a79d03b0829b8fce152d8b2","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"ba1f814c22fd970255ddd60d61fb7e00c28271c933ab5d5cc19cd3ca66b8f57c","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"125d792ec6c0c0f657d758055c494301cc5fdb327d9d9d5960b3f129aff76093","impliedFormat":1},{"version":"0dbcebe2126d03936c70545e96a6e41007cf065be38a1ce4d32a39fcedefead4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1851a3b4db78664f83901bb9cac9e45e03a37bb5933cc5bf37e10bb7e91ab4eb","impliedFormat":1},{"version":"09d479208911ac3ac6a7c2fe86217fc1abe6c4f04e2d52e4890e500699eeab32","affectsGlobalScope":true,"impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"c40b3d3cfbb1227c8935f681c2480a32b560e387dd771d329cdbd1641f2d6da5","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"5b566927cad2ed2139655d55d690ffa87df378b956e7fe1c96024c4d9f75c4cf","affectsGlobalScope":true,"impliedFormat":1},{"version":"c4a3720550d1787c8d6284040853c0781ff1e2cd8d842f2cb44547525ee34c36","affectsGlobalScope":true,"impliedFormat":1},{"version":"d3dffd70e6375b872f0b4e152de4ae682d762c61a24881ecc5eb9f04c5caf76f","impliedFormat":1},{"version":"fe5748232eaa52bbfd7ce314e52b246871731c5f41318fdaf6633cb14fa20da0","impliedFormat":1},{"version":"d91a7d8b5655c42986f1bdfe2105c4408f472831c8f20cf11a8c3345b6b56c8c","impliedFormat":1},{"version":"616075a6ac578cf5a013ee12964188b4412823796ce0b202c6f1d2e4ca8480d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"e8a979b8af001c9fc2e774e7809d233c8ca955a28756f52ee5dee88ccb0611d2","impliedFormat":1},{"version":"cac793cc47c29e26e4ac3601dcb00b4435ebed26203485790e44f2ad8b6ad847","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"aa5524e0509c2168c9493604acf51ef97d2027f03f3b38da097802d3aa719dc8","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"c5213e770282e93d685de14181bee1486b556a1a90c7697529a86af375f4608d","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"299fd0c281633d8dbfbe5f44c5f2850fe37392da6fd3b9cca3cb4e10cda16432","impliedFormat":1},{"version":"fcd49e75e303b11506c91b618b5f50aa2d027e0c4219a016a4406a2fd6f6ea61","impliedFormat":99},{"version":"bdd94485f193af1db099a949bf16f5b06f87ed2fdfeeb8081ff75b16d74c182e","impliedFormat":99},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"8e20b585eed1b1afb844f5d1f32e726b1ef00a829ac408ca118b7bfbadd2dea9","impliedFormat":99},{"version":"3aa236d922d6447e405f662a789dfe99052a33e971eeda03c34982d636ae119a","impliedFormat":99},{"version":"367546a9101d0516f076a316b42788d4100c4b11ba8ab524e43da449ce427f1a","impliedFormat":99},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"d2fd65eea869f39cbdcc782ecd32932e1b327eba90d5bba4c0d0742e1f362bbf","impliedFormat":99},{"version":"bc640c39437752657c123ec9810ac440d3d3e5bf707a53e55218f56120f7db2f","impliedFormat":99},{"version":"0c3e4081cbc9e82cba7ab88e234b1ba5766d7c59b38ab58622c3074054f58d99","impliedFormat":99},{"version":"4fe80f12b1d5189384a219095c2eabadbb389c2d3703aae7c5376dbaa56061df","impliedFormat":1},{"version":"ad70fdf3826676b87e49c859035690311e6e1f27fc58c76ebfd5c714f7cee2e6","impliedFormat":1},{"version":"edd2bf117f61517d22264e2204925df0f422315f5df9be844feebb3aab4876f0","impliedFormat":1},"bec08f69273b95b152472bf0da1cc47d9b7ee50c60fd671fe6cd9be6ebafb2fa",{"version":"b40885a4e39fb67eb251fb009bf990f3571ccf7279dccad26c2261b4e5c8ebcd","impliedFormat":1},{"version":"2d0e63718a9ab15554cca1ef458a269ff938aea2ad379990a018a49e27aadf40","impliedFormat":1},{"version":"530e5c7e4f74267b7800f1702cf0c576282296a960acbdb2960389b2b1d0875b","impliedFormat":1},{"version":"1c483cc60a58a0d4c9a068bdaa8d95933263e6017fbea33c9f99790cf870f0a8","impliedFormat":1},{"version":"07863eea4f350458f803714350e43947f7f73d1d67a9ddf747017065d36b073a","impliedFormat":1},{"version":"396c2c14fa408707235d761a965bd84ce3d4fc3117c3b9f1404d6987d98a30d6","impliedFormat":1},{"version":"9ae7df67c30dc5f52b7b21e8bb36fd9ff05e7ed10e514e2d9ed879b4547c4cd3","impliedFormat":1},{"version":"5d3e656baf210f702e4006949a640730d6aef8d6afc3de264877e0ff76335f39","impliedFormat":1},{"version":"a42db31dacd0fa00d7b13608396ca4c9a5494ae794ad142e9fb4aa6597e5ca54","impliedFormat":1},{"version":"4d2b263907b8c03c5b2df90e6c1f166e9da85bd87bf439683f150afc91fce7e7","impliedFormat":1},{"version":"c70e38e0f30b7c0542af9aa7e0324a23dd2b0c1a64e078296653d1d3b36fa248","impliedFormat":1},{"version":"b7521b70b7fbcf0c3d83d6b48404b78b29a1baead19eb6650219e80fd8dcb6e1","impliedFormat":1},{"version":"b7b881ced4ed4dee13d6e0ccdb2296f66663ba6b1419767271090b3ff3478bb9","impliedFormat":1},{"version":"b70bd59e0e52447f0c0afe7935145ef53de813368f9dd02832fa01bb872c1846","impliedFormat":1},{"version":"63c36aa73242aa745fae813c40585111ead225394b0a0ba985c2683baa6b0ef9","impliedFormat":1},{"version":"3e7ffc7dd797e5d44d387d0892bc288480493e73dcab9832812907d1389e4a98","impliedFormat":1},{"version":"db011ec9589fd51995cbd0765673838e38e6485a6559163cc53dcf508b480909","impliedFormat":1},{"version":"e1a4253f0cca15c14516f52a2ad36c3520b140b5dfb3b3880a368cd75d45d6d9","impliedFormat":1},{"version":"159af954f2633a12fdee68605009e7e5b150dbeb6d70c46672fd41059c154d53","impliedFormat":1},{"version":"a1b36a1f91a54daf2e89e12b834fa41fb7338bc044d1f08a80817efc93c99ee5","impliedFormat":1},{"version":"8bb4a5b632dd5a868f3271750895cb61b0e20cff82032d87e89288faee8dd6e2","impliedFormat":1},{"version":"55ac6eb880722b04fed6b1ad0bae86f57856c7985575ba76a31013515e009316","impliedFormat":1},{"version":"017de6fdabea79015d493bf71e56cbbff092525253c1d76003b3d58280cd82a0","impliedFormat":1},{"version":"ab9ea2596cb7800bd79d1526930c785606ec4f439c275adbca5adc1ddf87747d","impliedFormat":1},{"version":"6b7fcccc9beebd2efadc51e969bf390629edce4d0a7504ee5f71c7655c0127b7","impliedFormat":1},{"version":"6745b52ab638aaf33756400375208300271d69a4db9d811007016e60a084830f","impliedFormat":1},{"version":"90ee466f5028251945ee737787ee5e920ee447122792ad3c68243f15efa08414","impliedFormat":1},{"version":"02ea681702194cfc62558d647243dbd209f19ee1775fb56f704fe30e2db58e08","impliedFormat":1},{"version":"1d567a058fe33c75604d2f973f5f10010131ab2b46cf5dddd2f7f5ee64928f07","impliedFormat":1},{"version":"5af5ebe8c9b84f667cd047cfcf1942d53e3b369dbd63fbea2a189bbf381146c6","impliedFormat":1},{"version":"a64e1daa4fc263dff88023c9e78bf725d7aba7def44a89a341c74c647afe80cc","impliedFormat":1},{"version":"f444cfd9eb5bcbc86fba3d7ca76d517e7d494458b4f04486090c6ccd40978ce7","impliedFormat":1},{"version":"5099990c9e11635f284bde098176e2e27e5afc562d98f9e4258b57b2930c5ea6","impliedFormat":1},{"version":"cf7dc8abfb13444c1756bbac06b2dd9f03b5bc90c0ebc1118796dae1981c12e6","impliedFormat":1},{"version":"3cc594d4e993618dc6a84d210b96ac1bd589a5a4b772fd2309e963132cb73cca","impliedFormat":1},{"version":"f189f28612dfeac956380eccea5be2f44dcac3d9a06cf55d41d23b7e99959387","impliedFormat":1},{"version":"b3f82681e61a3e1f4592c1554361a858087cd04ee3112ce73186fc79deeeabde","impliedFormat":1},{"version":"e647d13de80e1b6b4e1d94363ea6f5f8f77dfb95d562748b488a7248af25aabf","impliedFormat":1},{"version":"1567dbd347b2917ba5a386f713e45c346a15b0e1e408d4a83f496d6a3481768b","impliedFormat":1},{"version":"219a25474e58a8161b242776856ec5f6960839b63e74809445e51cadbfc18096","impliedFormat":1},{"version":"2f77672836c646d02dd1fb6c8d24e9cd8c63131c5e9c37e72f30856b1d740e62","impliedFormat":1},{"version":"6309a45fc3c03d3c4d56228e995d51974f53009a842374695b34f3607877e5a3","impliedFormat":1},{"version":"bef94eba81ae2c09059c0d9abdb1ae1b7090314f70550f3c8cd5d7ead4a4f212","impliedFormat":1},{"version":"48b787ad458be9b524fa5fdfef34f68798074132d4b8cfe6a6fe9c2bf334c532","impliedFormat":1},{"version":"37280465f8f9b2ea21d490979952b18b7f4d1f0d8fab2d627618fb2cfa1828e3","impliedFormat":1},{"version":"cefa33b76df8d9af73edcf02d9b03effbeec54b8200e97669ad454d770aee9ba","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f3f85dc43cb93c5a797f1ff0fa948d0e17843a443ae11a20cc032ccdf1b9997","impliedFormat":1},{"version":"581843e855d92557cbe9dfe242de4e53badae5e9096ca593b50788f7c89c37f2","impliedFormat":1},{"version":"869010bc679df668137cb3b78a3cb8196e97acf285208a57f6156ceac894a2f7","impliedFormat":1},{"version":"bcae62618c23047e36d373f0feac5b13f09689e4cd08e788af13271dbe73a139","impliedFormat":1},{"version":"2c49c6d7da43f6d21e2ca035721c31b642ebf12a1e5e64cbf25f9e2d54723c36","impliedFormat":1},{"version":"5ae003688265a1547bbcb344bf0e26cb994149ac2c032756718e9039302dfac8","impliedFormat":1},{"version":"02cf4ede9c240d5bf0d9ef2cb9454db2efe7db36692c7fe7ad53d92a08c26b8f","impliedFormat":1},{"version":"a86053981218db1594bd4839bde0fb998e342ecf04967622495434a8f52a4041","impliedFormat":1},{"version":"5c317403752871838140f70879b09509e37422e92e7364b4363c7b179310ee44","impliedFormat":1},{"version":"7b270dc53f35dd0b44bfa619ad4d351fffd512e14053c3688323ed007eda3f6d","impliedFormat":1},{"version":"3bfde94a5dab40b51ff3511a41cfb706d57f9584a15e938d243a0e36861e86fe","impliedFormat":1},{"version":"e86ad029224d4f2af3e188be8b5e9badf8c7083247572069bac7bd2193131fc7","impliedFormat":1},{"version":"057cac07c7bc5abdcfba44325fcea4906dff7919a3d7d82d4ec40f8b4c90cf2f","impliedFormat":1},{"version":"d94034601782f828aa556791279c86c37f09f7034a2ab873eefe136f77a6046b","impliedFormat":1},{"version":"105ae3dd61531488194f412386ba8c2b786f1389ac3415098cc47c712800da29","impliedFormat":1},{"version":"e3acb4eb63b7fc659d7c2ac476140f7c85842a516b98d0e8698ba81650a1abd4","impliedFormat":1},{"version":"4ee905052d0879e667444234d1462540107789cb1c80bd26e328574e4f3e4724","impliedFormat":1},{"version":"80e71af1e94ba805e791b9e8e03ff18dec32e8f483db3dca958441d284047d59","impliedFormat":1},{"version":"150f25e1df681ac86bf2224814e628ec8c67b3b0bf91c5642007f072fc403422","impliedFormat":1},{"version":"51812205a847a2a20e29b77238a146e0306564c53d6bd6bfa72167624e7ea370","impliedFormat":1},{"version":"445fe49dc52d5d654a97d142b143fa2fb1dc16a86906545619b521b1561df501","impliedFormat":1},{"version":"c0c0b22cefd1896b92d805556fcabda18720d24981b8cb74e08ffea1f73f96c2","impliedFormat":1},{"version":"ceec94a0cd2b3a121166b6bfe968a069f33974b48d9c3b45f6158e342396e6b2","impliedFormat":1},{"version":"49e35a90f8bd2aa4533286d7013d9c9ff4f1d9f2547188752c4a88c040e42885","impliedFormat":1},{"version":"09043c4926b04870c1fdfdea3f5fcf40a1c9912304a757326e505bebe04a6d5c","impliedFormat":1},{"version":"cc5dfb7ddc9ab17cf793506f342fffdcb2b6d1d7a9c0e7c8339772fee42b7f91","impliedFormat":1},{"version":"88c34f554b5926f4988d9ff26f84c4f18a4d010f261dac2ed52055eefb9e3c65","impliedFormat":1},{"version":"a7aec47aa991ef5080126c3e2732a8488c13fd846099f89b0d24dc35c0f790d3","impliedFormat":1},{"version":"35085777eb17b745911d00a75be17096fe28a8766081cbd644ef15b4ba756aa2","impliedFormat":1},{"version":"cb498c53a9d35ac1cf9a3515f3835d48b4626a612cf7540c5bfb99542c9ab1a5","impliedFormat":1},{"version":"0ace3010fe4a0e820155e3ccb0172375a01162e528ffc22eec2fa33d697bff24","impliedFormat":1},{"version":"a1b64f86e1279835a2edc6125121dff74b04ef116d0230c20995b013ba37150e","impliedFormat":1},{"version":"39121347a4fa76cf47e67e1259fb0136325528a22bd54b1af6dbec353edf4b01","impliedFormat":1},{"version":"f3c3f17825c6a78681186da04c2f3a0f1c60cfa95f3d4b82bbbd6ebd57214a6a","impliedFormat":1},{"version":"e80304a0977ad51a48bc9495eda8a57253c788f788ba31ba7425f4e7d58358bf","impliedFormat":1},{"version":"c67357cd90bab0388580428c18365a01b4b60f6528e780ec7c5c639798738657","impliedFormat":1},{"version":"6d41f18b1fec14f10853dc8e01ec962cc0a788d5e707cb7fa3583ef84f9c8eb6","impliedFormat":1},{"version":"1422b6b55f4a5376d4b405713ed418353587131b12e3857eb5d68a01cba929e2","impliedFormat":1},{"version":"8f374eeeb9e3beb2132d408b304c50b808de2e88f53bd751a6213df9a49bf5f4","impliedFormat":1},{"version":"586b7a877464cba4970b566a8ae469915d73865295b811f20dd6fd80b807db21","impliedFormat":1},{"version":"e7eb2f83279cd7d925810e19e592b692af0bd68885b4a70ee9b83b8075aa7e20","impliedFormat":1},{"version":"84618b2dd4f762891431011a9879ec24b731ca4ad3f6be74b89a239302d1ed54","impliedFormat":1},{"version":"ab36396e69ad906246fa70d6c4095e3efd687505e355cedce4aeddb8da0a9367","impliedFormat":1},{"version":"49b3c93485a6c4cbc837b1959b07725541da298ef24d0e9e261f634a3fd34935","impliedFormat":1},{"version":"2b1945f9ee3ccab0ecfed15c3d03ef5a196d62d0760cffab9ec69e5147f4b5aa","impliedFormat":1},{"version":"a54f60678f44415d01a810ca27244e04b4dde3d9b6d9492874262f1a95e56c7d","impliedFormat":1},{"version":"84058607d19ac1fdef225a04832d7480478808c094cbaedbceda150fa87c7e25","impliedFormat":1},{"version":"415d60633cf542e700dc0d6d5d320b31052efbdc519fcd8b6b30a1f992ef6d5c","impliedFormat":1},{"version":"901c640dced9243875645e850705362cb0a9a7f2eea1a82bb95ed53d162f38dd","impliedFormat":1},{"version":"ebb0d92294fe20f62a07925ce590a93012d6323a6c77ddce92b7743fa1e9dd20","impliedFormat":1},{"version":"b499f398b4405b9f073b99ad853e47a6394ae6e1b7397c5d2f19c23a4081f213","impliedFormat":1},{"version":"ef2cbb05dee40c0167de4e459b9da523844707ab4b3b32e40090c649ad5616e9","impliedFormat":1},{"version":"068a22b89ecc0bed7182e79724a3d4d3d05daacfe3b6e6d3fd2fa3d063d94f44","impliedFormat":1},{"version":"3f2009badf85a479d3659a735e40607d9f00f23606a0626ae28db3da90b8bf52","impliedFormat":1},{"version":"2c70425bd71c6c25c9765bc997b1cc7472bdc3cb4db281acda4b7001aec6f86f","impliedFormat":1},{"version":"8ed892f4b45c587ed34be88d4fc24cb9c72d1ed8675e4b710f7291fcba35d22a","impliedFormat":1},{"version":"d32b5a3d39b581f0330bd05a5ef577173bd1d51166a7fff43b633f0cc8020071","impliedFormat":1},{"version":"3f6af667357384c1f582ef006906ba36668dd87abe832f4497fffb315c160be9","impliedFormat":1},{"version":"363dd28f6a218239fbd45bbcc37202ad6a9a40b533b3e208e030137fa8037b03","impliedFormat":1},{"version":"c6986e90cf95cf639f7f55d8ca49c7aaf0d561d47e6d70ab6879e40f73518c8d","impliedFormat":1},{"version":"bb9918dbd22a2aa56203ed38b7e48d171262b09ce690ff39bae8123711b8e84a","impliedFormat":1},{"version":"1518707348d7bd6154e30d49487ba92d47b6bd9a32d320cd8e602b59700b5317","impliedFormat":1},{"version":"ede55f9bac348427d5b32a45ad7a24cc6297354289076d50c68f1692add61bce","impliedFormat":1},{"version":"d53a7e00791305f0bd04ea6e4d7ea9850ccc3538877f070f55308b3222f0a793","impliedFormat":1},{"version":"4ea5b45c6693288bb66b2007041a950a9d2fe765e376738377ba445950e927f6","impliedFormat":1},{"version":"7f25e826bfabe77a159a5fec52af069c13378d0a09d2712c6373ff904ba55d4b","impliedFormat":1},{"version":"ea2de1a0ec4c9b8828154a971bfe38c47df2f5e9ec511f1a66adce665b9f04b0","impliedFormat":1},{"version":"63c0926fcd1c3d6d9456f73ab17a6affcdfc41f7a0fa5971428a57e9ea5cf9e0","impliedFormat":1},{"version":"c30b346ad7f4df2f7659f5b3aff4c5c490a1f4654e31c44c839292c930199649","impliedFormat":1},{"version":"4ef0a17c5bcae3d68227136b562a4d54a4db18cfa058354e52a9ac167d275bbb","impliedFormat":1},{"version":"042b80988f014a04dd5808a4545b8a13ca226c9650cb470dc2bf6041fc20aca2","impliedFormat":1},{"version":"64269ed536e2647e12239481e8287509f9ee029cbb11169793796519cc37ecd4","impliedFormat":1},{"version":"c06fd8688dd064796b41170733bba3dcacfaf7e711045859364f4f778263fc7b","impliedFormat":1},{"version":"b0a8bf71fea54a788588c181c0bffbdd2c49904075a7c9cb8c98a3106ad6aa6d","impliedFormat":1},{"version":"434c5a40f2d5defeede46ae03fb07ed8b8c1d65e10412abd700291b24953c578","impliedFormat":1},{"version":"c5a6184688526f9cf53e3c9f216beb2123165bfa1ffcbfc7b1c3a925d031abf7","impliedFormat":1},{"version":"cd548f9fcd3cebe99b5ba91ae0ec61c3eae50bed9bc3cfd29d42dcfc201b68b5","affectsGlobalScope":true,"impliedFormat":1},{"version":"14a8ec10f9faf6e0baff58391578250a51e19d2e14abcc6fc239edb0fb4df7c5","impliedFormat":1},{"version":"81b0cf8cd66ae6736fd5496c5bbb9e19759713e29c9ed414b00350bd13d89d70","impliedFormat":1},{"version":"4992afbc8b2cb81e0053d989514a87d1e6c68cc7dedfe71f4b6e1ba35e29b77a","impliedFormat":1},{"version":"f15480150f26caaccf7680a61c410a07bd4c765eedc6cbdca71f7bca1c241c32","impliedFormat":1},{"version":"1c390420d6e444195fd814cb9dc2d9ca65e86eb2df9c1e14ff328098e1dc48ae","impliedFormat":1},{"version":"ec8b45e83323be47c740f3b573760a6f444964d19bbe20d34e3bca4b0304b3ad","impliedFormat":1},{"version":"ab8b86168ceb965a16e6fc39989b601c0857e1fd3fd63ff8289230163b114171","impliedFormat":1},{"version":"62d2f0134c9b53d00823c0731128d446defe4f2434fb84557f4697de70a62789","impliedFormat":1},{"version":"96f215cefc7628ac012e55c7c3e4e5ce342d66e83826777a28e7ed75f7935e10","impliedFormat":1},{"version":"82b4045609dc0918319f835de4f6cb6a931fd729602292921c443a732a6bb811","impliedFormat":1},{"version":"0fd70ca1eaef1e2dd6f48f16886df4838664821d992fd8076d07fc15e83c8498","impliedFormat":1},{"version":"ba30e6d2f1d20c707566cf485167331a10c539802a79040ced055b62a7aae53e","impliedFormat":1},{"version":"b129f3db6f7f63e3e0cafeb9ee9fc57ceede840577725dcdb01fe89b9d32cf2b","impliedFormat":1},{"version":"4ddd9b092c76bce6b8516c0c4d156de63af024994c2d1305a4812b6d64858f93","impliedFormat":1},{"version":"537a2b61594512c5e75fad7e29d25c23922e27e5a1506eb4fce74fe858472a6e","impliedFormat":1},{"version":"311ca94091f3db783c0874128808d0f93ab5d7be82abc20ceb74afe275315d4a","impliedFormat":1},{"version":"7c07838da165fd43759a54d2d490461315e977f9f37c046e0e357623c657fc42","impliedFormat":1},{"version":"b311d973a0028d6bc19dfbaae891ad3f7c5057684eb105cfbeec992ab71fbc13","impliedFormat":1},{"version":"115c8691bd8fac390f6f6eef5b356543d716da7cffa4c2f70f288d56c5b06aeb","impliedFormat":1},{"version":"e91516e66f9fbf39c978a4092c16ffda3bb0b32158fca6def75aae9fab358153","impliedFormat":1},{"version":"abd4563a6a7668fa6f8f5e5a425a0900b80fc2309fec5186e2cae67f3ce92663","impliedFormat":1},{"version":"cb48f3011e72efef9d5a5b312f4a956f699b8d423bf9f2772724cdded496bd50","impliedFormat":1},{"version":"9aed07904079877252e6c0aedf1d2cf1935ed91d4abc16f726c76b61ea453919","impliedFormat":1},{"version":"6621af294bd4af8f3f9dd9bd99bd83ed8d2facd16faa6690a5b02d305abd98ab","impliedFormat":1},{"version":"5eada4495ab95470990b51f467c78d47aecfccc42365df4b1e7e88a2952af1a3","impliedFormat":1},{"version":"44810c4c590f5c4517dfa39d74161cfa3a838437f92683cb2eed28ff83fb6a97","impliedFormat":1},{"version":"4a34de405e3017bf9e153850386aacdf6d26bbcd623073d13ab3c42c2ae7314c","impliedFormat":1},{"version":"fe2d1251f167d801a27f0dfb4e2c14f4f08bf2214d9784a1b8c310fdfdcdaaea","impliedFormat":1},{"version":"2a1182578228dc1faad14627859042d59ea5ab7e3ac69cb2a3453329aaaa3b83","impliedFormat":1},{"version":"dfa99386b9a1c1803eb20df3f6d3adc9e44effc84fa7c2ab6537ed1cb5cc8cfb","impliedFormat":1},{"version":"79b0d5635af72fb87a2a4b62334b0ab996ff7a1a14cfdb895702e74051917718","impliedFormat":1},{"version":"5f00b052713bfe8e9405df03a1bbe406006b30ec6b0c2ce57d207e70b48cf4e9","impliedFormat":1},{"version":"7abcae770f21794b5ffbc3186483c3dbcf8b0c8e37d3ef3ed6277ece5c5dd4be","impliedFormat":1},{"version":"4720efe0341867600b139bca9a8fa7858b56b3a13a4a665bd98c77052ca64ea4","impliedFormat":1},{"version":"566fc645642572ec1ae3981e3c0a7dc976636976bd7a1d09740c23e8521496e5","impliedFormat":1},{"version":"66182e2432a30468eb5e2225063c391262b6a6732928bbc8ee794642b041dd87","impliedFormat":1},{"version":"11792ab82e35e82f93690040fd634689cad71e98ab56e0e31c3758662fc85736","impliedFormat":1},{"version":"0b2095c299151bc492b6c202432cb456fda8d70741b4fd58e86220b2b86e0c30","impliedFormat":1},{"version":"6c53c05df974ece61aca769df915345dc6d5b7649a01dc715b7da1809ce00a77","impliedFormat":1},{"version":"18c505381728b8cc6ea6986728403c1969f0d81216ed04163a867780af89f839","impliedFormat":1},{"version":"d121a48de03095d7dd5cd09d39e1a1c4892b520dad4c1d9c339c5d5008cfb536","impliedFormat":1},{"version":"3592c16d8a782be215356cb78cc3f6fad6132e802d157a874c1942d163151dcc","impliedFormat":1},{"version":"480ea50ea1ee14d243ea72e09d947488300ac6d82e98d6948219f47219511b8b","impliedFormat":1},{"version":"d575bcf7ebd470d7accf5787a0cf0f3c88c33ca7c111f277c03ebbe6d0e8b0b5","impliedFormat":1},{"version":"72141538e52e99ca6e7a02d80186ba8c877ff47a606fea613be1b7a3439c2b90","impliedFormat":1},{"version":"b43a0693d7162abf3a5b3b9e78acfafd0d4713af4d54d1778900e30c11bc4f83","impliedFormat":1},{"version":"115b155584649eaf75d50bdc8aaa9a0f528b60fade90f0cf78137c875ff7de7c","impliedFormat":1},{"version":"98d88eefab45da6b844d2bee8f6efa8d20c879f6dc870c17b90608a4ac0ad527","impliedFormat":1},{"version":"4eb2ca099a3febd21e98c36e29b3a9472458a1e76e888bf6499614c895ba6be7","impliedFormat":1},{"version":"f4dc28fbbba727722cb1fd82f51a7b9540fbe410ed04ddf35cab191d6aa2ba10","impliedFormat":1},{"version":"414f9c021dde847ee2382c4086f7bd3a49a354be865f8db898ee89214b2d2ced","impliedFormat":1},{"version":"bbbc43627abe35080c1ab89865ec63645977025d0161bc5cc2121dfd8bc8bc2e","impliedFormat":1},{"version":"0be66c79867b62eabb489870ba9661c60c32a5b7295cce269e07e88e7bee5bf3","impliedFormat":1},{"version":"5766c26941ae00aa889335bcccc1ecb28271b774be92aede801354c9797074bb","impliedFormat":1},{"version":"3a19286bcc9303c9352c03d68bb4b63cecbf5c9b7848465847bb6c9ceafa1484","impliedFormat":1},{"version":"c573fef34c2e5cc5269fd9c95fe73a1eb9db17142f5d8f36ffe4a686378b8660","impliedFormat":1},{"version":"d97e30dd93590392fed422f2b27325d10ab007d034faaaf61e28e9ddc9d3825b","impliedFormat":1},{"version":"d1f8a829c5e90734bb47a1d1941b8819aeee6e81a2a772c3c0f70b30e3693fa9","impliedFormat":1},{"version":"be1dfacee25a14d79724ba21f1fde67f966b46e2128c68fed2e48c6e1e9822c5","impliedFormat":1},{"version":"19b3d0c212d241c237f79009b4cd0051e54971747fd89dc70a74f874d1192534","impliedFormat":1},{"version":"b8101e982968b04cfaabfc9613dc8f8244e0a8607007bba3537c1f7cbb2a9242","impliedFormat":1},{"version":"ed3e176bc769725ebc1d93f1d6890fc3d977b9155ae5d03be96ec2d49b303370","impliedFormat":1},{"version":"e2dc16f882661fe5e9e6cde0a9c3e6f18f56ce7243ab0a168e68bfab6a5b9830","impliedFormat":1},{"version":"fc5221aedb3b5c52b4fbdf7b940c2115bde632f6cba52e05599363d5cd31019e","impliedFormat":1},{"version":"0289a27db91cb5a004dcf1e6192a09a1f9e8ff8ce606ff8fd691d42de5752123","impliedFormat":1},{"version":"307c6b2de09a621629cef5b7d0ec0ccabe72a3cd1a8f3ee189229d9035f52051","impliedFormat":1},{"version":"3c196d2ef49db4ad0e33a2a7e515ae622106b06ee8479957303601fd3e00f4f8","impliedFormat":1},{"version":"7933769d84f5ae16546aef06537ca578f1c8d7cca0708452a00613050ac1f265","impliedFormat":1},{"version":"4a48a731413b6fae34620c2e458d0adf2f74083073544a72b1b3a96c32775b2f","impliedFormat":1},{"version":"d405963c5f69955e95c30ef121c7a3309f214f21ef09dceb5d7ac69557cbe0fa","impliedFormat":1},{"version":"0c03b1120ddb2fa74809f5d06516beb5b4a3b3561ee93619f1e1c98fdb74a660","impliedFormat":1},{"version":"c3dc147af5ef951e14797da29b2dcaf1fdddabb0175d538e1bedf64a34690b9e","impliedFormat":1},{"version":"77e6933a0f1e4e5d355175c6d5c517398002a3eb74f2218b7670a29814259e3a","impliedFormat":1},{"version":"90051a939d662322dbc062f856f82ccc13fbb6b3f3bbb5d863b4c5031d4e9a85","impliedFormat":1},{"version":"68969a0efd9030866f60c027aedbd600f66ea09e1c9290853cc24c2dcc92000f","impliedFormat":1},{"version":"757f7967151a9b1f043aba090f09c1bdb0abe54f229efd3b7a656eb6da616bf4","impliedFormat":1},{"version":"786691c952fe3feac79aca8f0e7e580d95c19afc8a4c6f8765e99fb756d8d9d7","impliedFormat":1},{"version":"c3b259ee9684c6680bd68159d47bf36b0f5f32ea3b707197bcd6921cf25bde36","impliedFormat":1},{"version":"ab0926fedbd1f97ec02ed906cf4b1cf74093ab7458a835c3617dba60f1950ba3","impliedFormat":1},{"version":"3e642f39da9ad0a4cd16ccbd7f363b6b5ad5fa16a5c6d44753f98fc1e3be9d96","impliedFormat":1},{"version":"7f5a6eac3d3d334e2f2eba41f659e9618c06361958762869055e22219f341554","impliedFormat":1},{"version":"e6773ee69d14a45b44efa16a473a6366d07f61cd4f131b9fea7cd2e5b36a265c","impliedFormat":1},{"version":"67f2cd6e208e68fdfa366967d1949575df6ccf90c104fc9747b3f1bdb69ad55a","impliedFormat":1},{"version":"4093c47f69ea7acf0931095d5e01bfe1a0fa78586dbf13f4ae1142f190d82cc4","impliedFormat":1},{"version":"4fc9939c86a7d80ab6a361264e5666336d37e080a00d831d9358ad83575267da","impliedFormat":1},{"version":"f4ba385eedea4d7be1feeeac05aaa05d6741d931251a85ab48e0610271d001ce","impliedFormat":1},{"version":"52ae1d7a4eb815c20512a1662ca83931919ac3bb96da04c94253064291b9d583","impliedFormat":1},{"version":"6fa6ceb04be38c932343d6435eb6a4054c3170829993934b013b110273fe40af","impliedFormat":1},{"version":"0e8536310d6ed981aa0d07c5e2ca0060355f1394b19e98654fdd5c4672431b70","impliedFormat":1},{"version":"e71d84f5c649e283b31835f174df2afe6a01f4ef2cb1aafca5726b7d2b73a2e4","impliedFormat":1},{"version":"6d26bc11d906309e5c3b12285f94d9ef8edd8529ddee60042aba8470280b8b55","impliedFormat":1},{"version":"8f2644578a3273f43fd700803b89b842d2cd09c1fba2421db45737357e50f5b1","impliedFormat":1},{"version":"639f94fe145a72ce520d3d7b9b3b6c9049624d90cbf85cff46fb47fb28d1d8fe","impliedFormat":1},{"version":"8327a51d574987a2b0f61ea40df4adddf959f67bc48c303d4b33d47ba3be114a","impliedFormat":1},{"version":"00e1da5fce4ae9975f7b3ca994dcb188cf4c21aee48643e1d6d4b44e72df21ee","impliedFormat":1},{"version":"976d20bb5533077a2135f456a2b48b7adb7149e78832b182066930bad94f053a","impliedFormat":1},{"version":"4d250e905299144850c6f8e74dad1ee892d847643bacf637e89adcce013f0700","impliedFormat":1},{"version":"51b4ab145645785c8ced29238192f870dbb98f1968a7c7ef2580cd40663b2940","impliedFormat":1},{"version":"589713fefe7282fd008a2672c5fbacc4a94f31138bae6a03db2c7b5453dc8788","impliedFormat":1},{"version":"26f7f55345682291a8280c99bb672e386722961063c890c77120aaca462ac2f9","impliedFormat":1},{"version":"100802c3378b835a3ce31f5d108de149bd152b45b555f22f50c2cafb3a962ead","impliedFormat":1},{"version":"fd4fef81d1930b60c464872e311f4f2da3586a2a398a1bdf346ffc7b8863150f","impliedFormat":1},{"version":"354f47aa8d895d523ebc47aea561b5fedb44590ac2f0eae94b56839a0f08056a","impliedFormat":1},{"version":"62b753ed351fba7e0f6b57103529ce90f2e11b949b8fc69c39464fe958535c25","impliedFormat":1},{"version":"514321f6616d04f0c879ac9f06374ed9cb8eac63e57147ac954e8c0e7440ce00","impliedFormat":1},{"version":"ce7b928daedd974205daf616493c6eb358069ed740ed9552c5f4e66da19fd4bf","impliedFormat":1},{"version":"3d59b606bca764ce06d7dd69130c48322d4a93a3acb26bb2968d4e79e1461c3c","impliedFormat":1},{"version":"0231f8c8413370642c1c061e66b5a03f075084edebf22af88e30f5ce8dbf69f4","impliedFormat":1},{"version":"474d9ca594140dffc0585ce4d4acdcfba9d691f30ae2cafacc86c97981101f5c","impliedFormat":1},{"version":"e9ae721d2f9df91bc707ea47ddd590b04328654cfea11e79a57e5aef832709ff","impliedFormat":1},{"version":"0e2a6b2eeadafbc7a27909527af46705d47e93c652d656f09cc3ef460774291b","impliedFormat":1},{"version":"ed56810efb2b1e988af16923b08b056508755245a2f8947e6ad491c5133664ed","impliedFormat":1},{"version":"ed012a19811c4010cb7d8920378f6dd50f22e1cf2842ecb44a157030667b165e","impliedFormat":1},{"version":"26a19453ef691cc08d257fbcbcc16edb1a2e78c9b116d5ee48ed69e473c8ff76","impliedFormat":1},{"version":"2c531043b1d58842c58e0a185c7bd5ce31e9a708667398373d6b113938629f90","impliedFormat":1},{"version":"5304a80e169ba8fe8d9c77806e393db1f708333afc1f95dede329fdbd84e29c7","impliedFormat":1},{"version":"7f0f90d0ffdd54875c464b940afaa0f711396f65392f20e9ffafc0af12ccbf14","impliedFormat":1},{"version":"2e93bb867fefffaecf9a54a91dbf271787e007ec2fe301d3dce080944c5518e5","impliedFormat":1},{"version":"3ab58250eb2968101cb0f3698aab0faa603660bc2d41d30ae13eaa22d75900d1","impliedFormat":1},{"version":"1f18ceea8d29b75099cc85f357622e87d6a2e0793486f89ab6da32cf9e434feb","impliedFormat":1},{"version":"c280ec77789efcf60ea1f6fd7159774422f588104dae9dfa438c9c921f5ab168","impliedFormat":1},{"version":"2826b3526af4f0e2c8f303e7a9a9a6bb8632e4a96fece2c787f2df286a696cea","impliedFormat":1},{"version":"3ec6d90ec9586e6e96120ff558429cac6ca656d81eb644ce703f736a316a0cd6","impliedFormat":1},{"version":"453b07099526a6d20fd30f357059d413677f919df8abf7346fab7c9abfec43fa","impliedFormat":1},{"version":"485f7d76af9e2b5af78aac874b0ac5563c2ae8c0a7833f62b24d837df8561fb9","impliedFormat":1},{"version":"8bdf41d41ff195838a5f9e92e5cb3dfcdc4665bcca9882b8d2f82a370a52384e","impliedFormat":1},{"version":"90f08678b00c7b7aaaad0c84fb6525a11b5c35dad624b59dcadd3d279a4366c4","impliedFormat":1},{"version":"97ba9ccb439e5269a46562c6201063fbf6310922012fd58172304670958c21f6","impliedFormat":1},{"version":"d037b771e89ef6dd81c71de92cc644d68b1b5d1ce25dbce9c2cfe407dd0b5796","impliedFormat":1},{"version":"25091d25f74760301f1e094456e2e6af52ceb6ef1ece48910463528e499992d8","impliedFormat":1},{"version":"853d02f4f46ca9700fefd0d45062f5b82c9335ba2224ca4d7bd34d6ae4fc4a7f","impliedFormat":1},{"version":"b3d1c579771490011614a16be1f6951aec87248fdc928dd46b682523edb8e503","impliedFormat":1},{"version":"b3cc1bb7311f35569b531e781d4a42d2b91f8dfd8bc194cc310c8b61011d6e43","impliedFormat":1},{"version":"cf6dc8f18bc5ee063dc1a37bccd3031dc0769f11622399018c375aacfcbda7c9","impliedFormat":1},{"version":"8ca2d01f5f3d4d4067aadea230570afa4c91e24e485fbe2e9d53ead3b33f80d0","impliedFormat":1},{"version":"87bbee3d308539bb6d85a18d84b852bcd91d5be73bc5366c8d394f3dd633a9e5","impliedFormat":1},{"version":"ab9d37bc03714e85a227a8db09cf4b217de99d3d297152c1d8bcd07d37753665","impliedFormat":1},{"version":"72bb2ca89105bb557c0b70a98503cdff69182d064c8ef4c50373ed2f27a31805","impliedFormat":1},{"version":"dac751a342d90dca2da68677a0ce9786395405de0e9c03f0c5e676fa4fd57e26","impliedFormat":1},{"version":"1eef74abb9048ffb7f773249080dc47a0f8eb220a02455721cc8779437525b2b","impliedFormat":1},{"version":"724a5ed046f87aec06d920fffa4d70ff3ea9cfb63d790ecece4d866018f2e8d3","impliedFormat":1},{"version":"0f986a4d38b0b6e66bf18d740be5c0b1f478154b6ca3530e12e0214fb44fbbdb","impliedFormat":1},{"version":"9fe25bdc82292a488469db295783c5187df43ac5a55a49b63cbacaf8cf12b75b","impliedFormat":1},{"version":"be59079768dc24a100fc8fa32f03f848598a8e0feb884135b6767cd7ffdfab68","impliedFormat":1},{"version":"f5fbcce4b7d3b6f0ab234eda4926bb069ea94744daf82377ee41d0f07bce4b03","impliedFormat":1},{"version":"0c2394fab97f1264b2fc68f4143a11a68c6221eb4c9959fe3ed4fe6627574282","impliedFormat":1},{"version":"e9b5a686e8e87d4529398ea1698a253a57e156f72cf9b245d4d3d39efc06c7fd","impliedFormat":1},{"version":"7662ff2925419c3bb854012a0658fbf63929eb246fcc2c3a346013147180aa6f","impliedFormat":1},{"version":"a566232381cab833f997f74524b1d5a73bc044353bb8d8f87f3942bf4e68d384","impliedFormat":1},{"version":"71e1e2eb6a6f2c451f537acc6d3f5a7d81947a27d7a5c5e3ae830d19a972ffc0","impliedFormat":1},{"version":"53871b5b3657d9a2e80c9f6fb1fa03e6a4e664a75bfebfb820c58b7a4b023c25","impliedFormat":1},{"version":"d474673dc7ed7a59223b25dd6413e89c0b3e4e207ef7ea490d6ddf24d78c89c5","impliedFormat":1},{"version":"e9a6308496927fe05ffd343a4f062f5d0369f5a5d674be58d92515b22aaba969","impliedFormat":1},{"version":"83a74372441872cb6f3688cab6009c3e0aafc4dd2414a2c8a2d340247945e3d7","impliedFormat":1},{"version":"1965472700ba36ecde4826cb978678709f42b768e2adb8d0f0fb118a81aafb37","impliedFormat":1},{"version":"3a19a395b9a6a76d174646bc9cd4504210d71ef5a5f894ab02182e2229b65509","impliedFormat":1},{"version":"419bab68ba67804f65e5a9a428b8630ee2a2a28e0c90a7a53d7f8504df9143e9","impliedFormat":1},{"version":"929022c311336faa083b05e57fd1781906b04995c968db3492f1da3fca2bf603","impliedFormat":1},{"version":"b209715d396013bbf794212887a2efd5f1b254da1aff261b9cc0117640561467","impliedFormat":1},{"version":"6adec68a56989c4f9282ae1df1802a519f14a931c1d2f62b3c1c826aa75c74a1","impliedFormat":1},{"version":"3c2ca15845d257b0e4f669100bb79c92e95ec84a5382aa02ec1bbbf36b00ac22","impliedFormat":1},{"version":"a89e1f874f3ca3bc357a85f7ad80be88304a55703a93807efa258d0ab968373f","impliedFormat":1},{"version":"c2732eff1a3410aa8c04d7b1c9dff791147f6d439ebab95e551ae937eee514f0","impliedFormat":1},{"version":"cb480ac9e7274685a23c7ddf968d26c8106ecab241238c8019b807df20146fc4","impliedFormat":1},{"version":"d4996c548b362000867f44769ad69664fdfbea6f61d9a08e0d65ced6ea48dbcc","impliedFormat":1},{"version":"ce7614e04f1107aa877a25a40ad8d0d57ded4a292938537a82202b852c99a50d","impliedFormat":1},{"version":"4ee861d5c8b34436a2832ecae6be89003a20b341726edac5a4fd6c9d43f92f71","impliedFormat":1},{"version":"d26ed788de38009ac5c1f1e44efe6529ad7a2e8686fb0a025f25206b9cf324ed","impliedFormat":1},{"version":"563c87a7400e0cf80c3c1200169994600b74eb8f4052a340f2717c3c16596885","impliedFormat":1},{"version":"64de49be47b71904704f0836c6a79ef239c64995a7c90ca90b79782fea70e028","impliedFormat":1},{"version":"712c377914bd99f33eca1b2f01e8c64b4237e435360bed7b71af938a6f1b389c","impliedFormat":1},{"version":"92a2771f2ee58b03db68410cac6e242fe56de1d377d12e97df5e06203cebce14","impliedFormat":1},{"version":"55e4e9a5a7d32f6672463e5fa558bf15cc61dffc383808396340e79daa3761cd","impliedFormat":1},{"version":"50d23c36ac76399f95c497635d7da2f00749953fca1467e02fbde0dc4a3c158b","impliedFormat":1},{"version":"1fa764b1e9cee971438c530a42472f15381b27bdfb13ee5aeb265be2d497ff90","impliedFormat":1},{"version":"2045c40fc80f87796764e485c0844645d4f0def984e09f679730f558838de31b","impliedFormat":1},{"version":"eced59a4309f86330b447d0b198a0fb6ccb8adcb7e3e43054f191059023d7239","impliedFormat":1},{"version":"a69acdca953c3bad6e8a9bc390a10eacf92b527874a54a82c3111718e9f831c2","impliedFormat":1},{"version":"4be7e6d6a70aebeab656a12245beb5283f348fdd97c7a20622ee80e84c1dd87d","impliedFormat":1},{"version":"9d5938c3f2c9a318bedf68c6819daacad8a57ab4cb3acdbcb66f5deb6b039171","impliedFormat":1},{"version":"ee1d05153c3538c3610a3bfa1c168f6eddd2c739c9c1e59cffc53c6b47c48201","impliedFormat":1},{"version":"f6d956bfa8d8bde35197d1031ec90d4246c8bfbeab8fdfd4dd505a77e3eccbf2","impliedFormat":1},{"version":"a2b647554c4b0c76bb5e627063c0212529a7eb25aecf9a26eb860c3cb4fa1300","impliedFormat":1},{"version":"73e3af044cd3b4413d9bf91660df2c49ff0ecaef916ad8e3b06fdb036f583e65","impliedFormat":1},{"version":"315068cb082d34441c0740e44fa219454b616640a7509f9a7c49ac4d19796c37","impliedFormat":1},{"version":"3fbe23a2f67c7a4656ee6c18cc81ad7c1687b9dc585aa7028a3c3de9d317fc1f","impliedFormat":1},{"version":"f5a8e77e9aa7f7e3e68c1e51af9156ba1a228b85862fa8a23d62d72a0dea0134","impliedFormat":1},{"version":"8c3a97db11d1dda66ac53dff88a448ea1ab66929775a7ce7591347e58cbb3a0e","impliedFormat":1},{"version":"69d39897280332d00b4450abbcf3370a10d3511f5138cdd9d689889f0281cebf","impliedFormat":1},{"version":"afb17c84ebf0d44e467546f0a6717dfd25ee5e93c0217f5c589cc4211494a11c","impliedFormat":1},{"version":"eb7b00cee00e5a4a224dad756ed1234d90918bd65d8bb479d32922d807011abe","impliedFormat":1},{"version":"84e102a9693f84ebd2e2f861bacabae91ab30b386e9c6e648e1e0d7eb5b45a73","impliedFormat":1},{"version":"7f87674a2ef4473f7eb6563e1c0845ec9a9c0ad47328d957daadb815db6370e0","impliedFormat":1},{"version":"d69308b03417784cc4e1f53857c8e8a3356e50a1cb5b3c88b49666c30a57b115","impliedFormat":1},{"version":"34368020641c77512a1c7656b32f41baffdda276e88a24d08d2e5da88a33acc7","impliedFormat":1},{"version":"acd9c36dab9c452ec230b764e9240d42a3120215a0c33386e82b91a9e96ac7bd","impliedFormat":1},{"version":"bf347934d9a6f1de26dc9c7a74872a8b045beca76f8dcff4fb4d9e4f87e0d492","impliedFormat":1},{"version":"3d022d24649126647a0945e536b9ffa011513f5b149f55f5225831dc0fa28dde","impliedFormat":1},{"version":"257783c9297f89c8d3ab484cec51af8266990404a07276c51080bcda2bc13b01","impliedFormat":1},{"version":"b7a5bdb5aa75b03ecc92deaa72385c5a084c68f262d5ecb776a115ad7fe480f1","impliedFormat":1},{"version":"38c2fe561609becdac52f26415a922d50aca0d725cfc1c3a0c72427e4b17c048","impliedFormat":1},{"version":"b059f90563e79aa31286a84019f519ecca62db22e163fb529ef5475d5ea34e16","impliedFormat":1},{"version":"c8246db61ea766e75596dcfd22b8c5bf4d0dc10caff8b9b49ebe44839f1861d0","impliedFormat":1},{"version":"e9135ba65ba4f53d1ab7b7140ef1c89a1712c05389109acf886dd0086bbde820","impliedFormat":1},{"version":"41431a556e31f1e200ff4018978cdbd0b80837634b7970e9b7bd1cacc369b8f8","impliedFormat":1},{"version":"6548a33a3be2a07bd758a23598cdbe178716ddbba23c8322ac01baf9a55c9d3c","impliedFormat":1},{"version":"4f10117e2caf3f3e3e9ff8bd968041ad56254a2826d2ed084e2bd9056db9c4b5","impliedFormat":1},{"version":"76b7efafc80beaf49948c08aa9272ee79d6b2b0f154ac13398659fc160432328","impliedFormat":1},{"version":"80fe6c3f67f83b20cd2871d987f9907e481d8ff074ec711a8e916662ee5f0950","impliedFormat":1},{"version":"756bde5eb8bc63e94fc9f1e552b3e5972fd4b146cf4ed677e56196a3d0174b6d","impliedFormat":1},{"version":"fbcdb2ccec93060304b878e7f65246b6b2c992e896774e9eaf7744f58a9cd8a6","impliedFormat":1},{"version":"935094dc19b20214f20677d5b871aa34e0e3280e6c852dd57b6a118134a15764","impliedFormat":1},{"version":"ea99aa2e537966df22f8192e99929ee81719c1cf0b9d9d83d0c6fed53325ccc6","impliedFormat":1},{"version":"c12cadc4cee710868ee7a6e92777a8f05ad1b3474a8447b3ccc8f592d7f2c68c","impliedFormat":1},{"version":"d2ffef91eb8a2e0d01f4ba547acd72aefa7093257b8e1d6ecea797cce7c19489","impliedFormat":1},{"version":"6783cb8ca3727edc2c07ab456925cb5cc9242f5fed46a2c82505ae9146300ac7","impliedFormat":1},{"version":"72be668a833df00839fc3be968c1f38e0503e7c867de89f2128bcc2883d90aee","impliedFormat":1},{"version":"4fcdf36200c6bc25ac2fe037ded1f829f7a9ae745025dce2765ac7e7c30a8bef","impliedFormat":1},{"version":"c960d2aeabc5a7fd8e4b43e2f311a9f3e3f4693b7979262c23b46fc73df7304a","affectsGlobalScope":true,"impliedFormat":1},{"version":"9f86422d99b6ab08e7dc326d0a4379a800145a50a59459c013ffe5c6d6e3277d","impliedFormat":1},{"version":"71d5bf7694229b4572c479d31892c1e16339e9b5b63cdb6fa366db5ed5e93446","impliedFormat":1},{"version":"6c4e5a0233a7187e99b007577b4539dc07ac085823f99d9c5020fbfe145a3e5e","impliedFormat":1},{"version":"56b33300b318f41f87c4787a332fab43aa59bb20d38948717c10d18e78c4c5ec","impliedFormat":1},{"version":"eba5208b964d943d716108750130b95fe77375df1db1448f413259617ae8fae0","impliedFormat":1},{"version":"d8fa7e657586879f2d981152555e7cdace28d50731aeb03e7a0b73382a3b1634","impliedFormat":1},{"version":"50c84717d9f1283b49d19224bfe44dfacd09b3fb1e9281383025203593ae3272","impliedFormat":1},{"version":"dd6e162901d23df737eea709b079a91e0aed494c4c61dd56601133e746d8e0c2","impliedFormat":1},{"version":"eb388eb21f5992ebd8cfd86fff7023f90457b5ff2dbc21ee99832c5a92852cde","impliedFormat":1},{"version":"e720d7a4f3b292ca965c2cba746e59630e55f1ba968d9cd655d1e1f709661c84","impliedFormat":1},{"version":"88f4ae4809f1848574d58d009cf5aeba9b24a11dbdee6ec3e7c825831b050c98","impliedFormat":1},{"version":"a6e1c40dbc025de553c4bac9a43bbffa246d5d4ab6a40fc160763d5a00088497","impliedFormat":1},{"version":"47ce460e63cb9f8efb5b1f27fcbd25e4738961a741655660df4dbe9f62ed96cd","impliedFormat":1},{"version":"55818a1bda2b786f974d4ff6c421dcc136ee3da240a3405611bff8ca1870696e","impliedFormat":1},{"version":"170ec1ff7c84bd37c5dcc50a84faa81fd940234d3682929488259f1cd76744c5","impliedFormat":1},{"version":"e8b746d0926711ebdd39912d8898681851f4b5c579cec9a314ca85310110eff6","impliedFormat":1},{"version":"586d1c4452e4cebb997781d1c202bb10ae9b809eca2b1331afcd89cb70b6c136","impliedFormat":1},{"version":"407b17b27a8edf2ae2e00c11e397c51b8e3e5dd651453839f5e65563f9047c65","impliedFormat":1},{"version":"1508be69637d4a514f7cedc38a97236fe122ab204f5817501fe6b0a0346161b4","impliedFormat":1},{"version":"8ae9ac808ef254555b9b41a0bb676ff7f083da1809cf249dfd940c5c815211bf","impliedFormat":1},{"version":"809169acb3a791afda29e7eedc10c82473a5864acd264b406b6e1ff54bf06add","impliedFormat":1},{"version":"fa10b4fc8e6be9d674026049a83d5f6dadc5ae0ef65f2c1425a76c9c6f8d52b8","impliedFormat":1},{"version":"3fb17c109ccbbbb23b94635ea9895025f8c59e35e78547316ed4bf820d4d4226","impliedFormat":1},{"version":"2c4d0f383ea6f71e00baa32137b7838bf4c04308456da98028b95683f7fd87f6","impliedFormat":1},{"version":"54dd9e1d3d04853ef1390ad46f993ae340c799c2ae0f7921e67f176c44641590","impliedFormat":1},{"version":"2a9c19eb5aa8985aa98b49613a03015235a206853606f3db9c8c38ab3268c40f","impliedFormat":1},{"version":"2bcbf9dcbf2f58352a923d8d600f4616ea2efa946d22a3c2eb3a49e66315c6b3","impliedFormat":1},{"version":"1a195405484ebe575183cc2461386d12bbb18d1e3c35b0e3fd8b445f057c8507","impliedFormat":1},{"version":"c8a3a415d2202b031766c34f1564bc9e6bbf25ea657c178e403c85013bf8f925","impliedFormat":1},"5217737350961dca3518d675a14cd1c25dfd876b4896a5288dd954730a85f1c9","e920714bdec6879d48171f3b52b76ebd61262c7c41fef3a554fbfd4d3b368bde","83ae07a53dbcb916c5f9d880eb2e2e56e2b6f9c951a3ec1492b7f56ddc9e378a","98852b7d59b280385a16a2540b8939aa81c011809f0d0ba86bc081c2bbabab8d","dd8b0023d51264708494cd6cc0f3b5e6b8919cfe02c06bc83ba95e1a5d944668","b3ce6322e0ed3aa971aaf29bdb66f0a3321edb97da117ce6abbd9505c6e5ddd9",{"version":"b166e33cf8226ac8781899da244397e77e5b6528271339ce26ece0c2c7242d7f","impliedFormat":1},{"version":"a623d5cf7925e72dbf4602862499564389c7c3dc0ce049733cc0ec756a846667","impliedFormat":1},{"version":"d9028ded7b00c211d789db29f1b2d9d1b7600a4edcbbd087f1faf0495229d179","impliedFormat":1},{"version":"63634c0855e639ea7f609613d799bbb0dc774ec9f3242bc272c5567dc5ccd485","impliedFormat":1},{"version":"592f06c425ab27b4bafec624ef5b153cbdde9ac58f7113100a2da1c4309d1309","impliedFormat":1},{"version":"19c8ab51b4b07c529d95cd4d5c8d100a68dca247ec83a5097d35106fd8a7acca","impliedFormat":1},{"version":"72adc8e79ac32a81f3d515850cf8944a94f0dbc3c567835b37a45f601ccc1d3d","impliedFormat":1},{"version":"fb4f06b2af9ee4b2d2be8c964b0a8f6dd260be9048488ffcf04eb5c0fcb8bf61","impliedFormat":1},{"version":"f185055f36d76e2df5eeb87ae1148a25a125be2bff2095e1bd39c1c7ce85a640","impliedFormat":1},{"version":"9fcb4ef8bf8955c4e9c81bdf4e239d4c0c22869b6cf6ce2ecc95743bf683cb9f","impliedFormat":1},{"version":"979fdebc12d30becce6a15e68d99bc8a2a470a8dcf0898ac9e2d241a7e531940","impliedFormat":1},{"version":"1824ad7d4259910646279d667e517334c0aa24d5c810e8ea6da756fc2e02372f","impliedFormat":1},{"version":"989e9060e220ff86025044ba3c867a83512a655b7cf6253b2bd682192debf390","impliedFormat":1},{"version":"8b1feb568c859feb59236e9723b7a86e2ff8f9a8f2012366ffd1798164dc2798","impliedFormat":1},{"version":"8fab988b0129e674afc0bc0e95329b4052cf027f5d5b5b3e6e92d055b5ba88ef","impliedFormat":1},{"version":"4fe56d524ab24c225668803c1792945053e648b4e8fa4e50fa35594495b56732","impliedFormat":1},{"version":"2652931b8f7dca9a57f21aeb25b5d46851dcf17e4d5ed54b9b57d5d26e647680","impliedFormat":1},{"version":"d364c8df7d52199f5d011b4ded96f36dd114b984f5ee2e50ffe7d30ac1ab4bba","impliedFormat":1},{"version":"408f9eb3c7a3533bf5f07e0cde110a5ee0702864795ee6727792520fe60320b6","impliedFormat":1},{"version":"ba79eb15c36ff23e352ef608ceb7f9f0f278b15ad42512c05eedbe78f228e0e4","impliedFormat":1},{"version":"4cd233c6af471432253a67ae4f3b43c85e58a71418d98c3e162a1dac975c68f6","impliedFormat":1},{"version":"aa77c7d8ddc961e8192bcaa92da140e1205f8aee78bfadead5f52b8844d7d05c","impliedFormat":1},{"version":"37e37d3a525a207efab5458069fd9a27a174d2dc3af729702c81729ca03a349f","impliedFormat":1},{"version":"70997e63b7b3d90188fa2106753d35afd3b43b2bde957c46a5516d89e3ef0c1a","impliedFormat":1},{"version":"7fdaebdb3780d0549a8e0abcb18965e2f62224bdde633aeafb22c64c02fe9e9d","impliedFormat":1},{"version":"24f848479d1fd142d3d7cf034bedca247d1d9b8b31c2632c09695bd6a0441141","impliedFormat":1},{"version":"7e977910c045ec087f435905eb730e9c84e8d6b97f0dd0fe0c022dfed665613a","impliedFormat":1},{"version":"9c4ec2692cdb791823b9407753dec50d69b1b990cf7038cac3fab01e8ed5f709","impliedFormat":1},{"version":"176e7ce333b9988d68cfd5ab6717b20421a03b415af57f2a3bea1aa6b8d634a9","impliedFormat":1},{"version":"301a1ba797c537d2598a557af4862e7823353c80529c9a58bc1a0c08779deb5d","impliedFormat":1},{"version":"2f37ef3a5d3fb119b390cb48c77352914c814b98948633deac90099faae320a6","impliedFormat":1},{"version":"ca2ce76fd743888d0f0c5be48b1b17a864f5ff2b0d09e954d3690645a794533f","impliedFormat":1},{"version":"d4832d1deaacad5d196b2a83239fb94c80f97df889c02a75859b05b460885300","impliedFormat":1},{"version":"1b105a40480faa8c292868597cccea1384e26c034ea0b7e2c6e9d834259f7ef3","impliedFormat":1},{"version":"c53f7caa42ad0bff2b3cad20e4780990aadf647c845cb66cec004062cc4ae549","impliedFormat":1},{"version":"a82f1d66de93c80bca7a744647c748657c050341e53de63fae5aecb72f85f5e6","impliedFormat":1},{"version":"b066b4fde4ba0c1f85aefcd6424a5c670694c871ef2f0fdbf43c5c37e3b0cf3e","impliedFormat":99},{"version":"301f3adc8c06c98797d994c52155f0262379c9679bff79d2f8bfafcb9cbf06ac","impliedFormat":99},{"version":"114acf974bab47eadf40fc7d1ddb0e872d8d8230b111ce4465540ad48d2d5001","impliedFormat":99},{"version":"7755d7edd5edd4b5a8cd308aa9c05c767a8d3d17bc09673165128e0b6e8cee7e","impliedFormat":99},{"version":"27a7c50de3aea981dd08e99e4de2bd29599537e07ffc5e85d20f40f2cfb79bac","impliedFormat":1},{"version":"400ba51008a98a5afc065b12c3aee8f447a0b66c2a4c1bcc3e5a2f41015ddee7","impliedFormat":1},{"version":"49f735c4888a72b7e70b4a90db308ea672967fc2a1670c5b6b598f6b09403baf","impliedFormat":1},{"version":"a2e86477a12540ef9e439245b959b2d8b96d674d5215d154ff22ad26141f4cfb","impliedFormat":1},{"version":"29150e44771dac0aeb711badc04e08fccd01b46efc560bd6e01b96d746a3f26c","impliedFormat":1},{"version":"e09f096004d70d6e98f5e5fee165849b3944f706861cdeffce5339dfd8426db5","impliedFormat":1},{"version":"1ddd1ca692a6c656ade0a85c9a722b3679b3d0bf113b699908e0325cf3537dbe","impliedFormat":99},{"version":"a7a4ea3e08f0ca7139ef99db3be34db005406e795bdeaa519998ad4666c5dfb9","impliedFormat":1},{"version":"4fb2df0b48ac55d960fedfb7e7b917d2d29608d7f351b70b6b3104e2d02d2f11","impliedFormat":1},{"version":"728ec07c8a50b9f22da9c9aa8859e29462526fd996ac1d21c6c9a81b78106dd5","impliedFormat":1},{"version":"3f48d378dba0b95f2d431d60efd4f3225791c0a880d1166181d6edb563160bde","impliedFormat":1},{"version":"f58e5f53ffdcac8ebbfdad16ea7e6164fc25e63f5e3cae8cb13395100ebb8da8","impliedFormat":1},{"version":"be9ef0a0446cf28d529a684e4a7d14101f03e054896704fbdc5470d8fa4de6b4","impliedFormat":1},{"version":"acd32f2f192d93e8161938ebfd74fa063e67a09cbe0156a74ae2e421a1e8f786","impliedFormat":1},{"version":"1eeb9deebe9a0a6cc52a32aa1533a1535ecc1b4e831290c753e72e0394e866a9","impliedFormat":1},{"version":"ae1f27a5966db7640edb4c82974b985acb7b1fa0859bff7cd769629436822d9a","impliedFormat":1},{"version":"a3d0b36bb3185da856cc0a7df02f63008935602ed09f84b0d960c7f9f7f6d63d","impliedFormat":1},{"version":"60319cf75d460432a0769a2f98a9ab6fc3ad39290bf7f1b33b922e832ff5b40e","impliedFormat":1},{"version":"30ceaf6e65817221c5c62cedfc26892a4b79a78c7eb7367bcccc0e217b517bf1","impliedFormat":1},{"version":"a3ea4adb87d130799d26945196bba7e889056c74dac98069d58c015d10f3c053","impliedFormat":1},{"version":"83dc49d957cb3b4af3a45cd7b54958149d21088d49f95e8ba6e3d3fb2b37d880","impliedFormat":1},{"version":"b7825c3d04bfc38caf9cb94341cede132d227654b28e3a603d1576bf199a7e47","impliedFormat":1},{"version":"888180b3d951298bf85d430543a1fa2fc6264fc847aef5baa821c743b5d84a58","impliedFormat":1},{"version":"4ec19d58993999260e0df245eec5fd6d7dd92978360c4f0706c9260091f55c70","impliedFormat":1},{"version":"0bc4f86d58f4a4b5a9563ba8d2b23a3fac187a6e167772f6689ea807081ed631","impliedFormat":1},{"version":"7a4e38850bfca2b105fd3e5609b68b52271fd7f2cab9f1d4031748e8bfd29633","impliedFormat":1},{"version":"496ee894efcd5de63169a3a4e47d74f16f754eb212b1ef209f9255aaaeef3450","impliedFormat":1},{"version":"246bec681a7465de230b083e0e63633b568a2d79c20fe167d3280e21200b22c8","impliedFormat":1},{"version":"3ee38e0bac65430814b195ed22b5aadfbe4fbd8890c5e5b45a7ba13f05c0ea0d","impliedFormat":1},{"version":"45181e4221f90d98bf2046ba55cdc22411dc64b9a8cc04f1c8702038b7334d01","impliedFormat":1},{"version":"7fe0253ff44f072ea13fa372e2fbd007aa439df9560762950d38b4c203b2c51a","impliedFormat":1},{"version":"bf4ebcedc7324dd0cbe83488830f7966e808fabf4836d516d1b591ea91417c68","impliedFormat":1},{"version":"5cc968707e8d5e146d075fb83c33a242dd874ef44356969f0ac243dcfd483270","impliedFormat":1},{"version":"af0dfd141ecb2e24ef9a3028727214a69aa528d0be91e8728a7abd4fd6659b5f","impliedFormat":1},{"version":"786d583f831d03da4aed9f9354fd9c4ef00aa8122564da5e683631423639c258","impliedFormat":1},{"version":"418fdcdefc32953c6c7ea7e9979ce84b87618de9def698e73da2c16697fe023b","impliedFormat":1},{"version":"4d0db315ab6869de22694dc968fe740cfef635a21455a4d2bd33bc95b8eec381","impliedFormat":1},{"version":"31b529d1940d4b37e101c4497f7b55965a667985c931b1d16821f7a120e88b4c","impliedFormat":99},{"version":"e9ecf153356cbe27354242dcb6a62234bf6d83c8c19d5204694694783c0b905c","impliedFormat":99},{"version":"83d783e14ae73ab5adeced6c66526daa1155f74512c00ce72902d1fc7c02484d","impliedFormat":99},{"version":"e2a062632ce9bd3663f3821c04f912957ba093cf9cebe532d9ce3187fc837b8c","impliedFormat":1},{"version":"08447e8b528a1f8d1162aa044695d460ce5179a78bd174fa0673fa16b06011aa","impliedFormat":1},{"version":"8e532c6486042736463d1116d45b0db814d969ffd2ee822e4e5ce975807c16f0","impliedFormat":1},{"version":"fad47f66fef1ff277730abff9c9330dd70284eb0ced43d6dd6aee15fc5f19a1b","impliedFormat":1},{"version":"7b4b0aaf0978122b44aa6317977be3e2f9d3d261ae4a8d93bfd511a7ddee7dfe","impliedFormat":1},{"version":"cb5def9d6efe73b09a7adce13bbb7fad7ee6df7a59259300de6ca77fe84041fc","impliedFormat":1},{"version":"16c6ff8bcfef0ad22abffa3329760bb611c4c4aa098ece0d6bcfd1cd16610997","impliedFormat":1},{"version":"3d15157b6685e63a7e43a39bbc1fbcfdbf1250fa3598af55a2384f6f31260c86","impliedFormat":1},{"version":"58b5bc399cd98b87eff2c80d995d4dd63e69c801ec880b85c7da73ddc561a751","impliedFormat":1},{"version":"401c5b0f01bb0dce7a85899d8665c7d9c0b1637dc642805320d76c1a071135dd","impliedFormat":1},{"version":"af81e13747ef7589a726505dd4c2dcf00bb2b9fd7c3c84d580c1d02dbc3b58a9","impliedFormat":1},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"516c53364c6b242591c65afc8b0f0f0cee74ac8a04f52470a539fcb33da2e318","impliedFormat":1},{"version":"cdf612f32afd760cd4a568e3f0c4646394f18fe2277a5ec1c084f1430776f1e0","impliedFormat":1},{"version":"e8ee036c1281885b9cc58f9d1d47472037d080a45b44a3ecbb8fea445e87415d","impliedFormat":1},{"version":"27679e96d1bd38c5938178aaf4abe8627493090b63d6bae2ce8436e6a87ebe4d","impliedFormat":1},{"version":"90887074bbd664eb4726465ccc6740fa8886e525e5c0afcc734e41df41851a60","impliedFormat":1},{"version":"67ddace2fd97646b97e56794034fe5147674a83b7b21c47ec822c25284287497","impliedFormat":1},{"version":"0a3d92e1ed031f67294fc02692352444c0514e371b7093b8d224b6f9ea02d958","impliedFormat":1},{"version":"cc31889ffc5c322ff53137f54f3aa8f74a969cd01adbb296737231f31a870322","impliedFormat":1},{"version":"0ca73c49265550f240230440fbd4dbdb1e332c14620b6a13fd02c08ca96f6018","impliedFormat":1},{"version":"3df74fc90d6cf9c51ad6864a7d9e1e6d162a6e158f99ab2b7d878b4646aa343b","impliedFormat":1},{"version":"306712d7dc95ea2006413dec36b165bff346626340d2ba5adc14a3bafdcb57db","impliedFormat":1},{"version":"cca7da500accfa2e8689e453b1d74d05bcbf1dc6ef86f12b8cb1518a880adffa","impliedFormat":1},{"version":"15b2cfe4d0234d8b21250f6b93c2a4bf7b56fd9e5c740c8d0d5086e3878386f5","impliedFormat":1},{"version":"3470c8f802d69951553de4bf72f42a77b1d273c971dc8462d7ac94b2d5069171","impliedFormat":1},{"version":"312476b9c5aa822a32c969ad650d1b475b631506af9a1448abf2d714997f7510","impliedFormat":1},{"version":"2dc955a0fbc3c0b9a49bcc3ffb9dfb31b3a53af0db862260dd4f824c6b4ff36c","impliedFormat":1},{"version":"0f513df152e8cd877ddc47e1a767f77d2111d7b5dfbc4f68ca355d1dd59c062c","impliedFormat":1},{"version":"e6e01423d7599e1155ab10e2a4ab1549c7f78af0d80fc8c641298989b7dc90b3","impliedFormat":1},{"version":"0c904d0442caed7effc17e2c70c7c96df0b34797e1adb9999ce5e5bbbf7e1471","impliedFormat":1},{"version":"4e42a180e6ad34da29c0f9e0e34dfe728292d4148aeb1a36e3ca8e6551f0fc42","impliedFormat":1},{"version":"8722ec4640f5eb5dcc91be6e59e6148b861e93954a766e05d5d55dd96b29e1c1","impliedFormat":1},{"version":"3118f4f3494834d0a131955088b28cba84639a66e23e6de211bdb75fe518ea90","impliedFormat":1},{"version":"8ec50f5d9824f3692fe32a80fb160d72ea39d94c5aac4f3334f7724ae61de6df","impliedFormat":1},{"version":"dfafee7cd0b796c959cd7f4c6d4ae2f1f89fab40129d993dd564f9ef0bd0068d","impliedFormat":1},{"version":"24056a75e8e602d911cea68b06b5e238604aff92d30ec8a119a2ecf07568d4fb","impliedFormat":1},{"version":"bc5fa245e7a3eb9216ce30106e37294a9691efd85391e3de61478c3ca0da360e","impliedFormat":1},{"version":"4523237b5a992a30850668522bb1719bab8f9e50c00b6428f660ca75a451a7b1","impliedFormat":1},{"version":"f116a1399a2583ff7ce15068f007e5c47d06c9964674bc48ea6e69867d0692a5","impliedFormat":1},{"version":"68cabe63e69d17160c77eeefafd83df10a4c0ec3353b6a91a48a205e9dd505ab","impliedFormat":1},{"version":"5a75e49d8e0a78e2cc02bd13fcab4f26d5d6729912e2096b6fe442b0960c0cf7","impliedFormat":1},{"version":"3f1c80ba487c318a1e4c03186fbae29fd76c8159e84d7db7ec07dbfaab2d3d58","impliedFormat":1},{"version":"a6390968657990e16f06624b29112be8efb6b6ef3e008b6dc7e604fec1120893","impliedFormat":1},{"version":"af009985990e75086edf8efe08fbd396366224537aaff80cbeac37f04b34ece6","impliedFormat":1},{"version":"07ab076e1d2663b27c7ea5e565bef05dd2106ee9be762237f7ed35482f5fc14c","impliedFormat":1},{"version":"007dfb1f314277f6e211fec9c5f62fd182e3bb76f1fe1f165228a259ae0b91b8","impliedFormat":1},{"version":"a6aa3bd9c165acb07db158897587581d7b081ce4271579b720a94f95c8c487d5","impliedFormat":1},{"version":"904714e49891cc1e136cf104f4bc9adfc846be9bd28ac55e101145a0d8103b30","impliedFormat":1},{"version":"3fede259ef5c9dd9a97e662da9f6774dbc82f390d29563319b658ebd7f958135","impliedFormat":1},{"version":"9b8ba907ff8c52756b1a0aeac192a22591ac9431ac688cddad8111c8fd5124a3","impliedFormat":1},{"version":"7aae89808421b5e7ff74ea48f715337fcd592e06eeb9850cf378b5141be6415c","impliedFormat":1},{"version":"b9c9c9352d6606fe440735ccad134563017fc5aff8dcd418c58f778437339f06","impliedFormat":1},{"version":"8577cc05a714f4c5a087dfd25bd1459aa4bf401a68e7edbf5c6ac96c0e298e7d","impliedFormat":1},{"version":"d09f6a6dab49823b554255030c4ee8d49a2a993bd02f2cff2e444b2627dffc5a","impliedFormat":1},{"version":"86f1fe35b16ed4282a226d77eff2ad2519500c566833a0c8cd65a780a3c161e1","impliedFormat":1},{"version":"c85b382e6517677e39b234142b1ce97c7672ae72a89d683a4e875692be3b854c","impliedFormat":1},{"version":"83015c82b1d847b367f773a217f1bbd9d9a2f6e205e3710830db89c67ca477e0","impliedFormat":1},{"version":"a62075dd9999f04f8e5fd1c3d675766f7641bb6dfa6596dbdf000617831c800a","impliedFormat":1},{"version":"0717c1a24cd66da2d50833ba78f89d994d1ebe494e0105ac67caa1e1a32a298d","impliedFormat":1},{"version":"d60b952dc30c239e7ed78756eae6b7d7585a2a0a457ac364f5325e6f9127bb80","impliedFormat":1},{"version":"7a932e7cd29555624035a2892b8636e8a61cc2a0b796df2c9bb4526a251bc30c","impliedFormat":1},{"version":"e3e20ed4715775989c0ee8c2be8e657503503ba75c03defe13b99dc317baf3e7","impliedFormat":1},{"version":"c2f1b0272966ba4ec45818b50813210e3abaa993664e26db5617df45672e49aa","impliedFormat":1},{"version":"6faca0f0e857cab15c7ec26f36dc28b73730b184ce942a25654bbcf4ece22f59","impliedFormat":1},{"version":"189ddd84047c597c0fb44c5b03ce5608b0d7d77b3df1a6dfd0f7ff5b82dd71e1","impliedFormat":1},{"version":"9a1cb3741e94561a56bb4b9360220cfa5d64f02c2d51e35f59e433612638ee77","impliedFormat":1},{"version":"743e3303fed6823026dba4b34833ee6b59779678fd7daf64e1e9049114016b1a","impliedFormat":1},{"version":"4664cabfb4158ffebcb583b60e6730dae651d15049ff610ee3ff609fe23249e3","impliedFormat":1},{"version":"d2f06037b2b81794c9159972ede786f5d2b0f77f5e809f5427d838c6dd004603","impliedFormat":1},{"version":"1d9d2dbc90a080f54021a9f8eddd6430a8b290659579a2549c38762fd6a4424c","impliedFormat":1},{"version":"4ddac3cdf6eb7dfbbfbdd004bf9e90d263c227888cda110a8bfaed500929c14f","impliedFormat":1},{"version":"cf4bdd9324f9116bf29daf9add3fefe4e609be0dc3bdba1759cf1a6654047726","impliedFormat":1},{"version":"48ff4dab14889a41f5b0b94aacb853b96f8778888167625a42ba7a45250a15b7","impliedFormat":1},{"version":"0b59bc43ab08b3bb00a8a4978683c872fe4c6c3206bc68316ff7a3cbe70d75b0","impliedFormat":1},{"version":"d3763a4abd763d825a766d636661ee3ec52fa8477eb63c243b8dcd033ba23789","impliedFormat":1},{"version":"f4377e81d50af3f689cc5dd2005be3b79dfbbcb3f5a0301c843e8daf1cc9ddda","impliedFormat":1},{"version":"ac1e8ae42e98e9a296d467169321f4cf8802643302f619b025117c4ed5a2d200","impliedFormat":1},{"version":"4cdbcd7e8e8a5beb593e726a2abc758d54efd4828048dce812b4c94fed24a62d","impliedFormat":1},{"version":"27c66f434db3a00fb5b286c88582f2da3a85a2108cdfafe9bf63fa6df206aa2a","impliedFormat":1},{"version":"e2ef2006aa0a9b806063cb510989bafad85e71f21cd7e25783b8876203594dc7","impliedFormat":1},{"version":"5683b6c327ab05195ba14856985488b486117687e3f1b94991e787b25fd6cbb0","impliedFormat":1},{"version":"32d08e56282b632a4ff2aabf97d8e2ca72c872e99453de231684f0347a46c41c","impliedFormat":1},{"version":"f26ba893d9cda649365c19c9929d53ba069d829caa98dea1ad3c90374704cf54","impliedFormat":1},{"version":"9eea04c6c43649983516ae586e2b40ea99b808552d3ddf8a0b7725a490c5914a","impliedFormat":1},{"version":"4179d52fc45e3c72cab28cedf19d10a915522d5f3f83979e61213137bfc794e9","impliedFormat":1},{"version":"3c628794e72068afb3d10eb8e7022f2e7e66594981edae5d24fbdbdc3a34d412","impliedFormat":1},{"version":"2748451f1cb5d1594fec48577685ef0cdefea02fea292873b9ab74aa47ff57ad","impliedFormat":1},{"version":"cece3e0e89f3e9a526ce76bf9bf3aab41bf83a58d625558a671f9058b5e822e6","impliedFormat":1},{"version":"8f7706493348b0f5960d778f804905e68bf7564bc037a9954cc71c18d419e562","impliedFormat":1},{"version":"dd1bb0047f911d2fa01662720bf5f8da6e9cb30db7b2909f3ac4fdcf0eec34db","impliedFormat":1},{"version":"4ab90837f0df1a6c8039689ea77d7d28a06eb1bbf2bc129c271e8a6c01a0f391","impliedFormat":1},{"version":"2c6fcafbedc3bf7e030fbda5acc875e0f2f98b253477105ef5cf0f674409b525","impliedFormat":1},{"version":"171f9f3da4589275b3ca1472e2ee0f32f4b16d5e2c41f79db8bb209433f30d67","impliedFormat":1},{"version":"e495c1011281c8900998e4001777acd8863d9c901410ef2ff2cc21174ef3af49","impliedFormat":1},{"version":"0d7db9b74a017be10aa36509dd2ae4499260381aabc6772feef677fa16f3a1f4","impliedFormat":1},{"version":"e59ef219cec3c3faab54d5cb12222a04d3e095c84abf94088920c1584832ce43","impliedFormat":1},{"version":"786c15fcfa8b821410e278a740f9dc81c44546259d1cc0143646876a0c030cc0","impliedFormat":1},{"version":"99ea681335aa97ba7618ac3db69a2e2da87da7faf8a39f822030ec4db96ca023","impliedFormat":1},{"version":"d7169a2b449d5b8e309edd84624649d04b746be48fe93b2e69bb7a85653b1e97","impliedFormat":1},{"version":"c462479720ea1932e5adc0bd4808be8ee2c83488be1012bf48f4bbb532b63758","impliedFormat":1},{"version":"d72479ce8210c21451cadef350179fbf3729c0e29005aca2d7e0c6ad031a4afa","impliedFormat":1},{"version":"d0e0354d3d4ac41cb7a67c10ca59652f8cba9eeb0929fcc878e492691f73d02a","impliedFormat":1},{"version":"fbe06770551602ccc8e240a24793a8268b1bce44de38c26a7710f7bf1702f9b5","impliedFormat":1},{"version":"e4859560e5d635efa084427db27d6e31780eb570c2a567e95ed12f3828199710","impliedFormat":1},{"version":"6f29c691b977d5fdebefbc109c896fa863e95ae4464d959cc1506f45ad01da8e","impliedFormat":1},{"version":"ddf805d002fbf463fe2e40e78a4c7d1773a62f18716ce452cc02ba185c6c9c0e","impliedFormat":1},{"version":"d7aeffb82f803488ad4f918929a3a980e387c64c395ea793f6167c9704d4502a","impliedFormat":1},{"version":"2ede90710bab4dcdef47b532a8b3a1d63b7c366b058e95c705e9d9634f29f445","impliedFormat":1},{"version":"887a73b0167b36d4aed6d2549b19c4bcc6f2f50248b20d4d10ee2a10ef0516e8","impliedFormat":1},{"version":"f86c2e22ce8546272f0c7fed4909cd0b3db99bb95e7d91f584340f2b158e0ba4","impliedFormat":1},{"version":"d1d43f6f1a6a766dabe2a6db17f737d2c0cdefd747fc52b70dcc4ee011d6ff85","impliedFormat":1},{"version":"62c9a85d5dc9da38e54f1d802b7b62b82170f3a4571e3c992f1db09f60dce051","impliedFormat":1},{"version":"56e14052acc507ace03e94e8ec6cc22c84a65db751f11ca20349a4ea396f72ab","impliedFormat":1},{"version":"1c7dde9d6e45e71504fd8ba6a9c29db164e7a8040bc1782c2a80a3098d0a86c8","impliedFormat":1},{"version":"916e966405a9923eef3123175b1d31188945917edc14027ebe5df1c1f4ba0c70","impliedFormat":1},{"version":"d742f86f826cd1d46f45cc6c106cf34077b10239da02393fc2b6a6490bb4059a","impliedFormat":1},{"version":"8c1fad24452b6f1cab8f02cdec02931524a31467c2602fa9b8c6e5683faa76e1","impliedFormat":1},{"version":"639e7fd024205c3c4af58bb193c1d7790618fcb8b70e9b15068c647ab729ee3a","impliedFormat":1},{"version":"2c26bbcb3898665e821d93f28d9c4b7d712ca23743d8a7a9d89e2aec794bdf40","impliedFormat":1},{"version":"c0e0fc040511ce5af4e546fabe949945c67507cf1f1bc7211448f2e6832bf0bc","impliedFormat":1},{"version":"867266698190564ef5cda597ea6378e766e9c22f65058c94ff8356d166d1f2d3","impliedFormat":1},{"version":"e6f70e3c94d2b1d7c5112ad6df2dd7c2ae5dc81bc89510bbdd4478614cf80594","impliedFormat":1},{"version":"146e5c86d78b4a7ff6dcaf9835b3a6a639dd414d21a30c69df5183bca5596d15","impliedFormat":1},{"version":"b01572aed7f01080dd28016c43cb1520978593992908450ea362cbfbb5fe556e","impliedFormat":1},{"version":"2e24d2d878e6b0e745d3814ccb2186520c6ffc6b3ee3facc329741c100ff42ae","impliedFormat":1},{"version":"0810966f2dcad79a429a4f156d3ec090c5de34fd70fe13a44141b8642bb42701","impliedFormat":1},{"version":"00b9f288c0a241fb4316737af41e0ff0e64be1c03c90640bc3a9f1449742ca9b","impliedFormat":1},{"version":"f392ed5b86fb56157e08a5fc1859506f8bb20f33a1a6d5922833e2c7a268a7e4","impliedFormat":1},{"version":"7f70f7d51c3232d6e7546bc8f9d6b91df3a9e001de4c755771dd052d9fbc9a07","impliedFormat":1},{"version":"175cdf7e9b2d7178e5b73a4f3dea1f02abe320f6585ee8a6c16991c92e4220e8","impliedFormat":1},{"version":"52580cbcf61e2707abe5d16ee3bd03ea8c22722fef2026c27ff8cb206523effa","impliedFormat":1},{"version":"c6c694fe37d60819f29e998c03d875609d07a2f3d2a280d096474823384bff70","impliedFormat":1},{"version":"1a176b3032ec0fab791c658844c3c1d3df8fbe985b194858c8b31d736781942a","impliedFormat":1},{"version":"82e5bb555d1f1b9344b367e2761eeca6609ff1bc69908d779660e0ddb1c192c3","impliedFormat":1},{"version":"b6892973f319a69aaf5e80a61ba5b42ddebc0d83b1f1ab7c25f09133fdf1cb7a","impliedFormat":1},{"version":"ea87e08b2a990ff767bcdc40e99eff30028d98af8d401f14b08974223c58c06a","impliedFormat":1},{"version":"389a2c2135dd3de1844b996d661ef3a5ffb978356994841fca0f0a99b1728e28","impliedFormat":1},{"version":"a582c8844a6809984a681db3997068d5d8144bee3f889c5240c559c5502c165a","impliedFormat":1},{"version":"e0494aecf0482850786831665c0f976125882c17084022efc6f8a51443b3a7f4","impliedFormat":1},{"version":"ede7ecc62da0236596749292448b282d9c5e846c95e107d6e87720204b792250","impliedFormat":1},{"version":"557981373fbd676739d62fb4aa7b601a639bfb39f7b563ab2c9a2350aa5d7298","impliedFormat":1},{"version":"078045f76bc547eeae562dde79c81e2565be6fecbdbbc4bfbd03fd16cfcad523","impliedFormat":1},{"version":"04783d0830346173973d5283d10b91fd7d6c1c0aaacd93a95455ddedaac4fc0d","impliedFormat":1},{"version":"6185cad87bf4da80c49a2f7a06af8e3e47eab0bfb31a9bf49520989b1b86056d","impliedFormat":1},{"version":"c002bfb107918122bba26d8d0736f293b22866dadc501f9ce27def3230233be5","impliedFormat":1},{"version":"131906682a56016d19849546fc5f9e0076b4e35bc2c5af362d79a50998215d4d","impliedFormat":1},{"version":"ee0c30ecd200ed26166dc9f9ca3f502e5584d61912f894563c7db45292b5833b","impliedFormat":1},{"version":"c47057eea375a394643d081d86ddfa621b3de1aa4072a41fde6731a07aa050b4","impliedFormat":1},{"version":"fa2d827d435777dbfc4a41a70d836b6a401bea8f77903cc22f939425f9da0b8b","impliedFormat":1},{"version":"8a59602dc83ec951feaf5cb7125393d3ebe38914c921e07ca0383a63857435d8","impliedFormat":1},{"version":"0654c77e8427f5125066d551e5f7c273735a92f4e7a2be6f12daf46ffa92ec3c","impliedFormat":1},{"version":"6f2a826f77810913e18a6a5ac87e5783f600961d4d7bc20315db13f69e2280de","impliedFormat":1},{"version":"14e3d141c66a44d32beff51678ba0abd236e18c520b12678a73936e78955cae2","impliedFormat":1},{"version":"bcc4218ae8d2f99608412f5917a663c7c764da0dd63be12d01ec49bf0148fe70","impliedFormat":1},{"version":"4136928c1cc5825cd17ecce5ae4a1671cf0047679e452d4886cfb33e74fed5c7","impliedFormat":1},{"version":"21f4388f6d904f8b0d17565fb331eb25d0f2af0704ed7d6247af4cc9631f7c67","impliedFormat":1},{"version":"546b944e81166843668e7b7a1153ccd1e565834ffc29e1df38aa6d26de9e1c81","impliedFormat":1},{"version":"8d7ea4d73e8d305820b9067f4167558a9d295d901a2d2891a8dd9de66590f931","impliedFormat":1},{"version":"f8d0e96fe8f2cbb5e617eec5f198ab78e13ba2c66176ad202b287aa3cc667e23","impliedFormat":1},{"version":"1375b2b59bde71a963ff2cb306eceea05060ded0b7cbcdaf1206e4e8245e605a","impliedFormat":1},{"version":"f5dcef5516ecd8836256359ed4b9c6bb8c73fcce697d1c343b11ee8e7fd15a8a","impliedFormat":1},{"version":"e55a68bbc963c9520f0492892d642fa145d34a351d483cd144a11e3346c18cfb","impliedFormat":1},{"version":"da14f80dc904a20fe5a98009f117d8f977ad6d50fdab685e75d6b38322ea56cb","impliedFormat":1},{"version":"ca90e5e191954b9b8c43ed5d5bc787107c071315c4acaae515e7d918e8814e15","impliedFormat":1},{"version":"8ef0c5c7cba59cbccd0ac5e17ec42dc4a8250cd267f9cdb08a4dcb1a099068ad","impliedFormat":1},{"version":"63ed74c721b55f614bef2b233b03c7e56377b0e38ea16f1dc3fc57a06ce2ca8e","impliedFormat":1},{"version":"c89dff0cb3845b6234ce201e2a2d8460d08dfdae2b5a5b137e17822b31188752","impliedFormat":1},{"version":"32fb4c22ffa9a118b115e2c3f65026a9819c0e093bf938ca96ba4ac10e1fecad","impliedFormat":1},{"version":"1f142b1a6a8b7b29da43a88c8a5f6bbad28f7cf1b67457596ab6d71bed584e8a","impliedFormat":1},{"version":"a203895f2d4b51c8799af4a17e6d72657c6dfdc4a08ab338970e257e5e083d85","impliedFormat":1},{"version":"c67a3535fe218dac271adc4d9c91cabbcf99d09081dc3fe3567e3a354bf632e2","impliedFormat":1},{"version":"7670372101b08f0d0a2a8cf4d107d969df407a74cba20e9f3991b50d9d3c590c","impliedFormat":1},{"version":"00e5569a05e32c005b18db36cf4e0fd477d8e98d58b82489e4c0abad95d5500f","impliedFormat":1},{"version":"fe831d90ec6b5e04075ae831936f1e2049cce2473ad1aecf3d5ee37d66ea84cc","impliedFormat":1},{"version":"93b5102a702eb62880ae6fb3be2eb6910694ccf77a2e9063eb5d94bd0b2b32b2","impliedFormat":1},{"version":"622ebbd7d12ba6519bd5dd3d23892ec1f79991a9b15d09b77d8c7dd1ac32b8a4","impliedFormat":1},{"version":"14d03fe0675db97e401cbdfe2144cff5c3a84dc23f05c21acf3dfd3668a13fc8","impliedFormat":1},{"version":"d0622e1a5d9ee2b4b8a1a6db2c0f02fc34f4f865d7ece6ec86800074210d2f4d","impliedFormat":1},{"version":"5300e082fe9398613c3b5a4975df67318951c46b4a033d159bbe082793ca2c3a","impliedFormat":1},{"version":"be05176f0f7347f4a9faed9a400c182f107b7499d79f4c6e67ec3d830ed6cde9","impliedFormat":1},{"version":"498b8e59b7659c0ce11ce3323bd0d23c923e21c7290e5bd96ce0f3ca639fb4fe","impliedFormat":1},{"version":"740bf9b794f8fcecb6c3761598372f16a7835dddb4c163a21ae0c7f472dc6bd3","impliedFormat":1},{"version":"12816e95a6bc1b4a98195c0e6747b33cfd178f0424579a3eb21b49911283f79a","impliedFormat":1},{"version":"ccc9e8f887951895386cafcff62aff2617397584ce48ca891646b901272b9d12","impliedFormat":1},{"version":"bffc26bac30d45f1e5fea885f17cafb6a943bcc21fd1122c71b9fe466ece8fdf","impliedFormat":1},{"version":"82ccbd00eeb8a81a8ee882c6dc8de591d2c174fd0bdc2cd8e9617f39d88eb52b","impliedFormat":1},{"version":"81580d0db97bc8f13bcf79cc7a97e9606cca948df6f0b26e3084d5db0a41089e","impliedFormat":1},{"version":"fd4ddb3d82b68edf2f7dd1b10ca66c5b108007c46067d0dfac4167a4492577cb","impliedFormat":1},{"version":"8c5414d8170f8fca7d8cdf74dba186370e35cc895c3e25f10ce42fff3ef9b49d","impliedFormat":1},{"version":"2caa4ad00b1f3ca5b07ff3d84beab2d9a4a8d841b677aa1546b78054a890a902","impliedFormat":1},{"version":"c96415ec4a5ff2202c8f5db2b8163a605100b6b47435c5b31d8280e06233958e","impliedFormat":1},{"version":"93b1c61409fbf44c4e666937c0cacb36d006b9901a53a2750e520f6ba9b1fcc2","impliedFormat":1},{"version":"981af6a24b8e1531dd933ff6df096a7a50dfd79f24c5e5be1134b684465a807d","impliedFormat":1},{"version":"d3b51ab522194f5ffd145f57fc2b2017e35d11593a8a5468fd3da7767dba0d57","impliedFormat":1},{"version":"85e1ca7719d73273b0b07356071e046f27c039441666504e6143600f0f5de5eb","impliedFormat":1},{"version":"14b5a5227655bff3a02231986be2a1ab4d2749584147c6f93ad6167d31d78fd8","impliedFormat":1},{"version":"f68e3a3eba1a531a71c8cb53bedafae2c25c376c147e3bc6ec96613a5de9dc84","impliedFormat":1},{"version":"8c3f672ca4179a0313a67aa8525384d1f7a3d7c692f4f39a3482d9997389381e","impliedFormat":1},{"version":"367ef08f1d0de5ec4d4786cb8a1b8a17abf395bb0c5f8d151ec10fb66a2ce50e","impliedFormat":1},{"version":"ede4a9299b475e71baffcfd20b9b5056f77b8da69e7c824692fa7601be181ce7","impliedFormat":1},{"version":"c92c476c4463a4a96da5ed77010afd4bfa94944e298359bbff940cdde33c5f16","impliedFormat":1},{"version":"a484890e7212977036ce5965e7ca7b49e53436a66906a29093f91d4e02260fdf","impliedFormat":1},{"version":"4ea2003d86a9c68928ef069ce548c3e6ae35cbcb34184a71f1c566dde2160cf8","impliedFormat":1},{"version":"f727d3e75bfc036625d6920c725a3e4cbc564eef78f47d6b68c6351bb480d799","impliedFormat":1},{"version":"a87fcc9011e8a5e244d6e9af4902c315670aa852fa75dc82ae7cb62f98233a1a","impliedFormat":1},{"version":"dc7f110b06cd26a6153d026c7ce8414fb2d20815a20c840bb12143436458babc","impliedFormat":1},{"version":"90afaa269677aeb839cc0e7479e0c3152248e4c8b440954b66a0e13fff08d64b","impliedFormat":1},{"version":"e97434f04631c027264a37897935d5686cbb53547128043f8ce9df36a62f8456","impliedFormat":1},{"version":"49d38dec73850de29da6e77ac4636b7195d18ef7c7695851a2f2fe9fca859323","impliedFormat":1},{"version":"33e41623f36fd2a950c40acb481d938d186a85436eeca076e27a1bf799945148","impliedFormat":1},{"version":"b76dfd57ce16b5cce7602c59827c01d7c6a7e9bf1f46531f90b4f35e7aeee19e","impliedFormat":1},{"version":"16a13b6507929a211bb65cbaba39a42943c034c7cff58bc9fa326a2dc9be3d93","impliedFormat":1},{"version":"88f173385e44e0ee39ff2b1e2313df7c07c17932d51da40d6ad3a518957b80af","impliedFormat":1},{"version":"38ce3311fee1438e32f767e068dd496dd923afaf32816f1d4e521a3eeed59603","impliedFormat":1},{"version":"278c4281561f930857b40f04b092fc2a5649076ee00ecb6c1cb9d4abed3ad239","impliedFormat":1},{"version":"6d1f9b3f050467c2cc5292d2762b0ede9d605fcfff152210426da2eba607e1af","impliedFormat":1},{"version":"8f8c6a79e620f8a63952de19f38927f7da119cd0a5408d7289532f68b8017d98","impliedFormat":1},{"version":"bdf518ed49e9ad6926ecaee24a183828a23a061a1dfac8788cfc09da02a0bf91","impliedFormat":1},{"version":"c83ae875a44933a76a37949bc96569a414f5fd74f4089edcb4caad0db6bd7e6c","impliedFormat":1},{"version":"69870c54caf722bc568fd348b5e813500e964d820c7482bdb82d94d5aa6f19ed","impliedFormat":1},{"version":"504ffacc3312189dad74385206715390bd98e424aff384f67b21331bd16cf7e3","impliedFormat":1},{"version":"1870eb1fe1a14d19041559a003bb79753347b6da6d87703548b6b20faef30e6e","impliedFormat":1},{"version":"016f83e01163cc23543489f52d53fd235730f2c754d26ea0891f66d3e57b9985","impliedFormat":1},{"version":"58ed0a6574485bcf18d4d775084258ed49f7b92ac9f8735488d19ab14bc6db88","impliedFormat":1},{"version":"02aeaa95c9b6125f8b6e5bcc16fc6df7d8f2bf945801defb73e1c13e1fe57c51","impliedFormat":1},{"version":"0bc153f11f30e6fb856a2a6c50970d386aaf7daa93ac106cd70920a1cb81841e","impliedFormat":1},{"version":"fe995eb8b806358aebf1e963824ea181b2fa9cc52e2dc4022eec67730b742753","impliedFormat":1},{"version":"52db5fc6d8fa0809b2110d96434a06ad26776677e825a10f93fe133497f6c93b","impliedFormat":1},{"version":"d9411ee7bb83d2304f0fced054eef996c5fbc2dfee2936c42c8696f0ce1b5b51","impliedFormat":1},{"version":"73ce7d983d2ee14698eb90ef369807a03a1be94170ee2461ebfd3db4c6329e4e","impliedFormat":1},{"version":"204ef1918267feb2040caad874caebd9bbf4f018367517750eeae16d880b0698","impliedFormat":1},{"version":"f6e8311e83274671b80860cb83c1c6393971d596200c4fc504ac7dd3ffa50340","impliedFormat":1},{"version":"c4117a326ced8cc18ed60273de14f4c5e78a53cf2c59092f6278a8afca8d9ced","impliedFormat":1},{"version":"34787d4cfe21491065b9e8c3038a66c78747dc97b171b1201ff3913f2181e5c8","impliedFormat":1},{"version":"fe4c08b22b011d68b3625c665cc302f77bb8aed4b35853a53e3efaf082bc8e83","impliedFormat":1},{"version":"7caae0b58bdfbedfbdd1a2f5b41779a08cbf62d62f7be63cd70cc71fb97165a0","impliedFormat":1},{"version":"b611b2a0b82dc6e520bc8c6698c0bf4481aba89c4923450f0753c062e4754c7e","impliedFormat":1},{"version":"d0272598cf5b05948b01aa2fda2b2cd190561897909bbbad709b51454f8d2e10","impliedFormat":1},{"version":"dcbc3cecf73f68c9d63280f3c9747bc6140b1eb9d8b5e5f04de58ea67c564a70","impliedFormat":1},{"version":"57f6aaa7e079189a64c2b15909cc89aa4a6f54c81b185108e906deeffdee1516","impliedFormat":1},{"version":"7b86682a3abdade9ceed5cfb5503097496223b93fc257de6795c4736efa841c1","impliedFormat":1},{"version":"94fc87a2a7387d958dbaaa392225a533bfce92f6daff79d9e11e921884b5590d","impliedFormat":1},{"version":"f41d35d2248604bbb6ea7dc64a2e024926ccc00beed30e3d2f356589bcc89a7c","impliedFormat":1},{"version":"07afa56980800740ec44e0b2e08d37d31c3ba1bcff58417ab7c26478bc37e4ac","impliedFormat":1},{"version":"960fc68443fe84caffb6f06af4589cd11e05dc89835c3b56d809ba46c893b6f6","impliedFormat":1},{"version":"02b6175908b56ca273252e8f734cde6cbc88c298384f4b397e63e41240184dc9","impliedFormat":1},{"version":"59fdde76b9d1518ee3a6711b14dc0b7582b7f9cf702c0cb8acc0bda3aef9e1bd","impliedFormat":1},{"version":"6b3ab19355f7f6208c5c5372216d03ce67076fa8f537e94757a074ea21d70102","impliedFormat":1},{"version":"bab0c52d8ab84e578191ac559b70f9bff9e763ff42b5a0f7ace8d134785a689d","impliedFormat":1},{"version":"d570e59bb706b1f442c1c7f12f252a215fff1ed867c72275b525abcbba6b5b86","impliedFormat":1},{"version":"50dc335fb38fa5b552b6377833c1a77d4f406c4c344589bea29d4661ae8e1810","impliedFormat":1},{"version":"0a20f875729ca5de76aa486ba9cbb1913e349ae2d7d1c2e1ad3b45e142ca815d","impliedFormat":1},{"version":"477b09f880a9f9364b68fe02e237f3779fbffb0761bfbc3f77fa895ca49c44ce","impliedFormat":1},{"version":"d85a0edc67a11fa750331746b55fd5af4b41f1bd11e550ff7090abc9e9f83ebc","impliedFormat":1},{"version":"666732d3b18e0ae093bc48e5cd08380a7fcc64c06b7d8d0b4899567c5de7f5cb","impliedFormat":1},{"version":"be789dbab62f36a20dcb50cf0e67d0ef6b3e3cac17bc0aa9bb30bbe51756ea63","impliedFormat":1},{"version":"20a6b98adf98f5f826f2d2c2738599837586e458b7ed5eb4a1494f7caf00d22d","impliedFormat":1},{"version":"501bc80db30be62bdbaa3640c7416df62990977fa403178f88812188c7e1ad26","impliedFormat":1},{"version":"d1658de6ff4ccce2e9cfd8b11722a6279bd3524644d0b65e3e8fc6b69b5ca49a","impliedFormat":1},{"version":"e5757819ad8a9ec2fd62d5157afd552ae95841039f1e9bba119dd26692dec64a","impliedFormat":1},{"version":"4091c43b763549c33d662afe79d75c078622bef954d4a473eca6aef8c251c169","impliedFormat":1},{"version":"d5e3f1268d795416b81ad2cae0b15b77147878bc672cdeb19ff5dd77272da017","impliedFormat":1},{"version":"43e510c8d059b40ce5e441a909a85f019ad8812890a8f936370a629752db69b4","impliedFormat":1},{"version":"5990d3194dafd93fc7a9e51032d11a57756c31fdcd88fac3b9be08af303972c5","impliedFormat":1},{"version":"987562ea1c31f04677cd3b46cbd4cdc6363f6178dbfd4db2a0788fe22947b8a5","impliedFormat":1},{"version":"0de5e8597a103c005b774f8892352a5f123a5e272924fe967b7d82305113bc4d","impliedFormat":1},{"version":"16185bd9e115626e25bca46fb8238f9ef3706c22b62ce940ae66c4e4cfde0df9","impliedFormat":1},{"version":"5711b07fe1b6426486276dd67efdee7ec4e70bcfdcaf39c6626594bbd7d51c34","impliedFormat":1},{"version":"7f81c91c6febbd59728630098f6f2b1e4afeba6af9128645634520d5681096a1","impliedFormat":1},{"version":"269296ab0ca6cc30fad3ccb911b1ff589d4a2c6ea7077c26c7ea5fe650103d6e","impliedFormat":1},{"version":"a49ef7664e1afe51062e193f0008ed621d8a3af547d994123ca44dbbb68c75a2","impliedFormat":1},{"version":"165ee417439a725fbd0a04278830c1056354556188d6000e5dc8ecd12cd3cb10","impliedFormat":1},{"version":"9539893a03d2cf718e8c38adf1a845ec0183ab455c8b257c64cd6727f57b0e1c","impliedFormat":1},{"version":"5e0f0b5968cb81b81847619fb6643f364d0eeb630e575fd0029d22c1171b3a37","impliedFormat":1},{"version":"45fb63c6d3a608b091c3baaaafe97de027a061e2f10813aa97d003b654417ed9","impliedFormat":1},{"version":"9a1bce80c36643bbc3e66c7db014c849b81a1d2d3ebfa69000f03e64545566a0","impliedFormat":1},{"version":"f438823b9ca13c413beaee87829111be171b305995bcf71d67ddd941de6dd999","impliedFormat":1},{"version":"623e7ec6876645a7e93a1a67506f3852b8e5e79ba3cb4c9a90ff8a24d3377a12","impliedFormat":1},{"version":"0ddba574bf51b1e47c502caa07ff96528b0c49878c2521ceb322a94557a824ee","impliedFormat":1},{"version":"3111b876a50a391cac841049c1683d20bf7d83eb05d5ff10b0a49689ca0dc49c","impliedFormat":1},{"version":"de84187571b3fb57d7d47f3199fe75845d024fa2c4aeb0a8bca8a281e37e9b62","impliedFormat":1},{"version":"4e302b950595396f49e539c733b44c52b77a9d3b85cc7c6fd24fcc7df1e30031","impliedFormat":1},{"version":"668eb6f044ef3e07635b3da9b29413de381299f80fdeb90e3ba5bea910d9d588","impliedFormat":1},{"version":"f75b6da37adf4f4fcb1b3e6e30099d345bfcfcc2024dc304bf6eaf40ed477c5a","impliedFormat":1},{"version":"39701d3533318e98924f5e5a4fb0ea5b49527853ae63e78e26190955c1ba4d62","impliedFormat":1},{"version":"30cb04bc8d380ecb7053659c2b42b48f87ffd05af3abe9f7b4783e07777a8d96","impliedFormat":1},{"version":"96847849b0b8472d06b023c7f6fd630cb5cb3e6129bf16c6ce58a931084c1d04","impliedFormat":1},{"version":"f15bb0a6bb20f0a494969d93f68c02a8e8076717fe7dcda6db06ab9e31041c22","impliedFormat":1},{"version":"db9d0b3c71348adf62b4c2eebd0bc872b0b3895ee6285980463f6acfe7aa36e6","impliedFormat":1},{"version":"58b8d98c9e39b0a1bab10c9a19a61d9fcac111aba5a6ff47e86525c079ddcbbb","impliedFormat":1},{"version":"a69abca4388cc76962773b4c869d5d34781cf0be92853d7bec53eac7a2f75c60","impliedFormat":1},{"version":"471b5d5986eff907c7f4b7047b54c15648495f94e219a27fd8cc91f35fa0e970","impliedFormat":1},{"version":"75cc2a2e33c7d3fe1574d9c93712950b5556dd4af48a1d1e5a657c66ff2eedf9","impliedFormat":1},{"version":"05c44f2a752cfbef15a81e90bc63eb96efcd3d07dd9b378df5a150a06775a2fb","impliedFormat":1},{"version":"9699ff431424e42dfeeb6417ea7b4d1ed66fc6bfc530748dfedebd2683fcc1b6","impliedFormat":1},{"version":"496197b06b51aeae8323da87d042ed2224e654994a3d9b5e3350df9c9576dc50","impliedFormat":1},{"version":"93521d40a9636980e32574e7419b975fb1b400644eea349bd64f76ee808749bc","impliedFormat":1},{"version":"86b7e0f835e2d550541c27e03abf5270a42f5876e1e915568289142b317a0ffd","impliedFormat":1},{"version":"ac6990a9034baddaf28cb15200bd2f0a46efb118d08f4d341abc16669ad577a1","impliedFormat":1},{"version":"29faa0f1ab122161019ca07b328664d62b5b1ec742606fa5b34851603a49a77c","impliedFormat":1},{"version":"80623c074b076a1c98719ebf8e882e9c977ff9c040444c825bf9427f0f21d420","impliedFormat":1},{"version":"52cb5d5beedcff01d5b851653cfdbe9a8e8e953a8462a357e71d93eee3ed760b","impliedFormat":1},{"version":"ba6d810e67aef7d6ed15cdd8223d5a207a111077c88d99ce7af5fe959a079803","impliedFormat":1},{"version":"3e02766c76edcd0486eeecad81ca4982a532a80293d71a8d94973e89feb5be2b","impliedFormat":1},{"version":"96bb9f13a0f42ba0f9e458a10be3db0bbb52e7498b8ef49ab90c404f3e5f735a","impliedFormat":1},{"version":"6f322a0ec0f5782396e21068158629f5b1ba084f722459a4ced24252ee1eb0ba","impliedFormat":1},{"version":"13e4ce5de72a42cf67e6af9a96132e428696d8054548580e68f8f376d114a459","impliedFormat":1},{"version":"1b4262a15a86e72e78d7fdbb6a6d20e8794f7fa4aa7c54f0b18ac7270e4fab08","impliedFormat":1},{"version":"9334b283bedfcd488ccb33b3e942905c86fa163e919653a5379eb8f28a2d5f7d","impliedFormat":1},{"version":"f3f62eb4cf38d86cc7f56d0879b49656a21f2eef4fd0acef3936889327d7f256","impliedFormat":1},{"version":"e32c5cb1819686336a2101f31b91c2e8e06f8f8311abd1195c203b81b62247b0","impliedFormat":1},{"version":"683734687779547527b05fdcef60947f6fc51758185d788531e9ac7bde84fd6f","impliedFormat":1},{"version":"c418f31663f9aa18537f6443172821265c078de18427ff136a24c536e76b7fc4","impliedFormat":1},{"version":"dc14049ed7aab615142091af18c8033550203d91c18c5ad2101f891b877cf265","impliedFormat":1},{"version":"1df375435c44c94f1bce343de4ff81b8c82e644d6b33a801bc6cf4beceb76b71","impliedFormat":1},{"version":"fed5b5c20508c5f84a929161f452dbf769cc2d2ee1371b94ddc2feb418a0cf70","impliedFormat":1},{"version":"76755db046290dad61362d95c03b440a0feaf507edfb5744304c7f98c81faccc","impliedFormat":1},{"version":"e16841ad044e21c48c6065627566a2ac216e067cc34b9ad3b47312d208d9a262","impliedFormat":1},{"version":"7150b4a18287da2e25c68a12bd0cff78f6141a2425a27431a10cd4a91cb9626b","impliedFormat":1},{"version":"214a581fbe6902059a64de2bd75c56b6030c6388c29de93c4296380a99c04e4a","impliedFormat":1},{"version":"78b758d401e53f5319bc143ebdc7714ebe0f1e94fc3906d5e93816e5736bf299","impliedFormat":1},{"version":"ce50872ae30242ed1ce2ddb9d9226c85f17098e901bc456cfc365887ab553127","impliedFormat":1},{"version":"cae86d70eabc661dff2f46f34018ff4840228f01709c8399a9c012711dfe5292","impliedFormat":1},{"version":"77b463688f41048f449fa30b45393b81fd6dfe3eb71f7734c1a6d580373b6a12","impliedFormat":1},{"version":"b6ccce9156aa85ca2e836bc572d4697800739ab008b0a6ae9bfa0361b8baa04c","impliedFormat":1},{"version":"07dcca6e9f155b79d087216735842ab1f7c020ce41f095507afdffecbac06a03","impliedFormat":1},{"version":"1fab3bc9db401033ed6ef6dca9114b3a0a875b475b6c1b2ce52efddf3c4fa130","impliedFormat":1},{"version":"269b37626ed3fc5d6aff2b3103bfecdb86ab69e5fe28933b63a17ac83a547ede","impliedFormat":1},{"version":"1ef3cc7b03643e330cf9bcaeb42257a19f573bfafdaf51e2e45e52c19e20c3ff","impliedFormat":1},{"version":"e05f14953944c6b7f9c8a51c5739cad11e7ea4e441fd5659cbc3a5ebdc28bcfb","impliedFormat":1},{"version":"98fe9a0d3adc98c4aadc97a5bcb8c9589525e16e82e6714333e0315d1ff40a12","impliedFormat":1},{"version":"941c51312144ba38e2d86c081d212bc1f22f64eeb1dc342a1c7aeaaece7a7770","impliedFormat":1},{"version":"8d204669e89ac66eb2fa93e17daf42dc9fa33b3d865158327819df72f4fa3f1f","impliedFormat":1},{"version":"4f66c595621f6dd5c693d12c122def1c9eac9c48ace86deeb7c1a0fe54d63c61","impliedFormat":1},{"version":"6b26f80f079695a24ca28f6b19bb074ddb70cd79bc837ae8437e54ac8727aa14","impliedFormat":1},{"version":"1686e8b2a3bca066aafbb9bea2ac249e7205af7e6b878955741c66b3a4eaba63","impliedFormat":1},{"version":"f974c4abba2e7ae62cc358c6c1589df489406ef517a48355cbcc5f09cf11d8a8","impliedFormat":1},{"version":"949ab063079fbbcbf8a96c093b9cc465f83fd2ce49f4558492d6f95065cb201d","impliedFormat":1},{"version":"2d1c8bc1708e58c9aa73d71f89dc69d45fd00ed42841d022bbffa467c88464f4","impliedFormat":1},{"version":"55c3e286e757f731c3b80c1e6d4a567bcc6d5d512438016240e7da573a554dc3","impliedFormat":1},{"version":"33cb723eea3ced280f163fa717045e233b801081a64509d4d59b47620fde9ef5","impliedFormat":1},{"version":"8c357660e14e4ae047c44211f7d024d48eacf3d5ad6ac805095a436a4d3e268c","impliedFormat":1},{"version":"e67731d353b0f48ec4c7b1cee2358e2b7b6ea56c86775f2f3c07029b73b8bf06","impliedFormat":1},{"version":"e2eccdc38e22cc3882939c7fca91570a8379112c03f6206986e0bd78afeed21c","impliedFormat":1},{"version":"58a60f1ff614a331f5de62b4a629b5f41066430f7b72f65ec27f0cf841403c9e","impliedFormat":1},{"version":"bade739298ee5cd485966b3f2812cd94ed23be0bd8991624bde84db9e41e4240","impliedFormat":1},{"version":"4289204445b85c740954797654b504406befd2168731ec18efffb3ea22674a5c","impliedFormat":1},{"version":"e8ac4073fe7b469e55e1fc7b1540363d5a99b507839135fc97cfe5f2d0e36595","impliedFormat":1},{"version":"0f45169be3f2e0eb418bb1d5d480aa8fca7375af0b6e51dfccc3afbf77d9ef12","impliedFormat":1},{"version":"25699fd6154aa1d8ad42dd7739ebe65e15277c0f44d15ce6826cc43bde4ea5bf","impliedFormat":1},{"version":"d4fabc6a3e3110ed60c84e9ec6712265afe268601f3462198b57aa4359745c33","impliedFormat":1},{"version":"802353808bbaf39f8ce455fc7c459d39f13a2fefcf6f18a78c9ea0c61be089eb","impliedFormat":1},{"version":"a057b62631a72f836a8faa37332f03324b9610bf1bd7781fd6f93be063cd10f5","impliedFormat":1},{"version":"76c5f9421476e8762a83f970028b5b7e9ac13fade254d40c04c188f87be8fd7b","impliedFormat":1},{"version":"6378e4cad97066c62bf7bdd7fb6e2310f6a43cdf7aba950a2d37b4b0772c0554","impliedFormat":1},{"version":"3b6fddf2afbdf36f7bb869ccdeaffac8d53759e527e3425a6b8df4dca616d1fd","impliedFormat":1},{"version":"e88588861f78985ee212de6a72e45b445e5e04286b4ce1eb1d28d72bb781e269","impliedFormat":1},{"version":"22b9f52673fc11b687471594d6080d4319999e4d98903679a4ba94d24b056426","impliedFormat":1},{"version":"3d594041401ac69433c4a2ee492d356db4706adddd4f8201e7e5f542e58173b2","impliedFormat":1},{"version":"806aa43416ea1f5265e1cf94168fd4902348762aa8114dc53c131cff9f87b5ec","impliedFormat":1},{"version":"f27757e22127417f5daddd0ad4be81d5a743c95576d8c957ce39ef02a6cc1ec0","impliedFormat":1},{"version":"383679ac9fe44ffb52057dc5ad7ee2e4a90a3f4abbe9a1cf186d9a2cee617965","impliedFormat":1},{"version":"bb589593cea8974cbf3359b720e5dabba7deb6ac8b72e30539a9485d3c697640","impliedFormat":1},"4027f95da96ee828242662df11ef7a436ca3bb5c7f49595e0956e684b590d590","91a01d034eb89ea508e0bec53cbac02d31b4405b97334903b19dfd8bb9d4043f","2c9b6b6c7586e02554672d116a92987b4933d7660915a1d48b0b04ae9f0f0627",{"version":"989111eb66967e9017480d031aa26386144c1a0e4a50068bd4431ae0b127fe98","signature":"c14cab1d6812cbb262fdcecbe27c7e78fbf3c1d2d06a7cc79015b50aa1d1e7e7"},{"version":"2b34e02c3f543046fe56aaecc34e570aaf7bddf91cbd44a7438f7b23a05e86b0","signature":"2a9257b5e693039288d5ab8ca33d9525115cfa0ef3409fc6568363f91e5b3fdc"},{"version":"f634e4c7d5cdba8e092d98098033b311c8ef304038d815c63ffdb9f78f3f7bb7","impliedFormat":1},{"version":"7d39b1b948763490989e8fef8d1b62bd421eb267a2aa1972cce93becd4cb83a1","signature":"307df0ad556401dcba21816591d783fea51383ac0c9691a763001b3d781345b0"},"63ed8b7093bbebe9623fb503ce30a9b81888776ebba3733bd59df4709fd0cb9c",{"version":"a9f672caa1c5631a744b05f69c28b4cfdbcb35e16112b2596ad88c90d1491e90","impliedFormat":1},{"version":"8d36f5b65e38d64c7370a80cdd26d2b0eea3b200c90b4b1fa5b594de262b5adf","impliedFormat":1},{"version":"2d5094424c7e06500d51088d6182e1324704010c54e4df440cf687da6d196ca1","impliedFormat":1},{"version":"69333b916a0a4329de4fed1191ec176b476bf419d5c56b3d66c2736ce1e6a4de","impliedFormat":1},{"version":"a955a5652fac7e3f6adc1ad7f4c22774e08251f06091779d48db944c32d54b9c","impliedFormat":1},{"version":"701dd298edaaba85d9c71a940f956a7699b4254084adbe03dfbdb6ffcc611411","impliedFormat":1},{"version":"15eee289dbd1369243ce767502b3d48bbdf50638249df90555c0f02f5b2107b6","impliedFormat":1},{"version":"633f7c4ebb6f3a3ab186b8ad44af6b7a41355b19e4125bd378899a50ba5991e7","impliedFormat":1},{"version":"879ae3f8aafd8671ad855cdbac60f061a0f419ef81612a795019c920cca5208a","impliedFormat":1},{"version":"8b3449c5b0bcc0f9b82cfd611179453444576ddc31ecfa0df32b94bba23c7962","impliedFormat":1},{"version":"28f13eae6f1c2e2c0b09b3a5899695881f586050cdc5e26ea70b84d53e245c53","impliedFormat":1},{"version":"eeb3eeaf375fc738138043ecc239471c0d4c1798e5426dadda6a370a6e430313","impliedFormat":1},{"version":"030915a009d241680518f74a8bde60a8fb05f9a33e3974ef7661c55377936108","impliedFormat":1},{"version":"53ae98cb8a690dcb13ff08468cd532817ceec23301cd2fbd1638a4509c75fb5a","impliedFormat":1},{"version":"284b8250a6fdaf36c9f789e211a420bd417873997c3347dfbc999ac9b9c4617c","impliedFormat":1},{"version":"5d303981e2efe7b75e303b9ba0b149f7dc52b60a716a37366d15c0ee7e06d71c","impliedFormat":1},{"version":"66f11f0455e2ddcd1d861ccb6222c9287ccdf5a4f775288ba4e84588c9f6e7d4","impliedFormat":1},{"version":"566d39c79490d7d3c0edf99528a27ddbc190a43187de9c6903c539310dc32876","impliedFormat":1},{"version":"f6d629d05333c4f6097d2e8d43622930677cfaa0d04451c19d149da012fb024e","impliedFormat":1},{"version":"8d1722eddb71400b416698dc4a4faf61d38f3c5fb191412b487877c12f92f5ce","impliedFormat":1},{"version":"37ff372218ab7f5fe97a3ea0d889aa22a9cf856f49f3c071b285bb57f61126a4","impliedFormat":1},{"version":"0697562c198ad4887ee0c6ba87c81674415bf08622c38761a35ce284f79000a6","impliedFormat":1},{"version":"ec298fb58b43841e59e9cf74e5c4da1b28211549a111361d1b814b6cf9846ba3","impliedFormat":1},{"version":"f6af127f8f33c31698e4162dc44e27faa32213c8029b01a75ec8d337e8a29d98","impliedFormat":1},{"version":"662269c944387f90669922e4e222e555331a46acd614aeebbcedf9af482099cc","impliedFormat":1},{"version":"0f35e2280558d1c601e89935071c14fec921768dd5c63eb14f975646b3d3d4ae","impliedFormat":1},{"version":"b29fca8647befa819e15522effef648208d240212705b5eea931107f252c2cd4","impliedFormat":1},{"version":"e9835d32adf989d3dadb2b3d230fadd47dddf3e10bfcfe037bdea59364da7744","impliedFormat":1},{"version":"90efedb2afa77beb63a1df83ab098109e796e08538e8157840c0b50e1da81a09","impliedFormat":1},{"version":"a08c515e2136d708b0cc25bf46888c7c87ca2b03235dcfd4ee98fc8af36f9c8a","impliedFormat":1},{"version":"2292b8ede5c530d2c30f5a6ea14b455612b85eaf7c817da5bf79daa245068041","impliedFormat":1},{"version":"43d44e19586630e0bb099d7aa2a69ee4165fa0287df3efceb032e3673c430b69","impliedFormat":1},{"version":"b35953238d81971bf17b838d6999a43220c7ef6e6f439683df50b57dcfc8256a","impliedFormat":1},{"version":"212bf5658e5e9a5c2339c6c4ed1a9b26048de14f21869e2df1bb7edcd730c54d","impliedFormat":1},{"version":"54de542e1f492d0b9df28493e771f7967c46d0285024f053ac6d81b8e24c05cb","impliedFormat":1},{"version":"a5b04b41838cd784ac841c351ae2c626a45a4d6b7981f805f41c0f332f632e0b","impliedFormat":1},{"version":"cb11accd47db05613ce31bcf360fe9357c25df8d50c3a7f0e953b7569ea4bee5","impliedFormat":1},{"version":"17810264cbbdc018764b9cbd0125892d47245d818d595ec94ddf23079bfeb732","impliedFormat":1},{"version":"04b32b104bf086362811496726a9a761a93ef1051e56107582433eeabb05216c","impliedFormat":1},{"version":"2d2c3ff10f8825d2a7120cb43addefb64111be064e35d270f662cde6ad1c8d5c","impliedFormat":1},{"version":"39daad2e3dbbf64841ded29036190c147051f44120169973c176cb1a2035ade5","impliedFormat":1},{"version":"89aff3abdf4a99430d0e8e90c51ee4ca7c63aa5add8c159f922f7e7e7864ca55","impliedFormat":1},{"version":"ee1c930e3da09a2296ed5518b4ee1538e9788ac34b0a60ac33e0a0a2badd76e3","impliedFormat":1},{"version":"9349ef8829763a15785c41e115eb77440570effcaff9b9482c1e6178c8c6f368","impliedFormat":1},{"version":"0dc5d4688e48ae8b598ece94a900885da2eaadff5c80e68afaf30264e421cce9","impliedFormat":1},{"version":"f5b3ebeb467837dd6593e4fe8f1de9b7598fb23981e02b32b7e72b81c04164da","impliedFormat":1},{"version":"68a75a201a5d1322df462c133020e5c639809c94a6698e3cc46363e56c174b30","impliedFormat":1},{"version":"265a4739974854eb43539419a6c86faab7e161b1133496c62f8bf2725542244d","impliedFormat":1},{"version":"a1accfaac01020c1b866634f7a698fdd48612caccf305e16844665cb7ecac399","impliedFormat":1},{"version":"ec00441ae4838b8d595acfe3b2750750e4335802b06ba1f41fb03453c2c776b5","impliedFormat":1},{"version":"ac1689d264991e5f58deb5a82ee44940f091a709b8ca815b38d5a7cb1305ce9f","impliedFormat":1},{"version":"8dca1366d02c160f39732f1a9ff2a882489903cd034e9c9c3f0ebfe9fa90f7ae","impliedFormat":1},{"version":"c548226db013facd262a4bc1c32c44a13eda7e1181aa6f569f9bdd531c95b0d5","impliedFormat":1},{"version":"37db669ef9a2ff2244d8e13aa8df9237fe3135c24facf0d62e7751fd49832386","impliedFormat":1},{"version":"543f461070fbd4b33bd05a5ba3e472e1297bb1db3c3101092bd69bfdddd3b1a1","impliedFormat":1},{"version":"929540ba3980906ac3f38e8567233028233c1c7e4d8921c1ce19604357028600","impliedFormat":1},{"version":"de5512f2a4c42776474808db1a6a8f12374be84392eeb649ad306330df41d0b3","impliedFormat":1},{"version":"7e96277aa5d7be6cddfdb78db26d986e00308e63f0202fb0d9fa39c826597dd4","impliedFormat":1},{"version":"3745762b83e5d49983a4183821125e3417473f992c4bf1d6dd6cea91efb4166f","impliedFormat":1},{"version":"ade458e350eda79fa74ecb678d9c51cc17f592d56df3e47286ef28e71401a989","impliedFormat":1},{"version":"695d23d7fb1f989d4d385001d8d8029f2f1a65dd91b4e47078e2586b8cdc4999","impliedFormat":1},{"version":"d73236e868cf6537240359fc4bea5733728567444ec7d2768e78ccc06ef22088","impliedFormat":1},{"version":"279c2ed4f57d90587de8e8dbadcb58b2ce2a0f6f7466ca07de24ad2cd50b6d12","impliedFormat":1},{"version":"02a711dc0da3eb73b8fae269ea1603cceaf395a7288429fdd724986974fa0ffa","impliedFormat":1},{"version":"3efbe9af669321ca845f2f793365271c17a6951833bebc1514b13fe76304e38a","impliedFormat":1},{"version":"caebb18abe3f02c23f8a16a2ee40ca5e26ac77f952cb15c660ff653cbad52144","impliedFormat":1},{"version":"49bddd70b375e6ba2b0f6e8dca81608dff0e9496dc28a87b79a622b8d1d4b41f","impliedFormat":1},{"version":"03058b0e31009f12edbb0af873512db9b736136132f2b8189241a8a797e0f3d9","impliedFormat":1},{"version":"4359e8ba73374bb7d25c0d4181c4e9f9fd6174569897788596feac600ec69639","impliedFormat":1},{"version":"2b31eaeb5ecf87fb46dc532da7b187a6711eb13bd58791d0470eb8ff16281991","impliedFormat":1},{"version":"c5f5bb7ae116bc0b2a68bf4f7578614df3144cb59a3af1e335e4bda1544ecbea","impliedFormat":1},{"version":"155fee3b5d1895a134c42d13aef2b6f2a951a177ebd33172aa456a90656dbff8","impliedFormat":1},{"version":"b21366779c846ce32d31e2af08d40f9a37961e4dfb7a20c16c37fe752047db5d","impliedFormat":1},{"version":"4130c2c57580e214060025c2df1460313ba070d3d6906c957755f10fc3b23ae0","impliedFormat":1},{"version":"5c56d077a2581c84910c8f9f0fad30ae45b2ca0a8cd78c7cf49ef6fe969bb809","impliedFormat":1},{"version":"0d81a9fdbcbe694d70175a1848a8be1c9281810a19d9c61ae197364149e4a8c0","impliedFormat":1},{"version":"b9be2374e2e97e580e0b08b41da0b8f4d6ebb743208e12c8ffdb0c8fc3d7de34","impliedFormat":1},{"version":"16f8e713001d58b9ee1bdcc52b43215c42ccd15da02fb639c32b942449244957","impliedFormat":1},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"0ddded05a6d5fddfac68d236af1b28fadb1206e882dec3943ce622df0c09fa22","signature":"d9c507256e1a075f7217ddb446a9ba6508c7518862ec2049818dd88347276fe3"},{"version":"95bf4b8b697f33da188bd98782b48232c122163987618846694015532f34eb65","signature":"ea05cba9e98da4ecf6585871ee57d5539bf190008ded2751ce5f4cf6bc6e455c"},{"version":"83a896c4f3f8d02d6aa1c0d572b9b45e916367a7a68e146b793e53a316553e59","signature":"9ea9a888ff28f5f438455b0eca5ba2b25e76f5d7d3003e6c29e474a50e05c811"},{"version":"8164a8b391deb7329758c127aa711f5c7ade4ab8b977d4e615651e6efea5a45a","signature":"19d39e50d022194b9e483136ca2e27bcebe56144ec3c6ffd8cf63f8fed6a0015"},{"version":"c9290dab1185a36e74d611702f6d046362ca9d3fd35a3a324f742d961d2912ac","signature":"7129e4c7cca338a300eb1daf9d04c31ce7e02cb27dc6f0e48fa4dbcc74ba0dc9"},{"version":"a747117e2a4f897904df1fb827bf06e7ac015f2aa5af593d91b873cad1d7cb24","signature":"1575121a5e12753c3bea15a9bdf621b31de2fecac204244ab6a3d805a136fe8c"},{"version":"d68fa129ed0416dead4652d6680a1d30bacfd1e80cc3586be2d55fbeb8f204cd","signature":"e18abe0e50b3d9ad8543b2af467fee2f71d06db75529fd119d711e40bcbd509b"},{"version":"fd2eb3c07f472f6fb4c5508cd7390b7e32e9e42992214fa4bb9752c457c07473","signature":"3ba35d4aeb5e1a578f1de001d37861192d1710cb6773185092aa2983363e061b"},{"version":"580158a155a82839ecfc9a9de44fa3ff796fdf0a05280595eae4ea92bb4185a7","signature":"9212399c8e1b8f824e8aba866164e956dfb66e61ae608284ecfd8eaafe1ae707"},{"version":"9d8c11c0e676f33e33eff94b9896f1c1692e9a1fc79801d56dfb03d71d190ad0","signature":"771be618ba4681eed1f3018dea912233f7aa90b83a3e9b48aad54e1609e9a69e"},{"version":"6c4c0fdcea6e98eec05d30b68b50dd90236b80aeba5f1ea3658854ddd4172522","signature":"effaed80b0b50ccd05b68dba785288b768cc2086ddce05c5f25ac18d577ad145"},{"version":"b8f466f3ff554628d5010ef833f935dd9def3ef7a478b0598afa48a01ebcb16d","signature":"e29cc1266adf2d50eec0c0b1c5b9e70bf2ddbf8a1da2f7490157586f805161e0"},{"version":"4f42d1861ee7a4af9c66738b30e2aa8a719acc85a87252a569f2d18fecbd456d","signature":"5a10f1bb90e4fc9bd3f2938add16de104d06286ffe30fc08e45c3f773dfd0c59"},{"version":"08b4fa31cbaed8cdaf6948b5c9ea617662e1b21d592a44d580d2d1b1de0e59a9","signature":"a5ab7f53472e5b0768bb90b5934ff715195e81fca889d964cb584a369246e9e9"},{"version":"ee7db5e897d58285f14196c02ac086f600487e08fa33d234ba60baac6d3d3c2b","signature":"023e6ac4588bf8059ae43bf29906584290fdfeeebc2e524df777f194d1583a9f"},{"version":"e3a7a6f79ab1b86455176ec9f0a675b4dd1f728fd4a0688f60382b28d4d2a17d","signature":"00a1977e76eb1046f457cecca3373fc74765c80c2164d462cb73789d2b2b09bc"},{"version":"f70d6381615bf528d11cb7cdc740683faadc8a66212a83dd28068b7dfa8e5539","signature":"9e876c0d0c3bd680126be89b88d7722cdb47ad9f58645b09702c3002e461dc3a"},{"version":"104c67f0da1bdf0d94865419247e20eded83ce7f9911a1aa75fc675c077ca66e","impliedFormat":1},{"version":"cc0d0b339f31ce0ab3b7a5b714d8e578ce698f1e13d7f8c60bfb766baeb1d35c","impliedFormat":1},{"version":"04600d4511481d8ea7293fb98d238c04e34dced959ffacb4f0c6147135ef7f7d","affectsGlobalScope":true,"impliedFormat":1},{"version":"ee31fab138939ef1903831933d524de9944511759778eedaaed56d6eb7f8697d","impliedFormat":1},{"version":"e45cc72cc9e7ad726ec83141fa4cd221d432062de34586ff107a0442ae28bf19","impliedFormat":1},{"version":"1d382840d8c30edfdf6c70bec101d72dbfdc629f409c0c4d9b32a79bf9bebae2","impliedFormat":1},{"version":"3083591fd0a77addd337b02f9fcf0d4f009e41c79fa42f862d6fcf76f3fceb48","impliedFormat":1},{"version":"34810cb47e6bee7cd4bad2f174793f5926ba5889c5d180e29b02c1871a820476","affectsGlobalScope":true,"impliedFormat":1},{"version":"7115f1157a00937d712e042a011eb85e9d80b13eff78bac5f210ee852f96879d","impliedFormat":1},{"version":"0ac74c7586880e26b6a599c710b59284a284e084a2bbc82cd40fb3fbfdea71ae","affectsGlobalScope":true,"impliedFormat":1},{"version":"2ce12357dadbb8efc4e4ec4dab709c8071bf992722fc9adfea2fe0bd5b50923f","impliedFormat":1},{"version":"d021d871089c519030a098fa3d32f5d95059b699b0fc6c45c85a96f92cae233c","impliedFormat":1},{"version":"c074a8cbfeb4d94915c4023dbe1eadf1215372efd3babbf982f1fed96ff8a695","impliedFormat":1},{"version":"b05b9ef20d18697e468c3ae9cecfff3f47e8976f9522d067047e3f236db06a41","affectsGlobalScope":true,"impliedFormat":1},{"version":"eec5e9a5629f6740aac21e49783a373a3767770ad559cd41285ebbb0db39a4a2","affectsGlobalScope":true,"impliedFormat":1},{"version":"1745f0b1ab53f414b4f8ebb2c6a902fda28d40f454edac8e92b4d7c974a2051c","affectsGlobalScope":true,"impliedFormat":1},{"version":"403f9ee3b18e550bccb23b0ef67ba61e4990a902f67db1afae1ad23602fef9d1","impliedFormat":1},{"version":"1a7a729938558fe198d979d3f53dece9c9112124b7b081a7fa0adcc98bf15fd8","impliedFormat":1},{"version":"067f76ab5254b1bdfc94154730b7a30c12e3aad8b9d04ec62c0d6b7a1f40ea0e","affectsGlobalScope":true,"impliedFormat":1},{"version":"f67f24b0d972d7d0f52a4e2f4f8ffd5cd786cb411044693026731918df935371","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be812b06e518320ba82e2aff3ac2ca37370a9df917db708f081b9043fa3315","impliedFormat":1},{"version":"2174e20517788d2a1379fc0aaacd87899a70f9e0197b4295edabfe75c4db03d8","impliedFormat":1},{"version":"25be1eb939c9c63242c7a45446edb20c40541da967f43f1aa6a00ed53c0552db","impliedFormat":1},{"version":"d3f2d715f57df3f04bf7b16dde01dec10366f64fce44503c92b8f78f614c1769","impliedFormat":1},{"version":"b78cd10245a90e27e62d0558564f5d9a16576294eee724a59ae21b91f9269e4a","impliedFormat":1},{"version":"936eb43a381712a8ec1249f2afc819f6fc7ca68f10dfec71762b428dfdc53bf1","impliedFormat":1},{"version":"2f5747b1508ccf83fad0c251ba1e5da2f5a30b78b09ffa1cfaf633045160afed","impliedFormat":1},{"version":"a45c25e77c911c1f2a04cade78f6f42b4d7d896a3882d4e226efd3a3fcd5f2c4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b71c603a539078a5e3a039b20f2b0a0d1708967530cf97dec8850a9ca45baa2b","impliedFormat":1},{"version":"0e13570a7e86c6d83dd92e81758a930f63747483e2cd34ef36fcdb47d1f9726a","impliedFormat":1},{"version":"5c45abf1e13e4463eacfd5dedda06855da8748a6a6cb3334f582b52e219acc04","impliedFormat":1},{"version":"63786b6f821dee19eb898afb385bd58f1846e6cba593a35edcf9631ace09ba25","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"e91ad231af87f864b3f07cd0e39b1cf6c133988156f087c1c3ccb0a5491c9115","impliedFormat":1},{"version":"03c258e060b7da220973f84b89615e4e9850e9b5d30b3a8e4840b3e3268ae8eb","impliedFormat":1},{"version":"319c37263037e8d9481a3dc7eadf6afa6a5f5c002189ebe28776ac1a62a38e15","impliedFormat":1},{"version":"4006c872e38a2c4e09c593bc0cdd32b7b4f5c4843910bea0def631c483fff6c5","impliedFormat":1},{"version":"ab6aa3a65d473871ee093e3b7b71ed0f9c69e07d1d4295f45c9efd91a771241d","impliedFormat":1},{"version":"22c313d18dc83e37a592cebb6e9366370dbcc6872b65f1c49b5cfc5fb84e6565","impliedFormat":1},{"version":"85a55229c4d0f20d42c59cec768df0cb83a492f8bb1351ead8524a58f278a005","impliedFormat":1},{"version":"7d2b7fe4adb76d8253f20e4dbdce044f1cdfab4902ec33c3604585f553883f7d","impliedFormat":1},{"version":"1ba59c8bbeed2cb75b239bb12041582fa3e8ef32f8d0bd0ec802e38442d3f317","impliedFormat":1}],"root":[85,1161,1163,1164,1166,[1247,1263]],"resolvedRoot":[[1161,1306]],"options":{"allowJs":true,"composite":true,"declaration":true,"declarationMap":true,"downlevelIteration":true,"esModuleInterop":true,"module":99,"noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitReturns":true,"noImplicitThis":true,"noUncheckedIndexedAccess":true,"noUnusedLocals":true,"noUnusedParameters":true,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"sourceMap":true,"strict":true,"strictNullChecks":true,"target":99,"useUnknownInCatchVariables":true,"verbatimModuleSyntax":true},"referencedMap":[[653,1],[652,2],[649,3],[588,4],[591,5],[592,5],[593,5],[594,5],[595,5],[596,5],[597,5],[598,5],[599,5],[600,5],[601,5],[602,5],[603,5],[604,5],[605,5],[606,5],[607,5],[608,5],[609,5],[610,5],[611,5],[612,5],[613,5],[614,5],[615,5],[616,5],[617,5],[618,5],[619,5],[620,5],[621,5],[622,5],[623,5],[624,5],[625,5],[626,5],[627,5],[628,5],[629,5],[630,5],[631,5],[632,5],[633,5],[634,5],[635,5],[636,5],[637,5],[638,5],[639,5],[640,5],[641,5],[642,5],[643,5],[644,5],[645,5],[646,5],[647,5],[654,6],[648,7],[650,8],[670,9],[589,10],[669,11],[590,12],[655,13],[656,14],[657,15],[658,16],[659,17],[660,18],[661,19],[662,20],[651,21],[668,22],[666,23],[667,23],[587,24],[395,25],[394,26],[410,27],[411,28],[559,26],[562,29],[560,30],[561,30],[565,31],[564,32],[566,33],[580,34],[563,35],[579,36],[581,37],[582,26],[586,38],[583,26],[584,7],[585,7],[413,26],[414,39],[415,40],[694,41],[691,42],[692,43],[693,44],[679,44],[680,44],[681,44],[682,44],[683,44],[684,44],[685,44],[686,44],[687,44],[688,44],[689,44],[690,44],[695,45],[678,46],[700,47],[696,48],[697,49],[698,50],[699,51],[412,33],[417,52],[418,53],[416,54],[419,7],[420,7],[462,55],[461,56],[421,7],[422,7],[423,7],[424,7],[425,7],[426,7],[427,7],[436,57],[437,7],[438,26],[439,7],[440,7],[441,7],[442,7],[430,26],[443,26],[444,7],[429,58],[431,59],[428,7],[432,58],[433,7],[434,60],[460,61],[445,7],[446,59],[447,7],[448,7],[449,26],[450,7],[451,7],[452,7],[453,7],[454,7],[455,7],[456,62],[457,7],[458,7],[435,7],[459,7],[672,63],[674,64],[676,65],[677,66],[673,67],[671,26],[675,67],[177,68],[168,26],[169,69],[95,26],[98,70],[143,71],[142,72],[144,73],[145,74],[146,75],[147,71],[148,75],[149,71],[141,76],[150,73],[151,77],[152,78],[153,71],[155,79],[156,80],[157,81],[154,82],[158,83],[159,84],[160,85],[140,86],[161,87],[162,88],[163,89],[139,90],[165,91],[109,92],[105,83],[166,93],[101,94],[167,95],[104,96],[106,97],[138,98],[164,99],[110,100],[111,83],[102,26],[99,83],[112,101],[113,102],[107,103],[103,102],[114,102],[136,104],[100,103],[137,103],[108,105],[97,26],[115,106],[116,107],[117,105],[119,108],[120,105],[121,85],[122,109],[123,110],[135,111],[125,112],[126,105],[127,113],[128,105],[118,113],[129,105],[130,105],[131,85],[132,114],[133,105],[134,105],[124,115],[170,113],[171,116],[96,26],[172,85],[173,117],[178,26],[175,118],[174,26],[317,119],[180,26],[179,117],[176,26],[321,120],[319,26],[318,117],[786,121],[745,122],[784,123],[744,26],[785,124],[743,26],[746,123],[320,26],[94,125],[324,26],[753,26],[798,26],[799,26],[800,26],[801,26],[802,26],[803,26],[804,26],[805,26],[806,26],[807,26],[463,33],[464,33],[467,126],[466,127],[465,7],[477,128],[468,33],[470,129],[469,7],[472,130],[471,26],[473,131],[474,131],[475,132],[476,133],[526,134],[527,26],[530,135],[528,136],[529,26],[480,137],[482,138],[481,7],[483,137],[484,137],[485,139],[478,7],[479,26],[496,140],[495,141],[497,35],[498,26],[502,142],[499,7],[500,7],[501,143],[494,7],[408,144],[396,7],[406,145],[407,7],[409,146],[508,7],[509,147],[506,148],[507,149],[505,150],[503,7],[504,7],[512,151],[510,26],[511,7],[397,26],[398,26],[399,26],[400,26],[405,152],[401,7],[402,7],[403,153],[404,7],[568,154],[567,7],[569,26],[575,7],[570,7],[571,7],[572,7],[576,7],[578,155],[573,7],[574,7],[577,7],[549,7],[513,7],[531,156],[532,157],[533,26],[534,158],[535,26],[536,26],[537,26],[538,26],[539,7],[540,156],[541,7],[543,159],[544,160],[542,7],[545,26],[546,26],[558,161],[547,26],[548,26],[550,26],[551,26],[552,26],[553,156],[554,26],[555,26],[556,26],[557,26],[330,162],[331,163],[333,26],[346,164],[347,165],[344,166],[345,167],[332,26],[348,168],[351,169],[353,170],[354,171],[336,172],[355,26],[359,173],[357,174],[358,26],[352,26],[361,175],[337,176],[363,177],[364,178],[366,179],[365,180],[367,181],[362,182],[360,183],[368,184],[369,185],[373,186],[374,187],[372,188],[350,189],[338,26],[341,190],[375,191],[376,192],[377,192],[334,26],[379,193],[378,192],[393,194],[339,26],[343,195],[380,196],[381,26],[335,26],[371,197],[382,198],[370,199],[383,200],[384,201],[385,169],[386,169],[387,202],[356,26],[389,203],[390,204],[349,26],[391,205],[388,26],[340,206],[342,183],[392,162],[487,207],[489,208],[490,209],[488,7],[491,26],[492,26],[493,210],[486,26],[514,26],[516,7],[515,211],[517,212],[518,213],[519,211],[520,211],[521,214],[525,215],[522,216],[523,217],[524,26],[664,218],[665,219],[663,7],[1265,220],[1284,221],[1285,26],[1264,222],[1286,222],[1291,223],[1294,224],[1292,26],[1295,225],[1296,26],[1287,26],[227,226],[228,226],[229,227],[188,228],[230,229],[231,230],[232,231],[183,26],[186,232],[184,26],[185,26],[233,233],[234,234],[235,235],[236,236],[237,237],[238,238],[239,238],[241,239],[240,240],[242,241],[243,242],[244,243],[226,244],[187,26],[245,245],[246,246],[247,247],[279,248],[248,249],[249,250],[250,251],[251,252],[252,253],[253,254],[254,255],[255,256],[256,257],[257,258],[258,258],[259,259],[260,26],[261,260],[263,261],[262,262],[264,263],[265,264],[266,265],[267,266],[268,267],[269,268],[270,269],[271,270],[272,271],[273,272],[274,273],[275,274],[276,275],[277,276],[278,277],[1289,26],[1290,26],[1299,278],[1297,279],[1288,280],[1293,281],[1300,26],[1301,26],[1302,26],[1303,282],[1298,26],[1304,26],[1305,283],[316,26],[709,284],[710,285],[729,286],[724,287],[725,288],[726,289],[727,287],[728,287],[717,290],[716,291],[714,292],[715,293],[720,294],[721,295],[722,295],[723,295],[713,296],[719,297],[718,298],[711,26],[707,26],[708,26],[712,299],[86,26],[1269,300],[1282,26],[1279,301],[1271,302],[1270,26],[1268,303],[1272,26],[1266,304],[1273,26],[1283,305],[1274,26],[1278,306],[1280,307],[1267,308],[1281,309],[1275,26],[1276,26],[1277,310],[1241,26],[1242,311],[1168,26],[1170,312],[1216,313],[1215,314],[1217,315],[1218,316],[1219,317],[1220,313],[1221,317],[1222,313],[1214,318],[1223,315],[1224,319],[1225,320],[1226,313],[1228,321],[1229,322],[1230,323],[1227,324],[1231,325],[1232,326],[1233,327],[1213,328],[1234,329],[1235,330],[1236,331],[1212,332],[1238,333],[1181,334],[1177,325],[1239,335],[1173,336],[1240,337],[1176,338],[1178,339],[1211,340],[1237,341],[1182,342],[1183,325],[1174,26],[1171,325],[1184,343],[1185,344],[1179,345],[1175,344],[1186,344],[1209,346],[1172,345],[1210,345],[1180,347],[1169,26],[1188,348],[1189,349],[1190,347],[1192,350],[1193,347],[1194,327],[1195,351],[1196,352],[1208,353],[1198,354],[1199,347],[1200,355],[1201,347],[1191,355],[1202,347],[1203,347],[1204,327],[1205,356],[1206,347],[1207,347],[1197,357],[1243,355],[1244,358],[1187,26],[1245,327],[1246,359],[322,117],[325,360],[323,361],[1165,362],[89,363],[90,364],[88,365],[87,26],[760,366],[762,367],[764,368],[772,369],[774,370],[755,371],[758,372],[765,373],[775,374],[738,375],[776,376],[767,377],[778,378],[741,376],[779,379],[781,380],[769,381],[740,382],[782,383],[787,384],[783,385],[734,386],[789,387],[790,388],[792,389],[730,26],[795,390],[770,391],[735,376],[794,392],[733,393],[796,394],[780,395],[797,373],[809,396],[747,397],[810,383],[820,398],[737,385],[766,399],[821,400],[839,401],[818,402],[824,403],[825,404],[742,385],[826,405],[827,26],[813,406],[768,407],[828,373],[830,408],[831,408],[832,409],[833,410],[829,411],[814,412],[815,413],[834,414],[835,415],[836,394],[749,416],[837,417],[739,418],[761,419],[763,419],[771,420],[773,419],[759,421],[757,422],[777,376],[731,395],[756,395],[791,423],[793,424],[732,418],[788,26],[808,425],[822,394],[812,426],[819,427],[816,428],[817,429],[823,430],[736,26],[748,431],[838,432],[811,26],[82,26],[83,26],[15,26],[13,26],[14,26],[19,26],[18,26],[2,26],[20,26],[21,26],[22,26],[23,26],[24,26],[25,26],[26,26],[27,26],[3,26],[28,26],[29,26],[4,26],[30,26],[34,26],[31,26],[32,26],[33,26],[35,26],[36,26],[37,26],[5,26],[38,26],[39,26],[40,26],[41,26],[6,26],[45,26],[42,26],[43,26],[44,26],[46,26],[7,26],[47,26],[52,26],[53,26],[48,26],[49,26],[50,26],[51,26],[8,26],[57,26],[54,26],[55,26],[56,26],[58,26],[9,26],[59,26],[60,26],[61,26],[63,26],[62,26],[64,26],[65,26],[10,26],[66,26],[67,26],[68,26],[11,26],[69,26],[70,26],[71,26],[72,26],[73,26],[1,26],[74,26],[75,26],[12,26],[79,26],[77,26],[81,26],[84,26],[76,26],[80,26],[78,26],[17,26],[16,26],[204,433],[214,434],[203,433],[224,435],[195,436],[194,437],[223,438],[217,439],[222,440],[197,441],[211,442],[196,443],[220,444],[192,445],[191,438],[221,446],[193,447],[198,448],[199,26],[202,448],[189,26],[225,449],[215,450],[206,451],[207,452],[209,453],[205,454],[208,455],[218,438],[200,456],[201,457],[210,458],[190,214],[213,450],[212,448],[216,26],[219,459],[315,460],[293,461],[303,462],[292,461],[313,463],[284,464],[283,437],[312,438],[306,465],[311,466],[286,467],[300,468],[285,469],[309,470],[281,471],[280,438],[310,472],[282,473],[287,474],[288,26],[291,474],[181,26],[314,475],[304,476],[295,477],[296,478],[298,479],[294,480],[297,481],[307,438],[289,482],[290,483],[299,484],[182,214],[302,485],[301,474],[305,26],[308,486],[1058,487],[852,488],[854,489],[853,490],[1059,491],[751,492],[907,493],[1046,494],[1048,495],[908,496],[1051,497],[964,498],[970,499],[971,500],[972,500],[969,501],[1060,502],[954,503],[973,504],[975,505],[979,506],[980,507],[981,505],[982,508],[930,509],[920,510],[929,511],[983,512],[984,513],[924,514],[986,515],[987,516],[915,517],[988,518],[992,519],[994,520],[996,521],[997,522],[998,523],[928,513],[991,524],[1000,525],[1001,518],[1002,526],[1004,527],[925,528],[1005,529],[1007,530],[963,531],[1009,532],[1010,533],[1012,534],[1013,505],[1015,535],[1016,536],[1020,537],[1026,538],[1025,539],[1028,540],[1029,541],[1030,541],[1031,542],[1033,543],[1087,544],[1061,544],[1062,545],[1063,546],[1064,545],[1065,547],[1066,545],[1067,547],[1068,544],[1069,545],[1089,545],[1070,545],[1071,548],[1072,549],[1090,545],[1073,547],[1074,545],[1075,545],[1076,550],[1077,547],[1078,545],[1091,545],[1079,545],[1080,545],[1081,545],[1082,547],[1092,545],[1083,550],[1088,545],[1084,547],[1035,551],[1036,552],[1037,553],[1038,554],[1039,555],[1040,556],[1041,557],[927,558],[1042,559],[1043,560],[1044,561],[916,562],[917,563],[1045,564],[1047,565],[1049,566],[1050,567],[1052,568],[1053,551],[1054,569],[1055,556],[1011,570],[1057,571],[1098,572],[1086,573],[1099,574],[1034,575],[1085,576],[1056,577],[867,578],[1093,579],[1022,580],[1097,581],[1101,582],[1102,26],[1103,26],[1107,26],[1104,26],[1106,26],[1108,26],[1105,26],[932,583],[909,584],[899,584],[855,26],[896,585],[921,585],[955,583],[900,586],[944,587],[881,584],[873,584],[993,588],[875,585],[966,584],[887,589],[868,584],[976,584],[901,584],[856,584],[857,590],[952,591],[888,592],[1094,584],[1110,588],[1109,584],[750,593],[862,594],[1159,595],[754,596],[841,597],[849,598],[1008,599],[865,600],[931,601],[845,602],[866,603],[842,604],[965,26],[843,605],[974,606],[844,607],[846,608],[840,605],[1006,609],[850,610],[864,611],[851,612],[869,597],[847,613],[1023,614],[1017,615],[752,26],[848,604],[941,616],[1111,617],[943,618],[989,619],[1112,620],[946,621],[947,622],[948,623],[1113,624],[978,625],[949,626],[1115,627],[1143,628],[942,629],[945,630],[1116,631],[1114,632],[939,633],[1118,634],[903,635],[1130,636],[885,637],[886,638],[890,639],[891,640],[892,640],[894,641],[895,642],[1138,643],[1137,644],[898,645],[897,646],[861,647],[956,648],[910,649],[1141,650],[1142,651],[950,652],[882,653],[871,654],[1117,654],[872,654],[874,655],[876,656],[933,657],[877,654],[940,658],[878,659],[1147,660],[880,661],[879,662],[883,643],[968,663],[967,664],[959,654],[957,656],[960,665],[958,666],[961,667],[951,668],[962,669],[919,670],[918,671],[911,672],[923,673],[995,674],[912,675],[990,676],[999,677],[922,678],[1003,679],[913,679],[934,680],[1153,681],[884,682],[935,683],[1154,682],[893,682],[1150,684],[977,685],[1148,686],[1151,684],[938,687],[1149,686],[936,688],[937,689],[1139,690],[1140,691],[902,26],[926,692],[1021,675],[1024,683],[858,683],[985,683],[859,683],[1095,683],[1096,693],[860,694],[1100,695],[1120,696],[1014,697],[1019,698],[1134,699],[1121,493],[1135,700],[1122,493],[870,701],[1123,702],[1124,703],[1126,704],[1127,705],[1129,706],[1136,701],[1125,707],[1128,696],[1152,708],[1131,709],[1132,710],[1133,711],[863,593],[1032,712],[953,713],[1027,683],[914,714],[904,715],[1119,716],[889,717],[1158,718],[905,719],[906,720],[1018,721],[1145,722],[1146,722],[1144,683],[1156,723],[1157,723],[1155,683],[1260,724],[85,26],[1263,725],[1247,726],[1262,727],[1261,728],[1259,729],[1254,730],[1258,731],[1256,732],[1257,733],[1252,734],[1163,735],[1250,736],[1253,737],[1166,733],[1249,738],[1164,26],[1255,739],[1248,740],[1251,741],[1160,742],[1162,743],[1161,26],[703,26],[704,744],[1167,26],[702,26],[701,745],[706,746],[329,747],[92,748],[93,748],[326,222],[327,749],[328,750],[705,26],[91,751]],"latestChangedDtsFile":"./dist/index.d.ts","version":"5.8.3"} \ No newline at end of file diff --git a/tooling/sparta/packages/ethereum/README.md b/tooling/sparta/packages/ethereum/README.md new file mode 100644 index 0000000..25176e3 --- /dev/null +++ b/tooling/sparta/packages/ethereum/README.md @@ -0,0 +1,103 @@ +# @sparta/ethereum + +Ethereum blockchain interaction library for the Sparta project. + +## Overview + +This package provides blockchain connectivity and utilities for interacting with Ethereum networks, specifically for Aztec validators management. It handles: + +- Connection to Ethereum nodes +- Transaction creation and sending +- Contract interactions +- Chain information retrieval + +## Usage + +```typescript +import { getEthereumInstance, l2InfoService } from '@sparta/ethereum'; + +// Get an ethereum instance +const ethereum = await getEthereumInstance(); + +// Get chain info +const chainInfo = await ethereum.getChainInfo(); +console.log(chainInfo); + +// Get L2 info +const blockInfo = await l2InfoService.getLatestL2Block(); +console.log(blockInfo); +``` + +## Components + +### Ethereum Client + +The main client for interacting with the Ethereum blockchain: + +```typescript +import { getEthereumInstance } from '@sparta/ethereum'; + +const ethereum = await getEthereumInstance(); + +// Check if an address is a validator +const isValidator = await ethereum.isValidator('0x1234...'); + +// Get chain information +const chainInfo = await ethereum.getChainInfo(); +``` + +### L2 Info Service + +Service for retrieving Layer 2 information, primarily validator statistics and sync proofs. + +```typescript +import { l2InfoService } from '@sparta/ethereum'; + +// Example: Fetching validator statistics +async function getValidatorStats(validatorAddress: string) { + try { + // Initialize the service (if not done globally) + // await l2InfoService.init(); // Or ensure it's called once at startup + + const stats = await l2InfoService.fetchValidatorStats(validatorAddress); + if (stats.error) { + console.error(`Error fetching stats for ${validatorAddress}: ${stats.error}`); + } else { + console.log(`Stats for ${validatorAddress}:`, stats); + // stats.hasAttested24h, stats.missedAttestationsCount, etc. + } + } catch (err) { + console.error('Failed to get validator stats:', err); + } +} + +// Example: Proving a node is synced (used in registration) +async function checkSyncProof(blockNumber: string, proof: string) { + try { + const syncResult = await l2InfoService.proveSynced(blockNumber, proof); + console.log('Sync proof result:', syncResult); + // Depending on the RPC response structure, check if valid + } catch (err) { + console.error('Failed to check sync proof:', err); + } +} + +// Make sure to initialize l2InfoService once, e.g., at application startup +// await l2InfoService.init(); +``` + +## Configuration + +The Ethereum client is configured through environment variables: + +- `ETHEREUM_HOST`: RPC endpoint URL +- `L1_CHAIN_ID`: Chain ID for the Ethereum network +- `STAKING_ASSET_HANDLER_ADDRESS`: Contract address for validator staking + +## Development + +Build the package: + +```bash +bun run build +``` \ No newline at end of file diff --git a/tooling/sparta/packages/ethereum/package.json b/tooling/sparta/packages/ethereum/package.json new file mode 100644 index 0000000..4ed7bde --- /dev/null +++ b/tooling/sparta/packages/ethereum/package.json @@ -0,0 +1,20 @@ +{ + "name": "@sparta/ethereum", + "version": "0.1.0", + "type": "module", + "scripts": { + "build": "tsc" + }, + "dependencies": { + "@sparta/utils": "^0.1.0", + "pino": "^8.16.0", + "viem": "^2.0.0" + }, + "devDependencies": { + "@types/bun": "latest", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "typescript": "^5.0.0" + } +} diff --git a/tooling/sparta/src/utils/abis/registryAbi.ts b/tooling/sparta/packages/ethereum/src/abis/ForwarderAbi.ts similarity index 90% rename from tooling/sparta/src/utils/abis/registryAbi.ts rename to tooling/sparta/packages/ethereum/src/abis/ForwarderAbi.ts index 5abeb60..8d2753d 100644 --- a/tooling/sparta/src/utils/abis/registryAbi.ts +++ b/tooling/sparta/packages/ethereum/src/abis/ForwarderAbi.ts @@ -1,18 +1,29 @@ /** - * Registry ABI. + * Forwarder ABI. */ -export const RegistryAbi = [ +export const ForwarderAbi = [ { type: "constructor", inputs: [ { - name: "_owner", + name: "__owner", type: "address", internalType: "address", }, ], stateMutability: "nonpayable", }, + { + type: "error", + name: "AddressEmptyCode", + inputs: [ + { + name: "target", + type: "address", + internalType: "address", + }, + ], + }, { type: "error", name: "CoinIssuer__InsufficientMintAvailable", @@ -50,6 +61,11 @@ export const RegistryAbi = [ name: "DevNet__NoPruningAllowed", inputs: [], }, + { + type: "error", + name: "FailedCall", + inputs: [], + }, { type: "error", name: "FeeJuicePortal__AlreadyInitialized", @@ -67,13 +83,24 @@ export const RegistryAbi = [ }, { type: "error", - name: "FeeMath__InvalidFeeAssetPriceModifier", + name: "FeeLib__InvalidFeeAssetPriceModifier", inputs: [], }, { type: "error", - name: "FeeMath__InvalidProvingCostModifier", - inputs: [], + name: "ForwarderLengthMismatch", + inputs: [ + { + name: "toLength", + type: "uint256", + internalType: "uint256", + }, + { + name: "dataLength", + type: "uint256", + internalType: "uint256", + }, + ], }, { type: "error", @@ -509,23 +536,20 @@ export const RegistryAbi = [ inputs: [], }, { - type: "event", - name: "InstanceAdded", + type: "error", + name: "InsufficientBalance", inputs: [ { - name: "instance", - type: "address", - indexed: true, - internalType: "address", + name: "balance", + type: "uint256", + internalType: "uint256", }, { - name: "version", + name: "needed", type: "uint256", - indexed: true, internalType: "uint256", }, ], - anonymous: false, }, { type: "error", @@ -834,6 +858,22 @@ export const RegistryAbi = [ }, ], }, + { + type: "error", + name: "Rollup__AlreadyClaimed", + inputs: [ + { + name: "prover", + type: "address", + internalType: "address", + }, + { + name: "epoch", + type: "uint256", + internalType: "Epoch", + }, + ], + }, { type: "error", name: "Rollup__InsufficientBondAmount", @@ -979,22 +1019,6 @@ export const RegistryAbi = [ }, ], }, - { - type: "error", - name: "Rollup__InvalidEpoch", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Epoch", - }, - { - name: "actual", - type: "uint256", - internalType: "Epoch", - }, - ], - }, { type: "error", name: "Rollup__InvalidInHash", @@ -1114,77 +1138,88 @@ export const RegistryAbi = [ }, { type: "error", - name: "Rollup__NoEpochToProve", + name: "Rollup__ManaLimitExceeded", inputs: [], }, { type: "error", - name: "Rollup__NonSequentialProving", + name: "Rollup__NoEpochToProve", inputs: [], }, { type: "error", - name: "Rollup__NonZeroDaFee", + name: "Rollup__NonSequentialProving", inputs: [], }, { type: "error", - name: "Rollup__NonZeroL2Fee", + name: "Rollup__NonZeroDaFee", inputs: [], }, { type: "error", - name: "Rollup__NotClaimingCorrectEpoch", + name: "Rollup__NotPastDeadline", inputs: [ { - name: "expected", + name: "deadline", type: "uint256", - internalType: "Epoch", + internalType: "Slot", }, { - name: "actual", + name: "currentSlot", type: "uint256", - internalType: "Epoch", + internalType: "Slot", }, ], }, { type: "error", - name: "Rollup__NotInClaimPhase", + name: "Rollup__NothingToPrune", + inputs: [], + }, + { + type: "error", + name: "Rollup__PastDeadline", inputs: [ { - name: "currentSlotInEpoch", + name: "deadline", type: "uint256", - internalType: "uint256", + internalType: "Slot", }, { - name: "claimDuration", + name: "currentSlot", type: "uint256", - internalType: "uint256", + internalType: "Slot", }, ], }, { type: "error", - name: "Rollup__NothingToPrune", - inputs: [], - }, - { - type: "error", - name: "Rollup__ProofRightAlreadyClaimed", - inputs: [], + name: "Rollup__ProverHaveAlreadySubmitted", + inputs: [ + { + name: "prover", + type: "address", + internalType: "address", + }, + { + name: "epoch", + type: "uint256", + internalType: "Epoch", + }, + ], }, { type: "error", - name: "Rollup__QuoteExpired", + name: "Rollup__SlotAlreadyInChain", inputs: [ { - name: "currentSlot", + name: "lastSlot", type: "uint256", internalType: "Slot", }, { - name: "quoteSlot", + name: "proposedSlot", type: "uint256", internalType: "Slot", }, @@ -1192,20 +1227,30 @@ export const RegistryAbi = [ }, { type: "error", - name: "Rollup__SlotAlreadyInChain", + name: "Rollup__StartAndEndNotSameEpoch", inputs: [ { - name: "lastSlot", + name: "start", type: "uint256", - internalType: "Slot", + internalType: "Epoch", }, { - name: "proposedSlot", + name: "end", type: "uint256", - internalType: "Slot", + internalType: "Epoch", }, ], }, + { + type: "error", + name: "Rollup__StartIsNotBuildingOnProven", + inputs: [], + }, + { + type: "error", + name: "Rollup__StartIsNotFirstBlockOfEpoch", + inputs: [], + }, { type: "error", name: "Rollup__TimestampInFuture", @@ -1340,6 +1385,22 @@ export const RegistryAbi = [ }, ], }, + { + type: "error", + name: "Staking__InvalidDeposit", + inputs: [ + { + name: "attester", + type: "address", + internalType: "address", + }, + { + name: "proposer", + type: "address", + internalType: "address", + }, + ], + }, { type: "error", name: "Staking__NoOneToSlash", @@ -1492,136 +1553,21 @@ export const RegistryAbi = [ }, { type: "function", - name: "getCurrentSnapshot", - inputs: [], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct DataStructures.RegistrySnapshot", - components: [ - { - name: "rollup", - type: "address", - internalType: "address", - }, - { - name: "blockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getGovernance", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getRollup", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getSnapshot", - inputs: [ - { - name: "_version", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct DataStructures.RegistrySnapshot", - components: [ - { - name: "rollup", - type: "address", - internalType: "address", - }, - { - name: "blockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getVersionFor", - inputs: [ - { - name: "_rollup", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "isRollupRegistered", + name: "forward", inputs: [ { - name: "_rollup", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", + name: "_to", + type: "address[]", + internalType: "address[]", }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "numberOfVersions", - inputs: [], - outputs: [ { - name: "", - type: "uint256", - internalType: "uint256", + name: "_data", + type: "bytes[]", + internalType: "bytes[]", }, ], - stateMutability: "view", + outputs: [], + stateMutability: "nonpayable", }, { type: "function", @@ -1656,23 +1602,4 @@ export const RegistryAbi = [ outputs: [], stateMutability: "nonpayable", }, - { - type: "function", - name: "upgrade", - inputs: [ - { - name: "_rollup", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "nonpayable", - }, ] as const; diff --git a/tooling/sparta/packages/ethereum/src/abis/RollupAbi.ts b/tooling/sparta/packages/ethereum/src/abis/RollupAbi.ts new file mode 100644 index 0000000..97fa7c0 --- /dev/null +++ b/tooling/sparta/packages/ethereum/src/abis/RollupAbi.ts @@ -0,0 +1,3671 @@ +/** + * Rollup ABI. + */ +export const RollupAbi = [ + { + "type": "constructor", + "inputs": [ + { + "name": "_feeAsset", + "type": "address", + "internalType": "contract IERC20" + }, + { + "name": "_rewardDistributor", + "type": "address", + "internalType": "contract IRewardDistributor" + }, + { + "name": "_stakingAsset", + "type": "address", + "internalType": "contract IERC20" + }, + { + "name": "_governance", + "type": "address", + "internalType": "address" + }, + { + "name": "_genesisState", + "type": "tuple", + "internalType": "struct GenesisState", + "components": [ + { + "name": "vkTreeRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "protocolContractTreeRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "genesisArchiveRoot", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "name": "_config", + "type": "tuple", + "internalType": "struct RollupConfigInput", + "components": [ + { + "name": "aztecSlotDuration", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "aztecEpochDuration", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "targetCommitteeSize", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "aztecProofSubmissionWindow", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minimumStake", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "slashingQuorum", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "slashingRoundSize", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "manaTarget", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provingCostPerMana", + "type": "uint256", + "internalType": "EthValue" + } + ] + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "error", + "name": "AddressSnapshotLib__IndexOutOfBounds", + "inputs": [ + { + "name": "index", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "size", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "CheckpointUnorderedInsertion", + "inputs": [] + }, + { + "type": "error", + "name": "CoinIssuer__InsufficientMintAvailable", + "inputs": [ + { + "name": "available", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "needed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "event", + "name": "Deposit", + "inputs": [ + { + "name": "attester", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "withdrawer", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "DevNet__InvalidProposer", + "inputs": [ + { + "name": "expected", + "type": "address", + "internalType": "address" + }, + { + "name": "actual", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "DevNet__NoPruningAllowed", + "inputs": [] + }, + { + "type": "event", + "name": "EIP712DomainChanged", + "inputs": [], + "anonymous": false + }, + { + "type": "error", + "name": "FeeJuicePortal__AlreadyInitialized", + "inputs": [] + }, + { + "type": "error", + "name": "FeeJuicePortal__InvalidInitialization", + "inputs": [] + }, + { + "type": "error", + "name": "FeeJuicePortal__Unauthorized", + "inputs": [] + }, + { + "type": "error", + "name": "FeeLib__InvalidFeeAssetPriceModifier", + "inputs": [] + }, + { + "type": "error", + "name": "GovernanceProposer__CanOnlyExecuteProposalInPast", + "inputs": [] + }, + { + "type": "error", + "name": "GovernanceProposer__FailedToPropose", + "inputs": [ + { + "name": "proposal", + "type": "address", + "internalType": "contract IPayload" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__InstanceHaveNoCode", + "inputs": [ + { + "name": "instance", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__InsufficientVotes", + "inputs": [ + { + "name": "votesCast", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "votesNeeded", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__InvalidNAndMValues", + "inputs": [ + { + "name": "n", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "m", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__NCannotBeLargerTHanM", + "inputs": [ + { + "name": "n", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "m", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__OnlyProposerCanVote", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__ProposalAlreadyExecuted", + "inputs": [ + { + "name": "roundNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__ProposalCannotBeAddressZero", + "inputs": [] + }, + { + "type": "error", + "name": "GovernanceProposer__ProposalHaveNoCode", + "inputs": [ + { + "name": "proposal", + "type": "address", + "internalType": "contract IPayload" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__ProposalTooOld", + "inputs": [ + { + "name": "roundNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "currentRoundNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__VoteAlreadyCastForSlot", + "inputs": [ + { + "name": "slot", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Governance__CallFailed", + "inputs": [ + { + "name": "target", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Governance__CallerNotGovernanceProposer", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + }, + { + "name": "governanceProposer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Governance__CallerNotSelf", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + }, + { + "name": "self", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Governance__CannotCallAsset", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__DifferentialTooBig", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__DifferentialTooSmall", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__InvalidMinimumVotes", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__LockAmountTooSmall", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__QuorumTooBig", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__QuorumTooSmall", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__TimeTooBig", + "inputs": [ + { + "name": "name", + "type": "string", + "internalType": "string" + } + ] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__TimeTooSmall", + "inputs": [ + { + "name": "name", + "type": "string", + "internalType": "string" + } + ] + }, + { + "type": "error", + "name": "Governance__InsufficientPower", + "inputs": [ + { + "name": "voter", + "type": "address", + "internalType": "address" + }, + { + "name": "have", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Governance__InvalidConfiguration", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__NoCheckpointsFound", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalAlreadyDropped", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalCannotBeDropped", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalDoesNotExists", + "inputs": [ + { + "name": "proposalId", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Governance__ProposalLib__MoreVoteThanExistNeeded", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalLib__MoreYeaVoteThanExistNeeded", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalLib__ZeroMinimum", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalLib__ZeroVotesNeeded", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalLib__ZeroYeaVotesNeeded", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalNotActive", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalNotExecutable", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__UserLib__NotInPast", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__WithdrawalAlreadyclaimed", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__WithdrawalNotUnlockedYet", + "inputs": [ + { + "name": "currentTime", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "unlocksAt", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "error", + "name": "HeaderLib__InvalidHeaderSize", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "HeaderLib__InvalidSlotNumber", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Inbox__ActorTooLarge", + "inputs": [ + { + "name": "actor", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Inbox__ContentTooLarge", + "inputs": [ + { + "name": "content", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Inbox__MustBuildBeforeConsume", + "inputs": [] + }, + { + "type": "error", + "name": "Inbox__SecretHashTooLarge", + "inputs": [ + { + "name": "secretHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Inbox__Unauthorized", + "inputs": [] + }, + { + "type": "error", + "name": "Inbox__VersionMismatch", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InvalidShortString", + "inputs": [] + }, + { + "type": "function", + "name": "L1_BLOCK_AT_GENESIS", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "L2BlockProposed", + "inputs": [ + { + "name": "blockNumber", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "archive", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "versionedBlobHashes", + "type": "bytes32[]", + "indexed": false, + "internalType": "bytes32[]" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "L2ProofVerified", + "inputs": [ + { + "name": "blockNumber", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "proverId", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ManaTargetUpdated", + "inputs": [ + { + "name": "manaTarget", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "MerkleLib__InvalidRoot", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "leaf", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "leafIndex", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__AlreadyNullified", + "inputs": [ + { + "name": "l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "leafIndex", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__BlockNotProven", + "inputs": [ + { + "name": "l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__IncompatibleEntryArguments", + "inputs": [ + { + "name": "messageHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "storedFee", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "feePassed", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "storedVersion", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "versionPassed", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "storedDeadline", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "deadlinePassed", + "type": "uint32", + "internalType": "uint32" + } + ] + }, + { + "type": "error", + "name": "Outbox__InvalidChainId", + "inputs": [] + }, + { + "type": "error", + "name": "Outbox__InvalidPathLength", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__InvalidRecipient", + "inputs": [ + { + "name": "expected", + "type": "address", + "internalType": "address" + }, + { + "name": "actual", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Outbox__NothingToConsume", + "inputs": [ + { + "name": "messageHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Outbox__NothingToConsumeAtBlock", + "inputs": [ + { + "name": "l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__RootAlreadySetAtBlock", + "inputs": [ + { + "name": "l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__Unauthorized", + "inputs": [] + }, + { + "type": "error", + "name": "Outbox__VersionMismatch", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "OwnableInvalidOwner", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "OwnableUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "ProofCommitmentEscrow__InsufficientBalance", + "inputs": [ + { + "name": "balance", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "requested", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ProofCommitmentEscrow__NotOwner", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ProofCommitmentEscrow__WithdrawRequestNotReady", + "inputs": [ + { + "name": "current", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "readyAt", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "event", + "name": "PrunedPending", + "inputs": [ + { + "name": "provenBlockNumber", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "pendingBlockNumber", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "Registry__NoRollupsRegistered", + "inputs": [] + }, + { + "type": "error", + "name": "Registry__RollupAlreadyRegistered", + "inputs": [ + { + "name": "rollup", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Registry__RollupNotRegistered", + "inputs": [ + { + "name": "version", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "RewardDistributor__InvalidCaller", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + }, + { + "name": "canonical", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Rollup__AlreadyClaimed", + "inputs": [ + { + "name": "prover", + "type": "address", + "internalType": "address" + }, + { + "name": "epoch", + "type": "uint256", + "internalType": "Epoch" + } + ] + }, + { + "type": "error", + "name": "Rollup__InsufficientBondAmount", + "inputs": [ + { + "name": "minimum", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provided", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InsufficientFundsInEscrow", + "inputs": [ + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "available", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidArchive", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBasisPointFee", + "inputs": [ + { + "name": "basisPointFee", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBlobHash", + "inputs": [ + { + "name": "blobHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBlobProof", + "inputs": [ + { + "name": "blobHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBlobPublicInputsHash", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBlockNumber", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidChainId", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidInHash", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidManaBaseFee", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidPreviousArchive", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidProof", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__InvalidProposedArchive", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidTimestamp", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidVersion", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__ManaLimitExceeded", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__NoEpochToProve", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__NonSequentialProving", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__NonZeroDaFee", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__NotPastDeadline", + "inputs": [ + { + "name": "deadline", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "currentSlot", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Rollup__NothingToPrune", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__PastDeadline", + "inputs": [ + { + "name": "deadline", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "currentSlot", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Rollup__ProverHaveAlreadySubmitted", + "inputs": [ + { + "name": "prover", + "type": "address", + "internalType": "address" + }, + { + "name": "epoch", + "type": "uint256", + "internalType": "Epoch" + } + ] + }, + { + "type": "error", + "name": "Rollup__SlotAlreadyInChain", + "inputs": [ + { + "name": "lastSlot", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "proposedSlot", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Rollup__StartAndEndNotSameEpoch", + "inputs": [ + { + "name": "start", + "type": "uint256", + "internalType": "Epoch" + }, + { + "name": "end", + "type": "uint256", + "internalType": "Epoch" + } + ] + }, + { + "type": "error", + "name": "Rollup__StartIsNotBuildingOnProven", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__StartIsNotFirstBlockOfEpoch", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__TimestampInFuture", + "inputs": [ + { + "name": "max", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "error", + "name": "Rollup__TimestampTooOld", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__TryingToProveNonExistingBlock", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__UnavailableTxs", + "inputs": [ + { + "name": "txsHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "SafeCastOverflowedIntToUint", + "inputs": [ + { + "name": "value", + "type": "int256", + "internalType": "int256" + } + ] + }, + { + "type": "error", + "name": "SafeCastOverflowedUintDowncast", + "inputs": [ + { + "name": "bits", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "SampleLib__IndexOutOfBounds", + "inputs": [ + { + "name": "requested", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "bound", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "SampleLib__SampleLargerThanIndex", + "inputs": [ + { + "name": "sample", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "index", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "SignatureLib__CannotVerifyEmpty", + "inputs": [] + }, + { + "type": "error", + "name": "SignatureLib__InvalidSignature", + "inputs": [ + { + "name": "expected", + "type": "address", + "internalType": "address" + }, + { + "name": "recovered", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "event", + "name": "Slashed", + "inputs": [ + { + "name": "attester", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "Staking__AlreadyActive", + "inputs": [ + { + "name": "attester", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__AlreadyRegistered", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__CannotSlashExitedStake", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__FailedToRemove", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__InsufficientStake", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Staking__InvalidDeposit", + "inputs": [ + { + "name": "attester", + "type": "address", + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NoOneToSlash", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NotExiting", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NotSlasher", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NotWithdrawer", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NothingToExit", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__WithdrawalNotUnlockedYet", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "error", + "name": "StringTooLong", + "inputs": [ + { + "name": "str", + "type": "string", + "internalType": "string" + } + ] + }, + { + "type": "error", + "name": "ValidatorSelection__EpochNotSetup", + "inputs": [] + }, + { + "type": "error", + "name": "ValidatorSelection__InsufficientAttestations", + "inputs": [ + { + "name": "minimumNeeded", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provided", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ValidatorSelection__InsufficientAttestationsProvided", + "inputs": [ + { + "name": "minimumNeeded", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provided", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ValidatorSelection__InvalidDeposit", + "inputs": [ + { + "name": "attester", + "type": "address", + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ValidatorSelection__InvalidProposer", + "inputs": [ + { + "name": "expected", + "type": "address", + "internalType": "address" + }, + { + "name": "actual", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "event", + "name": "WithdrawFinalised", + "inputs": [ + { + "name": "attester", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "recipient", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "WithdrawInitiated", + "inputs": [ + { + "name": "attester", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "recipient", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "function", + "name": "archive", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "archiveAt", + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "canProposeAtTime", + "inputs": [ + { + "name": "_ts", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "_archive", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "canPruneAtTime", + "inputs": [ + { + "name": "_ts", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "cheat__InitialiseValidatorSet", + "inputs": [ + { + "name": "_args", + "type": "tuple[]", + "internalType": "struct CheatDepositArgs[]", + "components": [ + { + "name": "attester", + "type": "address", + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "internalType": "address" + }, + { + "name": "withdrawer", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "checkBlob", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "claimProverRewards", + "inputs": [ + { + "name": "_recipient", + "type": "address", + "internalType": "address" + }, + { + "name": "_epochs", + "type": "uint256[]", + "internalType": "Epoch[]" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "claimSequencerRewards", + "inputs": [ + { + "name": "_recipient", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "deposit", + "inputs": [ + { + "name": "_attester", + "type": "address", + "internalType": "address" + }, + { + "name": "_proposer", + "type": "address", + "internalType": "address" + }, + { + "name": "_withdrawer", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "eip712Domain", + "inputs": [], + "outputs": [ + { + "name": "fields", + "type": "bytes1", + "internalType": "bytes1" + }, + { + "name": "name", + "type": "string", + "internalType": "string" + }, + { + "name": "version", + "type": "string", + "internalType": "string" + }, + { + "name": "chainId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "verifyingContract", + "type": "address", + "internalType": "address" + }, + { + "name": "salt", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "extensions", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "finaliseWithdraw", + "inputs": [ + { + "name": "_attester", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getActiveAttesterCount", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getAttesterAtIndex", + "inputs": [ + { + "name": "_index", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getAttesters", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getBlobPublicInputsHash", + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getBlock", + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct BlockLog", + "components": [ + { + "name": "archive", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "slotNumber", + "type": "uint256", + "internalType": "Slot" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getBurnAddress", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "pure" + }, + { + "type": "function", + "name": "getCollectiveProverRewardsForEpoch", + "inputs": [ + { + "name": "_epoch", + "type": "uint256", + "internalType": "Epoch" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getCommitteeAt", + "inputs": [ + { + "name": "_ts", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getCurrentEpoch", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Epoch" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getCurrentEpochCommittee", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getCurrentProposer", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getCurrentSampleSeed", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getCurrentSlot", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Slot" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getEpochAt", + "inputs": [ + { + "name": "_ts", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Epoch" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getEpochAtSlot", + "inputs": [ + { + "name": "_slotNumber", + "type": "uint256", + "internalType": "Slot" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Epoch" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getEpochCommittee", + "inputs": [ + { + "name": "_epoch", + "type": "uint256", + "internalType": "Epoch" + } + ], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getEpochDuration", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getEpochForBlock", + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Epoch" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getEpochProofPublicInputs", + "inputs": [ + { + "name": "_start", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_end", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_args", + "type": "tuple", + "internalType": "struct PublicInputArgs", + "components": [ + { + "name": "previousArchive", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "endArchive", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "endTimestamp", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "outHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "proverId", + "type": "address", + "internalType": "address" + } + ] + }, + { + "name": "_fees", + "type": "bytes32[]", + "internalType": "bytes32[]" + }, + { + "name": "_blobPublicInputs", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getExit", + "inputs": [ + { + "name": "_attester", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct Exit", + "components": [ + { + "name": "exitableAt", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "recipient", + "type": "address", + "internalType": "address" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getExitDelay", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getFeeAsset", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IERC20" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getFeeAssetPerEth", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "FeeAssetPerEthE9" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getFeeAssetPortal", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IFeeJuicePortal" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getFeeHeader", + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct FeeHeader", + "components": [ + { + "name": "excessMana", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "manaUsed", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "feeAssetPriceNumerator", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "congestionCost", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provingCost", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getGenesisTime", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getHasSubmitted", + "inputs": [ + { + "name": "_epoch", + "type": "uint256", + "internalType": "Epoch" + }, + { + "name": "_length", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_prover", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getInbox", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IInbox" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getInfo", + "inputs": [ + { + "name": "_attester", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct ValidatorInfo", + "components": [ + { + "name": "stake", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "withdrawer", + "type": "address", + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "internalType": "address" + }, + { + "name": "status", + "type": "uint8", + "internalType": "enum Status" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getL1FeesAt", + "inputs": [ + { + "name": "_timestamp", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct L1FeeData", + "components": [ + { + "name": "baseFee", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "blobFee", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getManaBaseFeeAt", + "inputs": [ + { + "name": "_timestamp", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "_inFeeAsset", + "type": "bool", + "internalType": "bool" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getManaBaseFeeComponentsAt", + "inputs": [ + { + "name": "_timestamp", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "_inFeeAsset", + "type": "bool", + "internalType": "bool" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct ManaBaseFeeComponents", + "components": [ + { + "name": "congestionCost", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "congestionMultiplier", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "dataCost", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasCost", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provingCost", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getManaLimit", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getManaTarget", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getMinimumStake", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getOperatorAtIndex", + "inputs": [ + { + "name": "_index", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct OperatorInfo", + "components": [ + { + "name": "proposer", + "type": "address", + "internalType": "address" + }, + { + "name": "attester", + "type": "address", + "internalType": "address" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getOutbox", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IOutbox" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPendingBlockNumber", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getProofSubmissionWindow", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getProposerAt", + "inputs": [ + { + "name": "_ts", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getProposerAtIndex", + "inputs": [ + { + "name": "_index", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getProposerForAttester", + "inputs": [ + { + "name": "_attester", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getProvenBlockNumber", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getProvingCostPerManaInEth", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "EthValue" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getProvingCostPerManaInFeeAsset", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "FeeAssetValue" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRewardDistributor", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IRewardDistributor" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getSampleSeedAt", + "inputs": [ + { + "name": "_ts", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getSequencerRewards", + "inputs": [ + { + "name": "_sequencer", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getSlasher", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getSlotAt", + "inputs": [ + { + "name": "_ts", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Slot" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getSlotDuration", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getSpecificProverRewardsForEpoch", + "inputs": [ + { + "name": "_epoch", + "type": "uint256", + "internalType": "Epoch" + }, + { + "name": "_prover", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getStakingAsset", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IERC20" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getTargetCommitteeSize", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getTimestampForSlot", + "inputs": [ + { + "name": "_slotNumber", + "type": "uint256", + "internalType": "Slot" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Timestamp" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getTips", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct ChainTips", + "components": [ + { + "name": "pendingBlockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provenBlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getVersion", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initiateWithdraw", + "inputs": [ + { + "name": "_attester", + "type": "address", + "internalType": "address" + }, + { + "name": "_recipient", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "propose", + "inputs": [ + { + "name": "_args", + "type": "tuple", + "internalType": "struct ProposeArgs", + "components": [ + { + "name": "archive", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "oracleInput", + "type": "tuple", + "internalType": "struct OracleInput", + "components": [ + { + "name": "feeAssetPriceModifier", + "type": "int256", + "internalType": "int256" + } + ] + }, + { + "name": "header", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "txHashes", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ] + }, + { + "name": "_signatures", + "type": "tuple[]", + "internalType": "struct Signature[]", + "components": [ + { + "name": "isEmpty", + "type": "bool", + "internalType": "bool" + }, + { + "name": "v", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "r", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "s", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "name": "_blobInput", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "prune", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setEpochVerifier", + "inputs": [ + { + "name": "_verifier", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setProtocolContractTreeRoot", + "inputs": [ + { + "name": "_protocolContractTreeRoot", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setProvingCostPerMana", + "inputs": [ + { + "name": "_provingCostPerMana", + "type": "uint256", + "internalType": "EthValue" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setVkTreeRoot", + "inputs": [ + { + "name": "_vkTreeRoot", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setupEpoch", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "slash", + "inputs": [ + { + "name": "_attester", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "status", + "inputs": [ + { + "name": "_myHeaderBlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "provenBlockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provenArchive", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "pendingBlockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "pendingArchive", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "archiveOfMyBlock", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "provenEpochNumber", + "type": "uint256", + "internalType": "Epoch" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "submitEpochRootProof", + "inputs": [ + { + "name": "_args", + "type": "tuple", + "internalType": "struct SubmitEpochRootProofArgs", + "components": [ + { + "name": "start", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "end", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "args", + "type": "tuple", + "internalType": "struct PublicInputArgs", + "components": [ + { + "name": "previousArchive", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "endArchive", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "endTimestamp", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "outHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "proverId", + "type": "address", + "internalType": "address" + } + ] + }, + { + "name": "fees", + "type": "bytes32[]", + "internalType": "bytes32[]" + }, + { + "name": "blobPublicInputs", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "proof", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "updateL1GasFeeOracle", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "updateManaTarget", + "inputs": [ + { + "name": "_manaTarget", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "validateBlobs", + "inputs": [ + { + "name": "_blobsInput", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32[]", + "internalType": "bytes32[]" + }, + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "validateHeader", + "inputs": [ + { + "name": "_header", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "_signatures", + "type": "tuple[]", + "internalType": "struct Signature[]", + "components": [ + { + "name": "isEmpty", + "type": "bool", + "internalType": "bool" + }, + { + "name": "v", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "r", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "s", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "name": "_digest", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_currentTime", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "_blobsHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_flags", + "type": "tuple", + "internalType": "struct BlockHeaderValidationFlags", + "components": [ + { + "name": "ignoreDA", + "type": "bool", + "internalType": "bool" + }, + { + "name": "ignoreSignatures", + "type": "bool", + "internalType": "bool" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + } +] as const; diff --git a/tooling/sparta/packages/ethereum/src/abis/StakingAssetHandlerAbi.ts b/tooling/sparta/packages/ethereum/src/abis/StakingAssetHandlerAbi.ts new file mode 100644 index 0000000..4d1b70a --- /dev/null +++ b/tooling/sparta/packages/ethereum/src/abis/StakingAssetHandlerAbi.ts @@ -0,0 +1,1908 @@ +/** + * StakingAssetHandler ABI. + */ +export const StakingAssetHandlerAbi = [ + { + "type": "constructor", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + }, + { + "name": "_stakingAsset", + "type": "address", + "internalType": "address" + }, + { + "name": "_registry", + "type": "address", + "internalType": "contract IRegistry" + }, + { + "name": "_withdrawer", + "type": "address", + "internalType": "address" + }, + { + "name": "_mintInterval", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_depositsPerMint", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_unhinged", + "type": "address[]", + "internalType": "address[]" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "error", + "name": "AddressSnapshotLib__IndexOutOfBounds", + "inputs": [ + { + "name": "index", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "size", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "CannotMintZeroAmount", + "inputs": [] + }, + { + "type": "error", + "name": "CoinIssuer__InsufficientMintAvailable", + "inputs": [ + { + "name": "available", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "needed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "event", + "name": "DepositsPerMintUpdated", + "inputs": [ + { + "name": "_depositsPerMint", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "DevNet__InvalidProposer", + "inputs": [ + { + "name": "expected", + "type": "address", + "internalType": "address" + }, + { + "name": "actual", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "DevNet__NoPruningAllowed", + "inputs": [] + }, + { + "type": "error", + "name": "FeeJuicePortal__AlreadyInitialized", + "inputs": [] + }, + { + "type": "error", + "name": "FeeJuicePortal__InvalidInitialization", + "inputs": [] + }, + { + "type": "error", + "name": "FeeJuicePortal__Unauthorized", + "inputs": [] + }, + { + "type": "error", + "name": "FeeLib__InvalidFeeAssetPriceModifier", + "inputs": [] + }, + { + "type": "error", + "name": "GovernanceProposer__CanOnlyExecuteProposalInPast", + "inputs": [] + }, + { + "type": "error", + "name": "GovernanceProposer__FailedToPropose", + "inputs": [ + { + "name": "proposal", + "type": "address", + "internalType": "contract IPayload" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__InstanceHaveNoCode", + "inputs": [ + { + "name": "instance", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__InsufficientVotes", + "inputs": [ + { + "name": "votesCast", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "votesNeeded", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__InvalidNAndMValues", + "inputs": [ + { + "name": "n", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "m", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__NCannotBeLargerTHanM", + "inputs": [ + { + "name": "n", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "m", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__OnlyProposerCanVote", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__ProposalAlreadyExecuted", + "inputs": [ + { + "name": "roundNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__ProposalCannotBeAddressZero", + "inputs": [] + }, + { + "type": "error", + "name": "GovernanceProposer__ProposalHaveNoCode", + "inputs": [ + { + "name": "proposal", + "type": "address", + "internalType": "contract IPayload" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__ProposalTooOld", + "inputs": [ + { + "name": "roundNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "currentRoundNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "GovernanceProposer__VoteAlreadyCastForSlot", + "inputs": [ + { + "name": "slot", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Governance__CallFailed", + "inputs": [ + { + "name": "target", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Governance__CallerNotGovernanceProposer", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + }, + { + "name": "governanceProposer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Governance__CallerNotSelf", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + }, + { + "name": "self", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Governance__CannotCallAsset", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__DifferentialTooBig", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__DifferentialTooSmall", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__InvalidMinimumVotes", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__LockAmountTooSmall", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__QuorumTooBig", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__QuorumTooSmall", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__TimeTooBig", + "inputs": [ + { + "name": "name", + "type": "string", + "internalType": "string" + } + ] + }, + { + "type": "error", + "name": "Governance__ConfigurationLib__TimeTooSmall", + "inputs": [ + { + "name": "name", + "type": "string", + "internalType": "string" + } + ] + }, + { + "type": "error", + "name": "Governance__InsufficientPower", + "inputs": [ + { + "name": "voter", + "type": "address", + "internalType": "address" + }, + { + "name": "have", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Governance__InvalidConfiguration", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__NoCheckpointsFound", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalAlreadyDropped", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalCannotBeDropped", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalDoesNotExists", + "inputs": [ + { + "name": "proposalId", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Governance__ProposalLib__MoreVoteThanExistNeeded", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalLib__MoreYeaVoteThanExistNeeded", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalLib__ZeroMinimum", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalLib__ZeroVotesNeeded", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalLib__ZeroYeaVotesNeeded", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalNotActive", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__ProposalNotExecutable", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__UserLib__NotInPast", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__WithdrawalAlreadyclaimed", + "inputs": [] + }, + { + "type": "error", + "name": "Governance__WithdrawalNotUnlockedYet", + "inputs": [ + { + "name": "currentTime", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "unlocksAt", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "error", + "name": "HeaderLib__InvalidHeaderSize", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "HeaderLib__InvalidSlotNumber", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Inbox__ActorTooLarge", + "inputs": [ + { + "name": "actor", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Inbox__ContentTooLarge", + "inputs": [ + { + "name": "content", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Inbox__MustBuildBeforeConsume", + "inputs": [] + }, + { + "type": "error", + "name": "Inbox__SecretHashTooLarge", + "inputs": [ + { + "name": "secretHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Inbox__Unauthorized", + "inputs": [] + }, + { + "type": "error", + "name": "Inbox__VersionMismatch", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "event", + "name": "IntervalUpdated", + "inputs": [ + { + "name": "_interval", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "MerkleLib__InvalidRoot", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "leaf", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "leafIndex", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__AlreadyNullified", + "inputs": [ + { + "name": "l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "leafIndex", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__BlockNotProven", + "inputs": [ + { + "name": "l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__IncompatibleEntryArguments", + "inputs": [ + { + "name": "messageHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "storedFee", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "feePassed", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "storedVersion", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "versionPassed", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "storedDeadline", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "deadlinePassed", + "type": "uint32", + "internalType": "uint32" + } + ] + }, + { + "type": "error", + "name": "Outbox__InvalidChainId", + "inputs": [] + }, + { + "type": "error", + "name": "Outbox__InvalidPathLength", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__InvalidRecipient", + "inputs": [ + { + "name": "expected", + "type": "address", + "internalType": "address" + }, + { + "name": "actual", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Outbox__NothingToConsume", + "inputs": [ + { + "name": "messageHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Outbox__NothingToConsumeAtBlock", + "inputs": [ + { + "name": "l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__RootAlreadySetAtBlock", + "inputs": [ + { + "name": "l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Outbox__Unauthorized", + "inputs": [] + }, + { + "type": "error", + "name": "Outbox__VersionMismatch", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "OwnableInvalidOwner", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "OwnableUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "ProofCommitmentEscrow__InsufficientBalance", + "inputs": [ + { + "name": "balance", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "requested", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ProofCommitmentEscrow__NotOwner", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ProofCommitmentEscrow__WithdrawRequestNotReady", + "inputs": [ + { + "name": "current", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "readyAt", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "function", + "name": "REGISTRY", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IRegistry" + } + ], + "stateMutability": "view" + }, + { + "type": "error", + "name": "Registry__NoRollupsRegistered", + "inputs": [] + }, + { + "type": "error", + "name": "Registry__RollupAlreadyRegistered", + "inputs": [ + { + "name": "rollup", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Registry__RollupNotRegistered", + "inputs": [ + { + "name": "version", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "RewardDistributor__InvalidCaller", + "inputs": [ + { + "name": "caller", + "type": "address", + "internalType": "address" + }, + { + "name": "canonical", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Rollup__AlreadyClaimed", + "inputs": [ + { + "name": "prover", + "type": "address", + "internalType": "address" + }, + { + "name": "epoch", + "type": "uint256", + "internalType": "Epoch" + } + ] + }, + { + "type": "error", + "name": "Rollup__InsufficientBondAmount", + "inputs": [ + { + "name": "minimum", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provided", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InsufficientFundsInEscrow", + "inputs": [ + { + "name": "required", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "available", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidArchive", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBasisPointFee", + "inputs": [ + { + "name": "basisPointFee", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBlobHash", + "inputs": [ + { + "name": "blobHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBlobProof", + "inputs": [ + { + "name": "blobHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBlobPublicInputsHash", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidBlockNumber", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidChainId", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidInHash", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidManaBaseFee", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidPreviousArchive", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidProof", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__InvalidProposedArchive", + "inputs": [ + { + "name": "expected", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "actual", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidTimestamp", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "error", + "name": "Rollup__InvalidVersion", + "inputs": [ + { + "name": "expected", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Rollup__ManaLimitExceeded", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__NoEpochToProve", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__NonSequentialProving", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__NonZeroDaFee", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__NotPastDeadline", + "inputs": [ + { + "name": "deadline", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "currentSlot", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Rollup__NothingToPrune", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__PastDeadline", + "inputs": [ + { + "name": "deadline", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "currentSlot", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Rollup__ProverHaveAlreadySubmitted", + "inputs": [ + { + "name": "prover", + "type": "address", + "internalType": "address" + }, + { + "name": "epoch", + "type": "uint256", + "internalType": "Epoch" + } + ] + }, + { + "type": "error", + "name": "Rollup__SlotAlreadyInChain", + "inputs": [ + { + "name": "lastSlot", + "type": "uint256", + "internalType": "Slot" + }, + { + "name": "proposedSlot", + "type": "uint256", + "internalType": "Slot" + } + ] + }, + { + "type": "error", + "name": "Rollup__StartAndEndNotSameEpoch", + "inputs": [ + { + "name": "start", + "type": "uint256", + "internalType": "Epoch" + }, + { + "name": "end", + "type": "uint256", + "internalType": "Epoch" + } + ] + }, + { + "type": "error", + "name": "Rollup__StartIsNotBuildingOnProven", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__StartIsNotFirstBlockOfEpoch", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__TimestampInFuture", + "inputs": [ + { + "name": "max", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "actual", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "error", + "name": "Rollup__TimestampTooOld", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__TryingToProveNonExistingBlock", + "inputs": [] + }, + { + "type": "error", + "name": "Rollup__UnavailableTxs", + "inputs": [ + { + "name": "txsHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "function", + "name": "STAKING_ASSET", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IMintableERC20" + } + ], + "stateMutability": "view" + }, + { + "type": "error", + "name": "SampleLib__IndexOutOfBounds", + "inputs": [ + { + "name": "requested", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "bound", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "SampleLib__SampleLargerThanIndex", + "inputs": [ + { + "name": "sample", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "index", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "SignatureLib__CannotVerifyEmpty", + "inputs": [] + }, + { + "type": "error", + "name": "SignatureLib__InvalidSignature", + "inputs": [ + { + "name": "expected", + "type": "address", + "internalType": "address" + }, + { + "name": "recovered", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__AlreadyActive", + "inputs": [ + { + "name": "attester", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__AlreadyRegistered", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__CannotSlashExitedStake", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__FailedToRemove", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__InsufficientStake", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "Staking__InvalidDeposit", + "inputs": [ + { + "name": "attester", + "type": "address", + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NoOneToSlash", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NotExiting", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NotSlasher", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NotWithdrawer", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__NothingToExit", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "Staking__WithdrawalNotUnlockedYet", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "Timestamp" + }, + { + "name": "", + "type": "uint256", + "internalType": "Timestamp" + } + ] + }, + { + "type": "event", + "name": "ToppedUp", + "inputs": [ + { + "name": "_amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "UnhingedAdded", + "inputs": [ + { + "name": "_address", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "UnhingedRemoved", + "inputs": [ + { + "name": "_address", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ValidatorAdded", + "inputs": [ + { + "name": "_rollup", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "_attester", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "_proposer", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "_withdrawer", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "ValidatorQuotaFilledUntil", + "inputs": [ + { + "name": "_timestamp", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ValidatorSelection__EpochNotSetup", + "inputs": [] + }, + { + "type": "error", + "name": "ValidatorSelection__InsufficientAttestations", + "inputs": [ + { + "name": "minimumNeeded", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provided", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ValidatorSelection__InsufficientAttestationsProvided", + "inputs": [ + { + "name": "minimumNeeded", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "provided", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ValidatorSelection__InvalidDeposit", + "inputs": [ + { + "name": "attester", + "type": "address", + "internalType": "address" + }, + { + "name": "proposer", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ValidatorSelection__InvalidProposer", + "inputs": [ + { + "name": "expected", + "type": "address", + "internalType": "address" + }, + { + "name": "actual", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "event", + "name": "WithdrawerUpdated", + "inputs": [ + { + "name": "_withdrawer", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "function", + "name": "addUnhinged", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "addValidator", + "inputs": [ + { + "name": "_attester", + "type": "address", + "internalType": "address" + }, + { + "name": "_proposer", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "depositsPerMint", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRollup", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "isUnhinged", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "lastMintTimestamp", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "mintInterval", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "removeUnhinged", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setDepositsPerMint", + "inputs": [ + { + "name": "_depositsPerMint", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setMintInterval", + "inputs": [ + { + "name": "_interval", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setWithdrawer", + "inputs": [ + { + "name": "_withdrawer", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "withdrawer", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + } +] as const; diff --git a/tooling/sparta/packages/ethereum/src/abis/index.ts b/tooling/sparta/packages/ethereum/src/abis/index.ts new file mode 100644 index 0000000..b0ced9d --- /dev/null +++ b/tooling/sparta/packages/ethereum/src/abis/index.ts @@ -0,0 +1,3 @@ +export * from "./ForwarderAbi.js"; +export * from "./StakingAssetHandlerAbi.js"; +export * from "./RollupAbi.js"; diff --git a/tooling/sparta/packages/ethereum/src/bytecode/ForwarderBytecode.ts b/tooling/sparta/packages/ethereum/src/bytecode/ForwarderBytecode.ts new file mode 100644 index 0000000..6728aed --- /dev/null +++ b/tooling/sparta/packages/ethereum/src/bytecode/ForwarderBytecode.ts @@ -0,0 +1,3 @@ + +export const ForwarderBytecode = + "0x6080604052348015600e575f5ffd5b506040516105f13803806105f1833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b610505806100ec5f395ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c8063715018a61461004e5780638da5cb5b14610058578063b028e60714610076578063f2fde38b14610089575b5f5ffd5b61005661009c565b005b5f54604080516001600160a01b039092168252519081900360200190f35b6100566100843660046103d0565b6100af565b61005661009736600461043c565b610197565b6100a46101d4565b6100ad5f610200565b565b6100b76101d4565b82818181146100e757604051633a2aeb4d60e01b8152600481019290925260248201526044015b60405180910390fd5b505f90505b838110156101905761018783838381811061010957610109610462565b905060200281019061011b9190610476565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525089925088915085905081811061016357610163610462565b9050602002016020810190610178919061043c565b6001600160a01b03169061024f565b506001016100ec565b5050505050565b61019f6101d4565b6001600160a01b0381166101c857604051631e4fbdf760e01b81525f60048201526024016100de565b6101d181610200565b50565b5f546001600160a01b031633146100ad5760405163118cdaa760e01b81523360048201526024016100de565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b606061025c83835f610263565b9392505050565b60608147101561028f5760405163cf47918160e01b8152476004820152602481018390526044016100de565b5f5f856001600160a01b031684866040516102aa91906104b9565b5f6040518083038185875af1925050503d805f81146102e4576040519150601f19603f3d011682016040523d82523d5f602084013e6102e9565b606091505b50915091506102f9868383610303565b9695505050505050565b606082610318576103138261035f565b61025c565b815115801561032f57506001600160a01b0384163b155b1561035857604051639996b31560e01b81526001600160a01b03851660048201526024016100de565b508061025c565b80511561036f5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f5f83601f840112610398575f5ffd5b50813567ffffffffffffffff8111156103af575f5ffd5b6020830191508360208260051b85010111156103c9575f5ffd5b9250929050565b5f5f5f5f604085870312156103e3575f5ffd5b843567ffffffffffffffff8111156103f9575f5ffd5b61040587828801610388565b909550935050602085013567ffffffffffffffff811115610424575f5ffd5b61043087828801610388565b95989497509550505050565b5f6020828403121561044c575f5ffd5b81356001600160a01b038116811461025c575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e1984360301811261048b575f5ffd5b83018035915067ffffffffffffffff8211156104a5575f5ffd5b6020019150368190038213156103c9575f5ffd5b5f82518060208501845e5f92019182525091905056fea26469706673582212201094da15988f4705d58503cdbc19677b21e89966fdc614400045372c2317a21b64736f6c634300081b0033"; diff --git a/tooling/sparta/packages/ethereum/src/ethereum.ts b/tooling/sparta/packages/ethereum/src/ethereum.ts new file mode 100644 index 0000000..4e3cd23 --- /dev/null +++ b/tooling/sparta/packages/ethereum/src/ethereum.ts @@ -0,0 +1,253 @@ +/** + * @fileoverview Ethereum client and utilities + * @description Provides Ethereum client configuration and interaction methods + * @module sparta/ethereum + */ + +import { + type Chain, + type Hex, + createPublicClient, + getContract, + http, + encodeDeployData, + getCreate2Address, + padHex, + createWalletClient, + type WalletClient, + type PublicClient, +} from "viem"; + +import { + RollupAbi, + ForwarderAbi, + StakingAssetHandlerAbi, +} from "./abis/index.js"; +import { ForwarderBytecode } from "./bytecode/ForwarderBytecode.js"; +import { privateKeyToAccount } from "viem/accounts"; +import { logger } from "@sparta/utils"; + +// Chain information data type +export type ChainInfo = { + pendingBlockNum: string; + provenBlockNum: string; + validators: string[]; + committee: string[]; + currentEpoch: string; + currentSlot: string; + proposerNow: string; +}; + +export const DEPLOYER_ADDRESS: Hex = + "0x4e59b44847b379578588920cA78FbF26c0B4956C"; + +/** + * Ethereum chain configuration + * @const {Object} ethereumChain + */ +const ethereumChain: Chain = { + id: parseInt(process.env.L1_CHAIN_ID as string), + name: "Sepolia", + nativeCurrency: { + decimals: 18, + name: "Ethereum", + symbol: "ETH", + }, + rpcUrls: { + default: { + http: [process.env.ETHEREUM_HOST as string], + }, + public: { + http: [process.env.ETHEREUM_HOST as string], + }, + }, +} as const; + +export function getExpectedAddress(args: [`0x${string}`], salt: Hex) { + const paddedSalt = padHex(salt, { size: 32 }); + const calldata = encodeDeployData({ + abi: ForwarderAbi, + bytecode: ForwarderBytecode, + args, + }); + const address = getCreate2Address({ + from: DEPLOYER_ADDRESS, + salt: paddedSalt, + bytecode: calldata, + }); + return { + address, + paddedSalt, + calldata, + }; +} + +export class Ethereum { + constructor(private rollup: any, private stakingAssetHandler: any, private publicClient: PublicClient, private walletClient: WalletClient) {} + + static new = async () => { + try { + logger.info("Initializing Ethereum client"); + const rpcUrl = process.env.ETHEREUM_HOST as string; + + if (!rpcUrl) { + throw new Error( + "ETHEREUM_HOST environment variable is not set or not loaded yet." + ); + } + + const publicClient = createPublicClient({ + chain: ethereumChain, + transport: http(rpcUrl), + }); + + + const privateKey = process.env.SPARTA_PRIVATE_KEY as `0x${string}`; + + const walletClient = createWalletClient({ + account: privateKeyToAccount(privateKey), + chain: ethereumChain, + transport: http(rpcUrl), + }); + + + const stakingAssetHandler = getContract({ + address: process.env + .STAKING_ASSET_HANDLER_ADDRESS as `0x${string}`, + abi: StakingAssetHandlerAbi, + client: walletClient, + }); + + const rollupAddress = await stakingAssetHandler.read.getRollup(); + + const rollup = getContract({ + address: rollupAddress as `0x${string}`, + abi: RollupAbi, + client: publicClient, + }); + + return new Ethereum(rollup, stakingAssetHandler, publicClient, walletClient); + } catch (error: unknown) { + logger.error({ error }, "Error initializing Ethereum client"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error(String(error)); + } + } + }; + + getRollup = () => { + return this.rollup; + }; + + /** + * Retrieves comprehensive information about the current blockchain state + * + * @returns {Promise} A promise that resolves to an object containing chain information + * @throws Will throw an error if retrieving chain information fails + */ + getRollupInfo = async (): Promise => { + try { + // Make API calls to fetch blockchain info + const [ + pendingBlockNum, + provenBlockNum, + validators, + committee, + currentEpoch, + currentSlot, + proposerNow, + ] = await Promise.all([ + this.rollup.read.getPendingBlockNumber(), + this.rollup.read.getProvenBlockNumber(), + this.rollup.read.getAttesters(), + this.rollup.read.getCurrentEpochCommittee(), + this.rollup.read.getCurrentEpoch(), + this.rollup.read.getCurrentSlot(), + this.rollup.read.getCurrentProposer(), + ]); + + logger.info("Retrieved chain info from Ethereum rollup"); + + return { + pendingBlockNum: pendingBlockNum, + provenBlockNum: provenBlockNum, + validators: validators, + committee: committee, + currentEpoch: currentEpoch, + currentSlot: currentSlot, + proposerNow: proposerNow, + }; + } catch (error: unknown) { + logger.error({ error }, "Error getting rollup info"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error(String(error)); + } + } + }; + + /** + * Adds a validator to the rollup system + * + * @param {string} validatorAddress - Ethereum address of the validator to add + * @returns {Promise} True if the validator was added successfully + * @throws Will throw an error if adding the validator fails + */ + addValidator = async (validatorAddress: string): Promise => { + try { + logger.info({ validatorAddress }, "Adding validator to rollup"); + + const tx = await this.stakingAssetHandler.write.addValidator([validatorAddress as `0x${string}`, validatorAddress as `0x${string}`]); + const receipt = await this.publicClient.waitForTransactionReceipt({ hash: tx }); + + if (receipt.status === "success") { + logger.info({ validatorAddress }, "Successfully added validator to rollup"); + return true; + } else { + logger.error({ validatorAddress }, "Failed to add validator to rollup"); + return false; + } + } catch (error: unknown) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error(String(error)); + } + } + }; +} + +// --- Lazy Initialization --- +let ethereumInstance: Ethereum | null = null; + +/** + * Gets the singleton instance of the Ethereum client, initializing it on first call. + */ +export async function getEthereumInstance(): Promise { + if (!ethereumInstance) { + logger.info( + "First call to getEthereumInstance, initializing Ethereum singleton..." + ); + try { + ethereumInstance = await Ethereum.new(); + logger.info("Ethereum singleton initialized successfully."); + } catch (error: unknown) { + logger.error( + { error }, + "Failed to initialize Ethereum singleton in getEthereumInstance" + ); + // Re-throw the error to propagate it to the caller + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error(String(error)); + } + } + } + return ethereumInstance; +} + +export { ethereumChain }; // Export chain config for validator-service diff --git a/tooling/sparta/packages/ethereum/src/index.ts b/tooling/sparta/packages/ethereum/src/index.ts new file mode 100644 index 0000000..652453a --- /dev/null +++ b/tooling/sparta/packages/ethereum/src/index.ts @@ -0,0 +1,15 @@ +/** + * @fileoverview Entry point for the ethereum package + * @module sparta/ethereum + */ + +export { + Ethereum, + getEthereumInstance, + ethereumChain, + getExpectedAddress, + DEPLOYER_ADDRESS, + type ChainInfo, +} from "./ethereum"; + +export { l2InfoService } from "./l2-info-service"; diff --git a/tooling/sparta/packages/ethereum/src/l2-info-service.ts b/tooling/sparta/packages/ethereum/src/l2-info-service.ts new file mode 100644 index 0000000..53a875c --- /dev/null +++ b/tooling/sparta/packages/ethereum/src/l2-info-service.ts @@ -0,0 +1,329 @@ +/** + * @fileoverview L2 Information service for blockchain data via JSON-RPC + * @description Provides methods for retrieving L2 blockchain state and validator information + * @module sparta/discord/services + */ + +import { logger } from "@sparta/utils/logger"; + +// RPC endpoint URL +const DEFAULT_RPC_URL = process.env.RPC_URL || "http://35.230.8.105:8080"; // Use env var or default +const RPC_METHOD_VALIDATOR_STATS = "node_getValidatorsStats"; + +// --- Define types based on RPC response --- + +interface SlotInfo { + timestamp: bigint; + slot: bigint; + date: string; +} + +interface ValidatorStats { + address: string; // EthAddress as string + lastProposal?: SlotInfo; + lastAttestation?: SlotInfo; + totalSlots: number; + // Simplified missed stats for this use case, add more if needed + missedProposals: { count: number }; + missedAttestations: { count: number }; + // history: ValidatorStatusHistory; // Assuming history is not directly needed for this check +} + +interface ValidatorsStatsResponse { + stats: { [address: string]: ValidatorStats }; + lastProcessedSlot?: bigint; + initialSlot?: bigint; + slotWindow: number; +} + +interface JsonRpcResponse { + jsonrpc: string; + result?: any; // Make result optional and generic for different RPC methods + id: number; + error?: { code: number; message: string }; // Optional error object +} + +/** + * Result structure for the RPC-based attestation check + */ +interface RpcAttestationResult { + hasAttested24h: boolean; + lastAttestationSlot?: bigint; + lastAttestationTimestamp?: bigint; + lastAttestationDate?: string; + lastProposalSlot?: bigint; + lastProposalTimestamp?: bigint; + lastProposalDate?: string; + missedAttestationsCount?: number; + missedProposalsCount?: number; + totalSlots?: number; + error?: string; +} + +/** + * Service for retrieving L2 blockchain information and validator data via RPC + */ +export class L2InfoService { + private static instance: L2InfoService | null = null; + private rpcUrl: string; + private initialized: boolean = false; + + private constructor() { + this.rpcUrl = DEFAULT_RPC_URL; + } + + /** + * Gets the singleton instance of L2InfoService + */ + public static getInstance(): L2InfoService { + if (!L2InfoService.instance) { + L2InfoService.instance = new L2InfoService(); + } + return L2InfoService.instance; + } + + /** + * Initialize the service with custom RPC URL if provided + */ + public async init(rpcUrl?: string): Promise { + if (this.initialized) return; // Already initialized + + try { + // If AZTEC_NODE_URL is available in env, use it instead of default + this.rpcUrl = + rpcUrl || process.env.AZTEC_NODE_URL || DEFAULT_RPC_URL; + this.initialized = true; + logger.info( + `L2InfoService initialized with RPC URL: ${this.rpcUrl}` + ); + } catch (error) { + logger.error(error, "Failed to initialize L2InfoService"); + throw error; + } + } + + /** + * Send a JSON-RPC request to the configured endpoint + * @param method RPC method name + * @param params Array of parameters to pass to the method + * @returns The result field from the RPC response + */ + private async sendJsonRpcRequest( + method: string, + params: any[] = [] + ): Promise { + try { + // Initialize if not already done + if (!this.initialized) { + await this.init(); + } + + const response = await fetch(this.rpcUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + method, + params, + id: 1, // Arbitrary ID + }), + }); + + if (!response.ok) { + throw new Error( + `HTTP error! status: ${response.status} ${response.statusText}` + ); + } + + const data: JsonRpcResponse = await response.json(); + + if (data.error) { + throw new Error( + `RPC error! code: ${data.error.code}, message: ${data.error.message}` + ); + } + + if (data.result === undefined) { + throw new Error("RPC response missing result field."); + } + + return data.result; + } catch (error) { + logger.error(error,`Error in RPC call to ${method}`); + throw error; + } + } + + /** + * Get the latest L2 block tips + * @returns The proven block number as a string + */ + public async getL2Tips(): Promise { + try { + const result = await this.sendJsonRpcRequest("node_getL2Tips"); + return result.proven.number as string; + } catch (error) { + logger.error(error, "Error getting L2 tips:"); + throw error; + } + } + + /** + * Get archive sibling path for a block + * @param blockNumber The block number to get the path for + * @returns The archive sibling path + */ + public async getArchiveSiblingPath(blockNumber: string): Promise { + try { + // Assuming the RPC method takes blockNumber as a parameter. + // The previous version passed it twice, let's try with one first. + return await this.sendJsonRpcRequest("node_getArchiveSiblingPath", [ + blockNumber, + blockNumber, + ]); + } catch (error) { + logger.error( + error, + `Error getting archive sibling path for block ${blockNumber}:`, + ); + throw error; + } + } + + /** + * Fetches validator stats via RPC and checks recent attestation. + * @param targetAddress Ethereum address to check (lowercase expected by RPC) + * @returns Attestation status with details from RPC + */ + public async fetchValidatorStats( + targetAddress: string + ): Promise { + try { + // Ensure address is lowercase for matching keys in the response + const lowerCaseAddress = targetAddress.toLowerCase(); + + const data = (await this.sendJsonRpcRequest( + RPC_METHOD_VALIDATOR_STATS, + [] + )) as ValidatorsStatsResponse; + + const validatorStats = data.stats[lowerCaseAddress]; + + if (!validatorStats) { + return { + hasAttested24h: false, + error: `Validator ${targetAddress} not found in node stats.`, + }; + } + + const lastAttestation = validatorStats.lastAttestation; + const lastProposal = validatorStats.lastProposal; + let hasAttested24h = false; + let lastAttestationTimestampBigInt: bigint | undefined = undefined; + let lastProposalTimestampBigInt: bigint | undefined = undefined; + let lastProposalSlotBigInt: bigint | undefined = undefined; + let lastProposalDate: string | undefined = undefined; + + if (lastAttestation) { + try { + lastAttestationTimestampBigInt = BigInt( + lastAttestation.timestamp + ); + const nowSeconds = BigInt(Math.floor(Date.now() / 1000)); + const twentyFourHoursAgoSeconds = + nowSeconds - BigInt(24 * 60 * 60); + + if ( + lastAttestationTimestampBigInt >= + twentyFourHoursAgoSeconds + ) { + hasAttested24h = true; + } + } catch (e) { + logger.error(e, "Error converting attestation timestamp to BigInt"); + } + } + + if (lastProposal) { + try { + lastProposalTimestampBigInt = BigInt( + lastProposal.timestamp + ); + lastProposalSlotBigInt = BigInt(lastProposal.slot); + lastProposalDate = lastProposal.date; + } catch (e) { + logger.error(e, "Error converting proposal timestamp/slot to BigInt"); + } + } + + return { + hasAttested24h, + lastAttestationSlot: lastAttestation + ? BigInt(lastAttestation.slot) + : undefined, + lastAttestationTimestamp: lastAttestationTimestampBigInt, + lastAttestationDate: lastAttestation?.date, + lastProposalSlot: lastProposalSlotBigInt, + lastProposalTimestamp: lastProposalTimestampBigInt, + lastProposalDate: lastProposalDate, + missedAttestationsCount: + validatorStats.missedAttestations?.count, + missedProposalsCount: validatorStats.missedProposals?.count, + totalSlots: validatorStats.totalSlots, + error: undefined, // No error if we got this far + }; + } catch (error) { + logger.error(error, "Error fetching or processing validator stats via RPC"); + return { + hasAttested24h: false, + error: + error instanceof Error + ? error.message + : "Unknown error during RPC fetch", + lastAttestationSlot: undefined, + lastAttestationTimestamp: undefined, + lastAttestationDate: undefined, + lastProposalSlot: undefined, + lastProposalTimestamp: undefined, + lastProposalDate: undefined, + missedAttestationsCount: undefined, + missedProposalsCount: undefined, + totalSlots: undefined, + }; + } + } + + /** + * Verifies if a provided proof is valid for a given block number + * @param blockNumber The block number to check + * @param proof The proof string to validate + * @returns True if proof is valid, false otherwise + */ + public async proveSynced(blockNumber: string, proof: string): Promise { + if (process.env.BYPASS_SYNC_CHECK === "true") { + // logger.info("Sync check bypassed via environment variable."); + return true; + } + + const tip = await this.getL2Tips(); + if (Number(tip) > Number(blockNumber) + 100) { + // Adding a specific log message for this condition + logger.warn(`Proof is too old for block ${blockNumber}. Current tip: ${tip}`); + throw new Error("Proof is too old"); + } + + const rpcProof = await this.getArchiveSiblingPath(blockNumber); + if (rpcProof === proof) { + return true; + } else { + // Adding a log message for failed proof verification + logger.warn(`Proof mismatch for block ${blockNumber}. Expected: ${rpcProof}, Got: ${proof}`); + return false; + } + } +} + +// Export a singleton instance +export const l2InfoService = L2InfoService.getInstance(); diff --git a/tooling/sparta/packages/ethereum/tsconfig.json b/tooling/sparta/packages/ethereum/tsconfig.json new file mode 100644 index 0000000..27329a5 --- /dev/null +++ b/tooling/sparta/packages/ethereum/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + "composite": true, + "declaration": true, + "declarationMap": true, + "noUnusedLocals": false, + "noUnusedParameters": false + }, + "include": ["src/**/*", "src/abis", "src/bytecode"], + "references": [{ "path": "../utils" }] +} diff --git a/tooling/sparta/packages/ethereum/tsconfig.tsbuildinfo b/tooling/sparta/packages/ethereum/tsconfig.tsbuildinfo new file mode 100644 index 0000000..3ace060 --- /dev/null +++ b/tooling/sparta/packages/ethereum/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/typescript/lib/lib.es2023.d.ts","../../node_modules/typescript/lib/lib.es2024.d.ts","../../node_modules/typescript/lib/lib.esnext.d.ts","../../node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../node_modules/typescript/lib/lib.dom.asynciterable.d.ts","../../node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../node_modules/typescript/lib/lib.scripthost.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../node_modules/typescript/lib/lib.es2023.array.d.ts","../../node_modules/typescript/lib/lib.es2023.collection.d.ts","../../node_modules/typescript/lib/lib.es2023.intl.d.ts","../../node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2024.collection.d.ts","../../node_modules/typescript/lib/lib.es2024.object.d.ts","../../node_modules/typescript/lib/lib.es2024.promise.d.ts","../../node_modules/typescript/lib/lib.es2024.regexp.d.ts","../../node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2024.string.d.ts","../../node_modules/typescript/lib/lib.esnext.array.d.ts","../../node_modules/typescript/lib/lib.esnext.collection.d.ts","../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../node_modules/typescript/lib/lib.esnext.promise.d.ts","../../node_modules/typescript/lib/lib.esnext.decorators.d.ts","../../node_modules/typescript/lib/lib.esnext.iterator.d.ts","../../node_modules/typescript/lib/lib.esnext.float16.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../node_modules/typescript/lib/lib.esnext.full.d.ts","../../node_modules/abitype/dist/types/register.d.ts","../../node_modules/abitype/dist/types/types.d.ts","../../node_modules/abitype/dist/types/abi.d.ts","../../node_modules/abitype/dist/types/errors.d.ts","../../node_modules/abitype/dist/types/narrow.d.ts","../../node_modules/abitype/dist/types/utils.d.ts","../../node_modules/abitype/dist/types/human-readable/types/signatures.d.ts","../../node_modules/abitype/dist/types/human-readable/formatAbiParameter.d.ts","../../node_modules/abitype/dist/types/human-readable/formatAbiParameters.d.ts","../../node_modules/abitype/dist/types/human-readable/formatAbiItem.d.ts","../../node_modules/abitype/dist/types/human-readable/formatAbi.d.ts","../../node_modules/abitype/dist/types/human-readable/types/utils.d.ts","../../node_modules/abitype/dist/types/human-readable/types/structs.d.ts","../../node_modules/abitype/dist/types/human-readable/parseAbi.d.ts","../../node_modules/abitype/dist/types/human-readable/parseAbiItem.d.ts","../../node_modules/abitype/dist/types/human-readable/parseAbiParameter.d.ts","../../node_modules/abitype/dist/types/human-readable/parseAbiParameters.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/abiItem.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/abiParameter.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/signature.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/splitParameters.d.ts","../../node_modules/abitype/dist/types/human-readable/errors/struct.d.ts","../../node_modules/abitype/dist/types/exports/index.d.ts","../../node_modules/ox/_types/core/Errors.d.ts","../../node_modules/ox/_types/core/internal/bytes.d.ts","../../node_modules/ox/_types/core/internal/hex.d.ts","../../node_modules/ox/_types/core/Hex.d.ts","../../node_modules/ox/_types/core/Bytes.d.ts","../../node_modules/ox/_types/core/Hash.d.ts","../../node_modules/ox/_types/core/internal/types.d.ts","../../node_modules/ox/_types/core/PublicKey.d.ts","../../node_modules/ox/_types/core/Address.d.ts","../../node_modules/ox/_types/core/Withdrawal.d.ts","../../node_modules/ox/_types/core/BlockOverrides.d.ts","../../node_modules/ox/_types/core/Base64.d.ts","../../node_modules/ox/_types/core/Signature.d.ts","../../node_modules/@noble/curves/esm/abstract/utils.d.ts","../../node_modules/@noble/curves/esm/abstract/modular.d.ts","../../node_modules/@noble/curves/esm/abstract/curve.d.ts","../../node_modules/@noble/curves/esm/abstract/weierstrass.d.ts","../../node_modules/ox/_types/core/P256.d.ts","../../node_modules/ox/_types/core/internal/webauthn.d.ts","../../node_modules/ox/_types/core/WebAuthnP256.d.ts","../../node_modules/viem/_types/errors/utils.d.ts","../../node_modules/viem/_types/accounts/utils/parseAccount.d.ts","../../node_modules/viem/_types/types/utils.d.ts","../../node_modules/@scure/bip32/lib/esm/index.d.ts","../../node_modules/viem/_types/types/account.d.ts","../../node_modules/ox/_types/core/AbiItem.d.ts","../../node_modules/ox/_types/core/internal/cursor.d.ts","../../node_modules/ox/_types/core/internal/abiParameters.d.ts","../../node_modules/ox/_types/core/AbiParameters.d.ts","../../node_modules/ox/_types/core/internal/abiItem.d.ts","../../node_modules/ox/_types/core/Abi.d.ts","../../node_modules/ox/_types/core/internal/abiConstructor.d.ts","../../node_modules/ox/_types/core/AbiConstructor.d.ts","../../node_modules/ox/_types/core/internal/abiError.d.ts","../../node_modules/ox/_types/core/AbiError.d.ts","../../node_modules/ox/_types/core/AccessList.d.ts","../../node_modules/ox/_types/core/Rlp.d.ts","../../node_modules/ox/_types/core/Authorization.d.ts","../../node_modules/ox/_types/core/Transaction.d.ts","../../node_modules/ox/_types/core/Block.d.ts","../../node_modules/ox/_types/core/Filter.d.ts","../../node_modules/ox/_types/core/internal/abiEvent.d.ts","../../node_modules/ox/_types/core/AbiEvent.d.ts","../../node_modules/ox/_types/core/internal/abiFunction.d.ts","../../node_modules/ox/_types/core/AbiFunction.d.ts","../../node_modules/ox/_types/core/AccountProof.d.ts","../../node_modules/ox/_types/core/AesGcm.d.ts","../../node_modules/ox/_types/core/internal/base58.d.ts","../../node_modules/ox/_types/core/Base58.d.ts","../../node_modules/ox/_types/core/BinaryStateTree.d.ts","../../node_modules/ox/_types/core/Kzg.d.ts","../../node_modules/ox/_types/core/Blobs.d.ts","../../node_modules/ox/_types/core/Bloom.d.ts","../../node_modules/ox/_types/core/BlsPoint.d.ts","../../node_modules/@noble/curves/esm/abstract/hash-to-curve.d.ts","../../node_modules/@noble/curves/esm/abstract/tower.d.ts","../../node_modules/@noble/curves/esm/abstract/bls.d.ts","../../node_modules/ox/_types/core/Bls.d.ts","../../node_modules/ox/_types/core/internal/lru.d.ts","../../node_modules/ox/_types/core/Caches.d.ts","../../node_modules/ox/_types/core/ContractAddress.d.ts","../../node_modules/ox/_types/core/internal/ens.d.ts","../../node_modules/ox/_types/core/Ens.d.ts","../../node_modules/ox/_types/core/internal/hdKey.d.ts","../../node_modules/ox/_types/core/HdKey.d.ts","../../node_modules/ox/_types/core/Fee.d.ts","../../node_modules/ox/_types/core/Json.d.ts","../../node_modules/ox/_types/core/Log.d.ts","../../node_modules/@scure/bip39/esm/wordlists/czech.d.ts","../../node_modules/@scure/bip39/esm/wordlists/english.d.ts","../../node_modules/@scure/bip39/esm/wordlists/french.d.ts","../../node_modules/@scure/bip39/esm/wordlists/italian.d.ts","../../node_modules/@scure/bip39/esm/wordlists/japanese.d.ts","../../node_modules/@scure/bip39/esm/wordlists/korean.d.ts","../../node_modules/@scure/bip39/esm/wordlists/portuguese.d.ts","../../node_modules/@scure/bip39/esm/wordlists/simplified-chinese.d.ts","../../node_modules/@scure/bip39/esm/wordlists/spanish.d.ts","../../node_modules/@scure/bip39/esm/wordlists/traditional-chinese.d.ts","../../node_modules/ox/_types/core/internal/mnemonic/wordlists.d.ts","../../node_modules/ox/_types/core/Mnemonic.d.ts","../../node_modules/ox/_types/core/PersonalMessage.d.ts","../../node_modules/ox/node_modules/eventemitter3/index.d.ts","../../node_modules/ox/_types/core/internal/register.d.ts","../../node_modules/ox/_types/core/StateOverrides.d.ts","../../node_modules/ox/_types/core/TransactionReceipt.d.ts","../../node_modules/ox/_types/core/TransactionRequest.d.ts","../../node_modules/ox/_types/core/internal/rpcSchemas/eth.d.ts","../../node_modules/ox/_types/core/internal/rpcSchemas/wallet.d.ts","../../node_modules/ox/_types/core/RpcSchema.d.ts","../../node_modules/ox/_types/core/internal/rpcSchema.d.ts","../../node_modules/ox/_types/core/Provider.d.ts","../../node_modules/ox/_types/core/RpcRequest.d.ts","../../node_modules/ox/_types/core/internal/promise.d.ts","../../node_modules/ox/_types/core/internal/rpcTransport.d.ts","../../node_modules/ox/_types/core/RpcTransport.d.ts","../../node_modules/ox/_types/core/Secp256k1.d.ts","../../node_modules/ox/_types/core/Siwe.d.ts","../../node_modules/ox/_types/core/Solidity.d.ts","../../node_modules/ox/_types/core/TransactionEnvelope.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeLegacy.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeEip1559.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeEip2930.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeEip4844.d.ts","../../node_modules/ox/_types/core/TransactionEnvelopeEip7702.d.ts","../../node_modules/ox/_types/core/TypedData.d.ts","../../node_modules/ox/_types/core/ValidatorData.d.ts","../../node_modules/ox/_types/core/Value.d.ts","../../node_modules/ox/_types/core/WebCryptoP256.d.ts","../../node_modules/ox/_types/index.d.ts","../../node_modules/ox/_types/core/RpcResponse.d.ts","../../node_modules/viem/_types/types/misc.d.ts","../../node_modules/viem/_types/types/authorization.d.ts","../../node_modules/viem/_types/types/eip4844.d.ts","../../node_modules/viem/_types/types/fee.d.ts","../../node_modules/viem/_types/types/kzg.d.ts","../../node_modules/viem/_types/types/contract.d.ts","../../node_modules/viem/_types/types/log.d.ts","../../node_modules/viem/_types/types/transaction.d.ts","../../node_modules/viem/_types/types/withdrawal.d.ts","../../node_modules/viem/_types/types/block.d.ts","../../node_modules/viem/_types/types/proof.d.ts","../../node_modules/viem/_types/types/rpc.d.ts","../../node_modules/viem/_types/account-abstraction/types/entryPointVersion.d.ts","../../node_modules/viem/_types/account-abstraction/types/userOperation.d.ts","../../node_modules/viem/_types/account-abstraction/types/rpc.d.ts","../../node_modules/viem/_types/errors/base.d.ts","../../node_modules/viem/_types/errors/request.d.ts","../../node_modules/viem/_types/errors/rpc.d.ts","../../node_modules/viem/_types/utils/promise/createBatchScheduler.d.ts","../../node_modules/viem/_types/utils/promise/withRetry.d.ts","../../node_modules/viem/_types/utils/rpc/socket.d.ts","../../node_modules/viem/_types/utils/buildRequest.d.ts","../../node_modules/viem/_types/experimental/erc7895/actions/addSubAccount.d.ts","../../node_modules/viem/_types/utils/siwe/types.d.ts","../../node_modules/viem/_types/types/register.d.ts","../../node_modules/viem/_types/types/capabilities.d.ts","../../node_modules/viem/_types/types/eip1193.d.ts","../../node_modules/viem/_types/clients/transports/createTransport.d.ts","../../node_modules/viem/_types/errors/fee.d.ts","../../node_modules/viem/_types/types/stateOverride.d.ts","../../node_modules/viem/_types/utils/signature/recoverAddress.d.ts","../../node_modules/viem/_types/utils/data/concat.d.ts","../../node_modules/viem/_types/utils/data/isHex.d.ts","../../node_modules/viem/_types/errors/data.d.ts","../../node_modules/viem/_types/utils/data/pad.d.ts","../../node_modules/viem/_types/errors/encoding.d.ts","../../node_modules/viem/_types/utils/data/size.d.ts","../../node_modules/viem/_types/utils/data/trim.d.ts","../../node_modules/viem/_types/utils/encoding/fromHex.d.ts","../../node_modules/viem/_types/utils/encoding/toHex.d.ts","../../node_modules/viem/_types/utils/encoding/toBytes.d.ts","../../node_modules/viem/_types/errors/cursor.d.ts","../../node_modules/viem/_types/utils/cursor.d.ts","../../node_modules/viem/_types/utils/encoding/toRlp.d.ts","../../node_modules/viem/_types/utils/hash/keccak256.d.ts","../../node_modules/viem/_types/utils/authorization/hashAuthorization.d.ts","../../node_modules/viem/_types/utils/authorization/recoverAuthorizationAddress.d.ts","../../node_modules/viem/_types/errors/estimateGas.d.ts","../../node_modules/viem/_types/errors/transaction.d.ts","../../node_modules/viem/_types/utils/transaction/getTransactionType.d.ts","../../node_modules/viem/_types/utils/authorization/serializeAuthorizationList.d.ts","../../node_modules/viem/_types/utils/blob/blobsToCommitments.d.ts","../../node_modules/viem/_types/utils/blob/blobsToProofs.d.ts","../../node_modules/viem/_types/utils/hash/sha256.d.ts","../../node_modules/viem/_types/utils/blob/commitmentToVersionedHash.d.ts","../../node_modules/viem/_types/utils/blob/commitmentsToVersionedHashes.d.ts","../../node_modules/viem/_types/errors/blob.d.ts","../../node_modules/viem/_types/utils/blob/toBlobs.d.ts","../../node_modules/viem/_types/utils/blob/toBlobSidecars.d.ts","../../node_modules/viem/_types/errors/address.d.ts","../../node_modules/viem/_types/errors/chain.d.ts","../../node_modules/viem/_types/errors/node.d.ts","../../node_modules/viem/_types/utils/lru.d.ts","../../node_modules/viem/_types/utils/address/isAddress.d.ts","../../node_modules/viem/_types/utils/transaction/assertTransaction.d.ts","../../node_modules/viem/_types/utils/transaction/serializeAccessList.d.ts","../../node_modules/viem/_types/utils/transaction/serializeTransaction.d.ts","../../node_modules/viem/_types/accounts/utils/sign.d.ts","../../node_modules/viem/_types/accounts/utils/signTransaction.d.ts","../../node_modules/viem/_types/errors/account.d.ts","../../node_modules/viem/_types/utils/chain/assertCurrentChain.d.ts","../../node_modules/viem/_types/utils/errors/getTransactionError.d.ts","../../node_modules/viem/_types/utils/formatters/formatter.d.ts","../../node_modules/viem/_types/utils/formatters/transactionRequest.d.ts","../../node_modules/viem/_types/utils/transaction/assertRequest.d.ts","../../node_modules/viem/_types/actions/public/getChainId.d.ts","../../node_modules/viem/_types/actions/wallet/sendRawTransaction.d.ts","../../node_modules/viem/_types/actions/wallet/sendTransaction.d.ts","../../node_modules/viem/_types/utils/errors/getNodeError.d.ts","../../node_modules/viem/_types/utils/errors/getEstimateGasError.d.ts","../../node_modules/viem/_types/actions/public/estimateGas.d.ts","../../node_modules/viem/_types/errors/block.d.ts","../../node_modules/viem/_types/utils/formatters/transaction.d.ts","../../node_modules/viem/_types/utils/formatters/block.d.ts","../../node_modules/viem/_types/actions/public/getBlock.d.ts","../../node_modules/viem/_types/actions/public/getTransactionCount.d.ts","../../node_modules/viem/_types/utils/nonceManager.d.ts","../../node_modules/viem/_types/actions/wallet/prepareTransactionRequest.d.ts","../../node_modules/viem/_types/actions/public/getGasPrice.d.ts","../../node_modules/viem/_types/actions/public/estimateMaxPriorityFeePerGas.d.ts","../../node_modules/viem/_types/actions/public/estimateFeesPerGas.d.ts","../../node_modules/viem/_types/types/chain.d.ts","../../node_modules/viem/_types/errors/abi.d.ts","../../node_modules/viem/_types/utils/data/slice.d.ts","../../node_modules/viem/_types/utils/hash/hashSignature.d.ts","../../node_modules/viem/_types/utils/hash/normalizeSignature.d.ts","../../node_modules/viem/_types/utils/hash/toSignature.d.ts","../../node_modules/viem/_types/utils/hash/toSignatureHash.d.ts","../../node_modules/viem/_types/utils/hash/toFunctionSelector.d.ts","../../node_modules/viem/_types/utils/address/getAddress.d.ts","../../node_modules/viem/_types/utils/encoding/fromBytes.d.ts","../../node_modules/viem/_types/utils/abi/decodeAbiParameters.d.ts","../../node_modules/viem/_types/utils/abi/formatAbiItem.d.ts","../../node_modules/viem/_types/utils/abi/decodeErrorResult.d.ts","../../node_modules/viem/_types/errors/contract.d.ts","../../node_modules/viem/_types/utils/abi/getAbiItem.d.ts","../../node_modules/viem/_types/utils/abi/decodeFunctionResult.d.ts","../../node_modules/viem/_types/utils/abi/encodeAbiParameters.d.ts","../../node_modules/viem/_types/utils/abi/encodeDeployData.d.ts","../../node_modules/viem/_types/utils/abi/encodeFunctionData.d.ts","../../node_modules/viem/_types/utils/chain/getChainContractAddress.d.ts","../../node_modules/viem/_types/utils/errors/getCallError.d.ts","../../node_modules/viem/_types/errors/stateOverride.d.ts","../../node_modules/viem/_types/utils/stateOverride.d.ts","../../node_modules/viem/_types/actions/public/call.d.ts","../../node_modules/viem/_types/errors/ccip.d.ts","../../node_modules/viem/_types/utils/ccip.d.ts","../../node_modules/viem/_types/utils/ens/encodedLabelToLabelhash.d.ts","../../node_modules/viem/_types/utils/ens/namehash.d.ts","../../node_modules/viem/_types/utils/ens/encodeLabelhash.d.ts","../../node_modules/viem/_types/utils/ens/labelhash.d.ts","../../node_modules/viem/_types/utils/ens/packetToBytes.d.ts","../../node_modules/viem/_types/utils/errors/getContractError.d.ts","../../node_modules/viem/_types/actions/public/readContract.d.ts","../../node_modules/viem/_types/actions/ens/getEnsAddress.d.ts","../../node_modules/viem/_types/types/ens.d.ts","../../node_modules/viem/_types/errors/ens.d.ts","../../node_modules/viem/_types/utils/ens/avatar/utils.d.ts","../../node_modules/viem/_types/utils/ens/avatar/parseAvatarRecord.d.ts","../../node_modules/viem/_types/actions/ens/getEnsText.d.ts","../../node_modules/viem/_types/actions/ens/getEnsAvatar.d.ts","../../node_modules/viem/_types/actions/ens/getEnsName.d.ts","../../node_modules/viem/_types/actions/ens/getEnsResolver.d.ts","../../node_modules/viem/_types/actions/public/createAccessList.d.ts","../../node_modules/viem/_types/types/filter.d.ts","../../node_modules/viem/_types/actions/public/createBlockFilter.d.ts","../../node_modules/viem/_types/errors/log.d.ts","../../node_modules/viem/_types/utils/hash/toEventSelector.d.ts","../../node_modules/viem/_types/utils/abi/encodeEventTopics.d.ts","../../node_modules/viem/_types/actions/public/createContractEventFilter.d.ts","../../node_modules/viem/_types/actions/public/createEventFilter.d.ts","../../node_modules/viem/_types/actions/public/createPendingTransactionFilter.d.ts","../../node_modules/viem/_types/actions/public/estimateContractGas.d.ts","../../node_modules/viem/_types/actions/public/getBalance.d.ts","../../node_modules/viem/_types/actions/public/getBlobBaseFee.d.ts","../../node_modules/viem/_types/utils/promise/withCache.d.ts","../../node_modules/viem/_types/actions/public/getBlockNumber.d.ts","../../node_modules/viem/_types/actions/public/getBlockTransactionCount.d.ts","../../node_modules/viem/_types/actions/public/getCode.d.ts","../../node_modules/viem/_types/utils/abi/decodeEventLog.d.ts","../../node_modules/viem/_types/utils/formatters/log.d.ts","../../node_modules/viem/_types/actions/public/getLogs.d.ts","../../node_modules/viem/_types/actions/public/getContractEvents.d.ts","../../node_modules/viem/_types/errors/eip712.d.ts","../../node_modules/viem/_types/actions/public/getEip712Domain.d.ts","../../node_modules/viem/_types/utils/formatters/feeHistory.d.ts","../../node_modules/viem/_types/actions/public/getFeeHistory.d.ts","../../node_modules/viem/_types/actions/public/getFilterChanges.d.ts","../../node_modules/viem/_types/actions/public/getFilterLogs.d.ts","../../node_modules/viem/_types/utils/formatters/proof.d.ts","../../node_modules/viem/_types/actions/public/getProof.d.ts","../../node_modules/viem/_types/actions/public/getStorageAt.d.ts","../../node_modules/viem/_types/actions/public/getTransaction.d.ts","../../node_modules/viem/_types/utils/formatters/transactionReceipt.d.ts","../../node_modules/viem/_types/actions/public/getTransactionConfirmations.d.ts","../../node_modules/viem/_types/actions/public/getTransactionReceipt.d.ts","../../node_modules/viem/_types/types/multicall.d.ts","../../node_modules/viem/_types/actions/public/multicall.d.ts","../../node_modules/viem/_types/types/calls.d.ts","../../node_modules/viem/_types/actions/public/simulateBlocks.d.ts","../../node_modules/viem/_types/actions/public/simulateCalls.d.ts","../../node_modules/viem/_types/actions/wallet/writeContract.d.ts","../../node_modules/viem/_types/actions/public/simulateContract.d.ts","../../node_modules/viem/_types/actions/public/uninstallFilter.d.ts","../../node_modules/viem/_types/utils/signature/hashMessage.d.ts","../../node_modules/viem/_types/actions/public/verifyHash.d.ts","../../node_modules/viem/_types/actions/public/verifyMessage.d.ts","../../node_modules/viem/_types/types/typedData.d.ts","../../node_modules/viem/_types/utils/typedData.d.ts","../../node_modules/viem/_types/utils/signature/hashTypedData.d.ts","../../node_modules/viem/_types/actions/public/verifyTypedData.d.ts","../../node_modules/viem/_types/utils/observe.d.ts","../../node_modules/viem/_types/clients/transports/fallback.d.ts","../../node_modules/viem/_types/types/transport.d.ts","../../node_modules/viem/_types/utils/poll.d.ts","../../node_modules/viem/_types/actions/public/watchBlockNumber.d.ts","../../node_modules/viem/_types/actions/public/waitForTransactionReceipt.d.ts","../../node_modules/viem/_types/utils/stringify.d.ts","../../node_modules/viem/_types/actions/public/watchBlocks.d.ts","../../node_modules/viem/_types/actions/public/watchContractEvent.d.ts","../../node_modules/viem/_types/actions/public/watchEvent.d.ts","../../node_modules/viem/_types/actions/public/watchPendingTransactions.d.ts","../../node_modules/viem/_types/utils/siwe/validateSiweMessage.d.ts","../../node_modules/viem/_types/actions/siwe/verifySiweMessage.d.ts","../../node_modules/viem/_types/clients/decorators/public.d.ts","../../node_modules/viem/_types/actions/wallet/addChain.d.ts","../../node_modules/viem/_types/actions/wallet/deployContract.d.ts","../../node_modules/viem/_types/actions/wallet/getAddresses.d.ts","../../node_modules/viem/_types/actions/wallet/getCallsStatus.d.ts","../../node_modules/viem/_types/actions/wallet/getCapabilities.d.ts","../../node_modules/viem/_types/actions/wallet/getPermissions.d.ts","../../node_modules/viem/_types/actions/wallet/prepareAuthorization.d.ts","../../node_modules/viem/_types/actions/wallet/requestAddresses.d.ts","../../node_modules/viem/_types/actions/wallet/requestPermissions.d.ts","../../node_modules/viem/_types/actions/wallet/sendCalls.d.ts","../../node_modules/viem/_types/actions/wallet/showCallsStatus.d.ts","../../node_modules/viem/_types/accounts/utils/signAuthorization.d.ts","../../node_modules/viem/_types/actions/wallet/signAuthorization.d.ts","../../node_modules/viem/_types/accounts/utils/signMessage.d.ts","../../node_modules/viem/_types/actions/wallet/signMessage.d.ts","../../node_modules/viem/_types/actions/wallet/signTransaction.d.ts","../../node_modules/viem/_types/accounts/utils/signTypedData.d.ts","../../node_modules/viem/_types/actions/wallet/signTypedData.d.ts","../../node_modules/viem/_types/actions/wallet/switchChain.d.ts","../../node_modules/viem/_types/actions/wallet/waitForCallsStatus.d.ts","../../node_modules/viem/_types/actions/wallet/watchAsset.d.ts","../../node_modules/viem/_types/clients/decorators/wallet.d.ts","../../node_modules/viem/_types/clients/createClient.d.ts","../../node_modules/viem/_types/account-abstraction/accounts/types.d.ts","../../node_modules/viem/_types/accounts/types.d.ts","../../node_modules/viem/_types/actions/getContract.d.ts","../../node_modules/viem/_types/actions/test/dumpState.d.ts","../../node_modules/viem/_types/actions/test/getAutomine.d.ts","../../node_modules/viem/_types/actions/test/getTxpoolContent.d.ts","../../node_modules/viem/_types/actions/test/getTxpoolStatus.d.ts","../../node_modules/viem/_types/actions/test/impersonateAccount.d.ts","../../node_modules/viem/_types/actions/test/increaseTime.d.ts","../../node_modules/viem/_types/actions/test/inspectTxpool.d.ts","../../node_modules/viem/_types/actions/test/loadState.d.ts","../../node_modules/viem/_types/actions/test/mine.d.ts","../../node_modules/viem/_types/actions/test/reset.d.ts","../../node_modules/viem/_types/actions/test/revert.d.ts","../../node_modules/viem/_types/actions/test/sendUnsignedTransaction.d.ts","../../node_modules/viem/_types/actions/test/setBalance.d.ts","../../node_modules/viem/_types/actions/test/setBlockGasLimit.d.ts","../../node_modules/viem/_types/actions/test/setBlockTimestampInterval.d.ts","../../node_modules/viem/_types/actions/test/setCode.d.ts","../../node_modules/viem/_types/actions/test/setCoinbase.d.ts","../../node_modules/viem/_types/actions/test/setIntervalMining.d.ts","../../node_modules/viem/_types/actions/test/setMinGasPrice.d.ts","../../node_modules/viem/_types/actions/test/setNextBlockBaseFeePerGas.d.ts","../../node_modules/viem/_types/actions/test/setNextBlockTimestamp.d.ts","../../node_modules/viem/_types/actions/test/setNonce.d.ts","../../node_modules/viem/_types/actions/test/setStorageAt.d.ts","../../node_modules/viem/_types/actions/test/stopImpersonatingAccount.d.ts","../../node_modules/viem/_types/clients/decorators/test.d.ts","../../node_modules/viem/_types/clients/createTestClient.d.ts","../../node_modules/viem/_types/actions/test/dropTransaction.d.ts","../../node_modules/viem/_types/actions/test/snapshot.d.ts","../../node_modules/viem/_types/actions/test/removeBlockTimestampInterval.d.ts","../../node_modules/viem/_types/actions/test/setAutomine.d.ts","../../node_modules/viem/_types/actions/test/setLoggingEnabled.d.ts","../../node_modules/viem/_types/actions/test/setRpcUrl.d.ts","../../node_modules/viem/_types/clients/transports/custom.d.ts","../../node_modules/viem/_types/errors/transport.d.ts","../../node_modules/viem/_types/utils/promise/withTimeout.d.ts","../../node_modules/viem/_types/utils/rpc/http.d.ts","../../node_modules/viem/_types/clients/transports/http.d.ts","../../node_modules/viem/_types/clients/createPublicClient.d.ts","../../node_modules/viem/_types/clients/createWalletClient.d.ts","../../node_modules/viem/_types/utils/rpc/webSocket.d.ts","../../node_modules/viem/_types/clients/transports/webSocket.d.ts","../../node_modules/viem/_types/constants/abis.d.ts","../../node_modules/viem/_types/constants/address.d.ts","../../node_modules/viem/_types/constants/contracts.d.ts","../../node_modules/viem/_types/constants/unit.d.ts","../../node_modules/viem/_types/constants/number.d.ts","../../node_modules/viem/_types/constants/bytes.d.ts","../../node_modules/viem/_types/constants/strings.d.ts","../../node_modules/viem/_types/errors/unit.d.ts","../../node_modules/viem/_types/errors/typedData.d.ts","../../node_modules/viem/_types/utils/abi/decodeDeployData.d.ts","../../node_modules/viem/_types/utils/abi/decodeFunctionData.d.ts","../../node_modules/viem/_types/utils/abi/encodeErrorResult.d.ts","../../node_modules/viem/_types/utils/abi/prepareEncodeFunctionData.d.ts","../../node_modules/viem/_types/utils/abi/encodeFunctionResult.d.ts","../../node_modules/viem/_types/utils/abi/parseEventLogs.d.ts","../../node_modules/viem/_types/utils/data/isBytes.d.ts","../../node_modules/viem/_types/utils/address/getContractAddress.d.ts","../../node_modules/viem/_types/utils/transaction/getSerializedTransactionType.d.ts","../../node_modules/viem/_types/utils/signature/compactSignatureToSignature.d.ts","../../node_modules/viem/_types/utils/signature/parseCompactSignature.d.ts","../../node_modules/viem/_types/utils/signature/parseSignature.d.ts","../../node_modules/viem/_types/utils/signature/recoverMessageAddress.d.ts","../../node_modules/viem/_types/utils/signature/recoverPublicKey.d.ts","../../node_modules/viem/_types/utils/signature/serializeSignature.d.ts","../../node_modules/viem/_types/utils/signature/recoverTransactionAddress.d.ts","../../node_modules/viem/_types/utils/signature/recoverTypedDataAddress.d.ts","../../node_modules/viem/_types/utils/signature/signatureToCompactSignature.d.ts","../../node_modules/viem/_types/utils/signature/serializeCompactSignature.d.ts","../../node_modules/viem/_types/utils/address/isAddressEqual.d.ts","../../node_modules/viem/_types/utils/signature/verifyHash.d.ts","../../node_modules/viem/_types/utils/signature/verifyMessage.d.ts","../../node_modules/viem/_types/utils/signature/verifyTypedData.d.ts","../../node_modules/viem/_types/utils/signature/isErc6492Signature.d.ts","../../node_modules/viem/_types/utils/signature/parseErc6492Signature.d.ts","../../node_modules/viem/_types/utils/signature/serializeErc6492Signature.d.ts","../../node_modules/viem/_types/utils/blob/sidecarsToVersionedHashes.d.ts","../../node_modules/viem/_types/utils/blob/fromBlobs.d.ts","../../node_modules/viem/_types/utils/kzg/defineKzg.d.ts","../../node_modules/viem/_types/utils/kzg/setupKzg.d.ts","../../node_modules/viem/_types/utils/chain/defineChain.d.ts","../../node_modules/viem/_types/utils/chain/extractChain.d.ts","../../node_modules/viem/_types/utils/abi/encodePacked.d.ts","../../node_modules/viem/_types/utils/unit/formatUnits.d.ts","../../node_modules/viem/_types/utils/unit/formatEther.d.ts","../../node_modules/viem/_types/utils/unit/formatGwei.d.ts","../../node_modules/viem/_types/utils/encoding/fromRlp.d.ts","../../node_modules/viem/_types/utils/hash/toEventSignature.d.ts","../../node_modules/viem/_types/utils/hash/toFunctionSignature.d.ts","../../node_modules/viem/_types/utils/hash/toEventHash.d.ts","../../node_modules/viem/_types/utils/hash/toFunctionHash.d.ts","../../node_modules/viem/_types/utils/signature/toPrefixedMessage.d.ts","../../node_modules/viem/_types/utils/hash/isHash.d.ts","../../node_modules/viem/_types/utils/hash/ripemd160.d.ts","../../node_modules/viem/_types/utils/unit/parseUnits.d.ts","../../node_modules/viem/_types/utils/unit/parseEther.d.ts","../../node_modules/viem/_types/utils/unit/parseGwei.d.ts","../../node_modules/viem/_types/utils/transaction/parseTransaction.d.ts","../../node_modules/viem/_types/index.d.ts","./src/abis/ForwarderAbi.ts","./src/abis/StakingAssetHandlerAbi.ts","./src/abis/RollupAbi.ts","./src/abis/index.ts","./src/bytecode/ForwarderBytecode.ts","../../node_modules/viem/_types/accounts/wordlists.d.ts","../../node_modules/viem/_types/accounts/generateMnemonic.d.ts","../../node_modules/viem/_types/accounts/generatePrivateKey.d.ts","../../node_modules/viem/_types/accounts/toAccount.d.ts","../../node_modules/viem/_types/accounts/utils/publicKeyToAddress.d.ts","../../node_modules/viem/_types/accounts/privateKeyToAccount.d.ts","../../node_modules/viem/_types/accounts/hdKeyToAccount.d.ts","../../node_modules/viem/_types/accounts/mnemonicToAccount.d.ts","../../node_modules/viem/_types/accounts/utils/privateKeyToAddress.d.ts","../../node_modules/viem/_types/accounts/index.d.ts","../../node_modules/@types/node/compatibility/disposable.d.ts","../../node_modules/@types/node/compatibility/indexable.d.ts","../../node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/@types/node/compatibility/index.d.ts","../../node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/undici-types/header.d.ts","../../node_modules/undici-types/readable.d.ts","../../node_modules/undici-types/file.d.ts","../../node_modules/undici-types/fetch.d.ts","../../node_modules/undici-types/formdata.d.ts","../../node_modules/undici-types/connector.d.ts","../../node_modules/undici-types/client.d.ts","../../node_modules/undici-types/errors.d.ts","../../node_modules/undici-types/dispatcher.d.ts","../../node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/undici-types/global-origin.d.ts","../../node_modules/undici-types/pool-stats.d.ts","../../node_modules/undici-types/pool.d.ts","../../node_modules/undici-types/handlers.d.ts","../../node_modules/undici-types/balanced-pool.d.ts","../../node_modules/undici-types/agent.d.ts","../../node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/undici-types/mock-agent.d.ts","../../node_modules/undici-types/mock-client.d.ts","../../node_modules/undici-types/mock-pool.d.ts","../../node_modules/undici-types/mock-errors.d.ts","../../node_modules/undici-types/proxy-agent.d.ts","../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/undici-types/retry-handler.d.ts","../../node_modules/undici-types/retry-agent.d.ts","../../node_modules/undici-types/api.d.ts","../../node_modules/undici-types/interceptors.d.ts","../../node_modules/undici-types/util.d.ts","../../node_modules/undici-types/cookies.d.ts","../../node_modules/undici-types/patch.d.ts","../../node_modules/undici-types/websocket.d.ts","../../node_modules/undici-types/eventsource.d.ts","../../node_modules/undici-types/filereader.d.ts","../../node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/undici-types/content-type.d.ts","../../node_modules/undici-types/cache.d.ts","../../node_modules/undici-types/index.d.ts","../../node_modules/@types/node/globals.d.ts","../../node_modules/@types/node/assert.d.ts","../../node_modules/@types/node/assert/strict.d.ts","../../node_modules/@types/node/async_hooks.d.ts","../../node_modules/@types/node/buffer.d.ts","../../node_modules/@types/node/child_process.d.ts","../../node_modules/@types/node/cluster.d.ts","../../node_modules/@types/node/console.d.ts","../../node_modules/@types/node/constants.d.ts","../../node_modules/@types/node/crypto.d.ts","../../node_modules/@types/node/dgram.d.ts","../../node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/@types/node/dns.d.ts","../../node_modules/@types/node/dns/promises.d.ts","../../node_modules/@types/node/domain.d.ts","../../node_modules/@types/node/dom-events.d.ts","../../node_modules/@types/node/events.d.ts","../../node_modules/@types/node/fs.d.ts","../../node_modules/@types/node/fs/promises.d.ts","../../node_modules/@types/node/http.d.ts","../../node_modules/@types/node/http2.d.ts","../../node_modules/@types/node/https.d.ts","../../node_modules/@types/node/inspector.d.ts","../../node_modules/@types/node/module.d.ts","../../node_modules/@types/node/net.d.ts","../../node_modules/@types/node/os.d.ts","../../node_modules/@types/node/path.d.ts","../../node_modules/@types/node/perf_hooks.d.ts","../../node_modules/@types/node/process.d.ts","../../node_modules/@types/node/punycode.d.ts","../../node_modules/@types/node/querystring.d.ts","../../node_modules/@types/node/readline.d.ts","../../node_modules/@types/node/readline/promises.d.ts","../../node_modules/@types/node/repl.d.ts","../../node_modules/@types/node/sea.d.ts","../../node_modules/@types/node/stream.d.ts","../../node_modules/@types/node/stream/promises.d.ts","../../node_modules/@types/node/stream/consumers.d.ts","../../node_modules/@types/node/stream/web.d.ts","../../node_modules/@types/node/string_decoder.d.ts","../../node_modules/@types/node/test.d.ts","../../node_modules/@types/node/timers.d.ts","../../node_modules/@types/node/timers/promises.d.ts","../../node_modules/@types/node/tls.d.ts","../../node_modules/@types/node/trace_events.d.ts","../../node_modules/@types/node/tty.d.ts","../../node_modules/@types/node/url.d.ts","../../node_modules/@types/node/util.d.ts","../../node_modules/@types/node/v8.d.ts","../../node_modules/@types/node/vm.d.ts","../../node_modules/@types/node/wasi.d.ts","../../node_modules/@types/node/worker_threads.d.ts","../../node_modules/@types/node/zlib.d.ts","../../node_modules/@types/node/index.d.ts","../utils/node_modules/pino/node_modules/pino-std-serializers/index.d.ts","../utils/node_modules/pino/node_modules/sonic-boom/types/index.d.ts","../utils/node_modules/pino/pino.d.ts","../utils/dist/logger.d.ts","../../node_modules/@smithy/types/dist-types/abort-handler.d.ts","../../node_modules/@smithy/types/dist-types/abort.d.ts","../../node_modules/@smithy/types/dist-types/auth/auth.d.ts","../../node_modules/@smithy/types/dist-types/auth/HttpApiKeyAuth.d.ts","../../node_modules/@smithy/types/dist-types/identity/identity.d.ts","../../node_modules/@smithy/types/dist-types/response.d.ts","../../node_modules/@smithy/types/dist-types/command.d.ts","../../node_modules/@smithy/types/dist-types/endpoint.d.ts","../../node_modules/@smithy/types/dist-types/feature-ids.d.ts","../../node_modules/@smithy/types/dist-types/logger.d.ts","../../node_modules/@smithy/types/dist-types/uri.d.ts","../../node_modules/@smithy/types/dist-types/http.d.ts","../../node_modules/@smithy/types/dist-types/util.d.ts","../../node_modules/@smithy/types/dist-types/middleware.d.ts","../../node_modules/@smithy/types/dist-types/auth/HttpSigner.d.ts","../../node_modules/@smithy/types/dist-types/auth/IdentityProviderConfig.d.ts","../../node_modules/@smithy/types/dist-types/auth/HttpAuthScheme.d.ts","../../node_modules/@smithy/types/dist-types/auth/HttpAuthSchemeProvider.d.ts","../../node_modules/@smithy/types/dist-types/auth/index.d.ts","../../node_modules/@smithy/types/dist-types/transform/exact.d.ts","../../node_modules/@smithy/types/dist-types/externals-check/browser-externals-check.d.ts","../../node_modules/@smithy/types/dist-types/blob/blob-payload-input-types.d.ts","../../node_modules/@smithy/types/dist-types/crypto.d.ts","../../node_modules/@smithy/types/dist-types/checksum.d.ts","../../node_modules/@smithy/types/dist-types/client.d.ts","../../node_modules/@smithy/types/dist-types/connection/config.d.ts","../../node_modules/@smithy/types/dist-types/transfer.d.ts","../../node_modules/@smithy/types/dist-types/connection/manager.d.ts","../../node_modules/@smithy/types/dist-types/connection/pool.d.ts","../../node_modules/@smithy/types/dist-types/connection/index.d.ts","../../node_modules/@smithy/types/dist-types/eventStream.d.ts","../../node_modules/@smithy/types/dist-types/encode.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/shared.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/EndpointRuleObject.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/ErrorRuleObject.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/TreeRuleObject.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/RuleSetObject.d.ts","../../node_modules/@smithy/types/dist-types/endpoints/index.d.ts","../../node_modules/@smithy/types/dist-types/extensions/checksum.d.ts","../../node_modules/@smithy/types/dist-types/extensions/defaultClientConfiguration.d.ts","../../node_modules/@smithy/types/dist-types/shapes.d.ts","../../node_modules/@smithy/types/dist-types/retry.d.ts","../../node_modules/@smithy/types/dist-types/extensions/retry.d.ts","../../node_modules/@smithy/types/dist-types/extensions/defaultExtensionConfiguration.d.ts","../../node_modules/@smithy/types/dist-types/extensions/index.d.ts","../../node_modules/@smithy/types/dist-types/http/httpHandlerInitialization.d.ts","../../node_modules/@smithy/types/dist-types/identity/apiKeyIdentity.d.ts","../../node_modules/@smithy/types/dist-types/identity/awsCredentialIdentity.d.ts","../../node_modules/@smithy/types/dist-types/identity/tokenIdentity.d.ts","../../node_modules/@smithy/types/dist-types/identity/index.d.ts","../../node_modules/@smithy/types/dist-types/pagination.d.ts","../../node_modules/@smithy/types/dist-types/profile.d.ts","../../node_modules/@smithy/types/dist-types/serde.d.ts","../../node_modules/@smithy/types/dist-types/signature.d.ts","../../node_modules/@smithy/types/dist-types/stream.d.ts","../../node_modules/@smithy/types/dist-types/streaming-payload/streaming-blob-common-types.d.ts","../../node_modules/@smithy/types/dist-types/streaming-payload/streaming-blob-payload-input-types.d.ts","../../node_modules/@smithy/types/dist-types/streaming-payload/streaming-blob-payload-output-types.d.ts","../../node_modules/@smithy/types/dist-types/transform/type-transform.d.ts","../../node_modules/@smithy/types/dist-types/transform/client-method-transforms.d.ts","../../node_modules/@smithy/types/dist-types/transform/client-payload-blob-type-narrow.d.ts","../../node_modules/@smithy/types/dist-types/transform/no-undefined.d.ts","../../node_modules/@smithy/types/dist-types/waiter.d.ts","../../node_modules/@smithy/types/dist-types/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/account-id-endpoint/AccountIdEndpointModeConstants.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/account-id-endpoint/AccountIdEndpointModeConfigResolver.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/fromEnv.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/getHomeDir.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/getProfileName.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/getSSOTokenFilepath.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/getSSOTokenFromFile.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/loadSharedConfigFiles.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/loadSsoSessionData.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/parseKnownFiles.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/types.d.ts","../../node_modules/@smithy/shared-ini-file-loader/dist-types/index.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/fromSharedConfigFiles.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/fromStatic.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/configLoader.d.ts","../../node_modules/@smithy/node-config-provider/dist-types/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/account-id-endpoint/NodeAccountIdEndpointModeConfigOptions.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/account-id-endpoint/index.d.ts","../../node_modules/@aws-sdk/middleware-endpoint-discovery/dist-types/configurations.d.ts","../../node_modules/@aws-sdk/endpoint-cache/dist-types/Endpoint.d.ts","../../node_modules/@aws-sdk/endpoint-cache/dist-types/EndpointCache.d.ts","../../node_modules/@aws-sdk/endpoint-cache/dist-types/index.d.ts","../../node_modules/@aws-sdk/middleware-endpoint-discovery/dist-types/resolveEndpointDiscoveryConfig.d.ts","../../node_modules/@aws-sdk/middleware-endpoint-discovery/dist-types/getEndpointDiscoveryPlugin.d.ts","../../node_modules/@aws-sdk/middleware-endpoint-discovery/dist-types/index.d.ts","../../node_modules/@aws-sdk/middleware-host-header/dist-types/index.d.ts","../../node_modules/@aws-sdk/middleware-user-agent/dist-types/configurations.d.ts","../../node_modules/@aws-sdk/types/dist-types/abort.d.ts","../../node_modules/@aws-sdk/types/dist-types/auth.d.ts","../../node_modules/@aws-sdk/types/dist-types/blob/blob-types.d.ts","../../node_modules/@aws-sdk/types/dist-types/checksum.d.ts","../../node_modules/@aws-sdk/types/dist-types/client.d.ts","../../node_modules/@aws-sdk/types/dist-types/command.d.ts","../../node_modules/@aws-sdk/types/dist-types/connection.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/Identity.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/AnonymousIdentity.d.ts","../../node_modules/@aws-sdk/types/dist-types/feature-ids.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/AwsCredentialIdentity.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/LoginIdentity.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/TokenIdentity.d.ts","../../node_modules/@aws-sdk/types/dist-types/identity/index.d.ts","../../node_modules/@aws-sdk/types/dist-types/util.d.ts","../../node_modules/@aws-sdk/types/dist-types/credentials.d.ts","../../node_modules/@aws-sdk/types/dist-types/crypto.d.ts","../../node_modules/@aws-sdk/types/dist-types/dns.d.ts","../../node_modules/@aws-sdk/types/dist-types/encode.d.ts","../../node_modules/@aws-sdk/types/dist-types/endpoint.d.ts","../../node_modules/@aws-sdk/types/dist-types/eventStream.d.ts","../../node_modules/@aws-sdk/types/dist-types/extensions/index.d.ts","../../node_modules/@aws-sdk/types/dist-types/function.d.ts","../../node_modules/@aws-sdk/types/dist-types/http.d.ts","../../node_modules/@aws-sdk/types/dist-types/logger.d.ts","../../node_modules/@aws-sdk/types/dist-types/middleware.d.ts","../../node_modules/@aws-sdk/types/dist-types/pagination.d.ts","../../node_modules/@aws-sdk/types/dist-types/profile.d.ts","../../node_modules/@aws-sdk/types/dist-types/request.d.ts","../../node_modules/@aws-sdk/types/dist-types/response.d.ts","../../node_modules/@aws-sdk/types/dist-types/retry.d.ts","../../node_modules/@aws-sdk/types/dist-types/serde.d.ts","../../node_modules/@aws-sdk/types/dist-types/shapes.d.ts","../../node_modules/@aws-sdk/types/dist-types/signature.d.ts","../../node_modules/@aws-sdk/types/dist-types/stream.d.ts","../../node_modules/@aws-sdk/types/dist-types/token.d.ts","../../node_modules/@aws-sdk/types/dist-types/transfer.d.ts","../../node_modules/@aws-sdk/types/dist-types/uri.d.ts","../../node_modules/@aws-sdk/types/dist-types/waiter.d.ts","../../node_modules/@aws-sdk/types/dist-types/index.d.ts","../../node_modules/@aws-sdk/middleware-user-agent/dist-types/user-agent-middleware.d.ts","../../node_modules/@aws-sdk/middleware-user-agent/dist-types/index.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/NodeUseDualstackEndpointConfigOptions.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/NodeUseFipsEndpointConfigOptions.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/resolveEndpointsConfig.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/resolveCustomEndpointsConfig.d.ts","../../node_modules/@smithy/config-resolver/dist-types/endpointsConfig/index.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionConfig/config.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionConfig/resolveRegionConfig.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionConfig/index.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/EndpointVariantTag.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/EndpointVariant.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/PartitionHash.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/RegionHash.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/getRegionInfo.d.ts","../../node_modules/@smithy/config-resolver/dist-types/regionInfo/index.d.ts","../../node_modules/@smithy/config-resolver/dist-types/index.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/resolveEndpointConfig.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/types.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/adaptors/getEndpointFromInstructions.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/adaptors/toEndpointV1.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/adaptors/index.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/endpointMiddleware.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/getEndpointPlugin.d.ts","../../node_modules/@smithy/middleware-endpoint/dist-types/index.d.ts","../../node_modules/@smithy/util-retry/dist-types/types.d.ts","../../node_modules/@smithy/util-retry/dist-types/AdaptiveRetryStrategy.d.ts","../../node_modules/@smithy/util-retry/dist-types/StandardRetryStrategy.d.ts","../../node_modules/@smithy/util-retry/dist-types/ConfiguredRetryStrategy.d.ts","../../node_modules/@smithy/util-retry/dist-types/DefaultRateLimiter.d.ts","../../node_modules/@smithy/util-retry/dist-types/config.d.ts","../../node_modules/@smithy/util-retry/dist-types/constants.d.ts","../../node_modules/@smithy/util-retry/dist-types/index.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/types.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/StandardRetryStrategy.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/AdaptiveRetryStrategy.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/configurations.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/delayDecider.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/omitRetryHeadersMiddleware.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/retryDecider.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/retryMiddleware.d.ts","../../node_modules/@smithy/middleware-retry/dist-types/index.d.ts","../../node_modules/@smithy/protocol-http/dist-types/httpRequest.d.ts","../../node_modules/@smithy/protocol-http/dist-types/httpResponse.d.ts","../../node_modules/@smithy/protocol-http/dist-types/httpHandler.d.ts","../../node_modules/@smithy/protocol-http/dist-types/extensions/httpExtensionConfiguration.d.ts","../../node_modules/@smithy/protocol-http/dist-types/extensions/index.d.ts","../../node_modules/@smithy/protocol-http/dist-types/Field.d.ts","../../node_modules/@smithy/protocol-http/dist-types/Fields.d.ts","../../node_modules/@smithy/protocol-http/dist-types/isValidHostname.d.ts","../../node_modules/@smithy/protocol-http/dist-types/types.d.ts","../../node_modules/@smithy/protocol-http/dist-types/index.d.ts","../../node_modules/@smithy/smithy-client/dist-types/client.d.ts","../../node_modules/@smithy/util-stream/dist-types/blob/Uint8ArrayBlobAdapter.d.ts","../../node_modules/@smithy/util-stream/dist-types/checksum/ChecksumStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/checksum/ChecksumStream.browser.d.ts","../../node_modules/@smithy/util-stream/dist-types/checksum/createChecksumStream.browser.d.ts","../../node_modules/@smithy/util-stream/dist-types/checksum/createChecksumStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/createBufferedReadable.d.ts","../../node_modules/@smithy/util-stream/dist-types/getAwsChunkedEncodingStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/headStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/sdk-stream-mixin.d.ts","../../node_modules/@smithy/util-stream/dist-types/splitStream.d.ts","../../node_modules/@smithy/util-stream/dist-types/stream-type-check.d.ts","../../node_modules/@smithy/util-stream/dist-types/index.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/collect-stream-body.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/extended-encode-uri-component.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/requestBuilder.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/resolve-path.d.ts","../../node_modules/@smithy/core/dist-types/submodules/protocols/index.d.ts","../../node_modules/@smithy/smithy-client/dist-types/collect-stream-body.d.ts","../../node_modules/@smithy/smithy-client/dist-types/command.d.ts","../../node_modules/@smithy/smithy-client/dist-types/constants.d.ts","../../node_modules/@smithy/smithy-client/dist-types/create-aggregated-client.d.ts","../../node_modules/@smithy/smithy-client/dist-types/date-utils.d.ts","../../node_modules/@smithy/smithy-client/dist-types/default-error-handler.d.ts","../../node_modules/@smithy/smithy-client/dist-types/defaults-mode.d.ts","../../node_modules/@smithy/smithy-client/dist-types/emitWarningIfUnsupportedVersion.d.ts","../../node_modules/@smithy/smithy-client/dist-types/exceptions.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extended-encode-uri-component.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extensions/checksum.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extensions/retry.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extensions/defaultExtensionConfiguration.d.ts","../../node_modules/@smithy/smithy-client/dist-types/extensions/index.d.ts","../../node_modules/@smithy/smithy-client/dist-types/get-array-if-single-item.d.ts","../../node_modules/@smithy/smithy-client/dist-types/get-value-from-text-node.d.ts","../../node_modules/@smithy/smithy-client/dist-types/is-serializable-header-value.d.ts","../../node_modules/@smithy/smithy-client/dist-types/lazy-json.d.ts","../../node_modules/@smithy/smithy-client/dist-types/NoOpLogger.d.ts","../../node_modules/@smithy/smithy-client/dist-types/object-mapping.d.ts","../../node_modules/@smithy/smithy-client/dist-types/parse-utils.d.ts","../../node_modules/@smithy/smithy-client/dist-types/quote-header.d.ts","../../node_modules/@smithy/smithy-client/dist-types/resolve-path.d.ts","../../node_modules/@smithy/smithy-client/dist-types/ser-utils.d.ts","../../node_modules/@smithy/smithy-client/dist-types/serde-json.d.ts","../../node_modules/@smithy/smithy-client/dist-types/split-every.d.ts","../../node_modules/@smithy/smithy-client/dist-types/split-header.d.ts","../../node_modules/@smithy/smithy-client/dist-types/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/client/emitWarningIfUnsupportedVersion.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/client/setCredentialFeature.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/client/setFeature.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/client/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4AConfig.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/NODE_AUTH_SCHEME_PREFERENCE_OPTIONS.d.ts","../../node_modules/@smithy/signature-v4/dist-types/SignatureV4Base.d.ts","../../node_modules/@smithy/signature-v4/dist-types/SignatureV4.d.ts","../../node_modules/@smithy/signature-v4/dist-types/constants.d.ts","../../node_modules/@smithy/signature-v4/dist-types/getCanonicalHeaders.d.ts","../../node_modules/@smithy/signature-v4/dist-types/getCanonicalQuery.d.ts","../../node_modules/@smithy/signature-v4/dist-types/getPayloadHash.d.ts","../../node_modules/@smithy/signature-v4/dist-types/moveHeadersToQuery.d.ts","../../node_modules/@smithy/signature-v4/dist-types/prepareRequest.d.ts","../../node_modules/@smithy/signature-v4/dist-types/credentialDerivation.d.ts","../../node_modules/@smithy/signature-v4/dist-types/headerUtil.d.ts","../../node_modules/@smithy/signature-v4/dist-types/signature-v4a-container.d.ts","../../node_modules/@smithy/signature-v4/dist-types/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4Config.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/aws_sdk/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/httpAuthSchemes/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/coercing-serializers.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/json/awsExpectUnion.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/json/parseJsonBody.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/xml/parseXmlBody.d.ts","../../node_modules/@aws-sdk/core/dist-types/submodules/protocols/index.d.ts","../../node_modules/@aws-sdk/core/dist-types/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/auth/httpAuthSchemeProvider.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/models/DynamoDBServiceException.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/models/models_0.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/BatchExecuteStatementCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/BatchGetItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/BatchWriteItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/CreateBackupCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/CreateGlobalTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/CreateTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DeleteBackupCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DeleteItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DeleteResourcePolicyCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DeleteTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeBackupCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeContinuousBackupsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeContributorInsightsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeEndpointsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeExportCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeGlobalTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeGlobalTableSettingsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeImportCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeKinesisStreamingDestinationCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeLimitsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeTableReplicaAutoScalingCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DescribeTimeToLiveCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/DisableKinesisStreamingDestinationCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/EnableKinesisStreamingDestinationCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ExecuteStatementCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ExecuteTransactionCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ExportTableToPointInTimeCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/GetItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/GetResourcePolicyCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ImportTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListBackupsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListContributorInsightsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListExportsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListGlobalTablesCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListImportsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListTablesCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ListTagsOfResourceCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/PutItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/PutResourcePolicyCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/QueryCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/RestoreTableFromBackupCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/RestoreTableToPointInTimeCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/ScanCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/TagResourceCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/TransactGetItemsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/TransactWriteItemsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UntagResourceCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateContinuousBackupsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateContributorInsightsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateGlobalTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateGlobalTableSettingsCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateItemCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateKinesisStreamingDestinationCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateTableCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateTableReplicaAutoScalingCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/UpdateTimeToLiveCommand.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/endpoint/EndpointParameters.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/auth/httpAuthExtensionConfiguration.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/extensionConfiguration.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/runtimeExtensions.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/DynamoDBClient.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/DynamoDB.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/commands/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/Interfaces.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ListContributorInsightsPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ListExportsPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ListImportsPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ListTablesPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/QueryPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/ScanPaginator.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/pagination/index.d.ts","../../node_modules/@smithy/util-waiter/dist-types/waiter.d.ts","../../node_modules/@smithy/util-waiter/dist-types/createWaiter.d.ts","../../node_modules/@smithy/util-waiter/dist-types/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/waiters/waitForTableExists.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/waiters/waitForTableNotExists.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/waiters/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/models/index.d.ts","../../node_modules/@aws-sdk/client-dynamodb/dist-types/index.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/models.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/NumberValue.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/marshall.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/convertToAttr.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/unmarshall.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/convertToNative.d.ts","../../node_modules/@aws-sdk/util-dynamodb/dist-types/index.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/utils.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/BatchGetCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/BatchWriteCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/DeleteCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/ExecuteStatementCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/ExecuteTransactionCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/GetCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/PutCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/QueryCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/ScanCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/TransactGetCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/TransactWriteCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/UpdateCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/DynamoDBDocumentClient.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/baseCommand/DynamoDBDocumentClientCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/BatchExecuteStatementCommand.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/DynamoDBDocument.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/commands/index.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/pagination/Interfaces.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/pagination/QueryPaginator.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/pagination/ScanPaginator.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/pagination/index.d.ts","../../node_modules/@aws-sdk/lib-dynamodb/dist-types/index.d.ts","../utils/dist/dynamo-db.d.ts","../../node_modules/@sapphire/shapeshift/dist/esm/index.d.mts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/globals.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/utils/internals.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/common.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/common.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/permissions.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/user.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/emoji.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/oauth2.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/sticker.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/guild.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/autoModeration.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/guildScheduledEvent.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/stageInstance.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/webhook.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/auditLog.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/invite.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/monetization.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/poll.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/soundboard.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/teams.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/application.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/auditLog.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/autoModeration.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/poll.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/channel.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/emoji.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/gateway.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/guild.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/guildScheduledEvent.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/webhook.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/interactions.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/invite.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/monetization.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/oauth2.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/soundboard.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/stageInstance.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/sticker.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/template.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/user.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/voice.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rest/v10/index.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/template.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/voice.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/index.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/responses.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/base.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/shared.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/base.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/attachment.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/boolean.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/channel.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/integer.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/mentionable.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/number.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/role.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/string.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommand.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/subcommandGroup.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/_chatInput/user.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/internals.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/chatInput.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/contextMenu.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/entryPoint.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/_applicationCommands/permissions.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/applicationCommands.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/autocomplete.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/messageComponents.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/modalSubmit.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/_interactions/ping.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/interactions.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/application.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/channel.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/payloads/v10/gateway.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/gateway/common.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/gateway/v10.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rpc/common.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/rpc/v10.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/utils/v10.d.ts","../../node_modules/@discordjs/builders/node_modules/discord-api-types/v10.d.ts","../../node_modules/@discordjs/formatters/node_modules/discord-api-types/globals.d.ts","../../node_modules/@discordjs/formatters/dist/index.d.mts","../../node_modules/@discordjs/util/dist/index.d.mts","../../node_modules/@discordjs/builders/dist/index.d.mts","../../node_modules/@discordjs/collection/dist/index.d.ts","../../node_modules/@discordjs/rest/node_modules/discord-api-types/v10.d.ts","../../node_modules/@discordjs/rest/node_modules/@discordjs/collection/dist/index.d.mts","../../node_modules/undici/types/header.d.ts","../../node_modules/undici/types/readable.d.ts","../../node_modules/undici/types/file.d.ts","../../node_modules/undici/types/fetch.d.ts","../../node_modules/undici/types/formdata.d.ts","../../node_modules/undici/types/connector.d.ts","../../node_modules/undici/types/client.d.ts","../../node_modules/undici/types/errors.d.ts","../../node_modules/undici/types/dispatcher.d.ts","../../node_modules/undici/types/global-dispatcher.d.ts","../../node_modules/undici/types/global-origin.d.ts","../../node_modules/undici/types/pool-stats.d.ts","../../node_modules/undici/types/pool.d.ts","../../node_modules/undici/types/handlers.d.ts","../../node_modules/undici/types/balanced-pool.d.ts","../../node_modules/undici/types/agent.d.ts","../../node_modules/undici/types/mock-interceptor.d.ts","../../node_modules/undici/types/mock-agent.d.ts","../../node_modules/undici/types/mock-client.d.ts","../../node_modules/undici/types/mock-pool.d.ts","../../node_modules/undici/types/mock-errors.d.ts","../../node_modules/undici/types/proxy-agent.d.ts","../../node_modules/undici/types/env-http-proxy-agent.d.ts","../../node_modules/undici/types/retry-handler.d.ts","../../node_modules/undici/types/retry-agent.d.ts","../../node_modules/undici/types/api.d.ts","../../node_modules/undici/types/interceptors.d.ts","../../node_modules/undici/types/util.d.ts","../../node_modules/undici/types/cookies.d.ts","../../node_modules/undici/types/patch.d.ts","../../node_modules/undici/types/websocket.d.ts","../../node_modules/undici/types/eventsource.d.ts","../../node_modules/undici/types/filereader.d.ts","../../node_modules/undici/types/diagnostics-channel.d.ts","../../node_modules/undici/types/content-type.d.ts","../../node_modules/undici/types/cache.d.ts","../../node_modules/undici/types/index.d.ts","../../node_modules/undici/index.d.ts","../../node_modules/@vladfrangu/async_event_emitter/dist/index.d.mts","../../node_modules/@discordjs/rest/dist/web.d.mts","../../node_modules/@discordjs/ws/node_modules/discord-api-types/v10.d.ts","../../node_modules/@discordjs/ws/node_modules/@discordjs/collection/dist/index.d.mts","../../node_modules/@sapphire/async-queue/dist/esm/index.d.mts","../../node_modules/@discordjs/ws/dist/index.d.mts","../../node_modules/discord.js/node_modules/discord-api-types/v10.d.ts","../../node_modules/discord.js/typings/rawDataTypes.d.mts","../../node_modules/@sapphire/snowflake/dist/esm/index.d.mts","../../node_modules/discord.js/typings/index.d.mts","../utils/dist/inputValidator.d.ts","../utils/dist/index.d.ts","./src/ethereum.ts","./src/l2-info-service.ts","./src/index.ts","./node_modules/@types/bun/node_modules/bun-types/globals.d.ts","./node_modules/@types/bun/node_modules/bun-types/s3.d.ts","./node_modules/@types/bun/node_modules/bun-types/fetch.d.ts","./node_modules/@types/bun/node_modules/bun-types/bun.d.ts","./node_modules/@types/bun/node_modules/bun-types/extensions.d.ts","./node_modules/@types/bun/node_modules/bun-types/devserver.d.ts","./node_modules/@types/bun/node_modules/bun-types/ffi.d.ts","./node_modules/@types/bun/node_modules/bun-types/html-rewriter.d.ts","./node_modules/@types/bun/node_modules/bun-types/jsc.d.ts","./node_modules/@types/bun/node_modules/bun-types/sqlite.d.ts","./node_modules/@types/bun/node_modules/bun-types/test.d.ts","./node_modules/@types/bun/node_modules/bun-types/wasm.d.ts","./node_modules/@types/bun/node_modules/bun-types/overrides.d.ts","./node_modules/@types/bun/node_modules/bun-types/deprecated.d.ts","./node_modules/@types/bun/node_modules/bun-types/redis.d.ts","./node_modules/@types/bun/node_modules/bun-types/shell.d.ts","./node_modules/@types/bun/node_modules/bun-types/bun.ns.d.ts","./node_modules/@types/bun/node_modules/bun-types/index.d.ts","./node_modules/@types/bun/index.d.ts","../../node_modules/@types/aws-lambda/common/api-gateway.d.ts","../../node_modules/@types/aws-lambda/common/cloudfront.d.ts","../../node_modules/@types/aws-lambda/handler.d.ts","../../node_modules/@types/aws-lambda/trigger/alb.d.ts","../../node_modules/@types/aws-lambda/trigger/api-gateway-proxy.d.ts","../../node_modules/@types/aws-lambda/trigger/api-gateway-authorizer.d.ts","../../node_modules/@types/aws-lambda/trigger/appsync-resolver.d.ts","../../node_modules/@types/aws-lambda/trigger/autoscaling.d.ts","../../node_modules/@types/aws-lambda/trigger/cloudformation-custom-resource.d.ts","../../node_modules/@types/aws-lambda/trigger/cdk-custom-resource.d.ts","../../node_modules/@types/aws-lambda/trigger/cloudfront-request.d.ts","../../node_modules/@types/aws-lambda/trigger/cloudfront-response.d.ts","../../node_modules/@types/aws-lambda/trigger/cloudwatch-alarm.d.ts","../../node_modules/@types/aws-lambda/trigger/eventbridge.d.ts","../../node_modules/@types/aws-lambda/trigger/cloudwatch-events.d.ts","../../node_modules/@types/aws-lambda/trigger/cloudwatch-logs.d.ts","../../node_modules/@types/aws-lambda/trigger/codebuild-cloudwatch-state.d.ts","../../node_modules/@types/aws-lambda/trigger/codecommit.d.ts","../../node_modules/@types/aws-lambda/trigger/codepipeline.d.ts","../../node_modules/@types/aws-lambda/trigger/codepipeline-cloudwatch-action.d.ts","../../node_modules/@types/aws-lambda/trigger/codepipeline-cloudwatch-pipeline.d.ts","../../node_modules/@types/aws-lambda/trigger/codepipeline-cloudwatch-stage.d.ts","../../node_modules/@types/aws-lambda/trigger/codepipeline-cloudwatch.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/_common.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/create-auth-challenge.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/custom-email-sender.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/custom-message.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/custom-sms-sender.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/define-auth-challenge.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/post-authentication.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/post-confirmation.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/pre-authentication.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/pre-signup.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/pre-token-generation.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/pre-token-generation-v2.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/user-migration.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/verify-auth-challenge-response.d.ts","../../node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/index.d.ts","../../node_modules/@types/aws-lambda/trigger/connect-contact-flow.d.ts","../../node_modules/@types/aws-lambda/trigger/dynamodb-stream.d.ts","../../node_modules/@types/aws-lambda/trigger/guard-duty-event-notification.d.ts","../../node_modules/@types/aws-lambda/trigger/iot.d.ts","../../node_modules/@types/aws-lambda/trigger/iot-authorizer.d.ts","../../node_modules/@types/aws-lambda/trigger/kinesis-firehose-transformation.d.ts","../../node_modules/@types/aws-lambda/trigger/kinesis-stream.d.ts","../../node_modules/@types/aws-lambda/trigger/lambda-function-url.d.ts","../../node_modules/@types/aws-lambda/trigger/lex.d.ts","../../node_modules/@types/aws-lambda/trigger/lex-v2.d.ts","../../node_modules/@types/aws-lambda/trigger/amplify-resolver.d.ts","../../node_modules/@types/aws-lambda/trigger/msk.d.ts","../../node_modules/@types/aws-lambda/trigger/s3.d.ts","../../node_modules/@types/aws-lambda/trigger/s3-batch.d.ts","../../node_modules/@types/aws-lambda/trigger/s3-event-notification.d.ts","../../node_modules/@types/aws-lambda/trigger/secretsmanager.d.ts","../../node_modules/@types/aws-lambda/trigger/self-managed-kafka.d.ts","../../node_modules/@types/aws-lambda/trigger/ses.d.ts","../../node_modules/@types/aws-lambda/trigger/sns.d.ts","../../node_modules/@types/aws-lambda/trigger/sqs.d.ts","../../node_modules/@types/aws-lambda/trigger/transfer-family-authorizer.d.ts","../../node_modules/@types/aws-lambda/index.d.ts","../../node_modules/@types/connect/index.d.ts","../../node_modules/@types/body-parser/index.d.ts","../../node_modules/@types/caseless/index.d.ts","../../node_modules/@types/cors/index.d.ts","../../node_modules/@types/mime/index.d.ts","../../node_modules/@types/send/index.d.ts","../../node_modules/@types/qs/index.d.ts","../../node_modules/@types/range-parser/index.d.ts","../../node_modules/@types/express-serve-static-core/index.d.ts","../../node_modules/@types/http-errors/index.d.ts","../../node_modules/@types/serve-static/index.d.ts","../../node_modules/@types/express/index.d.ts","../../node_modules/@types/http-proxy/index.d.ts","../../node_modules/@types/json-schema/index.d.ts","../../node_modules/@types/request/node_modules/form-data/index.d.ts","../../node_modules/@types/tough-cookie/index.d.ts","../../node_modules/@types/request/index.d.ts","../../node_modules/@types/strip-bom/index.d.ts","../../node_modules/@types/strip-json-comments/index.d.ts","../../node_modules/@types/swagger-jsdoc/index.d.ts","../../node_modules/@types/swagger-ui-express/index.d.ts","../../node_modules/@types/uuid/index.d.ts","../../node_modules/@types/ws/index.d.ts"],"fileIdsList":[[558,600,717,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,976,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,735,742,743,786,801,809,826,836,882,912,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,975,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,912,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,911,976,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,809,882,914,976,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,784,836,973,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,913,972,974,975,976,977,978,986,992,993,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,882,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,914,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,882,913,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,976,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,947,979,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,948,979,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,950,979,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,951,979,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,955,979,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,958,979,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,979,980,981,982,983,984,985,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,974,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,990,991,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,935,976,989,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,886,905,910,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,718,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,718,733,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,718,719,734,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,883,884,885,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,784,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,888,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,887,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,733,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,887,888,889,890,903,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,733,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,784,902,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,904,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,906,907,908,909,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,737,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,737,738,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,994,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1017,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,882,994,1001,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1017,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,882,1002,1015,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,882,994,1001,1002,1015,1016,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1017,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1001,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1001,1015,1018,1019,1023,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,1015,1018,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,1010,1020,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,1011,1020,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1020,1021,1022,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,740,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,736,740,741,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,739,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,744,785,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,744,784,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,758,759,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,752,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,754,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,752,753,755,756,757,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,745,746,747,748,749,750,751,754,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,758,759,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,995,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,994,995,997,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,994,995,999,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,995,996,997,998,999,1000,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,994,995,996,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1026,1105,1107,1108,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1067,1070,1099,1100,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1029,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1073,1074,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1073,1105,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1073,1074,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1073,1074,1098,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1071,1073,1074,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1105,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1071,1073,1074,1087,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1071,1073,1074,1083,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1070,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1091,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1072,1086,1091,1098,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1072,1086,1091,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1091,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1071,1072,1086,1087,1088,1089,1090,1105,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1070,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1032,1036,1043,1071,1098,1105,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1072,1096,1098,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1070,1098,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1071,1072,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1091,1098,1105,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1030,1032,1034,1036,1040,1046,1096,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1031,1032,1035,1036,1037,1038,1039,1040,1096,1098,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1031,1032,1033,1035,1036,1044,1096,1097,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1031,1032,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1032,1033,1098,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1029,1031,1032,1033,1034,1035,1099,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1032,1036,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1068,1069,1096,1097,1098,1099,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1071,1072,1091,1092,1093,1094,1095,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1032,1036,1038,1039,1097,1098,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1033,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1032,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1036,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1029,1032,1067,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1070,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1028,1097,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1041,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1050,1070,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1029,1051,1070,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1105,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1029,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1056,1070,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1105,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1028,1070,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1050,1051,1070,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1102,1105,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1027,1028,1067,1070,1101,1103,1104,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,642,1027,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,634,642,1105,1108,1112,1150,1151,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1105,1108,1112,1151,1152,1155,1166,1167,1168,1169,1171,1177,1179,1180,1181],[121,122,124,162,163,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[122,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[121,122,123,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[122,124,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,643,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,787,788,789,790,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,789,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,791,794,800,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,792,793,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,795,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,796,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,797,798,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,797,798,799,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,849,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,850,851,852,853,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,836,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,802,803,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,804,805,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,802,803,806,807,808,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,817,819,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,818,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,819,820,821,822,823,824,825,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,821,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,720,730,731,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,729,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,720,730,731,732,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,832,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,829,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,830,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,827,828,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,827,828,829,831,832,833,834,835,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,721,722,723,724,725,726,727,728,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,725,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,891,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,891,892,893,894,895,896,897,898,899,900,901,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,854,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,809,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,837,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,865,866,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,867,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,837,855,856,857,858,859,860,861,862,863,864,868,869,870,871,872,873,874,875,876,877,878,879,880,881,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,655,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,654,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,658,667,668,669,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,667,670,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,658,665,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,658,670,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,656,657,668,669,670,671,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,649,674,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,676,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,659,660,666,667,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,659,667,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,679,681,682,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,679,680,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,684,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,656,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,661,686,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,686,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,689,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,686,687,688,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,686,687,688,689,690,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,663,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,659,665,667,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,676,677,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,692,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,692,696,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,692,693,696,697,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,666,695,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,673,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,655,664,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,615,617,649,663,665,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,658,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,658,700,701,702,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,655,659,660,661,662,663,664,665,666,667,672,675,676,677,678,680,683,684,685,691,694,695,698,699,703,704,705,706,707,708,709,710,711,712,714,715,716,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,656,660,661,662,663,666,670,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,660,678,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,694,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,665,666,680,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,659,665,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,665,684,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,666,676,677,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,615,631,649,674,706,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,659,660,711,712,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,615,616,649,660,665,678,706,710,711,712,713,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,660,678,694,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,665,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,810,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,717,812,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,810,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,810,811,812,813,814,815,816,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,649,717,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,840,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,649,839,841,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,838,839,842,843,844,845,846,847,848,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,717,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,987,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,987,988,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187,1191],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1185,1187,1189],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1185,1187],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187,1193],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1186,1187],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1198],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187,1204,1205,1206],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187,1208],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187,1190],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187,1189],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1187,1198],[558,600,615,649,1166,1167,1168,1169,1171,1177,1179,1180,1181,1245],[558,600,615,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,615,649,1166,1167,1168,1169,1171,1177,1179,1180,1181,1250,1251,1252],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1246,1251,1253,1255],[558,600,612,615,617,620,631,642,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,597,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,599,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,605,634,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,601,606,612,613,620,631,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,601,602,612,620,1166,1167,1168,1169,1171,1177,1179,1180,1181],[553,554,555,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,603,643,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,604,605,613,621,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,605,631,639,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,606,608,612,620,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,599,600,607,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,608,609,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,610,612,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,599,600,612,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,613,614,631,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,613,614,627,631,634,1166,1167,1168,1169,1171,1177,1178,1179,1180,1181],[558,595,600,647,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,608,612,615,620,631,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,613,615,616,620,631,639,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,615,617,631,639,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[556,557,558,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,618,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,619,642,647,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,608,612,620,631,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,621,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,622,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,599,600,623,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,597,598,599,600,601,602,603,604,605,606,607,608,609,610,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,1166,1167,1168,1169,1171,1177,1178,1179,1180,1181],[558,600,625,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,626,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,627,628,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,627,629,643,645,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,631,632,634,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,633,634,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,632,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,634,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,635,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,597,600,631,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,637,638,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,637,638,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,605,620,631,639,1166,1167,1168,1169,1171,1177,1178,1179,1180,1181],[558,600,640,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,620,641,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,615,626,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,605,643,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,644,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,619,645,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,646,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,605,612,614,623,631,642,645,647,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,648,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,613,615,617,620,631,642,649,1166,1167,1168,1169,1171,1177,1179,1180,1181,1247,1259,1260],[558,600,615,631,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,613,631,649,1166,1167,1168,1169,1171,1177,1179,1180,1181,1249],[558,600,615,649,1166,1167,1168,1169,1171,1177,1179,1180,1181,1250,1254],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1255,1256],[558,600,612,615,617,620,631,639,642,648,649,1166,1167,1168,1169,1171,1177,1178,1179,1180,1181],[85,86,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[86,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[85,87,88,89,90,92,93,94,95,98,99,100,101,102,103,104,105,106,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[88,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[87,88,91,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[87,88,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[87,94,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[87,91,93,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[86,87,91,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[86,87,92,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[86,87,91,96,97,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[86,87,89,91,96,97,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[86,87,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[86,87,91,96,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[85,86,87,91,97,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[85,86,87,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,601,612,631,647,1105,1107,1108,1109,1110,1152,1156,1158,1159,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1105,1160,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,137,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,111,114,133,136,138,139,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,111,114,133,136,137,138,141,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,111,112,113,114,116,133,136,137,138,149,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,111,114,133,135,136,137,138,151,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,111,113,114,137,138,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,111,112,135,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,114,116,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[216,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,112,113,115,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,113,114,116,120,144,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,155,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[112,114,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,114,134,158,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,114,116,117,146,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[111,116,117,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,113,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,114,161,164,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,114,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,109,110,111,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[166,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,113,114,116,144,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,113,169,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[111,114,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,114,116,147,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,115,131,171,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,109,110,112,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,112,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,172,186,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,115,120,121,122,124,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,114,116,189,196,197,217,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,114,134,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[114,196,197,216,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[114,216,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[114,190,194,195,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,114,196,197,200,201,217,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,114,115,116,120,121,122,124,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,114,116,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[111,114,116,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,114,116,120,143,145,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,113,114,116,120,143,144,206,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,113,114,120,143,144,159,206,208,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,113,114,116,120,143,144,145,206,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,113,114,116,120,144,206,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,114,116,175,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,114,116,143,145,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,111,112,113,114,116,136,174,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,113,116,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,113,114,115,119,120,125,126,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,114,115,120,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[114,137,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,111,114,137,148,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,114,133,136,138,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,108,111,112,114,116,134,136,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,170,216,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,131,172,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[176,177,178,179,180,181,182,183,184,185,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[196,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[114,196,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[111,116,118,146,147,148,153,173,175,191,192,193,196,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[111,114,116,193,196,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,114,196,199,202,217,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,115,127,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[108,111,112,113,115,116,117,118,119,120,125,127,133,136,138,140,142,143,144,145,146,147,148,150,152,153,154,156,157,158,159,160,161,165,167,168,170,172,173,174,175,187,188,190,191,192,193,196,198,199,202,203,204,205,206,207,208,209,210,211,212,213,214,215,217,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,567,571,600,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,567,600,631,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,562,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,564,567,600,639,642,1166,1167,1168,1169,1171,1177,1178,1179,1180,1181],[558,600,620,639,1166,1167,1168,1169,1171,1177,1178,1179,1180,1181],[558,600,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,562,600,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,564,567,600,620,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,559,560,563,566,600,612,631,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,567,574,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,559,565,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,567,588,589,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,563,567,600,634,642,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,588,600,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,561,562,600,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,567,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,561,562,563,564,565,566,567,568,569,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,589,590,591,592,593,594,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,567,582,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,567,574,575,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,565,567,575,576,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,566,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,559,562,567,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,567,571,575,576,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,571,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,565,567,570,600,642,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,559,564,567,574,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,562,567,588,600,647,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1149,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,642,1121,1125,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,631,642,1121,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1116,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,639,642,1118,1121,1166,1167,1168,1169,1171,1177,1178,1179,1180,1181],[558,600,649,1116,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,620,642,1118,1121,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,631,642,1113,1114,1117,1120,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1121,1128,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1113,1119,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1121,1142,1143,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,634,642,649,1117,1121,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,649,1142,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,649,1115,1116,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1121,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1115,1116,1117,1118,1119,1120,1121,1122,1123,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1143,1144,1145,1146,1147,1148,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,608,1121,1136,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1121,1128,1129,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1119,1121,1129,1130,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1120,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1113,1116,1121,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1121,1125,1129,1130,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1125,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,642,1119,1121,1124,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1113,1118,1121,1128,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1121,1136,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,647,649,1116,1121,1142,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,127,130,218,230,231,245,304,309,395,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[436,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[218,229,230,231,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,219,224,225,230,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,257,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,132,257,437,548,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,129,131,285,286,304,424,426,429,437,503,543,544,545,546,547,548,549,550,551,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,437,549,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,257,285,286,304,426,429,437,546,547,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,277,281,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,132,218,219,225,267,284,304,395,424,436,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,257,547,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,262,317,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,218,219,263,285,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,285,392,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,225,262,267,284,285,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,285,395,397,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,245,255,257,309,324,327,328,336,339,341,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,245,309,343,346,347,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,245,257,309,328,339,341,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,245,257,309,324,327,328,336,339,341,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,223,245,309,341,357,360,370,389,390,407,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,118,128,129,130,218,227,236,239,245,247,257,291,292,309,322,324,326,327,328,329,331,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,129,130,225,227,239,245,257,291,292,309,329,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,239,245,309,352,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,223,227,239,245,257,309,352,356,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,223,227,239,245,257,309,352,356,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,129,130,218,223,245,298,309,327,340,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,132,221,227,245,246,305,306,307,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,129,130,227,239,245,247,257,264,291,292,297,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,132,227,239,245,246,256,302,305,306,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,227,239,245,257,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,239,245,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,218,227,239,245,257,299,301,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,239,245,309,363,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,227,239,245,256,257,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,239,245,256,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,227,239,245,257,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,223,224,227,245,309,323,369,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,245,341,371,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[221,227,239,245,257,309,373,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,224,227,239,245,309,352,367,368,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,224,227,239,245,309,352,367,368,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,223,224,227,239,245,257,309,356,367,368,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,227,228,239,245,257,309,377,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,218,227,239,245,257,266,300,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,245,309,364,380,381,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,227,239,245,256,257,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,239,245,266,309,381,435,537,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,223,245,309,324,327,328,332,340,341,384,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,223,245,309,324,327,332,340,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,118,128,129,130,132,218,224,225,227,245,247,257,291,292,296,301,309,324,327,331,384,386,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,132,152,218,224,227,245,247,309,327,351,384,386,387,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,129,130,132,218,223,225,245,309,324,327,332,340,389,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,245,250,253,257,309,326,332,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,245,309,392,393,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,245,309,393,395,397,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,225,237,245,266,302,309,380,383,399,403,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,245,309,364,401,402,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,227,245,302,309,401,402,405,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,223,224,227,245,309,399,401,405,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,245,309,399,401,405,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,218,245,309,392,393,410,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,132,218,239,245,309,464,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,132,239,245,309,464,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,132,229,239,245,309,464,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,132,239,245,309,464,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,132,229,239,245,309,464,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,132,218,239,245,291,309,464,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,132,218,239,245,309,464,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,239,245,257,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,245,295,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,239,245,309,317,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,132,239,243,244,245,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,132,239,243,245,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,239,244,245,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,129,130,132,219,239,245,287,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,129,130,132,222,225,245,267,287,291,292,298,302,303,304,308,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,239,245,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,239,244,245,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,132,239,243,244,245,309,386,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,225,239,245,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,129,130,132,218,222,239,245,264,286,287,288,289,291,292,293,294,305,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,132,239,245,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,129,245,287,309,419,424,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,129,132,218,239,245,257,309,426,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,129,130,132,222,225,239,245,257,267,286,288,291,292,293,309,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,129,132,218,239,245,250,287,309,395,396,405,429,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,233,245,309,399,402,416,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,129,130,132,218,223,245,287,291,295,309,327,340,390,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,129,130,132,244,245,309,334,412,434,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,132,244,245,309,412,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,132,244,245,309,435,437,463,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,132,244,245,309,434,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,132,221,223,227,245,293,294,298,302,303,305,306,307,308,309,332,341,342,347,348,349,350,351,352,353,357,358,359,360,361,362,364,365,366,369,370,372,374,375,376,378,379,380,382,383,385,387,388,390,391,394,398,403,404,406,407,408,409,411,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[132,229,245,309,435,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,464,465,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,223,245,293,294,295,305,309,389,413,414,415,416,417,418,419,420,421,422,423,425,427,428,430,431,432,433,435,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,244,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,245,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,245,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,244,245,472,474,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,229,238,245,472,478,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,218,233,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[233,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[218,233,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[233,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,218,233,309,321,332,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,233,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[233,298,309,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[130,233,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[233,247,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[218,225,227,233,295,309,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,239,245,309,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,118,130,132,218,219,220,221,222,223,224,225,226,227,229,232,233,234,235,237,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,261,262,265,266,267,269,270,271,272,273,275,276,277,278,279,281,282,283,284,288,291,292,293,294,295,298,299,300,301,302,303,304,305,306,307,308,309,310,311,316,317,318,319,321,322,323,324,325,326,327,328,330,332,334,336,338,340,341,342,343,344,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,374,375,376,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,403,404,405,406,407,408,409,412,413,414,415,416,417,418,420,421,422,423,427,428,430,431,432,433,434,435,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,475,476,477,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,131,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,218,225,226,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,384,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[130,218,240,241,242,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,132,221,225,245,284,301,305,308,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,225,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,118,130,217,218,225,227,229,232,243,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[218,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[130,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,223,227,244,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,225,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,218,223,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,223,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,218,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[243,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,221,224,225,227,228,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,218,219,220,221,222,224,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[130,245,400,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,254,255,257,258,260,310,311,317,318,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,223,310,319,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,310,316,319,320,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,310,319,320,355,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,310,311,316,319,320,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,310,319,323,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,249,252,254,257,277,281,310,311,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,249,310,325,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,249,316,320,323,325,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,258,262,310,320,323,325,354,355,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,249,310,316,320,323,325,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,310,323,325,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,249,252,257,277,281,310,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,223,310,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,250,281,310,316,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,223,224,229,367,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,223,249,310,316,320,323,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,258,262,281,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,249,252,258,261,262,311,317,495,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,280,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,277,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,219,249,257,258,261,262,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,219,248,263,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,219,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,222,257,258,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,257,271,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,272,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,257,258,260,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,220,272,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,218,220,222,269,270,275,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,254,257,258,260,274,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,234,235,236,237,238,244,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,234,245,309,332,333,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,278,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[130,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[278,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,259,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,251,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,250,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,250,251,254,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,255,256,257,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,253,254,255,258,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,233,253,257,258,260,261,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,250,252,256,257,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,252,253,256,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,245,309,343,345,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,245,309,341,343,344,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,257,258,262,335,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,249,257,258,262,335,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,258,337,338,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,296,309,322,332,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,322,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,265,296,298,309,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[130,233,279,295,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,266,295,296,309,437,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,218,227,229,290,300,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,221,229,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,224,229,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,228,229,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,225,227,229,290,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,225,229,290,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,258,262,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,250,254,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,250,257,258,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[315,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,315,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[314,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,311,315,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,313,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,312,314,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,222,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,517,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,435,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,229,234,473,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,229,236,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[238,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,257,258,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,262,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,257,262,325,395,396,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,311,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,130,218,319,512,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,248,392,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,250,256,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,225,248,262,284,503,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,248,395,397,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,256,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,256,257,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,249,257,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,248,317,508,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,317,501,508,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,317,395,505,508,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,130,241,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[229,247,251,257,277,330,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,129,130,266,277,279,295,309,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,225,233,274,277,278,279,281,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,225,256,266,311,537,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,225,266,537,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,218,225,250,252,256,261,266,277,281,282,497,525,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,218,225,261,266,277,281,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,130,218,225,249,257,261,266,267,268,269,270,273,276,282,283,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[107,128,218,254,257,281,395,397,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[522,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[128,533,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181,1183],[558,595,600,605,613,615,639,643,647,1166,1167,1168,1171,1172,1177,1178,1179,1180,1181],[558,600,1166,1167,1168,1169,1171,1177,1180,1181],[558,600,1166,1167,1168,1169,1177,1179,1180,1181],[558,595,600,1166,1167,1169,1171,1177,1179,1180,1181],[558,600,605,623,631,634,639,643,647,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,649,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182],[558,600,605,613,614,621,639,648,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1166,1167,1168,1169,1171,1177,1179,1181],[558,600,613,1166,1168,1169,1171,1177,1179,1180,1181],[558,600,1166,1167,1168,1169,1171,1177,1179,1180],[558,600,1166,1167,1168,1169,1171,1179,1180,1181],[538,539,540,558,600,1166,1167,1168,1169,1171,1177,1179,1180,1181],[537,541,542,552,558,600,1162,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1163,1164,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,653,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1024,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,653,1025,1161,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,1160,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,652,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,649,1166,1167,1168,1169,1171,1177,1179,1180,1181],[558,600,612,647,650,651,1166,1167,1168,1169,1171,1177,1179,1180,1181]],"fileInfos":[{"version":"69684132aeb9b5642cbcd9e22dff7818ff0ee1aa831728af0ecf97d3364d5546","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"8fd575e12870e9944c7e1d62e1f5a73fcf23dd8d3a321f2a2c74c20d022283fe","impliedFormat":1},{"version":"8bf8b5e44e3c9c36f98e1007e8b7018c0f38d8adc07aecef42f5200114547c70","impliedFormat":1},{"version":"092c2bfe125ce69dbb1223c85d68d4d2397d7d8411867b5cc03cec902c233763","affectsGlobalScope":true,"impliedFormat":1},{"version":"07f073f19d67f74d732b1adea08e1dc66b1b58d77cb5b43931dee3d798a2fd53","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7a3c8b952931daebdfc7a2897c53c0a1c73624593fa070e46bd537e64dcd20a","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"b5ce7a470bc3628408429040c4e3a53a27755022a32fd05e2cb694e7015386c7","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"87dc0f382502f5bbce5129bdc0aea21e19a3abbc19259e0b43ae038a9fc4e326","affectsGlobalScope":true,"impliedFormat":1},{"version":"b1cb28af0c891c8c96b2d6b7be76bd394fddcfdb4709a20ba05a7c1605eea0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2fef54945a13095fdb9b84f705f2b5994597640c46afeb2ce78352fab4cb3279","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac77cb3e8c6d3565793eb90a8373ee8033146315a3dbead3bde8db5eaf5e5ec6","affectsGlobalScope":true,"impliedFormat":1},{"version":"56e4ed5aab5f5920980066a9409bfaf53e6d21d3f8d020c17e4de584d29600ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ece9f17b3866cc077099c73f4983bddbcb1dc7ddb943227f1ec070f529dedd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a6282c8827e4b9a95f4bf4f5c205673ada31b982f50572d27103df8ceb8013c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1c9319a09485199c1f7b0498f2988d6d2249793ef67edda49d1e584746be9032","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3a2a0cee0f03ffdde24d89660eba2685bfbdeae955a6c67e8c4c9fd28928eeb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"60037901da1a425516449b9a20073aa03386cce92f7a1fd902d7602be3a7c2e9","affectsGlobalScope":true,"impliedFormat":1},{"version":"d4b1d2c51d058fc21ec2629fff7a76249dec2e36e12960ea056e3ef89174080f","affectsGlobalScope":true,"impliedFormat":1},{"version":"22adec94ef7047a6c9d1af3cb96be87a335908bf9ef386ae9fd50eeb37f44c47","affectsGlobalScope":true,"impliedFormat":1},{"version":"4245fee526a7d1754529d19227ecbf3be066ff79ebb6a380d78e41648f2f224d","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"bde31fd423cd93b0eff97197a3f66df7c93e8c0c335cbeb113b7ff1ac35c23f4","impliedFormat":1},{"version":"b166e33cf8226ac8781899da244397e77e5b6528271339ce26ece0c2c7242d7f","impliedFormat":1},{"version":"a623d5cf7925e72dbf4602862499564389c7c3dc0ce049733cc0ec756a846667","impliedFormat":1},{"version":"d9028ded7b00c211d789db29f1b2d9d1b7600a4edcbbd087f1faf0495229d179","impliedFormat":1},{"version":"63634c0855e639ea7f609613d799bbb0dc774ec9f3242bc272c5567dc5ccd485","impliedFormat":1},{"version":"592f06c425ab27b4bafec624ef5b153cbdde9ac58f7113100a2da1c4309d1309","impliedFormat":1},{"version":"19c8ab51b4b07c529d95cd4d5c8d100a68dca247ec83a5097d35106fd8a7acca","impliedFormat":1},{"version":"72adc8e79ac32a81f3d515850cf8944a94f0dbc3c567835b37a45f601ccc1d3d","impliedFormat":1},{"version":"fb4f06b2af9ee4b2d2be8c964b0a8f6dd260be9048488ffcf04eb5c0fcb8bf61","impliedFormat":1},{"version":"f185055f36d76e2df5eeb87ae1148a25a125be2bff2095e1bd39c1c7ce85a640","impliedFormat":1},{"version":"9fcb4ef8bf8955c4e9c81bdf4e239d4c0c22869b6cf6ce2ecc95743bf683cb9f","impliedFormat":1},{"version":"979fdebc12d30becce6a15e68d99bc8a2a470a8dcf0898ac9e2d241a7e531940","impliedFormat":1},{"version":"1824ad7d4259910646279d667e517334c0aa24d5c810e8ea6da756fc2e02372f","impliedFormat":1},{"version":"989e9060e220ff86025044ba3c867a83512a655b7cf6253b2bd682192debf390","impliedFormat":1},{"version":"8b1feb568c859feb59236e9723b7a86e2ff8f9a8f2012366ffd1798164dc2798","impliedFormat":1},{"version":"8fab988b0129e674afc0bc0e95329b4052cf027f5d5b5b3e6e92d055b5ba88ef","impliedFormat":1},{"version":"4fe56d524ab24c225668803c1792945053e648b4e8fa4e50fa35594495b56732","impliedFormat":1},{"version":"2652931b8f7dca9a57f21aeb25b5d46851dcf17e4d5ed54b9b57d5d26e647680","impliedFormat":1},{"version":"d364c8df7d52199f5d011b4ded96f36dd114b984f5ee2e50ffe7d30ac1ab4bba","impliedFormat":1},{"version":"408f9eb3c7a3533bf5f07e0cde110a5ee0702864795ee6727792520fe60320b6","impliedFormat":1},{"version":"ba79eb15c36ff23e352ef608ceb7f9f0f278b15ad42512c05eedbe78f228e0e4","impliedFormat":1},{"version":"4cd233c6af471432253a67ae4f3b43c85e58a71418d98c3e162a1dac975c68f6","impliedFormat":1},{"version":"aa77c7d8ddc961e8192bcaa92da140e1205f8aee78bfadead5f52b8844d7d05c","impliedFormat":1},{"version":"37e37d3a525a207efab5458069fd9a27a174d2dc3af729702c81729ca03a349f","impliedFormat":1},{"version":"70997e63b7b3d90188fa2106753d35afd3b43b2bde957c46a5516d89e3ef0c1a","impliedFormat":1},{"version":"7fdaebdb3780d0549a8e0abcb18965e2f62224bdde633aeafb22c64c02fe9e9d","impliedFormat":1},{"version":"24f848479d1fd142d3d7cf034bedca247d1d9b8b31c2632c09695bd6a0441141","impliedFormat":1},{"version":"7e977910c045ec087f435905eb730e9c84e8d6b97f0dd0fe0c022dfed665613a","impliedFormat":1},{"version":"9c4ec2692cdb791823b9407753dec50d69b1b990cf7038cac3fab01e8ed5f709","impliedFormat":1},{"version":"176e7ce333b9988d68cfd5ab6717b20421a03b415af57f2a3bea1aa6b8d634a9","impliedFormat":1},{"version":"301a1ba797c537d2598a557af4862e7823353c80529c9a58bc1a0c08779deb5d","impliedFormat":1},{"version":"2f37ef3a5d3fb119b390cb48c77352914c814b98948633deac90099faae320a6","impliedFormat":1},{"version":"ca2ce76fd743888d0f0c5be48b1b17a864f5ff2b0d09e954d3690645a794533f","impliedFormat":1},{"version":"d4832d1deaacad5d196b2a83239fb94c80f97df889c02a75859b05b460885300","impliedFormat":1},{"version":"1b105a40480faa8c292868597cccea1384e26c034ea0b7e2c6e9d834259f7ef3","impliedFormat":1},{"version":"c53f7caa42ad0bff2b3cad20e4780990aadf647c845cb66cec004062cc4ae549","impliedFormat":1},{"version":"a82f1d66de93c80bca7a744647c748657c050341e53de63fae5aecb72f85f5e6","impliedFormat":1},{"version":"b066b4fde4ba0c1f85aefcd6424a5c670694c871ef2f0fdbf43c5c37e3b0cf3e","impliedFormat":99},{"version":"301f3adc8c06c98797d994c52155f0262379c9679bff79d2f8bfafcb9cbf06ac","impliedFormat":99},{"version":"114acf974bab47eadf40fc7d1ddb0e872d8d8230b111ce4465540ad48d2d5001","impliedFormat":99},{"version":"7755d7edd5edd4b5a8cd308aa9c05c767a8d3d17bc09673165128e0b6e8cee7e","impliedFormat":99},{"version":"27a7c50de3aea981dd08e99e4de2bd29599537e07ffc5e85d20f40f2cfb79bac","impliedFormat":1},{"version":"400ba51008a98a5afc065b12c3aee8f447a0b66c2a4c1bcc3e5a2f41015ddee7","impliedFormat":1},{"version":"49f735c4888a72b7e70b4a90db308ea672967fc2a1670c5b6b598f6b09403baf","impliedFormat":1},{"version":"a2e86477a12540ef9e439245b959b2d8b96d674d5215d154ff22ad26141f4cfb","impliedFormat":1},{"version":"29150e44771dac0aeb711badc04e08fccd01b46efc560bd6e01b96d746a3f26c","impliedFormat":1},{"version":"e09f096004d70d6e98f5e5fee165849b3944f706861cdeffce5339dfd8426db5","impliedFormat":1},{"version":"1ddd1ca692a6c656ade0a85c9a722b3679b3d0bf113b699908e0325cf3537dbe","impliedFormat":99},{"version":"a7a4ea3e08f0ca7139ef99db3be34db005406e795bdeaa519998ad4666c5dfb9","impliedFormat":1},{"version":"4fb2df0b48ac55d960fedfb7e7b917d2d29608d7f351b70b6b3104e2d02d2f11","impliedFormat":1},{"version":"728ec07c8a50b9f22da9c9aa8859e29462526fd996ac1d21c6c9a81b78106dd5","impliedFormat":1},{"version":"3f48d378dba0b95f2d431d60efd4f3225791c0a880d1166181d6edb563160bde","impliedFormat":1},{"version":"f58e5f53ffdcac8ebbfdad16ea7e6164fc25e63f5e3cae8cb13395100ebb8da8","impliedFormat":1},{"version":"be9ef0a0446cf28d529a684e4a7d14101f03e054896704fbdc5470d8fa4de6b4","impliedFormat":1},{"version":"acd32f2f192d93e8161938ebfd74fa063e67a09cbe0156a74ae2e421a1e8f786","impliedFormat":1},{"version":"1eeb9deebe9a0a6cc52a32aa1533a1535ecc1b4e831290c753e72e0394e866a9","impliedFormat":1},{"version":"ae1f27a5966db7640edb4c82974b985acb7b1fa0859bff7cd769629436822d9a","impliedFormat":1},{"version":"a3d0b36bb3185da856cc0a7df02f63008935602ed09f84b0d960c7f9f7f6d63d","impliedFormat":1},{"version":"60319cf75d460432a0769a2f98a9ab6fc3ad39290bf7f1b33b922e832ff5b40e","impliedFormat":1},{"version":"30ceaf6e65817221c5c62cedfc26892a4b79a78c7eb7367bcccc0e217b517bf1","impliedFormat":1},{"version":"a3ea4adb87d130799d26945196bba7e889056c74dac98069d58c015d10f3c053","impliedFormat":1},{"version":"83dc49d957cb3b4af3a45cd7b54958149d21088d49f95e8ba6e3d3fb2b37d880","impliedFormat":1},{"version":"b7825c3d04bfc38caf9cb94341cede132d227654b28e3a603d1576bf199a7e47","impliedFormat":1},{"version":"888180b3d951298bf85d430543a1fa2fc6264fc847aef5baa821c743b5d84a58","impliedFormat":1},{"version":"4ec19d58993999260e0df245eec5fd6d7dd92978360c4f0706c9260091f55c70","impliedFormat":1},{"version":"0bc4f86d58f4a4b5a9563ba8d2b23a3fac187a6e167772f6689ea807081ed631","impliedFormat":1},{"version":"7a4e38850bfca2b105fd3e5609b68b52271fd7f2cab9f1d4031748e8bfd29633","impliedFormat":1},{"version":"496ee894efcd5de63169a3a4e47d74f16f754eb212b1ef209f9255aaaeef3450","impliedFormat":1},{"version":"246bec681a7465de230b083e0e63633b568a2d79c20fe167d3280e21200b22c8","impliedFormat":1},{"version":"3ee38e0bac65430814b195ed22b5aadfbe4fbd8890c5e5b45a7ba13f05c0ea0d","impliedFormat":1},{"version":"45181e4221f90d98bf2046ba55cdc22411dc64b9a8cc04f1c8702038b7334d01","impliedFormat":1},{"version":"7fe0253ff44f072ea13fa372e2fbd007aa439df9560762950d38b4c203b2c51a","impliedFormat":1},{"version":"bf4ebcedc7324dd0cbe83488830f7966e808fabf4836d516d1b591ea91417c68","impliedFormat":1},{"version":"5cc968707e8d5e146d075fb83c33a242dd874ef44356969f0ac243dcfd483270","impliedFormat":1},{"version":"af0dfd141ecb2e24ef9a3028727214a69aa528d0be91e8728a7abd4fd6659b5f","impliedFormat":1},{"version":"786d583f831d03da4aed9f9354fd9c4ef00aa8122564da5e683631423639c258","impliedFormat":1},{"version":"418fdcdefc32953c6c7ea7e9979ce84b87618de9def698e73da2c16697fe023b","impliedFormat":1},{"version":"4d0db315ab6869de22694dc968fe740cfef635a21455a4d2bd33bc95b8eec381","impliedFormat":1},{"version":"31b529d1940d4b37e101c4497f7b55965a667985c931b1d16821f7a120e88b4c","impliedFormat":99},{"version":"e9ecf153356cbe27354242dcb6a62234bf6d83c8c19d5204694694783c0b905c","impliedFormat":99},{"version":"83d783e14ae73ab5adeced6c66526daa1155f74512c00ce72902d1fc7c02484d","impliedFormat":99},{"version":"e2a062632ce9bd3663f3821c04f912957ba093cf9cebe532d9ce3187fc837b8c","impliedFormat":1},{"version":"08447e8b528a1f8d1162aa044695d460ce5179a78bd174fa0673fa16b06011aa","impliedFormat":1},{"version":"8e532c6486042736463d1116d45b0db814d969ffd2ee822e4e5ce975807c16f0","impliedFormat":1},{"version":"fad47f66fef1ff277730abff9c9330dd70284eb0ced43d6dd6aee15fc5f19a1b","impliedFormat":1},{"version":"7b4b0aaf0978122b44aa6317977be3e2f9d3d261ae4a8d93bfd511a7ddee7dfe","impliedFormat":1},{"version":"cb5def9d6efe73b09a7adce13bbb7fad7ee6df7a59259300de6ca77fe84041fc","impliedFormat":1},{"version":"16c6ff8bcfef0ad22abffa3329760bb611c4c4aa098ece0d6bcfd1cd16610997","impliedFormat":1},{"version":"3d15157b6685e63a7e43a39bbc1fbcfdbf1250fa3598af55a2384f6f31260c86","impliedFormat":1},{"version":"58b5bc399cd98b87eff2c80d995d4dd63e69c801ec880b85c7da73ddc561a751","impliedFormat":1},{"version":"401c5b0f01bb0dce7a85899d8665c7d9c0b1637dc642805320d76c1a071135dd","impliedFormat":1},{"version":"af81e13747ef7589a726505dd4c2dcf00bb2b9fd7c3c84d580c1d02dbc3b58a9","impliedFormat":1},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"6a1197b37f8f406bfb74528ca1fb90659c6d1a251d472b1c65affb5c6a6ba5f8","impliedFormat":99},{"version":"516c53364c6b242591c65afc8b0f0f0cee74ac8a04f52470a539fcb33da2e318","impliedFormat":1},{"version":"cdf612f32afd760cd4a568e3f0c4646394f18fe2277a5ec1c084f1430776f1e0","impliedFormat":1},{"version":"e8ee036c1281885b9cc58f9d1d47472037d080a45b44a3ecbb8fea445e87415d","impliedFormat":1},{"version":"27679e96d1bd38c5938178aaf4abe8627493090b63d6bae2ce8436e6a87ebe4d","impliedFormat":1},{"version":"90887074bbd664eb4726465ccc6740fa8886e525e5c0afcc734e41df41851a60","impliedFormat":1},{"version":"67ddace2fd97646b97e56794034fe5147674a83b7b21c47ec822c25284287497","impliedFormat":1},{"version":"0a3d92e1ed031f67294fc02692352444c0514e371b7093b8d224b6f9ea02d958","impliedFormat":1},{"version":"cc31889ffc5c322ff53137f54f3aa8f74a969cd01adbb296737231f31a870322","impliedFormat":1},{"version":"0ca73c49265550f240230440fbd4dbdb1e332c14620b6a13fd02c08ca96f6018","impliedFormat":1},{"version":"3df74fc90d6cf9c51ad6864a7d9e1e6d162a6e158f99ab2b7d878b4646aa343b","impliedFormat":1},{"version":"306712d7dc95ea2006413dec36b165bff346626340d2ba5adc14a3bafdcb57db","impliedFormat":1},{"version":"cca7da500accfa2e8689e453b1d74d05bcbf1dc6ef86f12b8cb1518a880adffa","impliedFormat":1},{"version":"15b2cfe4d0234d8b21250f6b93c2a4bf7b56fd9e5c740c8d0d5086e3878386f5","impliedFormat":1},{"version":"3470c8f802d69951553de4bf72f42a77b1d273c971dc8462d7ac94b2d5069171","impliedFormat":1},{"version":"312476b9c5aa822a32c969ad650d1b475b631506af9a1448abf2d714997f7510","impliedFormat":1},{"version":"2dc955a0fbc3c0b9a49bcc3ffb9dfb31b3a53af0db862260dd4f824c6b4ff36c","impliedFormat":1},{"version":"0f513df152e8cd877ddc47e1a767f77d2111d7b5dfbc4f68ca355d1dd59c062c","impliedFormat":1},{"version":"e6e01423d7599e1155ab10e2a4ab1549c7f78af0d80fc8c641298989b7dc90b3","impliedFormat":1},{"version":"0c904d0442caed7effc17e2c70c7c96df0b34797e1adb9999ce5e5bbbf7e1471","impliedFormat":1},{"version":"4e42a180e6ad34da29c0f9e0e34dfe728292d4148aeb1a36e3ca8e6551f0fc42","impliedFormat":1},{"version":"8722ec4640f5eb5dcc91be6e59e6148b861e93954a766e05d5d55dd96b29e1c1","impliedFormat":1},{"version":"3118f4f3494834d0a131955088b28cba84639a66e23e6de211bdb75fe518ea90","impliedFormat":1},{"version":"8ec50f5d9824f3692fe32a80fb160d72ea39d94c5aac4f3334f7724ae61de6df","impliedFormat":1},{"version":"dfafee7cd0b796c959cd7f4c6d4ae2f1f89fab40129d993dd564f9ef0bd0068d","impliedFormat":1},{"version":"24056a75e8e602d911cea68b06b5e238604aff92d30ec8a119a2ecf07568d4fb","impliedFormat":1},{"version":"bc5fa245e7a3eb9216ce30106e37294a9691efd85391e3de61478c3ca0da360e","impliedFormat":1},{"version":"4523237b5a992a30850668522bb1719bab8f9e50c00b6428f660ca75a451a7b1","impliedFormat":1},{"version":"f116a1399a2583ff7ce15068f007e5c47d06c9964674bc48ea6e69867d0692a5","impliedFormat":1},{"version":"68cabe63e69d17160c77eeefafd83df10a4c0ec3353b6a91a48a205e9dd505ab","impliedFormat":1},{"version":"5a75e49d8e0a78e2cc02bd13fcab4f26d5d6729912e2096b6fe442b0960c0cf7","impliedFormat":1},{"version":"3f1c80ba487c318a1e4c03186fbae29fd76c8159e84d7db7ec07dbfaab2d3d58","impliedFormat":1},{"version":"a6390968657990e16f06624b29112be8efb6b6ef3e008b6dc7e604fec1120893","impliedFormat":1},{"version":"af009985990e75086edf8efe08fbd396366224537aaff80cbeac37f04b34ece6","impliedFormat":1},{"version":"07ab076e1d2663b27c7ea5e565bef05dd2106ee9be762237f7ed35482f5fc14c","impliedFormat":1},{"version":"007dfb1f314277f6e211fec9c5f62fd182e3bb76f1fe1f165228a259ae0b91b8","impliedFormat":1},{"version":"a6aa3bd9c165acb07db158897587581d7b081ce4271579b720a94f95c8c487d5","impliedFormat":1},{"version":"904714e49891cc1e136cf104f4bc9adfc846be9bd28ac55e101145a0d8103b30","impliedFormat":1},{"version":"3fede259ef5c9dd9a97e662da9f6774dbc82f390d29563319b658ebd7f958135","impliedFormat":1},{"version":"9b8ba907ff8c52756b1a0aeac192a22591ac9431ac688cddad8111c8fd5124a3","impliedFormat":1},{"version":"7aae89808421b5e7ff74ea48f715337fcd592e06eeb9850cf378b5141be6415c","impliedFormat":1},{"version":"b9c9c9352d6606fe440735ccad134563017fc5aff8dcd418c58f778437339f06","impliedFormat":1},{"version":"8577cc05a714f4c5a087dfd25bd1459aa4bf401a68e7edbf5c6ac96c0e298e7d","impliedFormat":1},{"version":"d09f6a6dab49823b554255030c4ee8d49a2a993bd02f2cff2e444b2627dffc5a","impliedFormat":1},{"version":"86f1fe35b16ed4282a226d77eff2ad2519500c566833a0c8cd65a780a3c161e1","impliedFormat":1},{"version":"c85b382e6517677e39b234142b1ce97c7672ae72a89d683a4e875692be3b854c","impliedFormat":1},{"version":"83015c82b1d847b367f773a217f1bbd9d9a2f6e205e3710830db89c67ca477e0","impliedFormat":1},{"version":"a62075dd9999f04f8e5fd1c3d675766f7641bb6dfa6596dbdf000617831c800a","impliedFormat":1},{"version":"0717c1a24cd66da2d50833ba78f89d994d1ebe494e0105ac67caa1e1a32a298d","impliedFormat":1},{"version":"d60b952dc30c239e7ed78756eae6b7d7585a2a0a457ac364f5325e6f9127bb80","impliedFormat":1},{"version":"7a932e7cd29555624035a2892b8636e8a61cc2a0b796df2c9bb4526a251bc30c","impliedFormat":1},{"version":"e3e20ed4715775989c0ee8c2be8e657503503ba75c03defe13b99dc317baf3e7","impliedFormat":1},{"version":"c2f1b0272966ba4ec45818b50813210e3abaa993664e26db5617df45672e49aa","impliedFormat":1},{"version":"6faca0f0e857cab15c7ec26f36dc28b73730b184ce942a25654bbcf4ece22f59","impliedFormat":1},{"version":"189ddd84047c597c0fb44c5b03ce5608b0d7d77b3df1a6dfd0f7ff5b82dd71e1","impliedFormat":1},{"version":"9a1cb3741e94561a56bb4b9360220cfa5d64f02c2d51e35f59e433612638ee77","impliedFormat":1},{"version":"743e3303fed6823026dba4b34833ee6b59779678fd7daf64e1e9049114016b1a","impliedFormat":1},{"version":"4664cabfb4158ffebcb583b60e6730dae651d15049ff610ee3ff609fe23249e3","impliedFormat":1},{"version":"d0eaf0b2ddb2a9545476900655073ed4a6fa5bc76c2e43a358e26f88f741d08f","impliedFormat":1},{"version":"1d9d2dbc90a080f54021a9f8eddd6430a8b290659579a2549c38762fd6a4424c","impliedFormat":1},{"version":"4ddac3cdf6eb7dfbbfbdd004bf9e90d263c227888cda110a8bfaed500929c14f","impliedFormat":1},{"version":"cf4bdd9324f9116bf29daf9add3fefe4e609be0dc3bdba1759cf1a6654047726","impliedFormat":1},{"version":"48ff4dab14889a41f5b0b94aacb853b96f8778888167625a42ba7a45250a15b7","impliedFormat":1},{"version":"0b59bc43ab08b3bb00a8a4978683c872fe4c6c3206bc68316ff7a3cbe70d75b0","impliedFormat":1},{"version":"d3763a4abd763d825a766d636661ee3ec52fa8477eb63c243b8dcd033ba23789","impliedFormat":1},{"version":"f4377e81d50af3f689cc5dd2005be3b79dfbbcb3f5a0301c843e8daf1cc9ddda","impliedFormat":1},{"version":"ac1e8ae42e98e9a296d467169321f4cf8802643302f619b025117c4ed5a2d200","impliedFormat":1},{"version":"4cdbcd7e8e8a5beb593e726a2abc758d54efd4828048dce812b4c94fed24a62d","impliedFormat":1},{"version":"27c66f434db3a00fb5b286c88582f2da3a85a2108cdfafe9bf63fa6df206aa2a","impliedFormat":1},{"version":"e2ef2006aa0a9b806063cb510989bafad85e71f21cd7e25783b8876203594dc7","impliedFormat":1},{"version":"5683b6c327ab05195ba14856985488b486117687e3f1b94991e787b25fd6cbb0","impliedFormat":1},{"version":"32d08e56282b632a4ff2aabf97d8e2ca72c872e99453de231684f0347a46c41c","impliedFormat":1},{"version":"f26ba893d9cda649365c19c9929d53ba069d829caa98dea1ad3c90374704cf54","impliedFormat":1},{"version":"9eea04c6c43649983516ae586e2b40ea99b808552d3ddf8a0b7725a490c5914a","impliedFormat":1},{"version":"4179d52fc45e3c72cab28cedf19d10a915522d5f3f83979e61213137bfc794e9","impliedFormat":1},{"version":"3c628794e72068afb3d10eb8e7022f2e7e66594981edae5d24fbdbdc3a34d412","impliedFormat":1},{"version":"2748451f1cb5d1594fec48577685ef0cdefea02fea292873b9ab74aa47ff57ad","impliedFormat":1},{"version":"cece3e0e89f3e9a526ce76bf9bf3aab41bf83a58d625558a671f9058b5e822e6","impliedFormat":1},{"version":"8f7706493348b0f5960d778f804905e68bf7564bc037a9954cc71c18d419e562","impliedFormat":1},{"version":"dd1bb0047f911d2fa01662720bf5f8da6e9cb30db7b2909f3ac4fdcf0eec34db","impliedFormat":1},{"version":"4ab90837f0df1a6c8039689ea77d7d28a06eb1bbf2bc129c271e8a6c01a0f391","impliedFormat":1},{"version":"2c6fcafbedc3bf7e030fbda5acc875e0f2f98b253477105ef5cf0f674409b525","impliedFormat":1},{"version":"171f9f3da4589275b3ca1472e2ee0f32f4b16d5e2c41f79db8bb209433f30d67","impliedFormat":1},{"version":"e495c1011281c8900998e4001777acd8863d9c901410ef2ff2cc21174ef3af49","impliedFormat":1},{"version":"0d7db9b74a017be10aa36509dd2ae4499260381aabc6772feef677fa16f3a1f4","impliedFormat":1},{"version":"e59ef219cec3c3faab54d5cb12222a04d3e095c84abf94088920c1584832ce43","impliedFormat":1},{"version":"786c15fcfa8b821410e278a740f9dc81c44546259d1cc0143646876a0c030cc0","impliedFormat":1},{"version":"99ea681335aa97ba7618ac3db69a2e2da87da7faf8a39f822030ec4db96ca023","impliedFormat":1},{"version":"d7169a2b449d5b8e309edd84624649d04b746be48fe93b2e69bb7a85653b1e97","impliedFormat":1},{"version":"c462479720ea1932e5adc0bd4808be8ee2c83488be1012bf48f4bbb532b63758","impliedFormat":1},{"version":"d72479ce8210c21451cadef350179fbf3729c0e29005aca2d7e0c6ad031a4afa","impliedFormat":1},{"version":"d0e0354d3d4ac41cb7a67c10ca59652f8cba9eeb0929fcc878e492691f73d02a","impliedFormat":1},{"version":"fbe06770551602ccc8e240a24793a8268b1bce44de38c26a7710f7bf1702f9b5","impliedFormat":1},{"version":"e4859560e5d635efa084427db27d6e31780eb570c2a567e95ed12f3828199710","impliedFormat":1},{"version":"6f29c691b977d5fdebefbc109c896fa863e95ae4464d959cc1506f45ad01da8e","impliedFormat":1},{"version":"ddf805d002fbf463fe2e40e78a4c7d1773a62f18716ce452cc02ba185c6c9c0e","impliedFormat":1},{"version":"d7aeffb82f803488ad4f918929a3a980e387c64c395ea793f6167c9704d4502a","impliedFormat":1},{"version":"2ede90710bab4dcdef47b532a8b3a1d63b7c366b058e95c705e9d9634f29f445","impliedFormat":1},{"version":"887a73b0167b36d4aed6d2549b19c4bcc6f2f50248b20d4d10ee2a10ef0516e8","impliedFormat":1},{"version":"f86c2e22ce8546272f0c7fed4909cd0b3db99bb95e7d91f584340f2b158e0ba4","impliedFormat":1},{"version":"d1d43f6f1a6a766dabe2a6db17f737d2c0cdefd747fc52b70dcc4ee011d6ff85","impliedFormat":1},{"version":"62c9a85d5dc9da38e54f1d802b7b62b82170f3a4571e3c992f1db09f60dce051","impliedFormat":1},{"version":"56e14052acc507ace03e94e8ec6cc22c84a65db751f11ca20349a4ea396f72ab","impliedFormat":1},{"version":"1c7dde9d6e45e71504fd8ba6a9c29db164e7a8040bc1782c2a80a3098d0a86c8","impliedFormat":1},{"version":"916e966405a9923eef3123175b1d31188945917edc14027ebe5df1c1f4ba0c70","impliedFormat":1},{"version":"d742f86f826cd1d46f45cc6c106cf34077b10239da02393fc2b6a6490bb4059a","impliedFormat":1},{"version":"8c1fad24452b6f1cab8f02cdec02931524a31467c2602fa9b8c6e5683faa76e1","impliedFormat":1},{"version":"639e7fd024205c3c4af58bb193c1d7790618fcb8b70e9b15068c647ab729ee3a","impliedFormat":1},{"version":"2c26bbcb3898665e821d93f28d9c4b7d712ca23743d8a7a9d89e2aec794bdf40","impliedFormat":1},{"version":"c0e0fc040511ce5af4e546fabe949945c67507cf1f1bc7211448f2e6832bf0bc","impliedFormat":1},{"version":"867266698190564ef5cda597ea6378e766e9c22f65058c94ff8356d166d1f2d3","impliedFormat":1},{"version":"e6f70e3c94d2b1d7c5112ad6df2dd7c2ae5dc81bc89510bbdd4478614cf80594","impliedFormat":1},{"version":"146e5c86d78b4a7ff6dcaf9835b3a6a639dd414d21a30c69df5183bca5596d15","impliedFormat":1},{"version":"b01572aed7f01080dd28016c43cb1520978593992908450ea362cbfbb5fe556e","impliedFormat":1},{"version":"2e24d2d878e6b0e745d3814ccb2186520c6ffc6b3ee3facc329741c100ff42ae","impliedFormat":1},{"version":"0810966f2dcad79a429a4f156d3ec090c5de34fd70fe13a44141b8642bb42701","impliedFormat":1},{"version":"00b9f288c0a241fb4316737af41e0ff0e64be1c03c90640bc3a9f1449742ca9b","impliedFormat":1},{"version":"f392ed5b86fb56157e08a5fc1859506f8bb20f33a1a6d5922833e2c7a268a7e4","impliedFormat":1},{"version":"7f70f7d51c3232d6e7546bc8f9d6b91df3a9e001de4c755771dd052d9fbc9a07","impliedFormat":1},{"version":"175cdf7e9b2d7178e5b73a4f3dea1f02abe320f6585ee8a6c16991c92e4220e8","impliedFormat":1},{"version":"52580cbcf61e2707abe5d16ee3bd03ea8c22722fef2026c27ff8cb206523effa","impliedFormat":1},{"version":"c6c694fe37d60819f29e998c03d875609d07a2f3d2a280d096474823384bff70","impliedFormat":1},{"version":"1a176b3032ec0fab791c658844c3c1d3df8fbe985b194858c8b31d736781942a","impliedFormat":1},{"version":"82e5bb555d1f1b9344b367e2761eeca6609ff1bc69908d779660e0ddb1c192c3","impliedFormat":1},{"version":"b6892973f319a69aaf5e80a61ba5b42ddebc0d83b1f1ab7c25f09133fdf1cb7a","impliedFormat":1},{"version":"ea87e08b2a990ff767bcdc40e99eff30028d98af8d401f14b08974223c58c06a","impliedFormat":1},{"version":"389a2c2135dd3de1844b996d661ef3a5ffb978356994841fca0f0a99b1728e28","impliedFormat":1},{"version":"a582c8844a6809984a681db3997068d5d8144bee3f889c5240c559c5502c165a","impliedFormat":1},{"version":"e0494aecf0482850786831665c0f976125882c17084022efc6f8a51443b3a7f4","impliedFormat":1},{"version":"ede7ecc62da0236596749292448b282d9c5e846c95e107d6e87720204b792250","impliedFormat":1},{"version":"557981373fbd676739d62fb4aa7b601a639bfb39f7b563ab2c9a2350aa5d7298","impliedFormat":1},{"version":"078045f76bc547eeae562dde79c81e2565be6fecbdbbc4bfbd03fd16cfcad523","impliedFormat":1},{"version":"04783d0830346173973d5283d10b91fd7d6c1c0aaacd93a95455ddedaac4fc0d","impliedFormat":1},{"version":"6185cad87bf4da80c49a2f7a06af8e3e47eab0bfb31a9bf49520989b1b86056d","impliedFormat":1},{"version":"c002bfb107918122bba26d8d0736f293b22866dadc501f9ce27def3230233be5","impliedFormat":1},{"version":"131906682a56016d19849546fc5f9e0076b4e35bc2c5af362d79a50998215d4d","impliedFormat":1},{"version":"ee0c30ecd200ed26166dc9f9ca3f502e5584d61912f894563c7db45292b5833b","impliedFormat":1},{"version":"c47057eea375a394643d081d86ddfa621b3de1aa4072a41fde6731a07aa050b4","impliedFormat":1},{"version":"fa2d827d435777dbfc4a41a70d836b6a401bea8f77903cc22f939425f9da0b8b","impliedFormat":1},{"version":"8a59602dc83ec951feaf5cb7125393d3ebe38914c921e07ca0383a63857435d8","impliedFormat":1},{"version":"0654c77e8427f5125066d551e5f7c273735a92f4e7a2be6f12daf46ffa92ec3c","impliedFormat":1},{"version":"6f2a826f77810913e18a6a5ac87e5783f600961d4d7bc20315db13f69e2280de","impliedFormat":1},{"version":"14e3d141c66a44d32beff51678ba0abd236e18c520b12678a73936e78955cae2","impliedFormat":1},{"version":"bcc4218ae8d2f99608412f5917a663c7c764da0dd63be12d01ec49bf0148fe70","impliedFormat":1},{"version":"4136928c1cc5825cd17ecce5ae4a1671cf0047679e452d4886cfb33e74fed5c7","impliedFormat":1},{"version":"21f4388f6d904f8b0d17565fb331eb25d0f2af0704ed7d6247af4cc9631f7c67","impliedFormat":1},{"version":"546b944e81166843668e7b7a1153ccd1e565834ffc29e1df38aa6d26de9e1c81","impliedFormat":1},{"version":"8d7ea4d73e8d305820b9067f4167558a9d295d901a2d2891a8dd9de66590f931","impliedFormat":1},{"version":"f8d0e96fe8f2cbb5e617eec5f198ab78e13ba2c66176ad202b287aa3cc667e23","impliedFormat":1},{"version":"1375b2b59bde71a963ff2cb306eceea05060ded0b7cbcdaf1206e4e8245e605a","impliedFormat":1},{"version":"f5dcef5516ecd8836256359ed4b9c6bb8c73fcce697d1c343b11ee8e7fd15a8a","impliedFormat":1},{"version":"e55a68bbc963c9520f0492892d642fa145d34a351d483cd144a11e3346c18cfb","impliedFormat":1},{"version":"da14f80dc904a20fe5a98009f117d8f977ad6d50fdab685e75d6b38322ea56cb","impliedFormat":1},{"version":"ca90e5e191954b9b8c43ed5d5bc787107c071315c4acaae515e7d918e8814e15","impliedFormat":1},{"version":"8ef0c5c7cba59cbccd0ac5e17ec42dc4a8250cd267f9cdb08a4dcb1a099068ad","impliedFormat":1},{"version":"63ed74c721b55f614bef2b233b03c7e56377b0e38ea16f1dc3fc57a06ce2ca8e","impliedFormat":1},{"version":"c89dff0cb3845b6234ce201e2a2d8460d08dfdae2b5a5b137e17822b31188752","impliedFormat":1},{"version":"32fb4c22ffa9a118b115e2c3f65026a9819c0e093bf938ca96ba4ac10e1fecad","impliedFormat":1},{"version":"1f142b1a6a8b7b29da43a88c8a5f6bbad28f7cf1b67457596ab6d71bed584e8a","impliedFormat":1},{"version":"a203895f2d4b51c8799af4a17e6d72657c6dfdc4a08ab338970e257e5e083d85","impliedFormat":1},{"version":"c67a3535fe218dac271adc4d9c91cabbcf99d09081dc3fe3567e3a354bf632e2","impliedFormat":1},{"version":"7670372101b08f0d0a2a8cf4d107d969df407a74cba20e9f3991b50d9d3c590c","impliedFormat":1},{"version":"00e5569a05e32c005b18db36cf4e0fd477d8e98d58b82489e4c0abad95d5500f","impliedFormat":1},{"version":"fe831d90ec6b5e04075ae831936f1e2049cce2473ad1aecf3d5ee37d66ea84cc","impliedFormat":1},{"version":"93b5102a702eb62880ae6fb3be2eb6910694ccf77a2e9063eb5d94bd0b2b32b2","impliedFormat":1},{"version":"622ebbd7d12ba6519bd5dd3d23892ec1f79991a9b15d09b77d8c7dd1ac32b8a4","impliedFormat":1},{"version":"14d03fe0675db97e401cbdfe2144cff5c3a84dc23f05c21acf3dfd3668a13fc8","impliedFormat":1},{"version":"d0622e1a5d9ee2b4b8a1a6db2c0f02fc34f4f865d7ece6ec86800074210d2f4d","impliedFormat":1},{"version":"5300e082fe9398613c3b5a4975df67318951c46b4a033d159bbe082793ca2c3a","impliedFormat":1},{"version":"be05176f0f7347f4a9faed9a400c182f107b7499d79f4c6e67ec3d830ed6cde9","impliedFormat":1},{"version":"498b8e59b7659c0ce11ce3323bd0d23c923e21c7290e5bd96ce0f3ca639fb4fe","impliedFormat":1},{"version":"740bf9b794f8fcecb6c3761598372f16a7835dddb4c163a21ae0c7f472dc6bd3","impliedFormat":1},{"version":"12816e95a6bc1b4a98195c0e6747b33cfd178f0424579a3eb21b49911283f79a","impliedFormat":1},{"version":"ccc9e8f887951895386cafcff62aff2617397584ce48ca891646b901272b9d12","impliedFormat":1},{"version":"bffc26bac30d45f1e5fea885f17cafb6a943bcc21fd1122c71b9fe466ece8fdf","impliedFormat":1},{"version":"82ccbd00eeb8a81a8ee882c6dc8de591d2c174fd0bdc2cd8e9617f39d88eb52b","impliedFormat":1},{"version":"81580d0db97bc8f13bcf79cc7a97e9606cca948df6f0b26e3084d5db0a41089e","impliedFormat":1},{"version":"fd4ddb3d82b68edf2f7dd1b10ca66c5b108007c46067d0dfac4167a4492577cb","impliedFormat":1},{"version":"8c5414d8170f8fca7d8cdf74dba186370e35cc895c3e25f10ce42fff3ef9b49d","impliedFormat":1},{"version":"2caa4ad00b1f3ca5b07ff3d84beab2d9a4a8d841b677aa1546b78054a890a902","impliedFormat":1},{"version":"c96415ec4a5ff2202c8f5db2b8163a605100b6b47435c5b31d8280e06233958e","impliedFormat":1},{"version":"93b1c61409fbf44c4e666937c0cacb36d006b9901a53a2750e520f6ba9b1fcc2","impliedFormat":1},{"version":"981af6a24b8e1531dd933ff6df096a7a50dfd79f24c5e5be1134b684465a807d","impliedFormat":1},{"version":"d3b51ab522194f5ffd145f57fc2b2017e35d11593a8a5468fd3da7767dba0d57","impliedFormat":1},{"version":"85e1ca7719d73273b0b07356071e046f27c039441666504e6143600f0f5de5eb","impliedFormat":1},{"version":"14b5a5227655bff3a02231986be2a1ab4d2749584147c6f93ad6167d31d78fd8","impliedFormat":1},{"version":"f68e3a3eba1a531a71c8cb53bedafae2c25c376c147e3bc6ec96613a5de9dc84","impliedFormat":1},{"version":"8c3f672ca4179a0313a67aa8525384d1f7a3d7c692f4f39a3482d9997389381e","impliedFormat":1},{"version":"367ef08f1d0de5ec4d4786cb8a1b8a17abf395bb0c5f8d151ec10fb66a2ce50e","impliedFormat":1},{"version":"ede4a9299b475e71baffcfd20b9b5056f77b8da69e7c824692fa7601be181ce7","impliedFormat":1},{"version":"c92c476c4463a4a96da5ed77010afd4bfa94944e298359bbff940cdde33c5f16","impliedFormat":1},{"version":"a484890e7212977036ce5965e7ca7b49e53436a66906a29093f91d4e02260fdf","impliedFormat":1},{"version":"4ea2003d86a9c68928ef069ce548c3e6ae35cbcb34184a71f1c566dde2160cf8","impliedFormat":1},{"version":"f727d3e75bfc036625d6920c725a3e4cbc564eef78f47d6b68c6351bb480d799","impliedFormat":1},{"version":"a87fcc9011e8a5e244d6e9af4902c315670aa852fa75dc82ae7cb62f98233a1a","impliedFormat":1},{"version":"dc7f110b06cd26a6153d026c7ce8414fb2d20815a20c840bb12143436458babc","impliedFormat":1},{"version":"90afaa269677aeb839cc0e7479e0c3152248e4c8b440954b66a0e13fff08d64b","impliedFormat":1},{"version":"e97434f04631c027264a37897935d5686cbb53547128043f8ce9df36a62f8456","impliedFormat":1},{"version":"49d38dec73850de29da6e77ac4636b7195d18ef7c7695851a2f2fe9fca859323","impliedFormat":1},{"version":"33e41623f36fd2a950c40acb481d938d186a85436eeca076e27a1bf799945148","impliedFormat":1},{"version":"2b881659708008e1c27269e1eb8dc476af0c2ab2f1fbf50f6e5f8cb6758d8b1f","impliedFormat":1},{"version":"16a13b6507929a211bb65cbaba39a42943c034c7cff58bc9fa326a2dc9be3d93","impliedFormat":1},{"version":"88f173385e44e0ee39ff2b1e2313df7c07c17932d51da40d6ad3a518957b80af","impliedFormat":1},{"version":"38ce3311fee1438e32f767e068dd496dd923afaf32816f1d4e521a3eeed59603","impliedFormat":1},{"version":"278c4281561f930857b40f04b092fc2a5649076ee00ecb6c1cb9d4abed3ad239","impliedFormat":1},{"version":"6d1f9b3f050467c2cc5292d2762b0ede9d605fcfff152210426da2eba607e1af","impliedFormat":1},{"version":"8f8c6a79e620f8a63952de19f38927f7da119cd0a5408d7289532f68b8017d98","impliedFormat":1},{"version":"bdf518ed49e9ad6926ecaee24a183828a23a061a1dfac8788cfc09da02a0bf91","impliedFormat":1},{"version":"c83ae875a44933a76a37949bc96569a414f5fd74f4089edcb4caad0db6bd7e6c","impliedFormat":1},{"version":"69870c54caf722bc568fd348b5e813500e964d820c7482bdb82d94d5aa6f19ed","impliedFormat":1},{"version":"504ffacc3312189dad74385206715390bd98e424aff384f67b21331bd16cf7e3","impliedFormat":1},{"version":"1870eb1fe1a14d19041559a003bb79753347b6da6d87703548b6b20faef30e6e","impliedFormat":1},{"version":"016f83e01163cc23543489f52d53fd235730f2c754d26ea0891f66d3e57b9985","impliedFormat":1},{"version":"58ed0a6574485bcf18d4d775084258ed49f7b92ac9f8735488d19ab14bc6db88","impliedFormat":1},{"version":"02aeaa95c9b6125f8b6e5bcc16fc6df7d8f2bf945801defb73e1c13e1fe57c51","impliedFormat":1},{"version":"0bc153f11f30e6fb856a2a6c50970d386aaf7daa93ac106cd70920a1cb81841e","impliedFormat":1},{"version":"fe995eb8b806358aebf1e963824ea181b2fa9cc52e2dc4022eec67730b742753","impliedFormat":1},{"version":"52db5fc6d8fa0809b2110d96434a06ad26776677e825a10f93fe133497f6c93b","impliedFormat":1},{"version":"d9411ee7bb83d2304f0fced054eef996c5fbc2dfee2936c42c8696f0ce1b5b51","impliedFormat":1},{"version":"73ce7d983d2ee14698eb90ef369807a03a1be94170ee2461ebfd3db4c6329e4e","impliedFormat":1},{"version":"204ef1918267feb2040caad874caebd9bbf4f018367517750eeae16d880b0698","impliedFormat":1},{"version":"f6e8311e83274671b80860cb83c1c6393971d596200c4fc504ac7dd3ffa50340","impliedFormat":1},{"version":"c4117a326ced8cc18ed60273de14f4c5e78a53cf2c59092f6278a8afca8d9ced","impliedFormat":1},{"version":"34787d4cfe21491065b9e8c3038a66c78747dc97b171b1201ff3913f2181e5c8","impliedFormat":1},{"version":"fe4c08b22b011d68b3625c665cc302f77bb8aed4b35853a53e3efaf082bc8e83","impliedFormat":1},{"version":"7caae0b58bdfbedfbdd1a2f5b41779a08cbf62d62f7be63cd70cc71fb97165a0","impliedFormat":1},{"version":"b611b2a0b82dc6e520bc8c6698c0bf4481aba89c4923450f0753c062e4754c7e","impliedFormat":1},{"version":"d0272598cf5b05948b01aa2fda2b2cd190561897909bbbad709b51454f8d2e10","impliedFormat":1},{"version":"dcbc3cecf73f68c9d63280f3c9747bc6140b1eb9d8b5e5f04de58ea67c564a70","impliedFormat":1},{"version":"57f6aaa7e079189a64c2b15909cc89aa4a6f54c81b185108e906deeffdee1516","impliedFormat":1},{"version":"7b86682a3abdade9ceed5cfb5503097496223b93fc257de6795c4736efa841c1","impliedFormat":1},{"version":"94fc87a2a7387d958dbaaa392225a533bfce92f6daff79d9e11e921884b5590d","impliedFormat":1},{"version":"f41d35d2248604bbb6ea7dc64a2e024926ccc00beed30e3d2f356589bcc89a7c","impliedFormat":1},{"version":"07afa56980800740ec44e0b2e08d37d31c3ba1bcff58417ab7c26478bc37e4ac","impliedFormat":1},{"version":"960fc68443fe84caffb6f06af4589cd11e05dc89835c3b56d809ba46c893b6f6","impliedFormat":1},{"version":"02b6175908b56ca273252e8f734cde6cbc88c298384f4b397e63e41240184dc9","impliedFormat":1},{"version":"59fdde76b9d1518ee3a6711b14dc0b7582b7f9cf702c0cb8acc0bda3aef9e1bd","impliedFormat":1},{"version":"6b3ab19355f7f6208c5c5372216d03ce67076fa8f537e94757a074ea21d70102","impliedFormat":1},{"version":"bab0c52d8ab84e578191ac559b70f9bff9e763ff42b5a0f7ace8d134785a689d","impliedFormat":1},{"version":"d570e59bb706b1f442c1c7f12f252a215fff1ed867c72275b525abcbba6b5b86","impliedFormat":1},{"version":"50dc335fb38fa5b552b6377833c1a77d4f406c4c344589bea29d4661ae8e1810","impliedFormat":1},{"version":"0a20f875729ca5de76aa486ba9cbb1913e349ae2d7d1c2e1ad3b45e142ca815d","impliedFormat":1},{"version":"477b09f880a9f9364b68fe02e237f3779fbffb0761bfbc3f77fa895ca49c44ce","impliedFormat":1},{"version":"d85a0edc67a11fa750331746b55fd5af4b41f1bd11e550ff7090abc9e9f83ebc","impliedFormat":1},{"version":"666732d3b18e0ae093bc48e5cd08380a7fcc64c06b7d8d0b4899567c5de7f5cb","impliedFormat":1},{"version":"be789dbab62f36a20dcb50cf0e67d0ef6b3e3cac17bc0aa9bb30bbe51756ea63","impliedFormat":1},{"version":"20a6b98adf98f5f826f2d2c2738599837586e458b7ed5eb4a1494f7caf00d22d","impliedFormat":1},{"version":"501bc80db30be62bdbaa3640c7416df62990977fa403178f88812188c7e1ad26","impliedFormat":1},{"version":"d1658de6ff4ccce2e9cfd8b11722a6279bd3524644d0b65e3e8fc6b69b5ca49a","impliedFormat":1},{"version":"e5757819ad8a9ec2fd62d5157afd552ae95841039f1e9bba119dd26692dec64a","impliedFormat":1},{"version":"4091c43b763549c33d662afe79d75c078622bef954d4a473eca6aef8c251c169","impliedFormat":1},{"version":"d5e3f1268d795416b81ad2cae0b15b77147878bc672cdeb19ff5dd77272da017","impliedFormat":1},{"version":"43e510c8d059b40ce5e441a909a85f019ad8812890a8f936370a629752db69b4","impliedFormat":1},{"version":"5990d3194dafd93fc7a9e51032d11a57756c31fdcd88fac3b9be08af303972c5","impliedFormat":1},{"version":"987562ea1c31f04677cd3b46cbd4cdc6363f6178dbfd4db2a0788fe22947b8a5","impliedFormat":1},{"version":"0de5e8597a103c005b774f8892352a5f123a5e272924fe967b7d82305113bc4d","impliedFormat":1},{"version":"16185bd9e115626e25bca46fb8238f9ef3706c22b62ce940ae66c4e4cfde0df9","impliedFormat":1},{"version":"5711b07fe1b6426486276dd67efdee7ec4e70bcfdcaf39c6626594bbd7d51c34","impliedFormat":1},{"version":"7f81c91c6febbd59728630098f6f2b1e4afeba6af9128645634520d5681096a1","impliedFormat":1},{"version":"269296ab0ca6cc30fad3ccb911b1ff589d4a2c6ea7077c26c7ea5fe650103d6e","impliedFormat":1},{"version":"a49ef7664e1afe51062e193f0008ed621d8a3af547d994123ca44dbbb68c75a2","impliedFormat":1},{"version":"165ee417439a725fbd0a04278830c1056354556188d6000e5dc8ecd12cd3cb10","impliedFormat":1},{"version":"9539893a03d2cf718e8c38adf1a845ec0183ab455c8b257c64cd6727f57b0e1c","impliedFormat":1},{"version":"5e0f0b5968cb81b81847619fb6643f364d0eeb630e575fd0029d22c1171b3a37","impliedFormat":1},{"version":"45fb63c6d3a608b091c3baaaafe97de027a061e2f10813aa97d003b654417ed9","impliedFormat":1},{"version":"9a1bce80c36643bbc3e66c7db014c849b81a1d2d3ebfa69000f03e64545566a0","impliedFormat":1},{"version":"f438823b9ca13c413beaee87829111be171b305995bcf71d67ddd941de6dd999","impliedFormat":1},{"version":"623e7ec6876645a7e93a1a67506f3852b8e5e79ba3cb4c9a90ff8a24d3377a12","impliedFormat":1},{"version":"0ddba574bf51b1e47c502caa07ff96528b0c49878c2521ceb322a94557a824ee","impliedFormat":1},{"version":"3111b876a50a391cac841049c1683d20bf7d83eb05d5ff10b0a49689ca0dc49c","impliedFormat":1},{"version":"de84187571b3fb57d7d47f3199fe75845d024fa2c4aeb0a8bca8a281e37e9b62","impliedFormat":1},{"version":"4e302b950595396f49e539c733b44c52b77a9d3b85cc7c6fd24fcc7df1e30031","impliedFormat":1},{"version":"668eb6f044ef3e07635b3da9b29413de381299f80fdeb90e3ba5bea910d9d588","impliedFormat":1},{"version":"f75b6da37adf4f4fcb1b3e6e30099d345bfcfcc2024dc304bf6eaf40ed477c5a","impliedFormat":1},{"version":"39701d3533318e98924f5e5a4fb0ea5b49527853ae63e78e26190955c1ba4d62","impliedFormat":1},{"version":"30cb04bc8d380ecb7053659c2b42b48f87ffd05af3abe9f7b4783e07777a8d96","impliedFormat":1},{"version":"96847849b0b8472d06b023c7f6fd630cb5cb3e6129bf16c6ce58a931084c1d04","impliedFormat":1},{"version":"f15bb0a6bb20f0a494969d93f68c02a8e8076717fe7dcda6db06ab9e31041c22","impliedFormat":1},{"version":"db9d0b3c71348adf62b4c2eebd0bc872b0b3895ee6285980463f6acfe7aa36e6","impliedFormat":1},{"version":"58b8d98c9e39b0a1bab10c9a19a61d9fcac111aba5a6ff47e86525c079ddcbbb","impliedFormat":1},{"version":"a69abca4388cc76962773b4c869d5d34781cf0be92853d7bec53eac7a2f75c60","impliedFormat":1},{"version":"471b5d5986eff907c7f4b7047b54c15648495f94e219a27fd8cc91f35fa0e970","impliedFormat":1},{"version":"75cc2a2e33c7d3fe1574d9c93712950b5556dd4af48a1d1e5a657c66ff2eedf9","impliedFormat":1},{"version":"05c44f2a752cfbef15a81e90bc63eb96efcd3d07dd9b378df5a150a06775a2fb","impliedFormat":1},{"version":"9699ff431424e42dfeeb6417ea7b4d1ed66fc6bfc530748dfedebd2683fcc1b6","impliedFormat":1},{"version":"496197b06b51aeae8323da87d042ed2224e654994a3d9b5e3350df9c9576dc50","impliedFormat":1},{"version":"93521d40a9636980e32574e7419b975fb1b400644eea349bd64f76ee808749bc","impliedFormat":1},{"version":"86b7e0f835e2d550541c27e03abf5270a42f5876e1e915568289142b317a0ffd","impliedFormat":1},{"version":"ac6990a9034baddaf28cb15200bd2f0a46efb118d08f4d341abc16669ad577a1","impliedFormat":1},{"version":"29faa0f1ab122161019ca07b328664d62b5b1ec742606fa5b34851603a49a77c","impliedFormat":1},{"version":"80623c074b076a1c98719ebf8e882e9c977ff9c040444c825bf9427f0f21d420","impliedFormat":1},{"version":"52cb5d5beedcff01d5b851653cfdbe9a8e8e953a8462a357e71d93eee3ed760b","impliedFormat":1},{"version":"ba6d810e67aef7d6ed15cdd8223d5a207a111077c88d99ce7af5fe959a079803","impliedFormat":1},{"version":"3e02766c76edcd0486eeecad81ca4982a532a80293d71a8d94973e89feb5be2b","impliedFormat":1},{"version":"96bb9f13a0f42ba0f9e458a10be3db0bbb52e7498b8ef49ab90c404f3e5f735a","impliedFormat":1},{"version":"6f322a0ec0f5782396e21068158629f5b1ba084f722459a4ced24252ee1eb0ba","impliedFormat":1},{"version":"13e4ce5de72a42cf67e6af9a96132e428696d8054548580e68f8f376d114a459","impliedFormat":1},{"version":"1b4262a15a86e72e78d7fdbb6a6d20e8794f7fa4aa7c54f0b18ac7270e4fab08","impliedFormat":1},{"version":"9334b283bedfcd488ccb33b3e942905c86fa163e919653a5379eb8f28a2d5f7d","impliedFormat":1},{"version":"f3f62eb4cf38d86cc7f56d0879b49656a21f2eef4fd0acef3936889327d7f256","impliedFormat":1},{"version":"e32c5cb1819686336a2101f31b91c2e8e06f8f8311abd1195c203b81b62247b0","impliedFormat":1},{"version":"683734687779547527b05fdcef60947f6fc51758185d788531e9ac7bde84fd6f","impliedFormat":1},{"version":"c418f31663f9aa18537f6443172821265c078de18427ff136a24c536e76b7fc4","impliedFormat":1},{"version":"dc14049ed7aab615142091af18c8033550203d91c18c5ad2101f891b877cf265","impliedFormat":1},{"version":"1df375435c44c94f1bce343de4ff81b8c82e644d6b33a801bc6cf4beceb76b71","impliedFormat":1},{"version":"fed5b5c20508c5f84a929161f452dbf769cc2d2ee1371b94ddc2feb418a0cf70","impliedFormat":1},{"version":"76755db046290dad61362d95c03b440a0feaf507edfb5744304c7f98c81faccc","impliedFormat":1},{"version":"e16841ad044e21c48c6065627566a2ac216e067cc34b9ad3b47312d208d9a262","impliedFormat":1},{"version":"7150b4a18287da2e25c68a12bd0cff78f6141a2425a27431a10cd4a91cb9626b","impliedFormat":1},{"version":"214a581fbe6902059a64de2bd75c56b6030c6388c29de93c4296380a99c04e4a","impliedFormat":1},{"version":"78b758d401e53f5319bc143ebdc7714ebe0f1e94fc3906d5e93816e5736bf299","impliedFormat":1},{"version":"ce50872ae30242ed1ce2ddb9d9226c85f17098e901bc456cfc365887ab553127","impliedFormat":1},{"version":"cae86d70eabc661dff2f46f34018ff4840228f01709c8399a9c012711dfe5292","impliedFormat":1},{"version":"77b463688f41048f449fa30b45393b81fd6dfe3eb71f7734c1a6d580373b6a12","impliedFormat":1},{"version":"b6ccce9156aa85ca2e836bc572d4697800739ab008b0a6ae9bfa0361b8baa04c","impliedFormat":1},{"version":"07dcca6e9f155b79d087216735842ab1f7c020ce41f095507afdffecbac06a03","impliedFormat":1},{"version":"1fab3bc9db401033ed6ef6dca9114b3a0a875b475b6c1b2ce52efddf3c4fa130","impliedFormat":1},{"version":"269b37626ed3fc5d6aff2b3103bfecdb86ab69e5fe28933b63a17ac83a547ede","impliedFormat":1},{"version":"1ef3cc7b03643e330cf9bcaeb42257a19f573bfafdaf51e2e45e52c19e20c3ff","impliedFormat":1},{"version":"e05f14953944c6b7f9c8a51c5739cad11e7ea4e441fd5659cbc3a5ebdc28bcfb","impliedFormat":1},{"version":"98fe9a0d3adc98c4aadc97a5bcb8c9589525e16e82e6714333e0315d1ff40a12","impliedFormat":1},{"version":"941c51312144ba38e2d86c081d212bc1f22f64eeb1dc342a1c7aeaaece7a7770","impliedFormat":1},{"version":"8d204669e89ac66eb2fa93e17daf42dc9fa33b3d865158327819df72f4fa3f1f","impliedFormat":1},{"version":"4f66c595621f6dd5c693d12c122def1c9eac9c48ace86deeb7c1a0fe54d63c61","impliedFormat":1},{"version":"6b26f80f079695a24ca28f6b19bb074ddb70cd79bc837ae8437e54ac8727aa14","impliedFormat":1},{"version":"1686e8b2a3bca066aafbb9bea2ac249e7205af7e6b878955741c66b3a4eaba63","impliedFormat":1},{"version":"f974c4abba2e7ae62cc358c6c1589df489406ef517a48355cbcc5f09cf11d8a8","impliedFormat":1},{"version":"949ab063079fbbcbf8a96c093b9cc465f83fd2ce49f4558492d6f95065cb201d","impliedFormat":1},{"version":"2d1c8bc1708e58c9aa73d71f89dc69d45fd00ed42841d022bbffa467c88464f4","impliedFormat":1},{"version":"55c3e286e757f731c3b80c1e6d4a567bcc6d5d512438016240e7da573a554dc3","impliedFormat":1},{"version":"33cb723eea3ced280f163fa717045e233b801081a64509d4d59b47620fde9ef5","impliedFormat":1},{"version":"8c357660e14e4ae047c44211f7d024d48eacf3d5ad6ac805095a436a4d3e268c","impliedFormat":1},{"version":"e67731d353b0f48ec4c7b1cee2358e2b7b6ea56c86775f2f3c07029b73b8bf06","impliedFormat":1},{"version":"e2eccdc38e22cc3882939c7fca91570a8379112c03f6206986e0bd78afeed21c","impliedFormat":1},{"version":"58a60f1ff614a331f5de62b4a629b5f41066430f7b72f65ec27f0cf841403c9e","impliedFormat":1},{"version":"bade739298ee5cd485966b3f2812cd94ed23be0bd8991624bde84db9e41e4240","impliedFormat":1},{"version":"4289204445b85c740954797654b504406befd2168731ec18efffb3ea22674a5c","impliedFormat":1},{"version":"e8ac4073fe7b469e55e1fc7b1540363d5a99b507839135fc97cfe5f2d0e36595","impliedFormat":1},{"version":"0f45169be3f2e0eb418bb1d5d480aa8fca7375af0b6e51dfccc3afbf77d9ef12","impliedFormat":1},{"version":"25699fd6154aa1d8ad42dd7739ebe65e15277c0f44d15ce6826cc43bde4ea5bf","impliedFormat":1},{"version":"d4fabc6a3e3110ed60c84e9ec6712265afe268601f3462198b57aa4359745c33","impliedFormat":1},{"version":"802353808bbaf39f8ce455fc7c459d39f13a2fefcf6f18a78c9ea0c61be089eb","impliedFormat":1},{"version":"a057b62631a72f836a8faa37332f03324b9610bf1bd7781fd6f93be063cd10f5","impliedFormat":1},{"version":"76c5f9421476e8762a83f970028b5b7e9ac13fade254d40c04c188f87be8fd7b","impliedFormat":1},{"version":"6378e4cad97066c62bf7bdd7fb6e2310f6a43cdf7aba950a2d37b4b0772c0554","impliedFormat":1},{"version":"3b6fddf2afbdf36f7bb869ccdeaffac8d53759e527e3425a6b8df4dca616d1fd","impliedFormat":1},{"version":"e88588861f78985ee212de6a72e45b445e5e04286b4ce1eb1d28d72bb781e269","impliedFormat":1},{"version":"22b9f52673fc11b687471594d6080d4319999e4d98903679a4ba94d24b056426","impliedFormat":1},{"version":"3d594041401ac69433c4a2ee492d356db4706adddd4f8201e7e5f542e58173b2","impliedFormat":1},{"version":"806aa43416ea1f5265e1cf94168fd4902348762aa8114dc53c131cff9f87b5ec","impliedFormat":1},{"version":"f27757e22127417f5daddd0ad4be81d5a743c95576d8c957ce39ef02a6cc1ec0","impliedFormat":1},{"version":"383679ac9fe44ffb52057dc5ad7ee2e4a90a3f4abbe9a1cf186d9a2cee617965","impliedFormat":1},{"version":"bb589593cea8974cbf3359b720e5dabba7deb6ac8b72e30539a9485d3c697640","impliedFormat":1},{"version":"cbfdb7e67d10e7f21d28ca3ccabfbfa18c756809b4ed0f6ce56a1d44c6ed4e1b","signature":"ce5565dfd475ff16baa3817c81d1b4fd19fb6ccb2702345a7f6ce0b86962e0b5"},{"version":"ad2d71c19f2cea2a9eaa70fea1317ed2937bf9a2d3ca8d107e99b20d94dc4034","signature":"5311e760944eaf15e5486146be0830873f6b7b5ddaafd227541e607d7dd4a936"},{"version":"4bd88b6fd041282aa8dee1bdb89bf6b321146b120d0a0000ee24e3ec31c23fb4","signature":"4a5c38168be72c1cb3be3982ce88d618ac629399eb31067037c4f06243c63967"},"a0f199dea09e61c7287a22ecd86a99330567e1a2250cea1453b28889cc2370bf",{"version":"32340e1519896d18c1155a4e515f8a14f999fd4dc7584f203c51dd93325a4e9a","signature":"a8783050b978249be148a4a50c15e19b75dc0ee09e75f2e44d978b6408827cb8"},{"version":"516c53364c6b242591c65afc8b0f0f0cee74ac8a04f52470a539fcb33da2e318","impliedFormat":1},{"version":"045fe6d9e971df69d53ed8f1551e60c4849b0529e407e5960b31096418fa8346","impliedFormat":1},{"version":"0974c0312c1fe25e56e8030b1830ce8bc071a973714ac6f2409894addc346fcd","impliedFormat":1},{"version":"d10db4f48a9957fba79c406fbc79af87d979d34a1bbf5e12ca4a53cef0f16cca","impliedFormat":1},{"version":"3493d3ac411c6977f391ab438a9940c3a8e06dc04b7e2d84e0571a30aa224314","impliedFormat":1},{"version":"2907069986d89f01c9151da8a01161545a283405369bf009dbad2e661c556703","impliedFormat":1},{"version":"0feee6a4ec2ca4ce1072d0bf3a9839094b5a651decd598b2fa79bcdee647fb16","impliedFormat":1},{"version":"5bac046f252b55e3b05035d5329e2ef15a944fe429d81ac7fe36a4cd8bb8ae7f","impliedFormat":1},{"version":"4e1949bcfbde9ae075bff5b15ce1d3a401624840cefdbabdd6516004b93b821d","impliedFormat":1},{"version":"17903f731e82ecd3928ebcff54c21ef098f8bb285053cc5913e7d3054c85930f","impliedFormat":1},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"a79e62f1e20467e11a904399b8b18b18c0c6eea6b50c1168bf215356d5bebfaf","affectsGlobalScope":true,"impliedFormat":1},{"version":"49a5a44f2e68241a1d2bd9ec894535797998841c09729e506a7cbfcaa40f2180","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"24bd580b5743dc56402c440dc7f9a4f5d592ad7a419f25414d37a7bfe11e342b","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"6bdc71028db658243775263e93a7db2fd2abfce3ca569c3cca5aee6ed5eb186d","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"4d2b0eb911816f66abe4970898f97a2cfc902bcd743cbfa5017fad79f7ef90d8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"e53a3c2a9f624d90f24bf4588aacd223e7bec1b9d0d479b68d2f4a9e6011147f","impliedFormat":1},{"version":"24b8685c62562f5d98615c5a0c1d05f297cf5065f15246edfe99e81ec4c0e011","impliedFormat":1},{"version":"93507c745e8f29090efb99399c3f77bec07db17acd75634249dc92f961573387","impliedFormat":1},{"version":"339dc5265ee5ed92e536a93a04c4ebbc2128f45eeec6ed29f379e0085283542c","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b08684f05523597e20de97c6d5d0bb663a8c20966d7a8ae3b006cb0583b31c1f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6b042aa5d277ad6963e2837179fd2f8fbb01968ac67115b0833c0244e93d1d50","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"9e025aa38cad40827cc30aca974fe33fe2c4652fe8c88f48dadbbbd6300c8b07","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3e58c4c18a031cbb17abec7a4ad0bd5ae9fc70c1f4ba1e7fb921ad87c504aca","impliedFormat":1},{"version":"84c1930e33d1bb12ad01bcbe11d656f9646bd21b2fb2afd96e8e10615a021aef","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4b87f767c7bc841511113c876a6b8bf1fd0cb0b718c888ad84478b372ec486b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d04e3640dd9eb67f7f1e5bd3d0bf96c784666f7aefc8ac1537af6f2d38d4c29","impliedFormat":1},{"version":"008e4cac37da1a6831aa43f6726da0073957ae89da2235082311eaf479b2ffa5","impliedFormat":1},{"version":"5a369483ac4cfbdf0331c248deeb36140e6907db5e1daed241546b4a2055f82c","impliedFormat":1},{"version":"e8f5b5cc36615c17d330eaf8eebbc0d6bdd942c25991f96ef122f246f4ff722f","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ada07543808f3b967624645a8e1ccd446f8b01ade47842acf1328aec899fed0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4c21aaa8257d7950a5b75a251d9075b6a371208fc948c9c8402f6690ef3b5b55","impliedFormat":1},{"version":"b5895e6353a5d708f55d8685c38a235c3a6d8138e374dee8ceb8ffde5aa8002a","impliedFormat":1},{"version":"b9b859f6e245c3c39ec85e65ab1b1ffe43473b75eaae16fe64f44c2d6832173e","impliedFormat":1},{"version":"93bd413918fa921c8729cef45302b24d8b6c7855d72d5bf82d3972595ae8dcbf","impliedFormat":1},{"version":"4ff41188773cbf465807dd2f7059c7494cbee5115608efc297383832a1150c43","impliedFormat":1},{"version":"dccdf1677e531e33f8ac961a68bc537418c9a414797c1ea7e91307501cdc3f5e","impliedFormat":1},{"version":"e184c4b8918ef56c8c9e68bd79f3f3780e2d0d75bf2b8a41da1509a40c2deb46","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3114a0b8ab879b52767d1225cb8420ec99a827e5f744dbeb4900afc08c3e341","impliedFormat":1},{"version":"93f437e1398a4f06a984f441f7fa7a9f0535c04399619b5c22e0b87bdee182cb","impliedFormat":1},{"version":"afbe24ab0d74694372baa632ecb28bb375be53f3be53f9b07ecd7fc994907de5","impliedFormat":1},{"version":"70731d10d5311bd4cf710ef7f6539b62660f4b0bfdbb3f9fbe1d25fe6366a7fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"6b19db3600a17af69d4f33d08cc7076a7d19fb65bb36e442cac58929ec7c9482","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"8145e07aad6da5f23f2fcd8c8e4c5c13fb26ee986a79d03b0829b8fce152d8b2","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"ba1f814c22fd970255ddd60d61fb7e00c28271c933ab5d5cc19cd3ca66b8f57c","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"125d792ec6c0c0f657d758055c494301cc5fdb327d9d9d5960b3f129aff76093","impliedFormat":1},{"version":"0dbcebe2126d03936c70545e96a6e41007cf065be38a1ce4d32a39fcedefead4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1851a3b4db78664f83901bb9cac9e45e03a37bb5933cc5bf37e10bb7e91ab4eb","impliedFormat":1},{"version":"09d479208911ac3ac6a7c2fe86217fc1abe6c4f04e2d52e4890e500699eeab32","affectsGlobalScope":true,"impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"c40b3d3cfbb1227c8935f681c2480a32b560e387dd771d329cdbd1641f2d6da5","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"5b566927cad2ed2139655d55d690ffa87df378b956e7fe1c96024c4d9f75c4cf","affectsGlobalScope":true,"impliedFormat":1},{"version":"c4a3720550d1787c8d6284040853c0781ff1e2cd8d842f2cb44547525ee34c36","affectsGlobalScope":true,"impliedFormat":1},{"version":"d3dffd70e6375b872f0b4e152de4ae682d762c61a24881ecc5eb9f04c5caf76f","impliedFormat":1},{"version":"fe5748232eaa52bbfd7ce314e52b246871731c5f41318fdaf6633cb14fa20da0","impliedFormat":1},{"version":"d91a7d8b5655c42986f1bdfe2105c4408f472831c8f20cf11a8c3345b6b56c8c","impliedFormat":1},{"version":"616075a6ac578cf5a013ee12964188b4412823796ce0b202c6f1d2e4ca8480d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"e8a979b8af001c9fc2e774e7809d233c8ca955a28756f52ee5dee88ccb0611d2","impliedFormat":1},{"version":"cac793cc47c29e26e4ac3601dcb00b4435ebed26203485790e44f2ad8b6ad847","impliedFormat":1},{"version":"4fe80f12b1d5189384a219095c2eabadbb389c2d3703aae7c5376dbaa56061df","impliedFormat":1},{"version":"ad70fdf3826676b87e49c859035690311e6e1f27fc58c76ebfd5c714f7cee2e6","impliedFormat":1},{"version":"edd2bf117f61517d22264e2204925df0f422315f5df9be844feebb3aab4876f0","impliedFormat":1},"56d4b6b8e40c19087a033ee66a166681472c5119aa13a9145fc4f99b7c77b409",{"version":"b40885a4e39fb67eb251fb009bf990f3571ccf7279dccad26c2261b4e5c8ebcd","impliedFormat":1},{"version":"2d0e63718a9ab15554cca1ef458a269ff938aea2ad379990a018a49e27aadf40","impliedFormat":1},{"version":"530e5c7e4f74267b7800f1702cf0c576282296a960acbdb2960389b2b1d0875b","impliedFormat":1},{"version":"1c483cc60a58a0d4c9a068bdaa8d95933263e6017fbea33c9f99790cf870f0a8","impliedFormat":1},{"version":"07863eea4f350458f803714350e43947f7f73d1d67a9ddf747017065d36b073a","impliedFormat":1},{"version":"396c2c14fa408707235d761a965bd84ce3d4fc3117c3b9f1404d6987d98a30d6","impliedFormat":1},{"version":"9ae7df67c30dc5f52b7b21e8bb36fd9ff05e7ed10e514e2d9ed879b4547c4cd3","impliedFormat":1},{"version":"5d3e656baf210f702e4006949a640730d6aef8d6afc3de264877e0ff76335f39","impliedFormat":1},{"version":"a42db31dacd0fa00d7b13608396ca4c9a5494ae794ad142e9fb4aa6597e5ca54","impliedFormat":1},{"version":"4d2b263907b8c03c5b2df90e6c1f166e9da85bd87bf439683f150afc91fce7e7","impliedFormat":1},{"version":"c70e38e0f30b7c0542af9aa7e0324a23dd2b0c1a64e078296653d1d3b36fa248","impliedFormat":1},{"version":"b7521b70b7fbcf0c3d83d6b48404b78b29a1baead19eb6650219e80fd8dcb6e1","impliedFormat":1},{"version":"b7b881ced4ed4dee13d6e0ccdb2296f66663ba6b1419767271090b3ff3478bb9","impliedFormat":1},{"version":"b70bd59e0e52447f0c0afe7935145ef53de813368f9dd02832fa01bb872c1846","impliedFormat":1},{"version":"63c36aa73242aa745fae813c40585111ead225394b0a0ba985c2683baa6b0ef9","impliedFormat":1},{"version":"3e7ffc7dd797e5d44d387d0892bc288480493e73dcab9832812907d1389e4a98","impliedFormat":1},{"version":"db011ec9589fd51995cbd0765673838e38e6485a6559163cc53dcf508b480909","impliedFormat":1},{"version":"e1a4253f0cca15c14516f52a2ad36c3520b140b5dfb3b3880a368cd75d45d6d9","impliedFormat":1},{"version":"159af954f2633a12fdee68605009e7e5b150dbeb6d70c46672fd41059c154d53","impliedFormat":1},{"version":"a1b36a1f91a54daf2e89e12b834fa41fb7338bc044d1f08a80817efc93c99ee5","impliedFormat":1},{"version":"8bb4a5b632dd5a868f3271750895cb61b0e20cff82032d87e89288faee8dd6e2","impliedFormat":1},{"version":"55ac6eb880722b04fed6b1ad0bae86f57856c7985575ba76a31013515e009316","impliedFormat":1},{"version":"017de6fdabea79015d493bf71e56cbbff092525253c1d76003b3d58280cd82a0","impliedFormat":1},{"version":"ab9ea2596cb7800bd79d1526930c785606ec4f439c275adbca5adc1ddf87747d","impliedFormat":1},{"version":"6b7fcccc9beebd2efadc51e969bf390629edce4d0a7504ee5f71c7655c0127b7","impliedFormat":1},{"version":"6745b52ab638aaf33756400375208300271d69a4db9d811007016e60a084830f","impliedFormat":1},{"version":"90ee466f5028251945ee737787ee5e920ee447122792ad3c68243f15efa08414","impliedFormat":1},{"version":"02ea681702194cfc62558d647243dbd209f19ee1775fb56f704fe30e2db58e08","impliedFormat":1},{"version":"1d567a058fe33c75604d2f973f5f10010131ab2b46cf5dddd2f7f5ee64928f07","impliedFormat":1},{"version":"5af5ebe8c9b84f667cd047cfcf1942d53e3b369dbd63fbea2a189bbf381146c6","impliedFormat":1},{"version":"a64e1daa4fc263dff88023c9e78bf725d7aba7def44a89a341c74c647afe80cc","impliedFormat":1},{"version":"f444cfd9eb5bcbc86fba3d7ca76d517e7d494458b4f04486090c6ccd40978ce7","impliedFormat":1},{"version":"5099990c9e11635f284bde098176e2e27e5afc562d98f9e4258b57b2930c5ea6","impliedFormat":1},{"version":"cf7dc8abfb13444c1756bbac06b2dd9f03b5bc90c0ebc1118796dae1981c12e6","impliedFormat":1},{"version":"3cc594d4e993618dc6a84d210b96ac1bd589a5a4b772fd2309e963132cb73cca","impliedFormat":1},{"version":"f189f28612dfeac956380eccea5be2f44dcac3d9a06cf55d41d23b7e99959387","impliedFormat":1},{"version":"b3f82681e61a3e1f4592c1554361a858087cd04ee3112ce73186fc79deeeabde","impliedFormat":1},{"version":"e647d13de80e1b6b4e1d94363ea6f5f8f77dfb95d562748b488a7248af25aabf","impliedFormat":1},{"version":"1567dbd347b2917ba5a386f713e45c346a15b0e1e408d4a83f496d6a3481768b","impliedFormat":1},{"version":"219a25474e58a8161b242776856ec5f6960839b63e74809445e51cadbfc18096","impliedFormat":1},{"version":"2f77672836c646d02dd1fb6c8d24e9cd8c63131c5e9c37e72f30856b1d740e62","impliedFormat":1},{"version":"6309a45fc3c03d3c4d56228e995d51974f53009a842374695b34f3607877e5a3","impliedFormat":1},{"version":"bef94eba81ae2c09059c0d9abdb1ae1b7090314f70550f3c8cd5d7ead4a4f212","impliedFormat":1},{"version":"48b787ad458be9b524fa5fdfef34f68798074132d4b8cfe6a6fe9c2bf334c532","impliedFormat":1},{"version":"37280465f8f9b2ea21d490979952b18b7f4d1f0d8fab2d627618fb2cfa1828e3","impliedFormat":1},{"version":"cefa33b76df8d9af73edcf02d9b03effbeec54b8200e97669ad454d770aee9ba","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f3f85dc43cb93c5a797f1ff0fa948d0e17843a443ae11a20cc032ccdf1b9997","impliedFormat":1},{"version":"581843e855d92557cbe9dfe242de4e53badae5e9096ca593b50788f7c89c37f2","impliedFormat":1},{"version":"869010bc679df668137cb3b78a3cb8196e97acf285208a57f6156ceac894a2f7","impliedFormat":1},{"version":"bcae62618c23047e36d373f0feac5b13f09689e4cd08e788af13271dbe73a139","impliedFormat":1},{"version":"2c49c6d7da43f6d21e2ca035721c31b642ebf12a1e5e64cbf25f9e2d54723c36","impliedFormat":1},{"version":"5ae003688265a1547bbcb344bf0e26cb994149ac2c032756718e9039302dfac8","impliedFormat":1},{"version":"02cf4ede9c240d5bf0d9ef2cb9454db2efe7db36692c7fe7ad53d92a08c26b8f","impliedFormat":1},{"version":"a86053981218db1594bd4839bde0fb998e342ecf04967622495434a8f52a4041","impliedFormat":1},{"version":"5c317403752871838140f70879b09509e37422e92e7364b4363c7b179310ee44","impliedFormat":1},{"version":"7b270dc53f35dd0b44bfa619ad4d351fffd512e14053c3688323ed007eda3f6d","impliedFormat":1},{"version":"3bfde94a5dab40b51ff3511a41cfb706d57f9584a15e938d243a0e36861e86fe","impliedFormat":1},{"version":"e86ad029224d4f2af3e188be8b5e9badf8c7083247572069bac7bd2193131fc7","impliedFormat":1},{"version":"057cac07c7bc5abdcfba44325fcea4906dff7919a3d7d82d4ec40f8b4c90cf2f","impliedFormat":1},{"version":"d94034601782f828aa556791279c86c37f09f7034a2ab873eefe136f77a6046b","impliedFormat":1},{"version":"105ae3dd61531488194f412386ba8c2b786f1389ac3415098cc47c712800da29","impliedFormat":1},{"version":"e3acb4eb63b7fc659d7c2ac476140f7c85842a516b98d0e8698ba81650a1abd4","impliedFormat":1},{"version":"4ee905052d0879e667444234d1462540107789cb1c80bd26e328574e4f3e4724","impliedFormat":1},{"version":"80e71af1e94ba805e791b9e8e03ff18dec32e8f483db3dca958441d284047d59","impliedFormat":1},{"version":"150f25e1df681ac86bf2224814e628ec8c67b3b0bf91c5642007f072fc403422","impliedFormat":1},{"version":"51812205a847a2a20e29b77238a146e0306564c53d6bd6bfa72167624e7ea370","impliedFormat":1},{"version":"445fe49dc52d5d654a97d142b143fa2fb1dc16a86906545619b521b1561df501","impliedFormat":1},{"version":"c0c0b22cefd1896b92d805556fcabda18720d24981b8cb74e08ffea1f73f96c2","impliedFormat":1},{"version":"ceec94a0cd2b3a121166b6bfe968a069f33974b48d9c3b45f6158e342396e6b2","impliedFormat":1},{"version":"49e35a90f8bd2aa4533286d7013d9c9ff4f1d9f2547188752c4a88c040e42885","impliedFormat":1},{"version":"09043c4926b04870c1fdfdea3f5fcf40a1c9912304a757326e505bebe04a6d5c","impliedFormat":1},{"version":"cc5dfb7ddc9ab17cf793506f342fffdcb2b6d1d7a9c0e7c8339772fee42b7f91","impliedFormat":1},{"version":"88c34f554b5926f4988d9ff26f84c4f18a4d010f261dac2ed52055eefb9e3c65","impliedFormat":1},{"version":"a7aec47aa991ef5080126c3e2732a8488c13fd846099f89b0d24dc35c0f790d3","impliedFormat":1},{"version":"35085777eb17b745911d00a75be17096fe28a8766081cbd644ef15b4ba756aa2","impliedFormat":1},{"version":"cb498c53a9d35ac1cf9a3515f3835d48b4626a612cf7540c5bfb99542c9ab1a5","impliedFormat":1},{"version":"0ace3010fe4a0e820155e3ccb0172375a01162e528ffc22eec2fa33d697bff24","impliedFormat":1},{"version":"a1b64f86e1279835a2edc6125121dff74b04ef116d0230c20995b013ba37150e","impliedFormat":1},{"version":"39121347a4fa76cf47e67e1259fb0136325528a22bd54b1af6dbec353edf4b01","impliedFormat":1},{"version":"f3c3f17825c6a78681186da04c2f3a0f1c60cfa95f3d4b82bbbd6ebd57214a6a","impliedFormat":1},{"version":"e80304a0977ad51a48bc9495eda8a57253c788f788ba31ba7425f4e7d58358bf","impliedFormat":1},{"version":"c67357cd90bab0388580428c18365a01b4b60f6528e780ec7c5c639798738657","impliedFormat":1},{"version":"6d41f18b1fec14f10853dc8e01ec962cc0a788d5e707cb7fa3583ef84f9c8eb6","impliedFormat":1},{"version":"1422b6b55f4a5376d4b405713ed418353587131b12e3857eb5d68a01cba929e2","impliedFormat":1},{"version":"8f374eeeb9e3beb2132d408b304c50b808de2e88f53bd751a6213df9a49bf5f4","impliedFormat":1},{"version":"586b7a877464cba4970b566a8ae469915d73865295b811f20dd6fd80b807db21","impliedFormat":1},{"version":"e7eb2f83279cd7d925810e19e592b692af0bd68885b4a70ee9b83b8075aa7e20","impliedFormat":1},{"version":"84618b2dd4f762891431011a9879ec24b731ca4ad3f6be74b89a239302d1ed54","impliedFormat":1},{"version":"ab36396e69ad906246fa70d6c4095e3efd687505e355cedce4aeddb8da0a9367","impliedFormat":1},{"version":"49b3c93485a6c4cbc837b1959b07725541da298ef24d0e9e261f634a3fd34935","impliedFormat":1},{"version":"2b1945f9ee3ccab0ecfed15c3d03ef5a196d62d0760cffab9ec69e5147f4b5aa","impliedFormat":1},{"version":"a54f60678f44415d01a810ca27244e04b4dde3d9b6d9492874262f1a95e56c7d","impliedFormat":1},{"version":"84058607d19ac1fdef225a04832d7480478808c094cbaedbceda150fa87c7e25","impliedFormat":1},{"version":"415d60633cf542e700dc0d6d5d320b31052efbdc519fcd8b6b30a1f992ef6d5c","impliedFormat":1},{"version":"901c640dced9243875645e850705362cb0a9a7f2eea1a82bb95ed53d162f38dd","impliedFormat":1},{"version":"ebb0d92294fe20f62a07925ce590a93012d6323a6c77ddce92b7743fa1e9dd20","impliedFormat":1},{"version":"b499f398b4405b9f073b99ad853e47a6394ae6e1b7397c5d2f19c23a4081f213","impliedFormat":1},{"version":"ef2cbb05dee40c0167de4e459b9da523844707ab4b3b32e40090c649ad5616e9","impliedFormat":1},{"version":"068a22b89ecc0bed7182e79724a3d4d3d05daacfe3b6e6d3fd2fa3d063d94f44","impliedFormat":1},{"version":"3f2009badf85a479d3659a735e40607d9f00f23606a0626ae28db3da90b8bf52","impliedFormat":1},{"version":"2c70425bd71c6c25c9765bc997b1cc7472bdc3cb4db281acda4b7001aec6f86f","impliedFormat":1},{"version":"8ed892f4b45c587ed34be88d4fc24cb9c72d1ed8675e4b710f7291fcba35d22a","impliedFormat":1},{"version":"d32b5a3d39b581f0330bd05a5ef577173bd1d51166a7fff43b633f0cc8020071","impliedFormat":1},{"version":"3f6af667357384c1f582ef006906ba36668dd87abe832f4497fffb315c160be9","impliedFormat":1},{"version":"363dd28f6a218239fbd45bbcc37202ad6a9a40b533b3e208e030137fa8037b03","impliedFormat":1},{"version":"c6986e90cf95cf639f7f55d8ca49c7aaf0d561d47e6d70ab6879e40f73518c8d","impliedFormat":1},{"version":"bb9918dbd22a2aa56203ed38b7e48d171262b09ce690ff39bae8123711b8e84a","impliedFormat":1},{"version":"1518707348d7bd6154e30d49487ba92d47b6bd9a32d320cd8e602b59700b5317","impliedFormat":1},{"version":"ede55f9bac348427d5b32a45ad7a24cc6297354289076d50c68f1692add61bce","impliedFormat":1},{"version":"d53a7e00791305f0bd04ea6e4d7ea9850ccc3538877f070f55308b3222f0a793","impliedFormat":1},{"version":"4ea5b45c6693288bb66b2007041a950a9d2fe765e376738377ba445950e927f6","impliedFormat":1},{"version":"7f25e826bfabe77a159a5fec52af069c13378d0a09d2712c6373ff904ba55d4b","impliedFormat":1},{"version":"ea2de1a0ec4c9b8828154a971bfe38c47df2f5e9ec511f1a66adce665b9f04b0","impliedFormat":1},{"version":"63c0926fcd1c3d6d9456f73ab17a6affcdfc41f7a0fa5971428a57e9ea5cf9e0","impliedFormat":1},{"version":"c30b346ad7f4df2f7659f5b3aff4c5c490a1f4654e31c44c839292c930199649","impliedFormat":1},{"version":"4ef0a17c5bcae3d68227136b562a4d54a4db18cfa058354e52a9ac167d275bbb","impliedFormat":1},{"version":"042b80988f014a04dd5808a4545b8a13ca226c9650cb470dc2bf6041fc20aca2","impliedFormat":1},{"version":"64269ed536e2647e12239481e8287509f9ee029cbb11169793796519cc37ecd4","impliedFormat":1},{"version":"c06fd8688dd064796b41170733bba3dcacfaf7e711045859364f4f778263fc7b","impliedFormat":1},{"version":"b0a8bf71fea54a788588c181c0bffbdd2c49904075a7c9cb8c98a3106ad6aa6d","impliedFormat":1},{"version":"434c5a40f2d5defeede46ae03fb07ed8b8c1d65e10412abd700291b24953c578","impliedFormat":1},{"version":"c5a6184688526f9cf53e3c9f216beb2123165bfa1ffcbfc7b1c3a925d031abf7","impliedFormat":1},{"version":"cd548f9fcd3cebe99b5ba91ae0ec61c3eae50bed9bc3cfd29d42dcfc201b68b5","affectsGlobalScope":true,"impliedFormat":1},{"version":"14a8ec10f9faf6e0baff58391578250a51e19d2e14abcc6fc239edb0fb4df7c5","impliedFormat":1},{"version":"81b0cf8cd66ae6736fd5496c5bbb9e19759713e29c9ed414b00350bd13d89d70","impliedFormat":1},{"version":"4992afbc8b2cb81e0053d989514a87d1e6c68cc7dedfe71f4b6e1ba35e29b77a","impliedFormat":1},{"version":"f15480150f26caaccf7680a61c410a07bd4c765eedc6cbdca71f7bca1c241c32","impliedFormat":1},{"version":"1c390420d6e444195fd814cb9dc2d9ca65e86eb2df9c1e14ff328098e1dc48ae","impliedFormat":1},{"version":"ec8b45e83323be47c740f3b573760a6f444964d19bbe20d34e3bca4b0304b3ad","impliedFormat":1},{"version":"ab8b86168ceb965a16e6fc39989b601c0857e1fd3fd63ff8289230163b114171","impliedFormat":1},{"version":"62d2f0134c9b53d00823c0731128d446defe4f2434fb84557f4697de70a62789","impliedFormat":1},{"version":"96f215cefc7628ac012e55c7c3e4e5ce342d66e83826777a28e7ed75f7935e10","impliedFormat":1},{"version":"82b4045609dc0918319f835de4f6cb6a931fd729602292921c443a732a6bb811","impliedFormat":1},{"version":"0fd70ca1eaef1e2dd6f48f16886df4838664821d992fd8076d07fc15e83c8498","impliedFormat":1},{"version":"ba30e6d2f1d20c707566cf485167331a10c539802a79040ced055b62a7aae53e","impliedFormat":1},{"version":"b129f3db6f7f63e3e0cafeb9ee9fc57ceede840577725dcdb01fe89b9d32cf2b","impliedFormat":1},{"version":"4ddd9b092c76bce6b8516c0c4d156de63af024994c2d1305a4812b6d64858f93","impliedFormat":1},{"version":"537a2b61594512c5e75fad7e29d25c23922e27e5a1506eb4fce74fe858472a6e","impliedFormat":1},{"version":"311ca94091f3db783c0874128808d0f93ab5d7be82abc20ceb74afe275315d4a","impliedFormat":1},{"version":"7c07838da165fd43759a54d2d490461315e977f9f37c046e0e357623c657fc42","impliedFormat":1},{"version":"b311d973a0028d6bc19dfbaae891ad3f7c5057684eb105cfbeec992ab71fbc13","impliedFormat":1},{"version":"115c8691bd8fac390f6f6eef5b356543d716da7cffa4c2f70f288d56c5b06aeb","impliedFormat":1},{"version":"e91516e66f9fbf39c978a4092c16ffda3bb0b32158fca6def75aae9fab358153","impliedFormat":1},{"version":"abd4563a6a7668fa6f8f5e5a425a0900b80fc2309fec5186e2cae67f3ce92663","impliedFormat":1},{"version":"cb48f3011e72efef9d5a5b312f4a956f699b8d423bf9f2772724cdded496bd50","impliedFormat":1},{"version":"9aed07904079877252e6c0aedf1d2cf1935ed91d4abc16f726c76b61ea453919","impliedFormat":1},{"version":"6621af294bd4af8f3f9dd9bd99bd83ed8d2facd16faa6690a5b02d305abd98ab","impliedFormat":1},{"version":"5eada4495ab95470990b51f467c78d47aecfccc42365df4b1e7e88a2952af1a3","impliedFormat":1},{"version":"44810c4c590f5c4517dfa39d74161cfa3a838437f92683cb2eed28ff83fb6a97","impliedFormat":1},{"version":"4a34de405e3017bf9e153850386aacdf6d26bbcd623073d13ab3c42c2ae7314c","impliedFormat":1},{"version":"fe2d1251f167d801a27f0dfb4e2c14f4f08bf2214d9784a1b8c310fdfdcdaaea","impliedFormat":1},{"version":"2a1182578228dc1faad14627859042d59ea5ab7e3ac69cb2a3453329aaaa3b83","impliedFormat":1},{"version":"dfa99386b9a1c1803eb20df3f6d3adc9e44effc84fa7c2ab6537ed1cb5cc8cfb","impliedFormat":1},{"version":"79b0d5635af72fb87a2a4b62334b0ab996ff7a1a14cfdb895702e74051917718","impliedFormat":1},{"version":"5f00b052713bfe8e9405df03a1bbe406006b30ec6b0c2ce57d207e70b48cf4e9","impliedFormat":1},{"version":"7abcae770f21794b5ffbc3186483c3dbcf8b0c8e37d3ef3ed6277ece5c5dd4be","impliedFormat":1},{"version":"4720efe0341867600b139bca9a8fa7858b56b3a13a4a665bd98c77052ca64ea4","impliedFormat":1},{"version":"566fc645642572ec1ae3981e3c0a7dc976636976bd7a1d09740c23e8521496e5","impliedFormat":1},{"version":"66182e2432a30468eb5e2225063c391262b6a6732928bbc8ee794642b041dd87","impliedFormat":1},{"version":"11792ab82e35e82f93690040fd634689cad71e98ab56e0e31c3758662fc85736","impliedFormat":1},{"version":"0b2095c299151bc492b6c202432cb456fda8d70741b4fd58e86220b2b86e0c30","impliedFormat":1},{"version":"6c53c05df974ece61aca769df915345dc6d5b7649a01dc715b7da1809ce00a77","impliedFormat":1},{"version":"18c505381728b8cc6ea6986728403c1969f0d81216ed04163a867780af89f839","impliedFormat":1},{"version":"d121a48de03095d7dd5cd09d39e1a1c4892b520dad4c1d9c339c5d5008cfb536","impliedFormat":1},{"version":"3592c16d8a782be215356cb78cc3f6fad6132e802d157a874c1942d163151dcc","impliedFormat":1},{"version":"480ea50ea1ee14d243ea72e09d947488300ac6d82e98d6948219f47219511b8b","impliedFormat":1},{"version":"d575bcf7ebd470d7accf5787a0cf0f3c88c33ca7c111f277c03ebbe6d0e8b0b5","impliedFormat":1},{"version":"72141538e52e99ca6e7a02d80186ba8c877ff47a606fea613be1b7a3439c2b90","impliedFormat":1},{"version":"b43a0693d7162abf3a5b3b9e78acfafd0d4713af4d54d1778900e30c11bc4f83","impliedFormat":1},{"version":"115b155584649eaf75d50bdc8aaa9a0f528b60fade90f0cf78137c875ff7de7c","impliedFormat":1},{"version":"98d88eefab45da6b844d2bee8f6efa8d20c879f6dc870c17b90608a4ac0ad527","impliedFormat":1},{"version":"4eb2ca099a3febd21e98c36e29b3a9472458a1e76e888bf6499614c895ba6be7","impliedFormat":1},{"version":"f4dc28fbbba727722cb1fd82f51a7b9540fbe410ed04ddf35cab191d6aa2ba10","impliedFormat":1},{"version":"414f9c021dde847ee2382c4086f7bd3a49a354be865f8db898ee89214b2d2ced","impliedFormat":1},{"version":"bbbc43627abe35080c1ab89865ec63645977025d0161bc5cc2121dfd8bc8bc2e","impliedFormat":1},{"version":"0be66c79867b62eabb489870ba9661c60c32a5b7295cce269e07e88e7bee5bf3","impliedFormat":1},{"version":"5766c26941ae00aa889335bcccc1ecb28271b774be92aede801354c9797074bb","impliedFormat":1},{"version":"3a19286bcc9303c9352c03d68bb4b63cecbf5c9b7848465847bb6c9ceafa1484","impliedFormat":1},{"version":"c573fef34c2e5cc5269fd9c95fe73a1eb9db17142f5d8f36ffe4a686378b8660","impliedFormat":1},{"version":"d97e30dd93590392fed422f2b27325d10ab007d034faaaf61e28e9ddc9d3825b","impliedFormat":1},{"version":"d1f8a829c5e90734bb47a1d1941b8819aeee6e81a2a772c3c0f70b30e3693fa9","impliedFormat":1},{"version":"be1dfacee25a14d79724ba21f1fde67f966b46e2128c68fed2e48c6e1e9822c5","impliedFormat":1},{"version":"19b3d0c212d241c237f79009b4cd0051e54971747fd89dc70a74f874d1192534","impliedFormat":1},{"version":"b8101e982968b04cfaabfc9613dc8f8244e0a8607007bba3537c1f7cbb2a9242","impliedFormat":1},{"version":"ed3e176bc769725ebc1d93f1d6890fc3d977b9155ae5d03be96ec2d49b303370","impliedFormat":1},{"version":"e2dc16f882661fe5e9e6cde0a9c3e6f18f56ce7243ab0a168e68bfab6a5b9830","impliedFormat":1},{"version":"fc5221aedb3b5c52b4fbdf7b940c2115bde632f6cba52e05599363d5cd31019e","impliedFormat":1},{"version":"0289a27db91cb5a004dcf1e6192a09a1f9e8ff8ce606ff8fd691d42de5752123","impliedFormat":1},{"version":"307c6b2de09a621629cef5b7d0ec0ccabe72a3cd1a8f3ee189229d9035f52051","impliedFormat":1},{"version":"3c196d2ef49db4ad0e33a2a7e515ae622106b06ee8479957303601fd3e00f4f8","impliedFormat":1},{"version":"7933769d84f5ae16546aef06537ca578f1c8d7cca0708452a00613050ac1f265","impliedFormat":1},{"version":"4a48a731413b6fae34620c2e458d0adf2f74083073544a72b1b3a96c32775b2f","impliedFormat":1},{"version":"d405963c5f69955e95c30ef121c7a3309f214f21ef09dceb5d7ac69557cbe0fa","impliedFormat":1},{"version":"0c03b1120ddb2fa74809f5d06516beb5b4a3b3561ee93619f1e1c98fdb74a660","impliedFormat":1},{"version":"c3dc147af5ef951e14797da29b2dcaf1fdddabb0175d538e1bedf64a34690b9e","impliedFormat":1},{"version":"77e6933a0f1e4e5d355175c6d5c517398002a3eb74f2218b7670a29814259e3a","impliedFormat":1},{"version":"90051a939d662322dbc062f856f82ccc13fbb6b3f3bbb5d863b4c5031d4e9a85","impliedFormat":1},{"version":"68969a0efd9030866f60c027aedbd600f66ea09e1c9290853cc24c2dcc92000f","impliedFormat":1},{"version":"757f7967151a9b1f043aba090f09c1bdb0abe54f229efd3b7a656eb6da616bf4","impliedFormat":1},{"version":"786691c952fe3feac79aca8f0e7e580d95c19afc8a4c6f8765e99fb756d8d9d7","impliedFormat":1},{"version":"c3b259ee9684c6680bd68159d47bf36b0f5f32ea3b707197bcd6921cf25bde36","impliedFormat":1},{"version":"ab0926fedbd1f97ec02ed906cf4b1cf74093ab7458a835c3617dba60f1950ba3","impliedFormat":1},{"version":"3e642f39da9ad0a4cd16ccbd7f363b6b5ad5fa16a5c6d44753f98fc1e3be9d96","impliedFormat":1},{"version":"7f5a6eac3d3d334e2f2eba41f659e9618c06361958762869055e22219f341554","impliedFormat":1},{"version":"e6773ee69d14a45b44efa16a473a6366d07f61cd4f131b9fea7cd2e5b36a265c","impliedFormat":1},{"version":"67f2cd6e208e68fdfa366967d1949575df6ccf90c104fc9747b3f1bdb69ad55a","impliedFormat":1},{"version":"4093c47f69ea7acf0931095d5e01bfe1a0fa78586dbf13f4ae1142f190d82cc4","impliedFormat":1},{"version":"4fc9939c86a7d80ab6a361264e5666336d37e080a00d831d9358ad83575267da","impliedFormat":1},{"version":"f4ba385eedea4d7be1feeeac05aaa05d6741d931251a85ab48e0610271d001ce","impliedFormat":1},{"version":"52ae1d7a4eb815c20512a1662ca83931919ac3bb96da04c94253064291b9d583","impliedFormat":1},{"version":"6fa6ceb04be38c932343d6435eb6a4054c3170829993934b013b110273fe40af","impliedFormat":1},{"version":"0e8536310d6ed981aa0d07c5e2ca0060355f1394b19e98654fdd5c4672431b70","impliedFormat":1},{"version":"e71d84f5c649e283b31835f174df2afe6a01f4ef2cb1aafca5726b7d2b73a2e4","impliedFormat":1},{"version":"6d26bc11d906309e5c3b12285f94d9ef8edd8529ddee60042aba8470280b8b55","impliedFormat":1},{"version":"8f2644578a3273f43fd700803b89b842d2cd09c1fba2421db45737357e50f5b1","impliedFormat":1},{"version":"639f94fe145a72ce520d3d7b9b3b6c9049624d90cbf85cff46fb47fb28d1d8fe","impliedFormat":1},{"version":"8327a51d574987a2b0f61ea40df4adddf959f67bc48c303d4b33d47ba3be114a","impliedFormat":1},{"version":"00e1da5fce4ae9975f7b3ca994dcb188cf4c21aee48643e1d6d4b44e72df21ee","impliedFormat":1},{"version":"976d20bb5533077a2135f456a2b48b7adb7149e78832b182066930bad94f053a","impliedFormat":1},{"version":"4d250e905299144850c6f8e74dad1ee892d847643bacf637e89adcce013f0700","impliedFormat":1},{"version":"51b4ab145645785c8ced29238192f870dbb98f1968a7c7ef2580cd40663b2940","impliedFormat":1},{"version":"589713fefe7282fd008a2672c5fbacc4a94f31138bae6a03db2c7b5453dc8788","impliedFormat":1},{"version":"26f7f55345682291a8280c99bb672e386722961063c890c77120aaca462ac2f9","impliedFormat":1},{"version":"100802c3378b835a3ce31f5d108de149bd152b45b555f22f50c2cafb3a962ead","impliedFormat":1},{"version":"fd4fef81d1930b60c464872e311f4f2da3586a2a398a1bdf346ffc7b8863150f","impliedFormat":1},{"version":"354f47aa8d895d523ebc47aea561b5fedb44590ac2f0eae94b56839a0f08056a","impliedFormat":1},{"version":"62b753ed351fba7e0f6b57103529ce90f2e11b949b8fc69c39464fe958535c25","impliedFormat":1},{"version":"514321f6616d04f0c879ac9f06374ed9cb8eac63e57147ac954e8c0e7440ce00","impliedFormat":1},{"version":"ce7b928daedd974205daf616493c6eb358069ed740ed9552c5f4e66da19fd4bf","impliedFormat":1},{"version":"3d59b606bca764ce06d7dd69130c48322d4a93a3acb26bb2968d4e79e1461c3c","impliedFormat":1},{"version":"0231f8c8413370642c1c061e66b5a03f075084edebf22af88e30f5ce8dbf69f4","impliedFormat":1},{"version":"474d9ca594140dffc0585ce4d4acdcfba9d691f30ae2cafacc86c97981101f5c","impliedFormat":1},{"version":"e9ae721d2f9df91bc707ea47ddd590b04328654cfea11e79a57e5aef832709ff","impliedFormat":1},{"version":"0e2a6b2eeadafbc7a27909527af46705d47e93c652d656f09cc3ef460774291b","impliedFormat":1},{"version":"ed56810efb2b1e988af16923b08b056508755245a2f8947e6ad491c5133664ed","impliedFormat":1},{"version":"ed012a19811c4010cb7d8920378f6dd50f22e1cf2842ecb44a157030667b165e","impliedFormat":1},{"version":"26a19453ef691cc08d257fbcbcc16edb1a2e78c9b116d5ee48ed69e473c8ff76","impliedFormat":1},{"version":"2c531043b1d58842c58e0a185c7bd5ce31e9a708667398373d6b113938629f90","impliedFormat":1},{"version":"5304a80e169ba8fe8d9c77806e393db1f708333afc1f95dede329fdbd84e29c7","impliedFormat":1},{"version":"7f0f90d0ffdd54875c464b940afaa0f711396f65392f20e9ffafc0af12ccbf14","impliedFormat":1},{"version":"2e93bb867fefffaecf9a54a91dbf271787e007ec2fe301d3dce080944c5518e5","impliedFormat":1},{"version":"3ab58250eb2968101cb0f3698aab0faa603660bc2d41d30ae13eaa22d75900d1","impliedFormat":1},{"version":"1f18ceea8d29b75099cc85f357622e87d6a2e0793486f89ab6da32cf9e434feb","impliedFormat":1},{"version":"c280ec77789efcf60ea1f6fd7159774422f588104dae9dfa438c9c921f5ab168","impliedFormat":1},{"version":"2826b3526af4f0e2c8f303e7a9a9a6bb8632e4a96fece2c787f2df286a696cea","impliedFormat":1},{"version":"3ec6d90ec9586e6e96120ff558429cac6ca656d81eb644ce703f736a316a0cd6","impliedFormat":1},{"version":"453b07099526a6d20fd30f357059d413677f919df8abf7346fab7c9abfec43fa","impliedFormat":1},{"version":"485f7d76af9e2b5af78aac874b0ac5563c2ae8c0a7833f62b24d837df8561fb9","impliedFormat":1},{"version":"8bdf41d41ff195838a5f9e92e5cb3dfcdc4665bcca9882b8d2f82a370a52384e","impliedFormat":1},{"version":"90f08678b00c7b7aaaad0c84fb6525a11b5c35dad624b59dcadd3d279a4366c4","impliedFormat":1},{"version":"97ba9ccb439e5269a46562c6201063fbf6310922012fd58172304670958c21f6","impliedFormat":1},{"version":"d037b771e89ef6dd81c71de92cc644d68b1b5d1ce25dbce9c2cfe407dd0b5796","impliedFormat":1},{"version":"25091d25f74760301f1e094456e2e6af52ceb6ef1ece48910463528e499992d8","impliedFormat":1},{"version":"853d02f4f46ca9700fefd0d45062f5b82c9335ba2224ca4d7bd34d6ae4fc4a7f","impliedFormat":1},{"version":"b3d1c579771490011614a16be1f6951aec87248fdc928dd46b682523edb8e503","impliedFormat":1},{"version":"b3cc1bb7311f35569b531e781d4a42d2b91f8dfd8bc194cc310c8b61011d6e43","impliedFormat":1},{"version":"cf6dc8f18bc5ee063dc1a37bccd3031dc0769f11622399018c375aacfcbda7c9","impliedFormat":1},{"version":"8ca2d01f5f3d4d4067aadea230570afa4c91e24e485fbe2e9d53ead3b33f80d0","impliedFormat":1},{"version":"87bbee3d308539bb6d85a18d84b852bcd91d5be73bc5366c8d394f3dd633a9e5","impliedFormat":1},{"version":"ab9d37bc03714e85a227a8db09cf4b217de99d3d297152c1d8bcd07d37753665","impliedFormat":1},{"version":"72bb2ca89105bb557c0b70a98503cdff69182d064c8ef4c50373ed2f27a31805","impliedFormat":1},{"version":"dac751a342d90dca2da68677a0ce9786395405de0e9c03f0c5e676fa4fd57e26","impliedFormat":1},{"version":"1eef74abb9048ffb7f773249080dc47a0f8eb220a02455721cc8779437525b2b","impliedFormat":1},{"version":"724a5ed046f87aec06d920fffa4d70ff3ea9cfb63d790ecece4d866018f2e8d3","impliedFormat":1},{"version":"0f986a4d38b0b6e66bf18d740be5c0b1f478154b6ca3530e12e0214fb44fbbdb","impliedFormat":1},{"version":"9fe25bdc82292a488469db295783c5187df43ac5a55a49b63cbacaf8cf12b75b","impliedFormat":1},{"version":"be59079768dc24a100fc8fa32f03f848598a8e0feb884135b6767cd7ffdfab68","impliedFormat":1},{"version":"f5fbcce4b7d3b6f0ab234eda4926bb069ea94744daf82377ee41d0f07bce4b03","impliedFormat":1},{"version":"0c2394fab97f1264b2fc68f4143a11a68c6221eb4c9959fe3ed4fe6627574282","impliedFormat":1},{"version":"e9b5a686e8e87d4529398ea1698a253a57e156f72cf9b245d4d3d39efc06c7fd","impliedFormat":1},{"version":"7662ff2925419c3bb854012a0658fbf63929eb246fcc2c3a346013147180aa6f","impliedFormat":1},{"version":"a566232381cab833f997f74524b1d5a73bc044353bb8d8f87f3942bf4e68d384","impliedFormat":1},{"version":"71e1e2eb6a6f2c451f537acc6d3f5a7d81947a27d7a5c5e3ae830d19a972ffc0","impliedFormat":1},{"version":"53871b5b3657d9a2e80c9f6fb1fa03e6a4e664a75bfebfb820c58b7a4b023c25","impliedFormat":1},{"version":"d474673dc7ed7a59223b25dd6413e89c0b3e4e207ef7ea490d6ddf24d78c89c5","impliedFormat":1},{"version":"e9a6308496927fe05ffd343a4f062f5d0369f5a5d674be58d92515b22aaba969","impliedFormat":1},{"version":"83a74372441872cb6f3688cab6009c3e0aafc4dd2414a2c8a2d340247945e3d7","impliedFormat":1},{"version":"1965472700ba36ecde4826cb978678709f42b768e2adb8d0f0fb118a81aafb37","impliedFormat":1},{"version":"3a19a395b9a6a76d174646bc9cd4504210d71ef5a5f894ab02182e2229b65509","impliedFormat":1},{"version":"419bab68ba67804f65e5a9a428b8630ee2a2a28e0c90a7a53d7f8504df9143e9","impliedFormat":1},{"version":"929022c311336faa083b05e57fd1781906b04995c968db3492f1da3fca2bf603","impliedFormat":1},{"version":"b209715d396013bbf794212887a2efd5f1b254da1aff261b9cc0117640561467","impliedFormat":1},{"version":"6adec68a56989c4f9282ae1df1802a519f14a931c1d2f62b3c1c826aa75c74a1","impliedFormat":1},{"version":"3c2ca15845d257b0e4f669100bb79c92e95ec84a5382aa02ec1bbbf36b00ac22","impliedFormat":1},{"version":"a89e1f874f3ca3bc357a85f7ad80be88304a55703a93807efa258d0ab968373f","impliedFormat":1},{"version":"c2732eff1a3410aa8c04d7b1c9dff791147f6d439ebab95e551ae937eee514f0","impliedFormat":1},{"version":"cb480ac9e7274685a23c7ddf968d26c8106ecab241238c8019b807df20146fc4","impliedFormat":1},{"version":"d4996c548b362000867f44769ad69664fdfbea6f61d9a08e0d65ced6ea48dbcc","impliedFormat":1},{"version":"ce7614e04f1107aa877a25a40ad8d0d57ded4a292938537a82202b852c99a50d","impliedFormat":1},{"version":"4ee861d5c8b34436a2832ecae6be89003a20b341726edac5a4fd6c9d43f92f71","impliedFormat":1},{"version":"d26ed788de38009ac5c1f1e44efe6529ad7a2e8686fb0a025f25206b9cf324ed","impliedFormat":1},{"version":"563c87a7400e0cf80c3c1200169994600b74eb8f4052a340f2717c3c16596885","impliedFormat":1},{"version":"64de49be47b71904704f0836c6a79ef239c64995a7c90ca90b79782fea70e028","impliedFormat":1},{"version":"712c377914bd99f33eca1b2f01e8c64b4237e435360bed7b71af938a6f1b389c","impliedFormat":1},{"version":"92a2771f2ee58b03db68410cac6e242fe56de1d377d12e97df5e06203cebce14","impliedFormat":1},{"version":"55e4e9a5a7d32f6672463e5fa558bf15cc61dffc383808396340e79daa3761cd","impliedFormat":1},{"version":"50d23c36ac76399f95c497635d7da2f00749953fca1467e02fbde0dc4a3c158b","impliedFormat":1},{"version":"1fa764b1e9cee971438c530a42472f15381b27bdfb13ee5aeb265be2d497ff90","impliedFormat":1},{"version":"2045c40fc80f87796764e485c0844645d4f0def984e09f679730f558838de31b","impliedFormat":1},{"version":"eced59a4309f86330b447d0b198a0fb6ccb8adcb7e3e43054f191059023d7239","impliedFormat":1},{"version":"a69acdca953c3bad6e8a9bc390a10eacf92b527874a54a82c3111718e9f831c2","impliedFormat":1},{"version":"4be7e6d6a70aebeab656a12245beb5283f348fdd97c7a20622ee80e84c1dd87d","impliedFormat":1},{"version":"9d5938c3f2c9a318bedf68c6819daacad8a57ab4cb3acdbcb66f5deb6b039171","impliedFormat":1},{"version":"ee1d05153c3538c3610a3bfa1c168f6eddd2c739c9c1e59cffc53c6b47c48201","impliedFormat":1},{"version":"f6d956bfa8d8bde35197d1031ec90d4246c8bfbeab8fdfd4dd505a77e3eccbf2","impliedFormat":1},{"version":"a2b647554c4b0c76bb5e627063c0212529a7eb25aecf9a26eb860c3cb4fa1300","impliedFormat":1},{"version":"73e3af044cd3b4413d9bf91660df2c49ff0ecaef916ad8e3b06fdb036f583e65","impliedFormat":1},{"version":"315068cb082d34441c0740e44fa219454b616640a7509f9a7c49ac4d19796c37","impliedFormat":1},{"version":"3fbe23a2f67c7a4656ee6c18cc81ad7c1687b9dc585aa7028a3c3de9d317fc1f","impliedFormat":1},{"version":"f5a8e77e9aa7f7e3e68c1e51af9156ba1a228b85862fa8a23d62d72a0dea0134","impliedFormat":1},{"version":"8c3a97db11d1dda66ac53dff88a448ea1ab66929775a7ce7591347e58cbb3a0e","impliedFormat":1},{"version":"69d39897280332d00b4450abbcf3370a10d3511f5138cdd9d689889f0281cebf","impliedFormat":1},{"version":"afb17c84ebf0d44e467546f0a6717dfd25ee5e93c0217f5c589cc4211494a11c","impliedFormat":1},{"version":"eb7b00cee00e5a4a224dad756ed1234d90918bd65d8bb479d32922d807011abe","impliedFormat":1},{"version":"84e102a9693f84ebd2e2f861bacabae91ab30b386e9c6e648e1e0d7eb5b45a73","impliedFormat":1},{"version":"7f87674a2ef4473f7eb6563e1c0845ec9a9c0ad47328d957daadb815db6370e0","impliedFormat":1},{"version":"d69308b03417784cc4e1f53857c8e8a3356e50a1cb5b3c88b49666c30a57b115","impliedFormat":1},{"version":"34368020641c77512a1c7656b32f41baffdda276e88a24d08d2e5da88a33acc7","impliedFormat":1},{"version":"acd9c36dab9c452ec230b764e9240d42a3120215a0c33386e82b91a9e96ac7bd","impliedFormat":1},{"version":"bf347934d9a6f1de26dc9c7a74872a8b045beca76f8dcff4fb4d9e4f87e0d492","impliedFormat":1},{"version":"3d022d24649126647a0945e536b9ffa011513f5b149f55f5225831dc0fa28dde","impliedFormat":1},{"version":"257783c9297f89c8d3ab484cec51af8266990404a07276c51080bcda2bc13b01","impliedFormat":1},{"version":"b7a5bdb5aa75b03ecc92deaa72385c5a084c68f262d5ecb776a115ad7fe480f1","impliedFormat":1},{"version":"38c2fe561609becdac52f26415a922d50aca0d725cfc1c3a0c72427e4b17c048","impliedFormat":1},{"version":"b059f90563e79aa31286a84019f519ecca62db22e163fb529ef5475d5ea34e16","impliedFormat":1},{"version":"c8246db61ea766e75596dcfd22b8c5bf4d0dc10caff8b9b49ebe44839f1861d0","impliedFormat":1},{"version":"e9135ba65ba4f53d1ab7b7140ef1c89a1712c05389109acf886dd0086bbde820","impliedFormat":1},{"version":"41431a556e31f1e200ff4018978cdbd0b80837634b7970e9b7bd1cacc369b8f8","impliedFormat":1},{"version":"6548a33a3be2a07bd758a23598cdbe178716ddbba23c8322ac01baf9a55c9d3c","impliedFormat":1},{"version":"4f10117e2caf3f3e3e9ff8bd968041ad56254a2826d2ed084e2bd9056db9c4b5","impliedFormat":1},{"version":"76b7efafc80beaf49948c08aa9272ee79d6b2b0f154ac13398659fc160432328","impliedFormat":1},{"version":"80fe6c3f67f83b20cd2871d987f9907e481d8ff074ec711a8e916662ee5f0950","impliedFormat":1},{"version":"756bde5eb8bc63e94fc9f1e552b3e5972fd4b146cf4ed677e56196a3d0174b6d","impliedFormat":1},{"version":"fbcdb2ccec93060304b878e7f65246b6b2c992e896774e9eaf7744f58a9cd8a6","impliedFormat":1},{"version":"935094dc19b20214f20677d5b871aa34e0e3280e6c852dd57b6a118134a15764","impliedFormat":1},{"version":"ea99aa2e537966df22f8192e99929ee81719c1cf0b9d9d83d0c6fed53325ccc6","impliedFormat":1},{"version":"c12cadc4cee710868ee7a6e92777a8f05ad1b3474a8447b3ccc8f592d7f2c68c","impliedFormat":1},{"version":"d2ffef91eb8a2e0d01f4ba547acd72aefa7093257b8e1d6ecea797cce7c19489","impliedFormat":1},{"version":"6783cb8ca3727edc2c07ab456925cb5cc9242f5fed46a2c82505ae9146300ac7","impliedFormat":1},{"version":"72be668a833df00839fc3be968c1f38e0503e7c867de89f2128bcc2883d90aee","impliedFormat":1},{"version":"4fcdf36200c6bc25ac2fe037ded1f829f7a9ae745025dce2765ac7e7c30a8bef","impliedFormat":1},{"version":"c960d2aeabc5a7fd8e4b43e2f311a9f3e3f4693b7979262c23b46fc73df7304a","affectsGlobalScope":true,"impliedFormat":1},{"version":"9f86422d99b6ab08e7dc326d0a4379a800145a50a59459c013ffe5c6d6e3277d","impliedFormat":1},{"version":"71d5bf7694229b4572c479d31892c1e16339e9b5b63cdb6fa366db5ed5e93446","impliedFormat":1},{"version":"6c4e5a0233a7187e99b007577b4539dc07ac085823f99d9c5020fbfe145a3e5e","impliedFormat":1},{"version":"56b33300b318f41f87c4787a332fab43aa59bb20d38948717c10d18e78c4c5ec","impliedFormat":1},{"version":"eba5208b964d943d716108750130b95fe77375df1db1448f413259617ae8fae0","impliedFormat":1},{"version":"d8fa7e657586879f2d981152555e7cdace28d50731aeb03e7a0b73382a3b1634","impliedFormat":1},{"version":"50c84717d9f1283b49d19224bfe44dfacd09b3fb1e9281383025203593ae3272","impliedFormat":1},{"version":"dd6e162901d23df737eea709b079a91e0aed494c4c61dd56601133e746d8e0c2","impliedFormat":1},{"version":"eb388eb21f5992ebd8cfd86fff7023f90457b5ff2dbc21ee99832c5a92852cde","impliedFormat":1},{"version":"e720d7a4f3b292ca965c2cba746e59630e55f1ba968d9cd655d1e1f709661c84","impliedFormat":1},{"version":"88f4ae4809f1848574d58d009cf5aeba9b24a11dbdee6ec3e7c825831b050c98","impliedFormat":1},{"version":"a6e1c40dbc025de553c4bac9a43bbffa246d5d4ab6a40fc160763d5a00088497","impliedFormat":1},{"version":"47ce460e63cb9f8efb5b1f27fcbd25e4738961a741655660df4dbe9f62ed96cd","impliedFormat":1},{"version":"55818a1bda2b786f974d4ff6c421dcc136ee3da240a3405611bff8ca1870696e","impliedFormat":1},{"version":"170ec1ff7c84bd37c5dcc50a84faa81fd940234d3682929488259f1cd76744c5","impliedFormat":1},{"version":"e8b746d0926711ebdd39912d8898681851f4b5c579cec9a314ca85310110eff6","impliedFormat":1},{"version":"586d1c4452e4cebb997781d1c202bb10ae9b809eca2b1331afcd89cb70b6c136","impliedFormat":1},{"version":"407b17b27a8edf2ae2e00c11e397c51b8e3e5dd651453839f5e65563f9047c65","impliedFormat":1},{"version":"1508be69637d4a514f7cedc38a97236fe122ab204f5817501fe6b0a0346161b4","impliedFormat":1},{"version":"8ae9ac808ef254555b9b41a0bb676ff7f083da1809cf249dfd940c5c815211bf","impliedFormat":1},{"version":"809169acb3a791afda29e7eedc10c82473a5864acd264b406b6e1ff54bf06add","impliedFormat":1},{"version":"fa10b4fc8e6be9d674026049a83d5f6dadc5ae0ef65f2c1425a76c9c6f8d52b8","impliedFormat":1},{"version":"3fb17c109ccbbbb23b94635ea9895025f8c59e35e78547316ed4bf820d4d4226","impliedFormat":1},{"version":"2c4d0f383ea6f71e00baa32137b7838bf4c04308456da98028b95683f7fd87f6","impliedFormat":1},{"version":"54dd9e1d3d04853ef1390ad46f993ae340c799c2ae0f7921e67f176c44641590","impliedFormat":1},{"version":"2a9c19eb5aa8985aa98b49613a03015235a206853606f3db9c8c38ab3268c40f","impliedFormat":1},{"version":"2bcbf9dcbf2f58352a923d8d600f4616ea2efa946d22a3c2eb3a49e66315c6b3","impliedFormat":1},{"version":"1a195405484ebe575183cc2461386d12bbb18d1e3c35b0e3fd8b445f057c8507","impliedFormat":1},{"version":"c8a3a415d2202b031766c34f1564bc9e6bbf25ea657c178e403c85013bf8f925","impliedFormat":1},"db8a8db80ac0bf1755fbbc9cca5330c50a940480f9359a38672a7b2d63d62ee7",{"version":"a2999ed84296a880c3f8ad4adc1c8c07617007cc55a2b6ad362b142a6fed9af0","impliedFormat":99},{"version":"a9f672caa1c5631a744b05f69c28b4cfdbcb35e16112b2596ad88c90d1491e90","impliedFormat":1},{"version":"8d1722eddb71400b416698dc4a4faf61d38f3c5fb191412b487877c12f92f5ce","impliedFormat":1},{"version":"8d36f5b65e38d64c7370a80cdd26d2b0eea3b200c90b4b1fa5b594de262b5adf","impliedFormat":1},{"version":"2d5094424c7e06500d51088d6182e1324704010c54e4df440cf687da6d196ca1","impliedFormat":1},{"version":"69333b916a0a4329de4fed1191ec176b476bf419d5c56b3d66c2736ce1e6a4de","impliedFormat":1},{"version":"a955a5652fac7e3f6adc1ad7f4c22774e08251f06091779d48db944c32d54b9c","impliedFormat":1},{"version":"133fd0be181d7c21fceeccfa59efeaabf949502d37288326ffe6b0383fdc0b9e","impliedFormat":1},{"version":"15eee289dbd1369243ce767502b3d48bbdf50638249df90555c0f02f5b2107b6","impliedFormat":1},{"version":"633f7c4ebb6f3a3ab186b8ad44af6b7a41355b19e4125bd378899a50ba5991e7","impliedFormat":1},{"version":"2f460be609337ac6d2dd5969d5336f8512e75bd4ec6282336a5b5f3485853c21","impliedFormat":1},{"version":"8b3449c5b0bcc0f9b82cfd611179453444576ddc31ecfa0df32b94bba23c7962","impliedFormat":1},{"version":"28f13eae6f1c2e2c0b09b3a5899695881f586050cdc5e26ea70b84d53e245c53","impliedFormat":1},{"version":"eeb3eeaf375fc738138043ecc239471c0d4c1798e5426dadda6a370a6e430313","impliedFormat":1},{"version":"75eda22ec0b6351316f9af18f9d714ac2cb708d8ede0ddd6b33d8314dbfc9fc0","impliedFormat":1},{"version":"53ae98cb8a690dcb13ff08468cd532817ceec23301cd2fbd1638a4509c75fb5a","impliedFormat":1},{"version":"716285ba259e4094d45564aa66c45a673d55cb7fa38745b35b8e0ca5b76431e8","impliedFormat":1},{"version":"5d303981e2efe7b75e303b9ba0b149f7dc52b60a716a37366d15c0ee7e06d71c","impliedFormat":1},{"version":"66f11f0455e2ddcd1d861ccb6222c9287ccdf5a4f775288ba4e84588c9f6e7d4","impliedFormat":1},{"version":"566d39c79490d7d3c0edf99528a27ddbc190a43187de9c6903c539310dc32876","impliedFormat":1},{"version":"f6d629d05333c4f6097d2e8d43622930677cfaa0d04451c19d149da012fb024e","impliedFormat":1},{"version":"37ff372218ab7f5fe97a3ea0d889aa22a9cf856f49f3c071b285bb57f61126a4","impliedFormat":1},{"version":"0697562c198ad4887ee0c6ba87c81674415bf08622c38761a35ce284f79000a6","impliedFormat":1},{"version":"ec298fb58b43841e59e9cf74e5c4da1b28211549a111361d1b814b6cf9846ba3","impliedFormat":1},{"version":"f6af127f8f33c31698e4162dc44e27faa32213c8029b01a75ec8d337e8a29d98","impliedFormat":1},{"version":"f2d25ffb9fa1ea3b6c4461d749fffb2943d89365ae492b5da914082e373ef319","impliedFormat":1},{"version":"033ff83964da431641bb12966218670b067eb875f40b867a2f13eccbd22d2ad0","impliedFormat":1},{"version":"b29fca8647befa819e15522effef648208d240212705b5eea931107f252c2cd4","impliedFormat":1},{"version":"e2c0e97358d22f3139d4a26d93c7120014171ef31993440a8b3b69f4bb877fcc","impliedFormat":1},{"version":"90efedb2afa77beb63a1df83ab098109e796e08538e8157840c0b50e1da81a09","impliedFormat":1},{"version":"f72866fd4b0f2ea1c088065c4d6445095d5d8204b5d47bcb567865ba807d0a13","impliedFormat":1},{"version":"2292b8ede5c530d2c30f5a6ea14b455612b85eaf7c817da5bf79daa245068041","impliedFormat":1},{"version":"a6f12f14dbcb3fa60e7972637c7fd2ebee8ecaa320f88e4a6ea0233c77037d98","impliedFormat":1},{"version":"9514002fe1f72b3049408f9d6ca86e3cb961652f0e537d46f9b5452d577bb8cd","impliedFormat":1},{"version":"212bf5658e5e9a5c2339c6c4ed1a9b26048de14f21869e2df1bb7edcd730c54d","impliedFormat":1},{"version":"54de542e1f492d0b9df28493e771f7967c46d0285024f053ac6d81b8e24c05cb","impliedFormat":1},{"version":"a5b04b41838cd784ac841c351ae2c626a45a4d6b7981f805f41c0f332f632e0b","impliedFormat":1},{"version":"cb11accd47db05613ce31bcf360fe9357c25df8d50c3a7f0e953b7569ea4bee5","impliedFormat":1},{"version":"17810264cbbdc018764b9cbd0125892d47245d818d595ec94ddf23079bfeb732","impliedFormat":1},{"version":"04b32b104bf086362811496726a9a761a93ef1051e56107582433eeabb05216c","impliedFormat":1},{"version":"2d2c3ff10f8825d2a7120cb43addefb64111be064e35d270f662cde6ad1c8d5c","impliedFormat":1},{"version":"4752749fa062c4b02e46a60143a0e13ef404ad6ea3282d1aacc7016a17f66369","impliedFormat":1},{"version":"89aff3abdf4a99430d0e8e90c51ee4ca7c63aa5add8c159f922f7e7e7864ca55","impliedFormat":1},{"version":"ee1c930e3da09a2296ed5518b4ee1538e9788ac34b0a60ac33e0a0a2badd76e3","impliedFormat":1},{"version":"9349ef8829763a15785c41e115eb77440570effcaff9b9482c1e6178c8c6f368","impliedFormat":1},{"version":"14affb15c4923cd38b98dda994a6338109067c6f94615ba21db4b8c20c9b2c67","impliedFormat":1},{"version":"f5b3ebeb467837dd6593e4fe8f1de9b7598fb23981e02b32b7e72b81c04164da","impliedFormat":1},{"version":"68a75a201a5d1322df462c133020e5c639809c94a6698e3cc46363e56c174b30","impliedFormat":1},{"version":"265a4739974854eb43539419a6c86faab7e161b1133496c62f8bf2725542244d","impliedFormat":1},{"version":"a1accfaac01020c1b866634f7a698fdd48612caccf305e16844665cb7ecac399","impliedFormat":1},{"version":"ec00441ae4838b8d595acfe3b2750750e4335802b06ba1f41fb03453c2c776b5","impliedFormat":1},{"version":"ac1689d264991e5f58deb5a82ee44940f091a709b8ca815b38d5a7cb1305ce9f","impliedFormat":1},{"version":"8dca1366d02c160f39732f1a9ff2a882489903cd034e9c9c3f0ebfe9fa90f7ae","impliedFormat":1},{"version":"c548226db013facd262a4bc1c32c44a13eda7e1181aa6f569f9bdd531c95b0d5","impliedFormat":1},{"version":"37db669ef9a2ff2244d8e13aa8df9237fe3135c24facf0d62e7751fd49832386","impliedFormat":1},{"version":"543f461070fbd4b33bd05a5ba3e472e1297bb1db3c3101092bd69bfdddd3b1a1","impliedFormat":1},{"version":"929540ba3980906ac3f38e8567233028233c1c7e4d8921c1ce19604357028600","impliedFormat":1},{"version":"de5512f2a4c42776474808db1a6a8f12374be84392eeb649ad306330df41d0b3","impliedFormat":1},{"version":"7e96277aa5d7be6cddfdb78db26d986e00308e63f0202fb0d9fa39c826597dd4","impliedFormat":1},{"version":"3745762b83e5d49983a4183821125e3417473f992c4bf1d6dd6cea91efb4166f","impliedFormat":1},{"version":"ade458e350eda79fa74ecb678d9c51cc17f592d56df3e47286ef28e71401a989","impliedFormat":1},{"version":"695d23d7fb1f989d4d385001d8d8029f2f1a65dd91b4e47078e2586b8cdc4999","impliedFormat":1},{"version":"d73236e868cf6537240359fc4bea5733728567444ec7d2768e78ccc06ef22088","impliedFormat":1},{"version":"279c2ed4f57d90587de8e8dbadcb58b2ce2a0f6f7466ca07de24ad2cd50b6d12","impliedFormat":1},{"version":"02a711dc0da3eb73b8fae269ea1603cceaf395a7288429fdd724986974fa0ffa","impliedFormat":1},{"version":"cec41f4ba1a759fd9913cf418f17fe6a9dd6379cffd6923bb7f7f5efdcab4dda","impliedFormat":1},{"version":"caebb18abe3f02c23f8a16a2ee40ca5e26ac77f952cb15c660ff653cbad52144","impliedFormat":1},{"version":"49bddd70b375e6ba2b0f6e8dca81608dff0e9496dc28a87b79a622b8d1d4b41f","impliedFormat":1},{"version":"fd6d1d663e9ffe474e0b340ca3960c5b1acd4a72c464a0eacfd035c4d178e10d","impliedFormat":1},{"version":"4359e8ba73374bb7d25c0d4181c4e9f9fd6174569897788596feac600ec69639","impliedFormat":1},{"version":"2b31eaeb5ecf87fb46dc532da7b187a6711eb13bd58791d0470eb8ff16281991","impliedFormat":1},{"version":"d4fe178cd599f1de33b0a18107fbaca86f23d0cee832a8b69aa76b8e991d2a94","impliedFormat":1},{"version":"888a96c2375741d846bf0cd44b233143ceca7be646780fd27c6dcb85f1f632e6","impliedFormat":1},{"version":"b21366779c846ce32d31e2af08d40f9a37961e4dfb7a20c16c37fe752047db5d","impliedFormat":1},{"version":"4130c2c57580e214060025c2df1460313ba070d3d6906c957755f10fc3b23ae0","impliedFormat":1},{"version":"5c56d077a2581c84910c8f9f0fad30ae45b2ca0a8cd78c7cf49ef6fe969bb809","impliedFormat":1},{"version":"0d81a9fdbcbe694d70175a1848a8be1c9281810a19d9c61ae197364149e4a8c0","impliedFormat":1},{"version":"2aede4f826e1717895a9b9b72afa7ace796267a37c2b36ce320366c84e3c540d","impliedFormat":1},{"version":"16f8e713001d58b9ee1bdcc52b43215c42ccd15da02fb639c32b942449244957","impliedFormat":1},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"a9f672caa1c5631a744b05f69c28b4cfdbcb35e16112b2596ad88c90d1491e90","impliedFormat":1},{"version":"64cd53feac77ca70c7ac520a67e8bd0331c64bb0faca28aa572d826f00527f98","impliedFormat":99},{"version":"ffdb36fdaa921ab5d6dd94414eb1a8bfcd71472aecd2476bce3c40a082ccaa2c","impliedFormat":99},{"version":"fe8e12d5151d3c526e5fd493757c9d3534c9b42338e7b4ac62a45c088b9a2e64","impliedFormat":99},{"version":"66181539572954871da89df777217a2feb17640a32c993fd25f9a004ff4bd1b2","impliedFormat":1},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"8e20b585eed1b1afb844f5d1f32e726b1ef00a829ac408ca118b7bfbadd2dea9","impliedFormat":99},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"aa5524e0509c2168c9493604acf51ef97d2027f03f3b38da097802d3aa719dc8","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"c5213e770282e93d685de14181bee1486b556a1a90c7697529a86af375f4608d","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"299fd0c281633d8dbfbe5f44c5f2850fe37392da6fd3b9cca3cb4e10cda16432","impliedFormat":1},{"version":"fcd49e75e303b11506c91b618b5f50aa2d027e0c4219a016a4406a2fd6f6ea61","impliedFormat":99},{"version":"bdd94485f193af1db099a949bf16f5b06f87ed2fdfeeb8081ff75b16d74c182e","impliedFormat":99},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"8e20b585eed1b1afb844f5d1f32e726b1ef00a829ac408ca118b7bfbadd2dea9","impliedFormat":99},{"version":"3aa236d922d6447e405f662a789dfe99052a33e971eeda03c34982d636ae119a","impliedFormat":99},{"version":"367546a9101d0516f076a316b42788d4100c4b11ba8ab524e43da449ce427f1a","impliedFormat":99},{"version":"f86e6fa947feda6a87db6dac122d7308b6060687adfec373e7a4f62249a42cf9","impliedFormat":1},{"version":"d2fd65eea869f39cbdcc782ecd32932e1b327eba90d5bba4c0d0742e1f362bbf","impliedFormat":99},{"version":"bc640c39437752657c123ec9810ac440d3d3e5bf707a53e55218f56120f7db2f","impliedFormat":99},{"version":"0c3e4081cbc9e82cba7ab88e234b1ba5766d7c59b38ab58622c3074054f58d99","impliedFormat":99},"f95b4c278328c255595681e4951204d6d75b051f60e8ed3bedc601ba929982f3","b1c4622f956645f6e836efa317cd0379bbd07429a8da1dd529d945e8dc1a599b",{"version":"11d595534bb5c5fae143ecd2f3bedb789258ea7664ba13835dd147578d32b2af","signature":"4027f95da96ee828242662df11ef7a436ca3bb5c7f49595e0956e684b590d590"},{"version":"67ba10250abe2f1e2f6183d8a4a3c453037828101de29a6d8bc2e671587d3548","signature":"91a01d034eb89ea508e0bec53cbac02d31b4405b97334903b19dfd8bb9d4043f"},{"version":"e7484cdbe939bad92be2c3c1ec2f81f26a801814ce47e8c9eb96acca330abf54","signature":"2c9b6b6c7586e02554672d116a92987b4933d7660915a1d48b0b04ae9f0f0627"},{"version":"04600d4511481d8ea7293fb98d238c04e34dced959ffacb4f0c6147135ef7f7d","affectsGlobalScope":true,"impliedFormat":1},{"version":"ee31fab138939ef1903831933d524de9944511759778eedaaed56d6eb7f8697d","impliedFormat":1},{"version":"e45cc72cc9e7ad726ec83141fa4cd221d432062de34586ff107a0442ae28bf19","impliedFormat":1},{"version":"1d382840d8c30edfdf6c70bec101d72dbfdc629f409c0c4d9b32a79bf9bebae2","impliedFormat":1},{"version":"3083591fd0a77addd337b02f9fcf0d4f009e41c79fa42f862d6fcf76f3fceb48","impliedFormat":1},{"version":"34810cb47e6bee7cd4bad2f174793f5926ba5889c5d180e29b02c1871a820476","affectsGlobalScope":true,"impliedFormat":1},{"version":"7115f1157a00937d712e042a011eb85e9d80b13eff78bac5f210ee852f96879d","impliedFormat":1},{"version":"0ac74c7586880e26b6a599c710b59284a284e084a2bbc82cd40fb3fbfdea71ae","affectsGlobalScope":true,"impliedFormat":1},{"version":"2ce12357dadbb8efc4e4ec4dab709c8071bf992722fc9adfea2fe0bd5b50923f","impliedFormat":1},{"version":"d021d871089c519030a098fa3d32f5d95059b699b0fc6c45c85a96f92cae233c","impliedFormat":1},{"version":"c074a8cbfeb4d94915c4023dbe1eadf1215372efd3babbf982f1fed96ff8a695","impliedFormat":1},{"version":"b05b9ef20d18697e468c3ae9cecfff3f47e8976f9522d067047e3f236db06a41","affectsGlobalScope":true,"impliedFormat":1},{"version":"eec5e9a5629f6740aac21e49783a373a3767770ad559cd41285ebbb0db39a4a2","affectsGlobalScope":true,"impliedFormat":1},{"version":"1745f0b1ab53f414b4f8ebb2c6a902fda28d40f454edac8e92b4d7c974a2051c","affectsGlobalScope":true,"impliedFormat":1},{"version":"403f9ee3b18e550bccb23b0ef67ba61e4990a902f67db1afae1ad23602fef9d1","impliedFormat":1},{"version":"1a7a729938558fe198d979d3f53dece9c9112124b7b081a7fa0adcc98bf15fd8","impliedFormat":1},{"version":"067f76ab5254b1bdfc94154730b7a30c12e3aad8b9d04ec62c0d6b7a1f40ea0e","affectsGlobalScope":true,"impliedFormat":1},{"version":"f67f24b0d972d7d0f52a4e2f4f8ffd5cd786cb411044693026731918df935371","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be812b06e518320ba82e2aff3ac2ca37370a9df917db708f081b9043fa3315","impliedFormat":1},{"version":"78ef0198c323d0f7b16f993ada3459f0e7e20567e7f56fe0c5ee78f31cb0840c","impliedFormat":1},{"version":"01dea450d742aa55ce9b8ab8877bbda8eb73bf88609e440cc34f6f59f35080db","impliedFormat":1},{"version":"a41a7c353549f78bd9f04526dbc50133c43f348360555f4d0e60d3bf77f17b46","affectsGlobalScope":true,"impliedFormat":1},{"version":"b788ef070e70003842cbd03c3e04f87d46b67a47b71e9e7d8713fd8c58c5f5ec","impliedFormat":1},{"version":"583d365dc19f813f1e2767771e844c7c4ea9ab1a01e85e0119f2e083488379c2","impliedFormat":1},{"version":"b82fc3869c625b828dd3feac4b5ebf335ed007d586dc16176602db73bc4e7c65","impliedFormat":1},{"version":"05e30605274c26f405c411eebed776fa2102418c05beec885e5c9bd0fa716f32","impliedFormat":1},{"version":"58c7f7820dc027a539b0437be7e1f8bdf663f91fbc9e861d80bb9368a38d4a94","impliedFormat":1},{"version":"d67d6b779d0dece9450d7a4170d3ee58ea7fcae0af2ab5e1d0ad711474b4f7f5","impliedFormat":1},{"version":"1066c11177d085898185548e1b38ed15fcea50061508f7c313ab8bec35d46b95","impliedFormat":1},{"version":"bbc49fd9dc6ee162ba3d270c834398e0c1d44e657ac4edfa55ac837902b7e0da","impliedFormat":1},{"version":"6993f360de4984b6743764fad3b88246d5dc6cfa45567783fc23833ad4e50c13","impliedFormat":1},{"version":"f11eb1fb4e569b293a7cae9e7cdae57e13efc12b0e4510e927868c93ec055e82","impliedFormat":1},{"version":"715682cddbefe50e27e5e7896acf4af0ffc48f9e18f64b0a0c2f8041e3ea869b","impliedFormat":1},{"version":"6d2f5a67bfe2034aa77b38f10977a57e762fd64e53c14372bcc5f1d3175ca322","impliedFormat":1},{"version":"4ff4add7b8cf26df217f2c883292778205847aefb0fd2aee64f5a229d0ffd399","impliedFormat":1},{"version":"33859aa36b264dd91bef77c279a5a0d259c6b63684d0c6ad538e515c69a489ec","impliedFormat":1},{"version":"33fa69f400b34c83e541dd5f4474f1c6fb2788614a1790c6c7b346b5c7eaa7dd","impliedFormat":1},{"version":"be213d7cbc3e5982b22df412cf223c2ac9d841c75014eae4c263761cd9d5e4c0","impliedFormat":1},{"version":"66451f9540fdf68a5fd93898257ccd7428cf7e49029f2e71b8ce70c8d927b87a","impliedFormat":1},{"version":"8a051690018330af516fd9ea42b460d603f0839f44d3946ebb4b551fe3bc7703","impliedFormat":1},{"version":"301fb04ef91ae1340bec1ebc3acdd223861c887a4a1127303d8eef7638b2d893","impliedFormat":1},{"version":"06236dfec90a14b0c3db8249831069ea3f90b004d73d496a559a4466e5a344a4","impliedFormat":1},{"version":"fc26991e51514bfc82e0f20c25132268b1d41e8928552dbaed7cc6f3d08fc3ac","impliedFormat":1},{"version":"5d82bb58dec5014c02aaeb3da465d34f4b7d5c724afea07559e3dfca6d8da5bc","impliedFormat":1},{"version":"44448f58f4d731dc28a02b5987ab6f20b9f77ad407dcf57b68c853fe52195cd7","impliedFormat":1},{"version":"b2818e8d05d6e6ad0f1899abf90a70309240a15153ea4b8d5e0c151e117b7338","impliedFormat":1},{"version":"1c708c15bb96473ce8ec2a946bd024ecded341169a0b84846931f979172244ba","impliedFormat":1},{"version":"ed0f5e1f45dc7c3f40356e0a855e8594aa57c125a5d8dfeef118e0a3024f98ff","impliedFormat":1},{"version":"dc187f457333356ddc1ab8ec7833cd836f85e0bbcade61290dc55116244867cb","impliedFormat":1},{"version":"25525e173de74143042e824eaa786fa18c6b19e9dafb64da71a5faacc5bd2a5c","impliedFormat":1},{"version":"7a3d649f2de01db4b316cf4a0ce5d96832ee83641f1dc84d3e9981accf29c3a1","impliedFormat":1},{"version":"26e4260ee185d4af23484d8c11ef422807fb8f51d33aa68d83fab72eb568f228","impliedFormat":1},{"version":"c4d52d78e3fb4f66735d81663e351cf56037270ed7d00a9b787e35c1fc7183ce","impliedFormat":1},{"version":"864a5505d0e9db2e1837dce8d8aae8b7eeaa5450754d8a1967bf2843124cc262","impliedFormat":1},{"version":"2d045f00292ac7a14ead30d1f83269f1f0ad3e75d1f8e5a245ab87159523cf98","impliedFormat":1},{"version":"54bcb32ab0c7c72b61becd622499a0ae1c309af381801a30878667e21cba85bb","impliedFormat":1},{"version":"20666518864143f162a9a43249db66ca1d142e445e2d363d5650a524a399b992","impliedFormat":1},{"version":"28439c9ebd31185ae3353dd8524115eaf595375cd94ca157eefcf1280920436a","impliedFormat":1},{"version":"84344d56f84577d4ac1d0d59749bb2fde14c0fb460d0bfb04e57c023748c48a6","impliedFormat":1},{"version":"89bcaf21b0531640604ca9e0796f54a6e1b4e2d43c07422ffa1e3d2e1bb0e456","impliedFormat":1},{"version":"66738976a7aa2d5fb2770a1b689f8bc643af958f836b7bc08e412d4092de3ab9","impliedFormat":1},{"version":"35a0eac48984d20f6da39947cf81cd71e0818feefc03dcb28b4ac7b87a636cfd","impliedFormat":1},{"version":"f6c226d8222108b3485eb0745e8b0ee48b0b901952660db20e983741e8852654","impliedFormat":1},{"version":"93c3b758c4dc64ea499c9416b1ed0e69725133644b299b86c5435e375d823c75","impliedFormat":1},{"version":"4e85f443714cff4858fdaffed31052492fdd03ff7883b22ed938fc0e34b48093","impliedFormat":1},{"version":"0146912d3cad82e53f779a0b7663f181824bba60e32715adb0e9bd02c560b8c6","impliedFormat":1},{"version":"70754650d1eba1fc96a4ed9bbbc8458b341b41063fe79f8fa828db7059696712","impliedFormat":1},{"version":"220783c7ca903c6ce296b210fae5d7e5c5cc1942c5a469b23d537f0fbd37eb18","impliedFormat":1},{"version":"0974c67cf3e2d539d0046c84a5e816e235b81c8516b242ece2ed1bdbb5dbd3d6","impliedFormat":1},{"version":"b4186237e7787a397b6c5ae64e155e70ac2a43fdd13ff24dfb6c1e3d2f930570","impliedFormat":1},{"version":"2647784fffa95a08af418c179b7b75cf1d20c3d32ed71418f0a13259bf505c54","impliedFormat":1},{"version":"0480102d1a385b96c05316b10de45c3958512bb9e834dbecbbde9cc9c0b22db3","impliedFormat":1},{"version":"eea44cfed69c9b38cc6366bd149a5cfa186776ca2a9fb87a3746e33b7e4f5e74","impliedFormat":1},{"version":"7f375e5ef1deb2c2357cba319b51a8872063d093cab750675ac2eb1cef77bee9","impliedFormat":1},{"version":"b7f06aec971823244f909996a30ef2bbeae69a31c40b0b208d0dfd86a8c16d4f","impliedFormat":1},{"version":"0421510c9570dfae34b3911e1691f606811818df00354df7abd028cee454979f","impliedFormat":1},{"version":"1517236728263863a79500653cc15ceb286f048907b3dba3141a482ca6946bd7","impliedFormat":1},{"version":"7c7b418e467a88a714b4c6dac321923b933f82875f063f48abf952021a2c2df1","impliedFormat":1},{"version":"33120063a7e106818ce109be9238569edca74d4e8530f853bd30d298d1375fd8","impliedFormat":1},{"version":"104c67f0da1bdf0d94865419247e20eded83ce7f9911a1aa75fc675c077ca66e","impliedFormat":1},{"version":"cc0d0b339f31ce0ab3b7a5b714d8e578ce698f1e13d7f8c60bfb766baeb1d35c","impliedFormat":1},{"version":"2174e20517788d2a1379fc0aaacd87899a70f9e0197b4295edabfe75c4db03d8","impliedFormat":1},{"version":"25be1eb939c9c63242c7a45446edb20c40541da967f43f1aa6a00ed53c0552db","impliedFormat":1},{"version":"d3f2d715f57df3f04bf7b16dde01dec10366f64fce44503c92b8f78f614c1769","impliedFormat":1},{"version":"b78cd10245a90e27e62d0558564f5d9a16576294eee724a59ae21b91f9269e4a","impliedFormat":1},{"version":"936eb43a381712a8ec1249f2afc819f6fc7ca68f10dfec71762b428dfdc53bf1","impliedFormat":1},{"version":"2f5747b1508ccf83fad0c251ba1e5da2f5a30b78b09ffa1cfaf633045160afed","impliedFormat":1},{"version":"a45c25e77c911c1f2a04cade78f6f42b4d7d896a3882d4e226efd3a3fcd5f2c4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b71c603a539078a5e3a039b20f2b0a0d1708967530cf97dec8850a9ca45baa2b","impliedFormat":1},{"version":"0e13570a7e86c6d83dd92e81758a930f63747483e2cd34ef36fcdb47d1f9726a","impliedFormat":1},{"version":"5c45abf1e13e4463eacfd5dedda06855da8748a6a6cb3334f582b52e219acc04","impliedFormat":1},{"version":"63786b6f821dee19eb898afb385bd58f1846e6cba593a35edcf9631ace09ba25","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"e91ad231af87f864b3f07cd0e39b1cf6c133988156f087c1c3ccb0a5491c9115","impliedFormat":1},{"version":"03c258e060b7da220973f84b89615e4e9850e9b5d30b3a8e4840b3e3268ae8eb","impliedFormat":1},{"version":"319c37263037e8d9481a3dc7eadf6afa6a5f5c002189ebe28776ac1a62a38e15","impliedFormat":1},{"version":"4006c872e38a2c4e09c593bc0cdd32b7b4f5c4843910bea0def631c483fff6c5","impliedFormat":1},{"version":"ab6aa3a65d473871ee093e3b7b71ed0f9c69e07d1d4295f45c9efd91a771241d","impliedFormat":1},{"version":"22c313d18dc83e37a592cebb6e9366370dbcc6872b65f1c49b5cfc5fb84e6565","impliedFormat":1},{"version":"85a55229c4d0f20d42c59cec768df0cb83a492f8bb1351ead8524a58f278a005","impliedFormat":1},{"version":"7d2b7fe4adb76d8253f20e4dbdce044f1cdfab4902ec33c3604585f553883f7d","impliedFormat":1},{"version":"1ba59c8bbeed2cb75b239bb12041582fa3e8ef32f8d0bd0ec802e38442d3f317","impliedFormat":1}],"root":[[538,542],[1163,1165]],"options":{"allowJs":true,"composite":true,"declaration":true,"declarationMap":true,"downlevelIteration":true,"esModuleInterop":true,"module":99,"noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitReturns":true,"noImplicitThis":true,"noUncheckedIndexedAccess":true,"noUnusedLocals":false,"noUnusedParameters":false,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"sourceMap":true,"strict":true,"strictNullChecks":true,"target":99,"useUnknownInCatchVariables":true,"verbatimModuleSyntax":true},"referencedMap":[[977,1],[976,2],[973,3],[912,4],[915,5],[916,5],[917,5],[918,5],[919,5],[920,5],[921,5],[922,5],[923,5],[924,5],[925,5],[926,5],[927,5],[928,5],[929,5],[930,5],[931,5],[932,5],[933,5],[934,5],[935,5],[936,5],[937,5],[938,5],[939,5],[940,5],[941,5],[942,5],[943,5],[944,5],[945,5],[946,5],[947,5],[948,5],[949,5],[950,5],[951,5],[952,5],[953,5],[954,5],[955,5],[956,5],[957,5],[958,5],[959,5],[960,5],[961,5],[962,5],[963,5],[964,5],[965,5],[966,5],[967,5],[968,5],[969,5],[970,5],[971,5],[978,6],[972,7],[974,8],[994,9],[913,10],[993,11],[914,12],[979,13],[980,14],[981,15],[982,16],[983,17],[984,18],[985,19],[986,20],[975,21],[992,22],[990,23],[991,23],[911,24],[719,25],[718,26],[734,27],[735,28],[883,26],[886,29],[884,30],[885,30],[889,31],[888,32],[890,33],[904,34],[887,35],[903,36],[905,37],[906,26],[910,38],[907,26],[908,7],[909,7],[737,26],[738,39],[739,40],[1018,41],[1015,42],[1016,43],[1017,44],[1003,44],[1004,44],[1005,44],[1006,44],[1007,44],[1008,44],[1009,44],[1010,44],[1011,44],[1012,44],[1013,44],[1014,44],[1019,45],[1002,46],[1024,47],[1020,48],[1021,49],[1022,50],[1023,51],[736,33],[741,52],[742,53],[740,54],[743,7],[744,7],[786,55],[785,56],[745,7],[746,7],[747,7],[748,7],[749,7],[750,7],[751,7],[760,57],[761,7],[762,26],[763,7],[764,7],[765,7],[766,7],[754,26],[767,26],[768,7],[753,58],[755,59],[752,7],[756,58],[757,7],[758,60],[784,61],[769,7],[770,59],[771,7],[772,7],[773,26],[774,7],[775,7],[776,7],[777,7],[778,7],[779,7],[780,62],[781,7],[782,7],[759,7],[783,7],[996,63],[998,64],[1000,65],[1001,66],[997,67],[995,26],[999,67],[1109,68],[1100,26],[1101,69],[1027,26],[1030,70],[1075,71],[1074,72],[1076,73],[1077,74],[1078,75],[1079,71],[1080,75],[1081,71],[1073,76],[1082,73],[1083,77],[1084,78],[1085,71],[1087,79],[1088,80],[1089,81],[1086,82],[1090,83],[1091,84],[1092,85],[1072,86],[1093,87],[1094,88],[1095,89],[1071,90],[1097,91],[1041,92],[1037,83],[1098,93],[1033,94],[1099,95],[1036,96],[1038,97],[1070,98],[1096,99],[1042,100],[1043,83],[1034,26],[1031,83],[1044,101],[1045,102],[1039,103],[1035,102],[1046,102],[1068,104],[1032,103],[1069,103],[1040,105],[1029,26],[1047,106],[1048,107],[1049,105],[1051,108],[1052,105],[1053,85],[1054,109],[1055,110],[1067,111],[1057,112],[1058,105],[1059,113],[1060,105],[1050,113],[1061,105],[1062,105],[1063,85],[1064,114],[1065,105],[1066,105],[1056,115],[1102,113],[1103,116],[1028,26],[1104,85],[1105,117],[1110,26],[1107,118],[1106,26],[1152,119],[1112,26],[1111,117],[1108,26],[1156,120],[1154,26],[1153,117],[164,121],[123,122],[162,123],[122,26],[163,124],[121,26],[124,123],[1155,26],[1026,125],[1159,26],[131,26],[176,26],[177,26],[178,26],[179,26],[180,26],[181,26],[182,26],[183,26],[184,26],[185,26],[787,33],[788,33],[791,126],[790,127],[789,7],[801,128],[792,33],[794,129],[793,7],[796,130],[795,26],[797,131],[798,131],[799,132],[800,133],[850,134],[851,26],[854,135],[852,136],[853,26],[804,137],[806,138],[805,7],[807,137],[808,137],[809,139],[802,7],[803,26],[820,140],[819,141],[821,35],[822,26],[826,142],[823,7],[824,7],[825,143],[818,7],[732,144],[720,7],[730,145],[731,7],[733,146],[832,7],[833,147],[830,148],[831,149],[829,150],[827,7],[828,7],[836,151],[834,26],[835,7],[721,26],[722,26],[723,26],[724,26],[729,152],[725,7],[726,7],[727,153],[728,7],[892,154],[891,7],[893,26],[899,7],[894,7],[895,7],[896,7],[900,7],[902,155],[897,7],[898,7],[901,7],[873,7],[837,7],[855,156],[856,157],[857,26],[858,158],[859,26],[860,26],[861,26],[862,26],[863,7],[864,156],[865,7],[867,159],[868,160],[866,7],[869,26],[870,26],[882,161],[871,26],[872,26],[874,26],[875,26],[876,26],[877,156],[878,26],[879,26],[880,26],[881,26],[654,162],[655,163],[657,26],[670,164],[671,165],[668,166],[669,167],[656,26],[672,168],[675,169],[677,170],[678,171],[660,172],[679,26],[683,173],[681,174],[682,26],[676,26],[685,175],[661,176],[687,177],[688,178],[690,179],[689,180],[691,181],[686,182],[684,183],[692,184],[693,185],[697,186],[698,187],[696,188],[674,189],[662,26],[665,190],[699,191],[700,192],[701,192],[658,26],[703,193],[702,192],[717,194],[663,26],[667,195],[704,196],[705,26],[659,26],[695,197],[706,198],[694,199],[707,200],[708,201],[709,169],[710,169],[711,202],[680,26],[713,203],[714,204],[673,26],[715,205],[712,26],[664,206],[666,183],[716,162],[811,207],[813,208],[814,209],[812,7],[815,26],[816,26],[817,210],[810,26],[838,26],[840,7],[839,211],[841,212],[842,213],[843,211],[844,211],[845,214],[849,215],[846,216],[847,217],[848,26],[988,218],[989,219],[987,7],[1185,26],[1186,26],[1187,214],[1244,220],[1188,221],[1233,222],[1190,223],[1189,224],[1191,221],[1192,221],[1194,225],[1193,221],[1195,226],[1196,226],[1197,221],[1199,227],[1200,221],[1201,227],[1202,221],[1204,221],[1205,221],[1206,221],[1207,228],[1203,221],[1208,26],[1209,229],[1210,229],[1211,229],[1212,229],[1213,229],[1222,230],[1214,229],[1215,229],[1216,229],[1217,229],[1219,229],[1218,229],[1220,229],[1221,229],[1223,221],[1224,221],[1198,221],[1225,227],[1227,231],[1226,221],[1228,221],[1229,221],[1230,232],[1232,221],[1231,221],[1234,221],[1236,221],[1237,233],[1235,221],[1238,221],[1239,221],[1240,221],[1241,221],[1242,221],[1243,221],[1246,234],[1247,26],[1245,235],[1248,235],[1253,236],[1256,237],[1254,26],[1257,238],[1258,26],[1249,26],[597,239],[598,239],[599,240],[558,241],[600,242],[601,243],[602,244],[553,26],[556,245],[554,26],[555,26],[603,246],[604,247],[605,248],[606,249],[607,250],[608,251],[609,251],[611,252],[610,253],[612,254],[613,255],[614,256],[596,257],[557,26],[615,258],[616,259],[617,260],[649,261],[618,262],[619,263],[620,264],[621,265],[622,266],[623,267],[624,268],[625,269],[626,270],[627,271],[628,271],[629,272],[630,26],[631,273],[633,274],[632,275],[634,276],[635,277],[636,278],[637,279],[638,280],[639,281],[640,282],[641,283],[642,284],[643,285],[644,286],[645,287],[646,288],[647,289],[648,290],[1251,26],[1252,26],[1261,291],[1259,292],[1250,293],[1255,294],[1262,26],[1263,26],[1264,26],[1265,295],[1260,26],[1266,26],[1267,296],[1151,26],[87,297],[88,298],[107,299],[102,300],[103,301],[104,302],[105,300],[106,300],[95,303],[94,304],[92,305],[93,306],[98,307],[99,308],[100,308],[101,308],[91,309],[97,310],[96,311],[89,26],[85,26],[86,26],[90,312],[1157,117],[1160,313],[1158,314],[138,315],[140,316],[142,317],[150,318],[152,319],[133,320],[136,321],[143,322],[153,323],[116,324],[154,325],[145,326],[156,327],[119,325],[157,328],[159,329],[147,330],[118,331],[160,332],[165,333],[161,334],[112,335],[167,336],[168,337],[170,338],[108,26],[173,339],[148,340],[113,325],[172,341],[111,342],[174,343],[158,344],[175,322],[187,345],[125,346],[188,332],[198,347],[115,334],[144,348],[199,349],[217,350],[196,351],[202,352],[203,353],[120,334],[204,354],[205,26],[191,355],[146,356],[206,322],[208,357],[209,357],[210,358],[211,359],[207,360],[192,361],[193,362],[212,363],[213,364],[214,343],[127,365],[215,366],[117,367],[139,368],[141,368],[149,369],[151,368],[137,370],[135,371],[155,325],[109,344],[134,344],[169,372],[171,373],[110,367],[166,26],[186,374],[200,343],[190,375],[197,376],[194,377],[195,378],[201,379],[114,26],[126,380],[216,381],[189,26],[82,26],[83,26],[15,26],[13,26],[14,26],[19,26],[18,26],[2,26],[20,26],[21,26],[22,26],[23,26],[24,26],[25,26],[26,26],[27,26],[3,26],[28,26],[29,26],[4,26],[30,26],[34,26],[31,26],[32,26],[33,26],[35,26],[36,26],[37,26],[5,26],[38,26],[39,26],[40,26],[41,26],[6,26],[45,26],[42,26],[43,26],[44,26],[46,26],[7,26],[47,26],[52,26],[53,26],[48,26],[49,26],[50,26],[51,26],[8,26],[57,26],[54,26],[55,26],[56,26],[58,26],[9,26],[59,26],[60,26],[61,26],[63,26],[62,26],[64,26],[65,26],[10,26],[66,26],[67,26],[68,26],[11,26],[69,26],[70,26],[71,26],[72,26],[73,26],[1,26],[74,26],[75,26],[12,26],[79,26],[77,26],[81,26],[84,26],[76,26],[80,26],[78,26],[17,26],[16,26],[574,382],[584,383],[573,382],[594,384],[565,385],[564,386],[593,387],[587,388],[592,389],[567,390],[581,391],[566,392],[590,393],[562,394],[561,387],[591,395],[563,396],[568,397],[569,26],[572,397],[559,26],[595,398],[585,399],[576,400],[577,401],[579,402],[575,403],[578,404],[588,387],[570,405],[571,406],[580,407],[560,214],[583,399],[582,397],[586,26],[589,408],[1150,409],[1128,410],[1138,411],[1127,410],[1148,412],[1119,413],[1118,386],[1147,387],[1141,414],[1146,415],[1121,416],[1135,417],[1120,418],[1144,419],[1116,420],[1115,387],[1145,421],[1117,422],[1122,423],[1123,26],[1126,423],[1113,26],[1149,424],[1139,425],[1130,426],[1131,427],[1133,428],[1129,429],[1132,430],[1142,387],[1124,431],[1125,432],[1134,433],[1114,214],[1137,434],[1136,423],[1140,26],[1143,435],[436,436],[230,437],[232,438],[231,439],[544,440],[545,441],[549,442],[552,443],[550,444],[548,445],[546,446],[437,447],[129,448],[551,449],[547,450],[285,441],[424,451],[426,452],[286,453],[429,454],[543,374],[342,455],[348,456],[349,457],[350,457],[347,458],[438,459],[332,460],[351,461],[353,462],[357,463],[358,464],[359,462],[360,465],[308,466],[298,467],[307,468],[361,469],[362,470],[302,471],[364,472],[365,473],[293,474],[366,475],[370,476],[372,477],[374,478],[375,479],[376,480],[306,470],[369,481],[378,482],[379,475],[380,483],[382,484],[303,485],[383,486],[385,487],[341,488],[387,489],[388,490],[390,491],[391,462],[393,492],[394,493],[398,494],[404,495],[403,496],[406,497],[407,498],[408,498],[409,499],[411,500],[465,501],[439,501],[440,502],[441,503],[442,502],[443,504],[444,502],[445,504],[446,501],[447,502],[467,502],[448,502],[449,505],[450,506],[468,502],[451,504],[452,502],[453,502],[454,507],[455,504],[456,502],[469,502],[457,502],[458,502],[459,502],[460,504],[470,502],[461,507],[466,502],[462,504],[413,508],[414,509],[415,510],[416,511],[417,512],[418,513],[419,514],[305,515],[420,516],[421,517],[422,518],[294,519],[295,520],[423,521],[425,522],[427,523],[428,524],[430,525],[431,508],[432,526],[433,513],[389,527],[435,528],[476,529],[464,530],[477,531],[412,532],[463,533],[434,534],[245,535],[471,536],[400,537],[475,538],[479,539],[480,26],[481,26],[485,26],[482,26],[484,26],[486,26],[483,26],[310,540],[287,541],[277,541],[233,26],[274,542],[299,542],[333,540],[278,543],[322,544],[259,541],[251,541],[371,545],[253,542],[344,541],[265,546],[246,541],[354,541],[279,541],[234,541],[235,547],[330,548],[266,549],[472,541],[488,545],[487,541],[128,550],[240,551],[537,552],[132,553],[219,554],[227,555],[386,556],[243,557],[309,558],[223,559],[244,560],[220,561],[343,26],[221,562],[352,563],[222,564],[224,565],[218,562],[384,566],[228,567],[242,568],[229,569],[247,554],[225,570],[401,571],[395,572],[130,26],[226,561],[319,573],[489,574],[321,575],[367,576],[490,577],[324,578],[325,579],[326,580],[491,581],[356,582],[327,583],[493,584],[521,585],[320,586],[323,587],[494,588],[492,589],[317,590],[496,591],[281,592],[508,593],[263,594],[264,595],[268,596],[269,597],[270,597],[272,598],[273,599],[516,600],[515,601],[276,602],[275,603],[239,604],[334,605],[288,606],[519,607],[520,608],[328,609],[260,610],[249,611],[495,611],[250,611],[252,612],[254,613],[311,614],[255,611],[318,615],[256,616],[525,617],[258,618],[257,619],[261,600],[346,620],[345,621],[337,611],[335,613],[338,622],[336,623],[339,624],[329,625],[340,626],[297,627],[296,628],[289,629],[301,630],[373,631],[290,632],[368,633],[377,634],[300,635],[381,636],[291,636],[312,637],[531,638],[262,639],[313,440],[532,639],[271,639],[528,640],[355,641],[526,642],[529,640],[316,643],[527,642],[314,644],[315,645],[517,646],[518,647],[280,26],[304,648],[399,632],[402,440],[236,440],[363,440],[237,440],[473,440],[474,649],[238,650],[478,651],[498,652],[392,653],[397,654],[512,655],[499,441],[513,656],[500,441],[248,657],[501,658],[502,659],[504,660],[505,661],[507,662],[514,657],[503,663],[506,652],[530,664],[509,665],[510,666],[511,667],[241,550],[410,668],[331,669],[405,440],[292,670],[282,671],[497,672],[267,673],[536,674],[283,675],[284,676],[396,677],[523,678],[524,678],[522,440],[534,679],[535,679],[533,440],[1184,680],[1169,681],[1182,26],[1179,682],[1171,683],[1170,26],[1168,684],[1172,26],[1166,685],[1173,26],[1183,686],[1174,26],[1178,687],[1180,688],[1167,689],[1181,690],[1175,26],[1176,26],[1177,691],[538,26],[540,26],[539,26],[541,692],[542,26],[1163,693],[1165,694],[1164,695],[1025,696],[1162,697],[1161,698],[653,699],[650,235],[651,700],[652,701]],"latestChangedDtsFile":"./dist/index.d.ts","version":"5.8.3"} \ No newline at end of file diff --git a/tooling/sparta/src/.gitignore b/tooling/sparta/packages/express/.gitignore similarity index 99% rename from tooling/sparta/src/.gitignore rename to tooling/sparta/packages/express/.gitignore index 212eb5c..9b1ee42 100644 --- a/tooling/sparta/src/.gitignore +++ b/tooling/sparta/packages/express/.gitignore @@ -173,4 +173,3 @@ dist # Finder (MacOS) folder config .DS_Store -dist diff --git a/tooling/sparta/packages/express/README.md b/tooling/sparta/packages/express/README.md new file mode 100644 index 0000000..0ffa67f --- /dev/null +++ b/tooling/sparta/packages/express/README.md @@ -0,0 +1,64 @@ +# @sparta/api + +Express API server for the Sparta project, providing RESTful endpoints for validator management and Discord integration. + +## Overview + +This package implements an Express-based API server that serves as the backend for the Sparta project: + +- RESTful API endpoints for validator management +- OpenAPI/Swagger documentation +- Session management via DynamoDB +- Integration with Discord and Ethereum services +- CORS configuration for frontend access + +## Key Endpoints + +- **Validator Management** + - `GET /api/validators` - List all validators + - `GET /api/validators/:address` - Get validator details + - `POST /api/validators` - Register a new validator + - `DELETE /api/validators/:address` - Remove a validator + +- **Chain Information** + - `GET /api/info` - Get general chain information + - `GET /api/blocks/latest` - Get latest block information + - `GET /api/epochs/current` - Get current epoch information + +- **Health Check** + - `GET /health` - Check if the API server is running + +## Configuration + +Configure the API server through environment variables: + +- `API_PORT`: Port to run the server on (default: 3000) +- `CORS_ALLOWED_ORIGINS`: Comma-separated list of allowed origins for CORS +- `NODE_ENV`: Environment setting (development, production) + +## Development + +```bash +# Build TypeScript files +bun run build + +# Run in development mode with hot reloading +bun run dev + +# Run in production mode +bun run start +``` + +## Project Structure + +``` +src/ +├── routes/ # API route implementations +├── services/ # Core business logic services +├── swagger.ts # Swagger API documentation +└── index.ts # Main entry point +``` + +## API Documentation + +API documentation is available at `/api-docs` when the server is running. \ No newline at end of file diff --git a/tooling/sparta/packages/express/package.json b/tooling/sparta/packages/express/package.json new file mode 100644 index 0000000..b07969b --- /dev/null +++ b/tooling/sparta/packages/express/package.json @@ -0,0 +1,34 @@ +{ + "name": "@sparta/api", + "module": "index.ts", + "type": "module", + "scripts": { + "build": "tsc", + "start": "bun run src/index.ts", + "dev": "bun --watch run src/index.ts" + }, + "dependencies": { + "@sparta/utils": "workspace:*", + "@sparta/discord": "workspace:*", + "@sparta/ethereum": "workspace:*", + "axios": "^1.6.7", + "cors": "^2.8.5", + "discord.js": "^14.14.1", + "dotenv": "^16.5.0", + "express": "^4.18.2", + "openapi-client-axios": "^7.6.0", + "swagger-autogen": "^2.23.7", + "swagger2openapi": "^7.0.8", + "viem": "^2.9.15" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/cors": "^2.8.17", + "@types/node": "^20.11.0", + "typescript": "^5.3.3", + "ts-node-dev": "^2.0.0", + "@types/bun": "latest", + "@types/uuid": "^9.0.8", + "openapi-client-axios-typegen": "^7.7.0" + } +} diff --git a/tooling/sparta/packages/express/src/db/nodeOperatorRepository.ts b/tooling/sparta/packages/express/src/db/nodeOperatorRepository.ts new file mode 100644 index 0000000..80136ec --- /dev/null +++ b/tooling/sparta/packages/express/src/db/nodeOperatorRepository.ts @@ -0,0 +1,364 @@ +import { + GetCommand, + PutCommand, + UpdateCommand, + DeleteCommand, + QueryCommand, + ScanCommand, + DynamoDBDocumentClient, // Keep this for type hint +} from "@aws-sdk/lib-dynamodb"; +import { logger } from "@sparta/utils"; +import type { NodeOperator } from "../domain/operators/service"; +import DynamoDBService from "@sparta/utils/dynamo-db.js"; // Import the shared service + +const NODE_OPERATORS_TABLE_NAME = + process.env.NODE_OPERATORS_TABLE_NAME || "sparta-node-operators-dev"; +const WALLET_ADDRESS_INDEX_NAME = "WalletAddressIndex"; +const DISCORD_USERNAME_INDEX_NAME = "DiscordUsernameIndex"; + +// Instantiate the shared service for the node operators table +const dynamoDBService = new DynamoDBService(NODE_OPERATORS_TABLE_NAME); + +export class NodeOperatorRepository { + private client: DynamoDBDocumentClient; + private tableName: string; + + constructor() { + this.tableName = NODE_OPERATORS_TABLE_NAME; + // Get the client instance from the shared service + this.client = dynamoDBService.getClient(); + logger.info( + `NodeOperatorRepository initialized using shared DynamoDBService for table: ${this.tableName}` + ); + } + + async findAll(pageToken?: string): Promise<{ operators: NodeOperator[]; nextPageToken?: string }> { + try { + const ITEMS_PER_PAGE = 100; + + // Build the scan command + const scanParams: any = { + TableName: this.tableName, + Limit: ITEMS_PER_PAGE + }; + + // If we have a page token, use it as the ExclusiveStartKey + if (pageToken) { + try { + const decodedToken = JSON.parse(Buffer.from(pageToken, 'base64').toString()); + scanParams.ExclusiveStartKey = decodedToken; + } catch (error) { + logger.error({ error, pageToken }, "Invalid page token format"); + } + } + + const command = new ScanCommand(scanParams); + const response = await this.client.send(command); + + // Generate the next page token if LastEvaluatedKey exists + let nextPageToken: string | undefined = undefined; + if (response.LastEvaluatedKey) { + nextPageToken = Buffer.from( + JSON.stringify(response.LastEvaluatedKey) + ).toString('base64'); + } + + return { + operators: (response.Items ?? []) as NodeOperator[], + nextPageToken, + }; + } catch (error) { + logger.error( + error, + "Error scanning NodeOperators table in repository" + ); + throw new Error("Repository failed to retrieve node operators."); + } + } + + async findByDiscordId( + discordId: string + ): Promise { + try { + const command = new GetCommand({ + TableName: this.tableName, + Key: { discordId }, + }); + const response = await this.client.send(command); + return response.Item as NodeOperator | undefined; + } catch (error) { + logger.error( + { error, discordId, tableName: this.tableName }, + "Error retrieving NodeOperator by Discord ID in repository" + ); + throw new Error( + "Repository failed to retrieve node operator by Discord ID." + ); + } + } + + async findByDiscordUsername( + discordUsername: string + ): Promise { + try { + try { + // First try to use the index if it exists + const command = new QueryCommand({ + TableName: this.tableName, + IndexName: DISCORD_USERNAME_INDEX_NAME, + KeyConditionExpression: "discordUsername = :discordUsername", + ExpressionAttributeValues: { + ":discordUsername": discordUsername, + }, + }); + const response = await this.client.send(command); + return response.Items && response.Items.length > 0 + ? (response.Items[0] as NodeOperator) + : undefined; + } catch (indexError: any) { + // If the index doesn't exist yet, fall back to scan + if (indexError.name === "ValidationException" && + indexError.message && + indexError.message.includes("specified index")) { + logger.warn( + { indexError, discordUsername, tableName: this.tableName }, + "Index not ready, falling back to scan for Discord username lookup" + ); + + // Fall back to scan + const scanCommand = new ScanCommand({ + TableName: this.tableName, + FilterExpression: "discordUsername = :discordUsername", + ExpressionAttributeValues: { + ":discordUsername": discordUsername, + }, + }); + const scanResponse = await this.client.send(scanCommand); + return scanResponse.Items && scanResponse.Items.length > 0 + ? (scanResponse.Items[0] as NodeOperator) + : undefined; + } else { + // Re-throw if it's a different error + throw indexError; + } + } + } catch (error) { + logger.error( + { error, discordUsername, tableName: this.tableName }, + "Error retrieving NodeOperator by Discord username in repository" + ); + throw new Error( + "Repository failed to retrieve node operator by Discord username." + ); + } + } + + async findByWalletAddress( + walletAddress: string + ): Promise { + try { + // Consider normalizing the address if needed (e.g., to lowercase) + // const normalizedAddress = walletAddress.toLowerCase(); + const command = new QueryCommand({ + TableName: this.tableName, + IndexName: WALLET_ADDRESS_INDEX_NAME, + KeyConditionExpression: "walletAddress = :walletAddress", + ExpressionAttributeValues: { + ":walletAddress": walletAddress, // Use normalizedAddress if normalizing + }, + }); + const response = await this.client.send(command); + return response.Items && response.Items.length > 0 + ? (response.Items[0] as NodeOperator) + : undefined; + } catch (error) { + logger.error( + { error, walletAddress, tableName: this.tableName }, + "Error querying NodeOperator by wallet address in repository" + ); + throw new Error( + "Repository failed to retrieve node operator by address." + ); + } + } + + async countAll(): Promise { + try { + const command = new ScanCommand({ + TableName: this.tableName, + Select: "COUNT", + }); + const response = await this.client.send(command); + return response.Count ?? 0; + } catch (error) { + logger.error( + { error, tableName: this.tableName }, + "Error counting NodeOperators in repository" + ); + throw new Error("Repository failed to count node operators."); + } + } + + async create( + discordId: string, + walletAddress: string, + discordUsername?: string, + isApproved?: boolean + ): Promise { + const now = Date.now(); + const newOperator: NodeOperator = { + discordId, + walletAddress, // Consider normalizing address before saving + ...(discordUsername && { discordUsername }), + ...(isApproved !== undefined && { isApproved }), + createdAt: now, + updatedAt: now, + }; + + try { + const command = new PutCommand({ + TableName: this.tableName, + Item: newOperator, + ConditionExpression: "attribute_not_exists(discordId)", + }); + await this.client.send(command); + logger.info( + { discordId, walletAddress, discordUsername, tableName: this.tableName }, + "Created new NodeOperator in repository" + ); + return newOperator; + } catch (error: any) { + logger.error( + { error, discordId, walletAddress, discordUsername, tableName: this.tableName }, + "Error creating NodeOperator in repository" + ); + // Re-throw specific error types if needed for service layer handling + if (error.name === "ConditionalCheckFailedException") { + throw new Error( + `Node operator with Discord ID ${discordId} already exists.` + ); + } + throw new Error("Repository failed to create node operator."); + } + } + + async updateWallet( + discordId: string, + newWalletAddress: string + ): Promise { + try { + const command = new UpdateCommand({ + TableName: this.tableName, + Key: { discordId }, + UpdateExpression: + "SET walletAddress = :walletAddress, updatedAt = :updatedAt", + ConditionExpression: "attribute_exists(discordId)", + ExpressionAttributeValues: { + ":walletAddress": newWalletAddress, // Consider normalizing + ":updatedAt": Date.now(), + }, + ReturnValues: "NONE", + }); + await this.client.send(command); + logger.info( + { discordId, newWalletAddress, tableName: this.tableName }, + "Updated NodeOperator wallet address in repository" + ); + return true; + } catch (error: any) { + logger.error( + { + error, + discordId, + newWalletAddress, + tableName: this.tableName, + }, + "Error updating NodeOperator wallet address in repository" + ); + if (error.name === "ConditionalCheckFailedException") { + logger.warn( + { discordId }, + "NodeOperator not found for update wallet operation" + ); + return false; + } + throw error; + } + } + + async updateApprovalStatus( + discordId: string, + isApproved: boolean + ): Promise { + try { + const command = new UpdateCommand({ + TableName: this.tableName, + Key: { discordId }, + UpdateExpression: + "SET isApproved = :isApproved, updatedAt = :updatedAt", + ConditionExpression: "attribute_exists(discordId)", + ExpressionAttributeValues: { + ":isApproved": isApproved, + ":updatedAt": Date.now(), + }, + ReturnValues: "NONE", + }); + await this.client.send(command); + logger.info( + { discordId, isApproved, tableName: this.tableName }, + "Updated NodeOperator approval status in repository" + ); + return true; + } catch (error: any) { + logger.error( + { + error, + discordId, + isApproved, + tableName: this.tableName, + }, + "Error updating NodeOperator approval status in repository" + ); + if (error.name === "ConditionalCheckFailedException") { + logger.warn( + { discordId }, + "NodeOperator not found for update approval status operation" + ); + return false; + } + throw error; + } + } + + async deleteByDiscordId(discordId: string): Promise { + try { + const command = new DeleteCommand({ + TableName: this.tableName, + Key: { discordId }, + ConditionExpression: "attribute_exists(discordId)", + }); + await this.client.send(command); + logger.info( + { discordId, tableName: this.tableName }, + "Deleted NodeOperator in repository" + ); + return true; + } catch (error: any) { + logger.error( + { error, discordId, tableName: this.tableName }, + "Error deleting NodeOperator in repository" + ); + if (error.name === "ConditionalCheckFailedException") { + logger.warn( + { discordId }, + "NodeOperator not found for delete operation" + ); + return false; + } + throw error; + } + } +} + +export const nodeOperatorRepository = new NodeOperatorRepository(); +export default nodeOperatorRepository; diff --git a/tooling/sparta/packages/express/src/db/validatorRepository.ts b/tooling/sparta/packages/express/src/db/validatorRepository.ts new file mode 100644 index 0000000..4dfba88 --- /dev/null +++ b/tooling/sparta/packages/express/src/db/validatorRepository.ts @@ -0,0 +1,278 @@ +import { + GetCommand, + PutCommand, + UpdateCommand, + DeleteCommand, + QueryCommand, + ScanCommand, + DynamoDBDocumentClient, +} from "@aws-sdk/lib-dynamodb"; +import { logger } from "@sparta/utils"; +import type { Validator } from "../domain/validators/service"; +import DynamoDBService from "@sparta/utils/dynamo-db.js"; + +const VALIDATORS_TABLE_NAME = process.env.VALIDATORS_TABLE_NAME || "sparta-validators-dev"; +const NODE_OPERATOR_INDEX_NAME = "NodeOperatorIndex"; + +// Instantiate the shared service for the validators table +const dynamoDBService = new DynamoDBService(VALIDATORS_TABLE_NAME); + +export class ValidatorRepository { + private client: DynamoDBDocumentClient; + private tableName: string; + + constructor() { + this.tableName = VALIDATORS_TABLE_NAME; + // Get the client instance from the shared service + this.client = dynamoDBService.getClient(); + logger.info( + `ValidatorRepository initialized using shared DynamoDBService for table: ${this.tableName}` + ); + } + + async findAll(pageToken?: string): Promise<{ validators: Validator[]; nextPageToken?: string }> { + try { + const ITEMS_PER_PAGE = 100; + + // Build the scan command + const scanParams: any = { + TableName: this.tableName, + Limit: ITEMS_PER_PAGE, + }; + + // If we have a page token, use it as the ExclusiveStartKey + if (pageToken) { + try { + const decodedToken = JSON.parse(Buffer.from(pageToken, 'base64').toString()); + scanParams.ExclusiveStartKey = decodedToken; + } catch (error) { + logger.error({ error, pageToken }, "Invalid page token format"); + } + } + + const command = new ScanCommand(scanParams); + const response = await this.client.send(command); + + // Generate the next page token if LastEvaluatedKey exists + let nextPageToken: string | undefined = undefined; + if (response.LastEvaluatedKey) { + nextPageToken = Buffer.from( + JSON.stringify(response.LastEvaluatedKey) + ).toString('base64'); + } + + return { + validators: (response.Items ?? []) as Validator[], + nextPageToken, + }; + } catch (error) { + logger.error( + { error, tableName: this.tableName }, + "Error scanning Validators table in repository" + ); + throw new Error("Repository failed to retrieve validators."); + } + } + + async findByAddress( + validatorAddress: string + ): Promise { + try { + // First try exact match + const command = new GetCommand({ + TableName: this.tableName, + Key: { validatorAddress }, + }); + const response = await this.client.send(command); + + // If found, return it + if (response.Item) { + return response.Item as Validator; + } + + // If exact match fails, try case-insensitive search + logger.debug( + { validatorAddress }, + "Exact match failed, trying case-insensitive search" + ); + + // Get all validators and find one that matches case-insensitively + const scanCommand = new ScanCommand({ + TableName: this.tableName, + }); + const scanResponse = await this.client.send(scanCommand); + const validators = scanResponse.Items as Validator[] || []; + + // Find case-insensitive match + const matchingValidator = validators.find(v => + v.validatorAddress.toLowerCase() === validatorAddress.toLowerCase() + ); + + return matchingValidator; + } catch (error) { + logger.error( + { error, validatorAddress, tableName: this.tableName }, + "Error retrieving Validator by address in repository" + ); + throw new Error( + "Repository failed to retrieve validator by address." + ); + } + } + + async findByNodeOperator( + nodeOperatorId: string + ): Promise { + try { + const command = new QueryCommand({ + TableName: this.tableName, + IndexName: NODE_OPERATOR_INDEX_NAME, + KeyConditionExpression: "nodeOperatorId = :nodeOperatorId", + ExpressionAttributeValues: { + ":nodeOperatorId": nodeOperatorId, + }, + }); + const response = await this.client.send(command); + return (response.Items || []) as Validator[]; + } catch (error) { + logger.error( + error, nodeOperatorId, this.tableName, + "Error querying Validators by node operator in repository" + ); + throw new Error( + "Repository failed to retrieve validators by node operator." + ); + } + } + + async countAll(): Promise { + try { + const command = new ScanCommand({ + TableName: this.tableName, + Select: "COUNT", + }); + const response = await this.client.send(command); + return response.Count ?? 0; + } catch (error) { + logger.error( + { error, tableName: this.tableName }, + "Error counting Validators in repository" + ); + throw new Error("Repository failed to count validators."); + } + } + + async create( + validatorAddress: string, + nodeOperatorId: string + ): Promise { + const now = Date.now(); + const newValidator: Validator = { + validatorAddress, + nodeOperatorId, + createdAt: now, + updatedAt: now, + }; + + try { + const command = new PutCommand({ + TableName: this.tableName, + Item: newValidator, + ConditionExpression: "attribute_not_exists(validatorAddress)", + }); + await this.client.send(command); + logger.info( + { validatorAddress, nodeOperatorId, tableName: this.tableName }, + "Created new Validator in repository" + ); + return newValidator; + } catch (error: any) { + logger.error( + { error, validatorAddress, nodeOperatorId, tableName: this.tableName }, + "Error creating Validator in repository" + ); + if (error.name === "ConditionalCheckFailedException") { + throw new Error( + `Validator with address ${validatorAddress} already exists.` + ); + } + throw new Error("Repository failed to create validator."); + } + } + + async updateNodeOperator( + validatorAddress: string, + newNodeOperatorId: string + ): Promise { + try { + const command = new UpdateCommand({ + TableName: this.tableName, + Key: { validatorAddress }, + UpdateExpression: + "SET nodeOperatorId = :nodeOperatorId, updatedAt = :updatedAt", + ConditionExpression: "attribute_exists(validatorAddress)", + ExpressionAttributeValues: { + ":nodeOperatorId": newNodeOperatorId, + ":updatedAt": Date.now(), + }, + ReturnValues: "NONE", + }); + await this.client.send(command); + logger.info( + { validatorAddress, newNodeOperatorId, tableName: this.tableName }, + "Updated Validator node operator in repository" + ); + return true; + } catch (error: any) { + logger.error( + { + error, + validatorAddress, + newNodeOperatorId, + tableName: this.tableName, + }, + "Error updating Validator node operator in repository" + ); + if (error.name === "ConditionalCheckFailedException") { + logger.warn( + { validatorAddress }, + "Validator not found for update operation" + ); + return false; + } + throw error; + } + } + + async deleteByAddress(validatorAddress: string): Promise { + try { + const command = new DeleteCommand({ + TableName: this.tableName, + Key: { validatorAddress }, + ConditionExpression: "attribute_exists(validatorAddress)", + }); + await this.client.send(command); + logger.info( + { validatorAddress, tableName: this.tableName }, + "Deleted Validator in repository" + ); + return true; + } catch (error: any) { + logger.error( + { error, validatorAddress, tableName: this.tableName }, + "Error deleting Validator in repository" + ); + if (error.name === "ConditionalCheckFailedException") { + logger.warn( + { validatorAddress }, + "Validator not found for delete operation" + ); + return false; + } + throw error; + } + } +} + +export const validatorRepository = new ValidatorRepository(); +export default validatorRepository; \ No newline at end of file diff --git a/tooling/sparta/packages/express/src/domain/operators/service.ts b/tooling/sparta/packages/express/src/domain/operators/service.ts new file mode 100644 index 0000000..8e8d21d --- /dev/null +++ b/tooling/sparta/packages/express/src/domain/operators/service.ts @@ -0,0 +1,301 @@ +import { logger } from "@sparta/utils"; // Assuming logger is accessible +import { + nodeOperatorRepository, // Import the repository instance + NodeOperatorRepository, // Import the repository type if needed for dependency injection +} from "../../db/nodeOperatorRepository"; // Corrected relative path from service to db +import { validatorService } from "../validators/service"; + +export interface NodeOperator { + discordId: string; // Primary Key + walletAddress: string; // GSI Partition Key: WalletAddressIndex + discordUsername?: string; // Optional Discord username + isApproved?: boolean; // Whether the operator is approved + createdAt: number; + updatedAt: number; +} + +class NodeOperatorService { + // Optionally inject repository for testability + private repository: NodeOperatorRepository; + + constructor(repository: NodeOperatorRepository = nodeOperatorRepository) { + this.repository = repository; + logger.info("NodeOperatorService initialized with repository."); + } + + /** + * Retrieves all node operators with pagination. + * @param pageToken Optional token for pagination + * @returns Object containing array of NodeOperator objects and optional nextPageToken. + */ + public async getAllOperators(pageToken?: string): Promise<{ operators: NodeOperator[]; nextPageToken?: string }> { + try { + return await this.repository.findAll(pageToken); + } catch (error) { + logger.error(error, "Service error getting all operators"); + // Re-throw or handle specific service-level errors + throw error; // Re-throwing the repository error for now + } + } + + /** + * Counts the total number of node operators. + * @returns The count of node operators. + */ + public async countOperators(): Promise { + try { + return await this.repository.countAll(); + } catch (error) { + logger.error(error, "Service error counting operators"); + throw error; + } + } + + /** + * Retrieves a node operator by their Discord ID. + * @param discordId The Discord ID. + * @returns The NodeOperator object or undefined if not found. + */ + public async getOperatorByDiscordId( + discordId: string + ): Promise { + try { + return await this.repository.findByDiscordId(discordId); + } catch (error) { + logger.error( + { error, discordId }, + "Service error getting operator by Discord ID" + ); + throw error; + } + } + + /** + * Retrieves a node operator by their Discord username. + * @param discordUsername The Discord username. + * @returns The NodeOperator object or undefined if not found. + */ + public async getOperatorByDiscordUsername( + discordUsername: string + ): Promise { + try { + return await this.repository.findByDiscordUsername(discordUsername); + } catch (error) { + logger.error( + { error, discordUsername }, + "Service error getting operator by Discord username" + ); + throw error; + } + } + + /** + * Retrieves a node operator by their wallet address. + * @param walletAddress The wallet address. + * @returns The NodeOperator object or undefined if not found. + */ + public async getOperatorByAddress( + walletAddress: string + ): Promise { + try { + // Add any service-level validation or logic here if needed + return await this.repository.findByWalletAddress(walletAddress); + } catch (error) { + logger.error( + { error, walletAddress }, + "Service error getting operator by wallet address" + ); + throw error; + } + } + + /** + * Creates a new node operator. + * @param discordId The Discord ID. + * @param walletAddress The wallet address. + * @param discordUsername The Discord username. + * @returns The created NodeOperator object or undefined if creation failed (e.g., duplicate discordId). + */ + public async createOperator( + discordId: string, + walletAddress: string, + discordUsername?: string, + isApproved?: boolean + ): Promise { + try { + // Add any service-level validation or transformation here + return await this.repository.create(discordId, walletAddress, discordUsername, isApproved); + } catch (error: any) { + logger.error( + { error: error.message, discordId, walletAddress, discordUsername }, // Log error message + "Service error creating operator" + ); + // Check for specific repository errors (like duplicate) and handle + if (error.message.includes("already exists")) { + return undefined; // Indicate conflict at the service level + } + throw new Error("Service failed to create node operator."); // Throw a generic service error + } + } + + /** + * Updates the wallet address for a node operator. + * @param discordId The Discord ID of the operator to update. + * @param newWalletAddress The new wallet address. + * @returns True if the update was successful, false otherwise (e.g., operator not found). + */ + public async updateOperatorWallet( + discordId: string, + newWalletAddress: string + ): Promise { + try { + // Add service-level validation if needed + return await this.repository.updateWallet( + discordId, + newWalletAddress + ); + } catch (error) { + logger.error( + { error, discordId, newWalletAddress }, + "Service error updating operator wallet" + ); + // The repository already returns false if not found due to condition check + // If other errors occur, re-throw + throw error; + } + } + + /** + * Deletes a node operator by their Discord ID. + * @param discordId The Discord ID of the operator to delete. + * @returns True if deletion was successful, false otherwise (e.g., operator not found). + */ + public async deleteOperatorByDiscordId( + discordId: string + ): Promise { + try { + return await this.repository.deleteByDiscordId(discordId); + } catch (error) { + logger.error( + { error, discordId }, + "Service error deleting operator by Discord ID" + ); + // Repository returns false if not found, re-throw other errors + throw error; + } + } + + /** + * Updates the approval status for a node operator. + * @param discordId The Discord ID of the operator to update. + * @param isApproved The approval status to set. + * @returns True if the update was successful, false otherwise (e.g., operator not found). + */ + public async updateApprovalStatus( + discordId: string, + isApproved: boolean + ): Promise { + try { + return await this.repository.updateApprovalStatus( + discordId, + isApproved + ); + } catch (error) { + logger.error( + { error, discordId, isApproved }, + "Service error updating operator approval status" + ); + // The repository already returns false if not found due to condition check + // If other errors occur, re-throw + throw error; + } + } + + /** + * Adds a validator to an operator using the validator service. + * @param discordId The Discord ID of the operator. + * @param validatorAddress The validator address to add. + * @returns True if the update was successful, false otherwise. + */ + public async addValidatorToOperator( + discordId: string, + validatorAddress: string + ): Promise { + try { + const operator = await this.repository.findByDiscordId(discordId); + + if (!operator) { + return false; + } + + // Check if the validator already exists + const existingValidator = await validatorService.getValidatorByAddress(validatorAddress); + if (existingValidator) { + // If it exists but belongs to a different operator, update it + if (existingValidator.nodeOperatorId !== discordId) { + return await validatorService.updateValidatorOperator(validatorAddress, discordId); + } + // If it's already associated with this operator, return success + return true; + } + + // Create a new validator associated with this operator + const validator = await validatorService.createValidator(validatorAddress, discordId); + return !!validator; + } catch (error) { + logger.error( + { error, discordId, validatorAddress }, + "Service error adding validator to operator" + ); + throw error; + } + } + + /** + * Updates the complete list of validators for an operator. + * @param discordId The Discord ID of the operator. + * @param validators Array of validator addresses to set. + * @returns True if the update was successful, false otherwise. + */ + public async updateValidatorsList( + discordId: string, + validators: string[] + ): Promise { + try { + // First, check if the operator exists + const operator = await this.repository.findByDiscordId(discordId); + if (!operator) { + return false; + } + + // Get all current validators for this operator + const currentValidators = await validatorService.getValidatorsByNodeOperator(discordId); + const currentAddresses = currentValidators.map(v => v.validatorAddress); + + // Determine which validators to add and which to remove + const validatorsToAdd = validators.filter(addr => !currentAddresses.includes(addr)); + const validatorsToRemove = currentAddresses.filter(addr => !validators.includes(addr)); + + // Remove validators not in the new list + for (const addr of validatorsToRemove) { + await validatorService.deleteValidator(addr); + } + + // Add new validators + for (const addr of validatorsToAdd) { + await validatorService.createValidator(addr, discordId); + } + + return true; + } catch (error) { + logger.error( + { error, discordId }, + "Service error updating validators list" + ); + throw error; + } + } +} + +export const nodeOperatorService = new NodeOperatorService(); +export default nodeOperatorService; diff --git a/tooling/sparta/packages/express/src/domain/validators/service.ts b/tooling/sparta/packages/express/src/domain/validators/service.ts new file mode 100644 index 0000000..bb40b3e --- /dev/null +++ b/tooling/sparta/packages/express/src/domain/validators/service.ts @@ -0,0 +1,144 @@ +import { logger } from "@sparta/utils"; +import { validatorRepository, ValidatorRepository } from "../../db/validatorRepository"; + +export interface Validator { + validatorAddress: string; // Primary Key + nodeOperatorId: string; // GSI Partition Key: NodeOperatorIndex + createdAt: number; + updatedAt: number; +} + +class ValidatorService { + private repository: ValidatorRepository; + + constructor(repository: ValidatorRepository = validatorRepository) { + this.repository = repository; + logger.info("ValidatorService initialized with repository."); + } + + /** + * Retrieves all validators with pagination. + * @param pageToken Optional token for pagination + * @returns Object containing array of Validator objects and optional nextPageToken. + */ + public async getAllValidators(pageToken?: string): Promise<{ validators: Validator[]; nextPageToken?: string }> { + try { + return await this.repository.findAll(pageToken); + } catch (error) { + logger.error(error, "Service error getting all validators"); + throw error; + } + } + + /** + * Counts the total number of validators. + * @returns The count of validators. + */ + public async countValidators(): Promise { + try { + return await this.repository.countAll(); + } catch (error) { + logger.error(error, "Service error counting validators"); + throw error; + } + } + + /** + * Retrieves a validator by address. + * @param validatorAddress The validator address. + * @returns The Validator object or undefined if not found. + */ + public async getValidatorByAddress(validatorAddress: string): Promise { + try { + return await this.repository.findByAddress(validatorAddress); + } catch (error) { + logger.error( + { error, validatorAddress }, + "Service error getting validator by address" + ); + throw error; + } + } + + /** + * Retrieves all validators for a node operator. + * @param nodeOperatorId The Discord ID of the node operator. + * @returns Array of Validator objects. + */ + public async getValidatorsByNodeOperator(nodeOperatorId: string): Promise { + try { + return await this.repository.findByNodeOperator(nodeOperatorId); + } catch (error) { + logger.error( + { error, nodeOperatorId }, + "Service error getting validators by node operator" + ); + throw error; + } + } + + /** + * Creates a new validator. + * @param validatorAddress The validator address. + * @param nodeOperatorId The Discord ID of the node operator. + * @returns The created Validator object or undefined if creation failed. + */ + public async createValidator( + validatorAddress: string, + nodeOperatorId: string + ): Promise { + try { + return await this.repository.create(validatorAddress, nodeOperatorId); + } catch (error: any) { + logger.error( + { error: error.message, validatorAddress, nodeOperatorId }, + "Service error creating validator" + ); + if (error.message.includes("already exists")) { + return undefined; + } + throw new Error("Service failed to create validator."); + } + } + + /** + * Updates the node operator for a validator. + * @param validatorAddress The validator address. + * @param newNodeOperatorId The new node operator Discord ID. + * @returns True if the update was successful, false otherwise. + */ + public async updateValidatorOperator( + validatorAddress: string, + newNodeOperatorId: string + ): Promise { + try { + return await this.repository.updateNodeOperator(validatorAddress, newNodeOperatorId); + } catch (error) { + logger.error( + { error, validatorAddress, newNodeOperatorId }, + "Service error updating validator operator" + ); + throw error; + } + } + + /** + * Deletes a validator by address. + * @param validatorAddress The validator address. + * @returns True if deletion was successful, false otherwise. + */ + public async deleteValidator(validatorAddress: string): Promise { + try { + return await this.repository.deleteByAddress(validatorAddress); + } catch (error) { + logger.error( + { error, validatorAddress }, + "Service error deleting validator" + ); + throw error; + } + } +} + +export const validatorService = new ValidatorService(); +export default validatorService; \ No newline at end of file diff --git a/tooling/sparta/packages/express/src/index.ts b/tooling/sparta/packages/express/src/index.ts new file mode 100644 index 0000000..679d4c1 --- /dev/null +++ b/tooling/sparta/packages/express/src/index.ts @@ -0,0 +1,111 @@ +import express from "express"; +import cors from "cors"; +import apiRoutes from "./routes/api.js"; +// import { dynamoDB } from "@sparta/utils"; // Unused +import { getDiscordInstance } from "@sparta/discord"; +import { logger } from "@sparta/utils"; +import path from "path"; // Import path module +import { fileURLToPath } from "url"; // Import fileURLToPath for ES modules + +// Define __dirname for ES modules +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +let allowedOrigins: string[] = []; +const corsAllowedOriginsEnv = process.env.CORS_ALLOWED_ORIGINS; +const nodeEnv = process.env.NODE_ENV; + +if (corsAllowedOriginsEnv) { + // Use origins from environment variable if provided + allowedOrigins = corsAllowedOriginsEnv + .split(",") + .map((origin) => origin.trim()); +} else if (nodeEnv === "development") { + // Default origins for local development if variable is not set + allowedOrigins = [ + "http://localhost:3000", // Allow Express itself if serving frontend + "http://localhost:5173", // Default Vite dev port + "http://192.168.100.52:3000", // Allow local IP address + ]; +} // In non-development environments, if CORS_ALLOWED_ORIGINS is not set, allowedOrigins remains empty (most restrictive) + +logger.info({ nodeEnv, resolvedOrigins: allowedOrigins }, "Initializing CORS"); + +const corsOptions = { + origin: function ( + origin: string | undefined, + callback: (err: Error | null, allow?: boolean) => void + ) { + // Allow requests with no origin (like mobile apps, curl, server-to-server) + if (!origin) { + logger.debug("CORS: Allowing request with no origin"); + return callback(null, true); + } + // Check if the origin is in the allowed list + if (allowedOrigins.includes(origin)) { + logger.debug({ origin }, "CORS: Allowing request from origin"); + callback(null, true); + } else { + logger.warn( + { origin, allowedOrigins }, + "CORS: Blocking request from disallowed origin" + ); + callback(new Error(`Origin ${origin} not allowed by CORS`), false); + } + }, + methods: ["GET", "POST", "OPTIONS"], // Specify allowed methods + allowedHeaders: ["Content-Type", "Authorization"], // Specify allowed headers + credentials: true, // Allow cookies/authorization headers + optionsSuccessStatus: 204, // Return 204 for preflight requests +}; + +const app = express(); +const distDir = path.resolve(__dirname, "../../vite/dist"); +const viteIndexHtml = path.resolve(distDir, "index.html"); + +// Serve static assets from distDir (like JS, CSS) - removing index: false +app.use(express.static(distDir)); + +// Debug middleware to log all requests +app.use((req, _res, next) => { + console.log( + `${new Date().toISOString()} | ${req.method} ${req.url} | Origin: ${ + req.headers.origin || "No origin" + }` + ); + next(); +}); + +// Middleware +app.use(cors(corsOptions)); +// API Routes +app.use("/api", apiRoutes); + +// Health check endpoint +app.get("/health", (_req, res) => { + res.json({ status: "ok" }); +}); + +// Start server +app.listen(process.env.API_PORT as unknown as number, "0.0.0.0", async () => { + console.log(`Server is running on port ${process.env.API_PORT}`); + console.log(`Allowing CORS for: ${allowedOrigins.join(", ")}`); + console.log( + `API Documentation available at: ${process.env.API_URL}/api-docs` + ); + + // Start Discord Bot and then the background processor + try { + // Wait for the client to be ready (login happens in Discord.new) + const discord = await getDiscordInstance(); + discord.getClient().once("ready", async () => { + logger.info("Discord bot client is ready."); + }); + // Log that we are waiting for the ready event + logger.info("Waiting for Discord bot client to signal ready..."); + } catch (error) { + logger.error({ error }, "Failed to start Discord bot client."); + // Decide if the server should exit or run without the bot + process.exit(1); + } +}); diff --git a/tooling/sparta/packages/express/src/middlewares/auth.ts b/tooling/sparta/packages/express/src/middlewares/auth.ts new file mode 100644 index 0000000..9c0baf9 --- /dev/null +++ b/tooling/sparta/packages/express/src/middlewares/auth.ts @@ -0,0 +1,39 @@ +/** + * @fileoverview Authentication middleware + * @description Middleware functions for authentication and authorization + * @module sparta/express/middlewares/auth-middleware + */ + +import { type Request, type Response, type NextFunction } from "express"; +import { logger } from "@sparta/utils/index.js"; + +/** + * API key middleware for authenticating API requests + * Validates the x-api-key header against the configured API key + */ +export const apiKeyMiddleware = ( + req: Request, + res: Response, + next: NextFunction +) => { + const apiKey = req.headers["x-api-key"]; + const configuredApiKey = process.env.BACKEND_API_KEY; + + if (!configuredApiKey) { + logger.error("BACKEND_API_KEY environment variable is not set"); + return res.status(500).json({ + success: false, + error: "Server configuration error: API key not configured", + }); + } + + if (!apiKey || apiKey !== configuredApiKey) { + return res.status(401).json({ + success: false, + error: "Unauthorized: Invalid or missing API key", + }); + } + + next(); + return; +}; diff --git a/tooling/sparta/packages/express/src/middlewares/index.ts b/tooling/sparta/packages/express/src/middlewares/index.ts new file mode 100644 index 0000000..e9193b6 --- /dev/null +++ b/tooling/sparta/packages/express/src/middlewares/index.ts @@ -0,0 +1,7 @@ +/** + * @fileoverview Middlewares index + * @description Export all middlewares from a central location + * @module sparta/express/middlewares + */ + +export * from './auth.js'; diff --git a/tooling/sparta/packages/express/src/routes/api.ts b/tooling/sparta/packages/express/src/routes/api.ts new file mode 100644 index 0000000..6c712b0 --- /dev/null +++ b/tooling/sparta/packages/express/src/routes/api.ts @@ -0,0 +1,36 @@ +import express from "express"; +import apiDocs from "@sparta/utils/openapi/api-docs.json"; +import swaggerUi from "swagger-ui-express"; +import operatorRouter from "./operators"; +import ethereumRoutes from "./ethereum"; + +const router = express.Router(); + +router.use(express.json()); + +router.get("/api-docs.json", (_req, res) => { + res.setHeader("Content-Type", "application/json"); + res.send(apiDocs); +}); + +// Modify the API docs to use the correct server URL +const modifiedApiDocs = JSON.parse(JSON.stringify(apiDocs)); +const apiUrl = process.env.API_URL || `${process.env.API_PROTOCOL || 'http'}://${process.env.API_HOST || 'localhost'}:${process.env.API_PORT || '3000'}`; + +if (modifiedApiDocs.servers && modifiedApiDocs.servers.length > 0) { + modifiedApiDocs.servers[0].variables.serverUrl.default = apiUrl; +} + +router.use( + "/docs", + swaggerUi.serve, + swaggerUi.setup(modifiedApiDocs, { + explorer: true, + customCss: ".swagger-ui .topbar { display: none }", // Hide the top bar (optional) + }) +); + +router.use("/operator", operatorRouter); +router.use("/ethereum", ethereumRoutes); + +export default router; diff --git a/tooling/sparta/packages/express/src/routes/ethereum.ts b/tooling/sparta/packages/express/src/routes/ethereum.ts new file mode 100644 index 0000000..271e15e --- /dev/null +++ b/tooling/sparta/packages/express/src/routes/ethereum.ts @@ -0,0 +1,284 @@ +/** + * @fileoverview Ethereum blockchain API routes + * @description Provides endpoints for retrieving Ethereum rollup state and validator information + * @module sparta/express/routes + */ + +import { Router } from "express"; +import { logger } from "@sparta/utils/logger"; +import { getEthereumInstance } from "@sparta/ethereum"; +import { apiKeyMiddleware } from "../middlewares/auth.js"; + +// --- Swagger Schemas --- +/** + * @swagger + * components: + * securitySchemes: + * ApiKeyAuth: + * type: apiKey + * in: header + * name: x-api-key + * description: API key for authenticating requests + * schemas: + * EthereumResponse: + * type: object + * properties: + * success: + * type: boolean + * description: Indicates if the request was successful + * example: true + * data: + * type: array + * description: Array of data returned from the endpoint + * items: + * type: string + * example: ["0x1234567890abcdef1234567890abcdef12345678", "0xabcdef1234567890abcdef1234567890abcdef12"] + * required: + * - success + * - data + * RollupStatusResponse: + * type: object + * properties: + * success: + * type: boolean + * description: Indicates if the request was successful + * example: true + * data: + * type: object + * properties: + * pendingBlockNum: + * type: string + * description: Current pending block number + * example: "123456" + * provenBlockNum: + * type: string + * description: Current proven block number + * example: "123450" + * validators: + * type: array + * description: List of validator addresses + * items: + * type: string + * forwardedValidators: + * type: array + * description: List of forwarded validator addresses + * items: + * type: string + * committee: + * type: array + * description: Current committee members + * items: + * type: string + * forwardedCommittee: + * type: array + * description: Forwarded committee members + * items: + * type: string + * archive: + * type: array + * description: Archive node addresses + * items: + * type: string + * currentEpoch: + * type: string + * description: Current epoch number + * example: "42" + * currentSlot: + * type: string + * description: Current slot number + * example: "1024" + * proposerNow: + * type: string + * description: Current proposer address + * example: "0x1234567890abcdef1234567890abcdef12345678" + * required: + * - success + * - data + * ErrorResponse: + * type: object + * properties: + * success: + * type: boolean + * description: Always false for error responses + * example: false + * error: + * type: string + * description: Error message describing what went wrong + * example: "Failed to retrieve rollup status" + * required: + * - success + * - error + */ + +const router = Router(); + +// Apply API key middleware to all Ethereum routes +router.use(apiKeyMiddleware); + +/** + * @swagger + * /api/ethereum/rollup/committee: + * get: + * summary: Get current epoch committee + * description: Retrieves the list of committee members for the current epoch + * tags: [Ethereum] + * operationId: getCurrentEpochCommittee + * security: + * - ApiKeyAuth: [] + * responses: + * 200: + * description: Successfully retrieved committee members + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/EthereumResponse' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + * 500: + * description: Server error occurred while retrieving committee data + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + */ +router.get("/rollup/committee", async (_req, res) => { + try { + const ethereum = await getEthereumInstance(); + const rollup = ethereum.getRollup(); + const committee = await rollup.read.getCurrentEpochCommittee(); + + return res.status(200).json({ + success: true, + data: committee, + }); + } catch (error: any) { + logger.error( + { error: error.message }, + "Error retrieving committee data" + ); + return res.status(500).json({ + success: false, + error: "Failed to retrieve committee data", + }); + } +}); + +/** + * @swagger + * /api/ethereum/rollup/validators: + * get: + * summary: Get all validators + * description: Retrieves the list of all attesters (validators) in the rollup system + * tags: [Ethereum] + * operationId: getAllValidatorsOnChain + * security: + * - ApiKeyAuth: [] + * responses: + * 200: + * description: Successfully retrieved validators + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/EthereumResponse' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + * 500: + * description: Server error occurred while retrieving validators data + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + */ +router.get("/rollup/validators", async (_req, res) => { + try { + const ethereum = await getEthereumInstance(); + const rollup = ethereum.getRollup(); + const validators = await rollup.read.getAttesters(); + + return res.status(200).json({ + success: true, + data: validators, + }); + } catch (error: any) { + logger.error( + { error: error.message }, + "Error retrieving validators data" + ); + return res.status(500).json({ + success: false, + error: "Failed to retrieve validators data", + }); + } +}); + +/** + * @swagger + * /api/ethereum/rollup/status: + * get: + * summary: Get comprehensive rollup status + * description: Retrieves complete information about the rollup's current state including block numbers, validators, committee members, and other chain data + * tags: [Ethereum] + * operationId: getRollupStatus + * security: + * - ApiKeyAuth: [] + * responses: + * 200: + * description: Successfully retrieved rollup status + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/RollupStatusResponse' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + * 500: + * description: Server error occurred while retrieving rollup status + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + */ +router.get("/rollup/status", async (_req, res) => { + try { + const ethereum = await getEthereumInstance(); + + // Get main chain info from the Ethereum instance directly + const chainInfo = await ethereum.getRollupInfo(); + + console.log(chainInfo); + return res.status(200).json({ + success: true, + data: { + pendingBlockNum: chainInfo.pendingBlockNum.toString(), + provenBlockNum: chainInfo.provenBlockNum.toString(), + validators: chainInfo.validators, + committee: chainInfo.committee, + currentEpoch: chainInfo.currentEpoch.toString(), + currentSlot: chainInfo.currentSlot.toString(), + proposerNow: chainInfo.proposerNow, + }, + }); + } catch (error: any) { + logger.error( + { error: error.message }, + "Error retrieving rollup status" + ); + return res.status(500).json({ + success: false, + error: "Failed to retrieve rollup status", + }); + } +}); + +export default router; diff --git a/tooling/sparta/packages/express/src/routes/operators.ts b/tooling/sparta/packages/express/src/routes/operators.ts new file mode 100644 index 0000000..fb6dc79 --- /dev/null +++ b/tooling/sparta/packages/express/src/routes/operators.ts @@ -0,0 +1,1597 @@ +import express, { type Request, type Response, Router } from "express"; +import { nodeOperatorService } from "../domain/operators/service"; // Adjust path if necessary +import { validatorService, type Validator } from "../domain/validators/service"; // Add import for validator service +import { logger } from "@sparta/utils"; // Assuming logger is accessible +import { apiKeyMiddleware } from "../middlewares/auth.js"; +import { getEthereumInstance } from "@sparta/ethereum"; // Add import for ethereum + +// --- Swagger Schemas --- +/** + * @swagger + * components: + * securitySchemes: + * ApiKeyAuth: + * type: apiKey + * in: header + * name: x-api-key + * description: API key for authenticating requests + * schemas: + * NodeOperator: + * type: object + * properties: + * discordId: + * type: string + * description: The Discord user ID of the node operator. + * example: "123456789012345678" + * walletAddress: + * type: string + * description: The Ethereum wallet address associated with the node operator. + * example: "0x1234567890abcdef1234567890abcdef12345678" + * discordUsername: + * type: string + * description: The Discord username of the node operator. + * example: "user#1234" + * createdAt: + * type: number + * description: Timestamp (milliseconds since epoch) when the operator was created. + * example: 1678886400000 + * updatedAt: + * type: number + * description: Timestamp (milliseconds since epoch) when the operator was last updated. + * example: 1678887400000 + * validators: + * type: array + * description: List of validators associated with this operator. + * items: + * type: object + * properties: + * validatorAddress: + * type: string + * description: The Ethereum address of the validator. + * example: "0x1234567890abcdef1234567890abcdef12345678" + * required: + * - discordId + * - walletAddress + * - createdAt + * - updatedAt + * OperatorInput: + * type: object + * properties: + * discordId: + * type: string + * description: The Discord user ID. + * walletAddress: + * type: string + * description: The Ethereum wallet address. + * example: "0x1234567890abcdef1234567890abcdef12345678" + * required: + * - discordId + * - walletAddress + * OperatorUpdateInput: + * type: object + * properties: + * walletAddress: + * type: string + * description: The new Ethereum wallet address. + * example: "0xabcdef1234567890abcdef1234567890abcdef12" + * required: + * - walletAddress + * OperatorError: + * type: object + * properties: + * error: + * type: string + * description: Error message describing the issue. + * OperatorResponse: + * type: object + * properties: + * discordId: + * type: string + * description: The Discord user ID of the node operator. + * walletAddress: + * type: string + * description: The Ethereum wallet address associated with the node operator. + * createdAt: + * type: number + * description: Timestamp when operator was created + * updatedAt: + * type: number + * description: Timestamp when operator was last updated + * ValidatorResponse: + * type: object + * properties: + * address: + * type: string + * description: The Ethereum address of the validator. + * example: "0x1234567890abcdef1234567890abcdef12345678" + * operatorId: + * type: string + * description: The Discord ID of the operator who owns this validator. + * example: "123456789012345678" + * stats: + * type: object + * properties: + * totalValidators: + * type: number + * description: Total number of validators in the system. + * example: 42 + */ + +const router: Router = express.Router(); + +// Apply API key middleware to all operator routes +router.use(apiKeyMiddleware); + +// GET /api/operator/operators - returns paginated list of operators +/** + * @swagger + * /api/operator/operators: + * get: + * summary: Get node operators + * description: Retrieves a list of registered node operators. + * tags: [NodeOperator] + * operationId: getOperators + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: pageToken + * schema: + * type: string + * required: false + * description: Token for pagination to get the next page of results. + * responses: + * 200: + * description: A list of node operators with pagination token. + * content: + * application/json: + * schema: + * type: object + * properties: + * operators: + * type: array + * items: + * $ref: '#/components/schemas/NodeOperator' + * nextPageToken: + * type: string + * description: Token to retrieve the next page of results. Not present on the last page. + * example: "eyJsYXN0S2V5IjoiMTIzNDU2Nzg5MCJ9" + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.get("/operators", async (_req: Request, res: Response) => { + const pageToken = _req.query.pageToken as string | undefined; + const { operators, nextPageToken } = await nodeOperatorService.getAllOperators(pageToken); + res.status(200).json({ operators, nextPageToken }); + return; +}); + +// GET /api/operator with query parameters - returns a specific operator +/** + * @swagger + * /api/operator: + * get: + * summary: Get a specific node operator + * description: Retrieves a specific node operator using either their Discord ID or username. + * tags: [NodeOperator] + * operationId: getOperator + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: discordId + * schema: + * type: string + * required: false + * description: The Discord ID of the operator to retrieve. + * - in: query + * name: discordUsername + * schema: + * type: string + * required: false + * description: The Discord username of the operator to retrieve. + * responses: + * 200: + * description: The requested node operator with associated validators. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/NodeOperator' + * 400: + * description: Bad Request - Missing query parameters + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Operator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.get("/", async (req: Request, res: Response) => { + const discordId = req.query.discordId as string | undefined; + const discordUsername = req.query.discordUsername as string | undefined; + + if (!discordId && !discordUsername) { + return res + .status(400) + .json({ error: "Missing discordId or discordUsername parameter" }); + } + + let operator: any = undefined; + + if (discordId) { + operator = await nodeOperatorService.getOperatorByDiscordId(discordId); + } else if (discordUsername) { + operator = await nodeOperatorService.getOperatorByDiscordUsername(discordUsername); + } + + if (operator) { + // Fetch validators associated with this operator + const validators = await validatorService.getValidatorsByNodeOperator(operator.discordId); + + // Add validators to the operator response + const operatorWithValidators = { + ...operator, + validators + }; + + res.status(200).json(operatorWithValidators); + } else { + res.status(404).json({ error: "Operator not found" }); + } + return; +}); + +// GET /api/operator/stats - returns operator statistics +/** + * @swagger + * /api/operator/stats: + * get: + * summary: Get node operator statistics + * description: Retrieves statistics about registered node operators. + * tags: [NodeOperator] + * operationId: getOperatorStats + * security: + * - ApiKeyAuth: [] + * responses: + * 200: + * description: Node operator statistics. + * content: + * application/json: + * schema: + * type: object + * properties: + * stats: + * type: object + * properties: + * totalCount: + * type: number + * description: Total number of registered operators. + * example: 42 + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.get("/stats", async (_req: Request, res: Response) => { + try { + // Get current stats + const totalCount = await nodeOperatorService.countOperators(); + + // Return stats object that can be expanded with more metrics in the future + res.status(200).json({ + stats: { + totalCount + // Future stats can be added here + } + }); + } catch (error) { + logger.error(error, "Error retrieving operator statistics"); + res.status(500).json({ error: "Failed to retrieve operator statistics" }); + } + return; +}); + +// GET /api/operator/address/:address - returns the operator by address +/** + * @swagger + * /api/operator/address/{address}: + * get: + * summary: Get operator by wallet address + * description: Retrieves a specific node operator using their wallet address. + * tags: [NodeOperator] + * operationId: getOperatorByAddress + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: path + * name: address + * schema: + * type: string + * required: true + * description: The wallet address of the operator to retrieve. + * responses: + * 200: + * description: The requested node operator. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/NodeOperator' + * 400: + * description: Bad Request - Missing or invalid address parameter + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Operator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.get( + "/address/:address", + async (req: Request, res: Response) => { + const { address } = req.params; + if (!address) { + return res.status(400).json({ error: "Missing address parameter" }); + } + // Basic address validation (can be improved) + if (!/^0x[a-fA-F0-9]{40}$/.test(address)) { + return res + .status(400) + .json({ error: "Invalid wallet address format" }); + } + const operator = await nodeOperatorService.getOperatorByAddress( + address + ); + if (operator) { + res.status(200).json(operator); + } else { + res.status(404).json({ error: "Operator not found" }); + } + return; + }); + +// POST /api/operator - adds a new operator +/** + * @swagger + * /api/operator: + * post: + * summary: Create a new node operator + * description: Registers a new node operator with their Discord ID and wallet address. + * tags: [NodeOperator] + * operationId: createOperator + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: discordId + * schema: + * type: string + * required: true + * description: The Discord user ID. + * - in: query + * name: walletAddress + * schema: + * type: string + * required: true + * description: The Ethereum wallet address. + * - in: query + * name: discordUsername + * schema: + * type: string + * required: false + * description: The Discord username. + * responses: + * 201: + * description: Node operator created successfully. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/NodeOperator' + * 400: + * description: Bad Request - Missing or invalid body parameters + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 409: + * description: Conflict - Operator with this Discord ID already exists + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.post( + "/", + async (req: Request, res: Response) => { + const discordId = req.query.discordId as string; + const walletAddress = req.query.walletAddress as string; + const discordUsername = req.query.discordUsername as string | undefined; + + if (!discordId || !walletAddress) { + return res.status(400).json({ + error: "Missing discordId or walletAddress parameter", + }); + } + + // Check if operator exists first + const existingOperator = + await nodeOperatorService.getOperatorByDiscordId(discordId); + if (existingOperator) { + return res.status(409).json({ + error: "Operator with this Discord ID already exists", + }); + } + + // If discord username is provided, check if it already exists + if (discordUsername) { + const existingOperatorByUsername = + await nodeOperatorService.getOperatorByDiscordUsername(discordUsername); + if (existingOperatorByUsername) { + return res.status(409).json({ + error: "Operator with this Discord username already exists", + }); + } + } + + const newOperator = await nodeOperatorService.createOperator( + discordId, + walletAddress, + discordUsername, + false + ); + + if (!newOperator) { + return res.status(500).json({ + error: "Failed to create operator", + }); + } + + return res.status(201).json(newOperator); + }); + +// DELETE /api/operator - deletes an operator by discordId or discordUsername +/** + * @swagger + * /api/operator: + * delete: + * summary: Delete an operator by Discord ID or username + * description: Removes a node operator registration using either their Discord ID or username. + * tags: [NodeOperator] + * operationId: deleteOperator + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: discordId + * schema: + * type: string + * required: false + * description: The Discord ID of the operator to delete. + * - in: query + * name: discordUsername + * schema: + * type: string + * required: false + * description: The Discord username of the operator to delete. + * responses: + * 204: + * description: Operator deleted successfully (No Content). + * 400: + * description: Bad Request - Missing discordId or discordUsername parameter + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Operator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.delete( + "/", + async (req: Request, res: Response) => { + const discordId = req.query.discordId as string | undefined; + const discordUsername = req.query.discordUsername as string | undefined; + + if (!discordId && !discordUsername) { + return res + .status(400) + .json({ error: "Missing discordId or discordUsername parameter" }); + } + + let operatorToDelete: any = undefined; + let idToDelete: string | undefined = discordId; + + if (discordId) { + operatorToDelete = await nodeOperatorService.getOperatorByDiscordId(discordId); + } else if (discordUsername) { + operatorToDelete = await nodeOperatorService.getOperatorByDiscordUsername(discordUsername); + if (operatorToDelete) { + idToDelete = operatorToDelete.discordId; + } + } + + if (!operatorToDelete || !idToDelete) { + return res.status(404).json({ + error: "Operator not found", + }); + } + + const deleted = await nodeOperatorService.deleteOperatorByDiscordId(idToDelete); + if (deleted) { + return res.status(204).send(); + } else { + return res.status(500).json({ + error: "Failed to delete operator", + }); + } + }); + +// PUT /api/operator - updates the operator with a new wallet +/** + * @swagger + * /api/operator: + * put: + * summary: Update operator's wallet address + * description: Updates the wallet address for a specific node operator using their Discord ID or username. + * tags: [NodeOperator] + * operationId: updateOperator + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: discordId + * schema: + * type: string + * required: false + * description: The Discord ID of the operator to update. + * - in: query + * name: discordUsername + * schema: + * type: string + * required: false + * description: The Discord username of the operator to update. + * - in: query + * name: walletAddress + * schema: + * type: string + * required: true + * description: The new wallet address. + * responses: + * 200: + * description: Operator updated successfully. Returns the updated operator. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/NodeOperator' + * 400: + * description: Bad Request - Missing parameters + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Operator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.put( + "/", + async (req: Request, res: Response) => { + const discordId = req.query.discordId as string | undefined; + const discordUsername = req.query.discordUsername as string | undefined; + const walletAddress = req.query.walletAddress as string; + + if (!discordId && !discordUsername) { + return res.status(400).json({ + error: "Missing discordId or discordUsername query parameter" + }); + } + + if (!walletAddress) { + return res.status(400).json({ + error: "Missing walletAddress query parameter" + }); + } + + let operatorToUpdate: any = undefined; + let idToUpdate: string | undefined = discordId; + + // Find the operator + if (discordId) { + operatorToUpdate = await nodeOperatorService.getOperatorByDiscordId(discordId); + } else if (discordUsername) { + operatorToUpdate = await nodeOperatorService.getOperatorByDiscordUsername(discordUsername); + if (operatorToUpdate) { + idToUpdate = operatorToUpdate.discordId; + } + } + + if (!operatorToUpdate || !idToUpdate) { + return res.status(404).json({ + error: "Operator not found", + }); + } + + // Update wallet address + const updated = await nodeOperatorService.updateOperatorWallet( + idToUpdate, + walletAddress + ); + + if (!updated) { + return res.status(500).json({ + error: "Failed to update operator wallet", + }); + } + + // Fetch the updated operator to return + const updatedOperator = await nodeOperatorService.getOperatorByDiscordId(idToUpdate); + return res.status(200).json(updatedOperator); + }); + +// PUT /api/operator/approve - approves an operator +/** + * @swagger + * /api/operator/approve: + * put: + * summary: Approve a node operator + * description: Approves a node operator using their Discord ID or username. + * tags: [NodeOperator] + * operationId: approveOperator + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: discordId + * schema: + * type: string + * required: false + * description: The Discord ID of the operator to approve. + * - in: query + * name: discordUsername + * schema: + * type: string + * required: false + * description: The Discord username of the operator to approve. + * responses: + * 200: + * description: Operator approved successfully. Returns the updated operator. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/NodeOperator' + * 400: + * description: Bad Request - Missing parameters + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Operator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.put( + "/approve", + async (req: Request, res: Response) => { + const discordId = req.query.discordId as string | undefined; + const discordUsername = req.query.discordUsername as string | undefined; + + if (!discordId && !discordUsername) { + return res + .status(400) + .json({ error: "Missing discordId or discordUsername parameter" }); + } + + let operatorToApprove: any = undefined; + let idToApprove: string | undefined = discordId; + + // Find the operator + if (discordId) { + operatorToApprove = await nodeOperatorService.getOperatorByDiscordId(discordId); + } else if (discordUsername) { + operatorToApprove = await nodeOperatorService.getOperatorByDiscordUsername(discordUsername); + if (operatorToApprove) { + idToApprove = operatorToApprove.discordId; + } + } + + if (!operatorToApprove || !idToApprove) { + return res.status(404).json({ + error: "Operator not found", + }); + } + + const updated = await nodeOperatorService.updateApprovalStatus( + idToApprove, + true + ); + + if (updated) { + // Fetch the updated operator to return + const updatedOperator = + await nodeOperatorService.getOperatorByDiscordId(idToApprove); + return res.status(200).json(updatedOperator); + } else { + return res.status(500).json({ + error: "Failed to approve operator", + }); + } + }); + +// GET /api/operator/validators - returns all validators +/** + * @swagger + * /api/operator/validators: + * get: + * summary: Get all validators + * description: Retrieves a list of all validators in the system. + * tags: [NodeOperator] + * operationId: getAllValidators + * security: + * - ApiKeyAuth: [] + * responses: + * 200: + * description: A list of validators from blockchain and known validators in the database. + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * description: Indicates if the request was successful. + * example: true + * data: + * type: object + * properties: + * blockchainValidators: + * type: object + * properties: + * validators: + * type: array + * items: + * type: string + * description: List of all validator addresses from the blockchain. + * stats: + * type: object + * properties: + * totalValidators: + * type: number + * description: Total number of validators in the blockchain. + * knownValidators: + * type: object + * properties: + * validators: + * type: array + * items: + * type: string + * description: List of validator addresses that have matching operators in the database. + * stats: + * type: object + * properties: + * totalValidators: + * type: number + * description: Total number of validators with matching operators. + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.get("/validators", async (_req, res) => { + try { + // Get Ethereum instance to retrieve all validators from blockchain + const ethereum = await getEthereumInstance(); + const rollupInfo = await ethereum.getRollupInfo(); + const blockchainValidators = rollupInfo.validators; + + // Get ALL validators from the database (handle pagination) + let allValidators: Validator[] = []; + let nextPageToken: string | undefined = undefined; + + do { + // Fetch page of validators + const result = await validatorService.getAllValidators(nextPageToken); + + // Add to our collection + allValidators = [...allValidators, ...result.validators]; + + // Get next page token + nextPageToken = result.nextPageToken; + + // Log progress + logger.info(`Fetched ${result.validators.length} validators from database, total so far: ${allValidators.length}`); + + } while (nextPageToken); // Continue until no more pages + + // Log for debugging + logger.info(`Retrieved ${blockchainValidators.length} validators from blockchain and ${allValidators.length} total validators from database`); + + // For each validator in blockchain, find if it has an operator in our database + // Using case-insensitive comparison to match addresses + const validatorsWithOperators = blockchainValidators.filter(address => { + // Find a match in the database regardless of case + const dbValidator = allValidators.find(v => + v.validatorAddress.toLowerCase() === address.toLowerCase() + ); + return dbValidator; + }); + + // Log for debugging + logger.info(`Found ${validatorsWithOperators.length} validators with matching operators in database`); + + return res.status(200).json({ + success: true, + data: { + blockchainValidators: { + validators: blockchainValidators, + stats: { + totalValidators: blockchainValidators.length, + }, + }, + knownValidators: { + validators: validatorsWithOperators, + stats: { + totalValidators: validatorsWithOperators.length, + }, + }, + }, + }); + } catch (error) { + logger.error(error, "Error retrieving validators"); + res.status(500).json({ error: "Failed to retrieve validators" }); + } + return; +}); + +// GET /api/operator/validator - returns a specific validator by address +/** + * @swagger + * /api/operator/validator: + * get: + * summary: Get validator information + * description: Retrieves validator information either by validator address or by operator (discordId/username). + * tags: [NodeOperator] + * operationId: getValidator + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: address + * schema: + * type: string + * required: false + * description: The wallet address of the validator to retrieve. + * - in: query + * name: discordId + * schema: + * type: string + * required: false + * description: The Discord ID of the operator to get validators for. + * - in: query + * name: discordUsername + * schema: + * type: string + * required: false + * description: The Discord username of the operator to get validators for. + * responses: + * 200: + * description: The requested validator information or validators for an operator. + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * data: + * oneOf: + * - $ref: '#/components/schemas/ValidatorResponse' + * - type: array + * items: + * $ref: '#/components/schemas/ValidatorResponse' + * 400: + * description: Bad Request - Missing or invalid query parameters + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Validator or operator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.get("/validator", async (req, res) => { + try { + const address = req.query.address as string | undefined; + const discordId = req.query.discordId as string | undefined; + const discordUsername = req.query.discordUsername as string | undefined; + + // Require at least one parameter + if (!address && !discordId && !discordUsername) { + return res.status(400).json({ + error: "At least one parameter is required: address, discordId, or discordUsername" + }); + } + + // Get Ethereum instance to access validators + const ethereum = await getEthereumInstance(); + const rollupInfo = await ethereum.getRollupInfo(); + + // Case 1: Lookup by validator address + if (address) { + // Check if address is a known validator + if (!rollupInfo.validators.includes(address)) { + // Try case-insensitive check before failing + const foundValidator = rollupInfo.validators.find(v => + v.toLowerCase() === address.toLowerCase() + ); + + if (!foundValidator) { + return res.status(404).json({ error: "Validator not found" }); + } + } + + // Find if this validator is associated with an operator + let dbValidator = await validatorService.getValidatorByAddress(address); + + // If not found by exact match, try case-insensitive match + if (!dbValidator) { + // Get ALL validators from the database (handle pagination) to find a case-insensitive match + let allValidators: any[] = []; + let nextPageToken: string | undefined = undefined; + + logger.info(`Validator not found by exact match, trying case-insensitive search for: ${address}`); + + do { + // Fetch page of validators + const result = await validatorService.getAllValidators(nextPageToken); + + // Add to our collection + allValidators = [...allValidators, ...result.validators]; + + // Get next page token + nextPageToken = result.nextPageToken; + + } while (nextPageToken); // Continue until no more pages + + // Now search through all validators with case-insensitive comparison + const matchingValidator = allValidators.find(v => + v.validatorAddress.toLowerCase() === address.toLowerCase() + ); + + if (matchingValidator) { + logger.info(`Found case-insensitive match for ${address}: ${matchingValidator.validatorAddress}`); + dbValidator = matchingValidator; + } else { + logger.info(`No case-insensitive match found for ${address} in ${allValidators.length} validators`); + } + } + + // Get operator info if validator has an associated operator + let operatorInfo = null; + if (dbValidator) { + operatorInfo = await nodeOperatorService.getOperatorByDiscordId(dbValidator.nodeOperatorId); + } + + return res.status(200).json({ + success: true, + data: { + address, + operatorId: dbValidator ? dbValidator.nodeOperatorId : null, + operatorInfo: operatorInfo || null, + stats: { + totalValidators: rollupInfo.validators.length, + }, + }, + }); + } + + // Case 2: Lookup by operator (discordId or discordUsername) + // Determine the operator's Discord ID + let operatorId = discordId; + let operator = null; + + if (discordId) { + operator = await nodeOperatorService.getOperatorByDiscordId(discordId); + } else if (discordUsername) { + operator = await nodeOperatorService.getOperatorByDiscordUsername(discordUsername); + if (operator) { + operatorId = operator.discordId; + } + } + + if (!operator || !operatorId) { + return res.status(404).json({ error: "Operator not found" }); + } + + // Get all validators for this operator + const validators = await validatorService.getValidatorsByNodeOperator(operatorId); + + // Get detailed info for each validator + const validatorDetails = validators.map(validator => { + const isInRollup = rollupInfo.validators.includes(validator.validatorAddress); + + return { + address: validator.validatorAddress, + operatorId: validator.nodeOperatorId, + isActive: isInRollup, // Whether the validator is active in the rollup + }; + }); + + return res.status(200).json({ + success: true, + data: { + operator: operator, + validators: validatorDetails, + stats: { + totalValidators: rollupInfo.validators.length, + operatorValidators: validators.length, + }, + }, + }); + } catch (error) { + logger.error(error, "Error retrieving validator"); + res.status(500).json({ error: "Failed to retrieve validator" }); + } + return; +}); + +// POST /api/operator/validator - adds a new validator +/** + * @swagger + * /api/operator/validator: + * post: + * summary: Add a new validator + * description: Adds a new validator and associates it with an operator. + * tags: [NodeOperator] + * operationId: addValidator + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: discordId + * schema: + * type: string + * required: false + * description: The Discord ID of the operator to associate with this validator. + * - in: query + * name: discordUsername + * schema: + * type: string + * required: false + * description: The Discord username of the operator to associate with this validator. + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * validatorAddress: + * type: string + * description: The validator address to add. + * example: "0x1234567890abcdef1234567890abcdef12345678" + * required: + * - validatorAddress + * responses: + * 201: + * description: Validator added successfully. + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * data: + * $ref: '#/components/schemas/ValidatorResponse' + * 400: + * description: Bad Request - Missing or invalid parameters + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Operator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.post("/validator", async (req, res) => { + try { + const { validatorAddress } = req.body; + const discordId = req.query.discordId as string | undefined; + const discordUsername = req.query.discordUsername as string | undefined; + + // Validate input parameters + if (!validatorAddress) { + return res.status(400).json({ + error: "Missing required parameter: validatorAddress", + }); + } + + if (!discordId && !discordUsername) { + return res.status(400).json({ + error: "Missing required parameter: either discordId or discordUsername must be provided as a query parameter", + }); + } + + // Basic address validation + if (!/^0x[a-fA-F0-9]{40}$/.test(validatorAddress)) { + return res.status(400).json({ + error: "Invalid validator address format", + }); + } + + // Find operator by discordId or discordUsername + let operator; + let operatorId = discordId; + + if (discordId) { + operator = await nodeOperatorService.getOperatorByDiscordId(discordId); + } else if (discordUsername) { + operator = await nodeOperatorService.getOperatorByDiscordUsername(discordUsername); + if (operator) { + operatorId = operator.discordId; + } + } + + if (!operator || !operatorId) { + return res.status(404).json({ + error: "Node operator not found", + }); + } + + // Check if the operator is approved + if (!operator.isApproved) { + return res.status(403).json({ + error: "Node operator is not approved", + message: "Your account requires approval before adding validators." + }); + } + + // Get Ethereum instance and add validator to rollup + const ethereum = await getEthereumInstance(); + await ethereum.addValidator(validatorAddress); + + // Add the validator to the operator in the database + await nodeOperatorService.addValidatorToOperator(operatorId, validatorAddress); + + // Get the validator count for this operator + const operatorValidators = await validatorService.getValidatorsByNodeOperator(operatorId); + + // Get the updated validators count for stats + const rollupInfo = await ethereum.getRollupInfo(); + + return res.status(201).json({ + success: true, + data: { + address: validatorAddress, + operatorId: operatorId, + operatorInfo: operator, + stats: { + totalValidators: rollupInfo.validators.length, + operatorValidators: operatorValidators.length, + }, + }, + }); + } catch (error) { + logger.error(error, "Error adding validator"); + res.status(500).json({ error: "Failed to add validator" }); + } + return; +}); + +// PUT /api/operator/validator - updates a validator's associated operator +/** + * @swagger + * /api/operator/validator: + * put: + * summary: Update validator's operator + * description: Transfers a validator from one operator to another. + * tags: [NodeOperator] + * operationId: updateValidator + * security: + * - ApiKeyAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * validatorAddress: + * type: string + * description: The validator address to transfer. + * example: "0x1234567890abcdef1234567890abcdef12345678" + * fromDiscordId: + * type: string + * description: The Discord ID of the current operator. + * example: "123456789012345678" + * toDiscordId: + * type: string + * description: The Discord ID of the new operator to transfer to. + * example: "987654321098765432" + * required: + * - validatorAddress + * - fromDiscordId + * - toDiscordId + * responses: + * 200: + * description: Validator transferred successfully. + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * data: + * $ref: '#/components/schemas/ValidatorResponse' + * 400: + * description: Bad Request - Missing or invalid parameters + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Operator or validator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.put("/validator", async (req, res) => { + try { + const { validatorAddress, fromDiscordId, toDiscordId } = req.body; + + // Validate input parameters + if (!validatorAddress || !fromDiscordId || !toDiscordId) { + return res.status(400).json({ + error: "Missing required parameters", + }); + } + + // Basic address validation + if (!/^0x[a-fA-F0-9]{40}$/.test(validatorAddress)) { + return res.status(400).json({ + error: "Invalid validator address format", + }); + } + + // Check if operators exist + const fromOperator = await nodeOperatorService.getOperatorByDiscordId(fromDiscordId); + const toOperator = await nodeOperatorService.getOperatorByDiscordId(toDiscordId); + + if (!fromOperator) { + return res.status(404).json({ + error: "Source operator not found", + }); + } + + if (!toOperator) { + return res.status(404).json({ + error: "Destination operator not found", + }); + } + + // Check if the validator exists in the database + const validator = await validatorService.getValidatorByAddress(validatorAddress); + + if (!validator) { + return res.status(404).json({ + error: "Validator not found in the database", + }); + } + + // Check if the validator is associated with the fromOperator + if (validator.nodeOperatorId !== fromDiscordId) { + return res.status(404).json({ + error: "Validator not found for the source operator", + }); + } + + // Get Ethereum instance to verify the validator exists + const ethereum = await getEthereumInstance(); + const rollupInfo = await ethereum.getRollupInfo(); + + if (!rollupInfo.validators.includes(validatorAddress)) { + return res.status(404).json({ + error: "Validator not found in the rollup", + }); + } + + // Update the validator to be associated with the new operator + await validatorService.updateValidatorOperator(validatorAddress, toDiscordId); + + // Get validator counts for both operators + const fromOperatorValidators = await validatorService.getValidatorsByNodeOperator(fromDiscordId); + const toOperatorValidators = await validatorService.getValidatorsByNodeOperator(toDiscordId); + + return res.status(200).json({ + success: true, + data: { + address: validatorAddress, + operatorId: toDiscordId, + previousOperatorId: fromDiscordId, + stats: { + totalValidators: rollupInfo.validators.length, + sourceOperatorValidators: fromOperatorValidators.length, + destinationOperatorValidators: toOperatorValidators.length, + }, + }, + }); + } catch (error) { + logger.error(error, "Error transferring validator"); + res.status(500).json({ error: "Failed to transfer validator" }); + } + return; +}); + +// DELETE /api/operator/validator - removes a validator from an operator +/** + * @swagger + * /api/operator/validator: + * delete: + * summary: Remove a validator + * description: Removes a validator from an operator's list of validators. + * tags: [NodeOperator] + * operationId: removeValidator + * security: + * - ApiKeyAuth: [] + * parameters: + * - in: query + * name: validatorAddress + * schema: + * type: string + * required: true + * description: The validator address to remove. + * - in: query + * name: discordId + * schema: + * type: string + * required: true + * description: The Discord ID of the operator. + * responses: + * 204: + * description: Validator removed successfully. + * 400: + * description: Bad Request - Missing or invalid parameters + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 401: + * description: Unauthorized - Invalid or missing API key + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 404: + * description: Operator or validator not found + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + * 500: + * description: Internal Server Error + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/OperatorError' + */ +router.delete("/validator", async (req, res) => { + try { + const validatorAddress = req.query.validatorAddress as string; + const discordId = req.query.discordId as string; + + // Validate input parameters + if (!validatorAddress || !discordId) { + return res.status(400).json({ + error: "Missing required parameters: validatorAddress or discordId", + }); + } + + // Basic address validation + if (!/^0x[a-fA-F0-9]{40}$/.test(validatorAddress)) { + return res.status(400).json({ + error: "Invalid validator address format", + }); + } + + // Check if operator exists + const operator = await nodeOperatorService.getOperatorByDiscordId(discordId); + if (!operator) { + return res.status(404).json({ + error: "Node operator not found", + }); + } + + // Check if the validator exists and is associated with the operator + const validator = await validatorService.getValidatorByAddress(validatorAddress); + + if (!validator) { + return res.status(404).json({ + error: "Validator not found", + }); + } + + if (validator.nodeOperatorId !== discordId) { + return res.status(404).json({ + error: "Validator not found for this operator", + }); + } + + // Delete the validator + const success = await validatorService.deleteValidator(validatorAddress); + + if (!success) { + return res.status(500).json({ + error: "Failed to remove validator", + }); + } + + // Optionally, you could also call ethereum.removeValidator(validatorAddress) + // if there's a need to remove from the blockchain as well + + return res.status(204).send(); + } catch (error) { + logger.error(error, "Error removing validator"); + res.status(500).json({ error: "Failed to remove validator" }); + } + return; +}); + +export default router; diff --git a/tooling/sparta/packages/express/src/types/dynamo-db.d.ts b/tooling/sparta/packages/express/src/types/dynamo-db.d.ts new file mode 100644 index 0000000..c4cd17f --- /dev/null +++ b/tooling/sparta/packages/express/src/types/dynamo-db.d.ts @@ -0,0 +1,17 @@ +import type { User } from "../routes/users/users"; + +// Extend the DynamoDBService type from @sparta/utils +declare module "@sparta/utils/dynamo-db" { + export default interface DynamoDBService { + // User operations + getUser(discordUserId: string): Promise; + getUserByWalletAddress(walletAddress: string): Promise; + getAllUsers(): Promise; + createUser(user: User): Promise; + updateUser( + discordUserId: string, + updates: Partial + ): Promise; + deleteUser(discordUserId: string): Promise; + } +} diff --git a/tooling/sparta/packages/express/tsconfig.json b/tooling/sparta/packages/express/tsconfig.json new file mode 100644 index 0000000..374dfa1 --- /dev/null +++ b/tooling/sparta/packages/express/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist"], + "references": [{ "path": "../utils" }, { "path": "../ethereum" }] +} diff --git a/tooling/sparta/packages/scheduler/README.md b/tooling/sparta/packages/scheduler/README.md new file mode 100644 index 0000000..ff69397 --- /dev/null +++ b/tooling/sparta/packages/scheduler/README.md @@ -0,0 +1,84 @@ +# @sparta/scheduler + +A serverless AWS Lambda-based service for monitoring validators and sending alerts when issues are detected. + +## Overview + +- Serverless AWS Lambda-based validator monitoring +- EventBridge scheduled triggers (default: hourly) +- Alerts sent to operators via Discord +- Summary reports posted to admin channels +- Lightweight Discord messaging via REST API + +## Local Development + +```bash +# Run locally +bun run dev +``` + +## Configuration + +Required environment variables: + +``` +# API Configuration +API_URL=http://localhost:3000 +BACKEND_API_KEY=your-api-key + +# AWS Configuration +AWS_REGION=eu-west-2 + +# Discord Configuration +NODE_ENV=development # Use 'production' for live systems +BOT_TOKEN=your-discord-bot-token +BOT_CLIENT_ID=your-discord-client-id +GUILD_ID=your-discord-guild-id + +# Logging +LOG_LEVEL=debug +``` + +## Deployment + +Deploy using Terraform (see project root's terraform directory): + +```terraform +resource "aws_lambda_function" "validator_monitor" { + function_name = "sparta-validator-monitor" + role = aws_iam_role.lambda_execution_role.arn + handler = "lambda.handler" + runtime = "nodejs18.x" + filename = "lambda-package.zip" + timeout = 300 # 5 minutes + memory_size = 256 # MB + + environment { + variables = { + NODE_ENV = var.environment + API_URL = "http://${aws_lb.sparta_alb.dns_name}" + BACKEND_API_KEY = var.backend_api_key + BOT_TOKEN = var.discord_bot_token + BOT_CLIENT_ID = var.discord_client_id + GUILD_ID = var.discord_guild_id + LOG_LEVEL = var.log_level + } + } +} +``` + +## AWS Lambda Best Practices + +This implementation follows AWS Lambda best practices: + +1. **Optimized handler**: Streamlined execution with minimal overhead +2. **Proper error handling**: All errors are caught and logged without crashing Lambda +3. **Connection reuse**: API connections are reused between invocations +4. **callbackWaitsForEmptyEventLoop = false**: Lambda returns promptly without waiting for event loop +5. **Minimal dependencies**: Only requires essential packages +6. **Efficient validation logic**: Early returns for valid validators +7. **Lightweight Discord messaging**: Uses REST API instead of full Discord client + +## License + +See the project license for details. \ No newline at end of file diff --git a/tooling/sparta/packages/scheduler/package.json b/tooling/sparta/packages/scheduler/package.json new file mode 100644 index 0000000..49bd642 --- /dev/null +++ b/tooling/sparta/packages/scheduler/package.json @@ -0,0 +1,19 @@ +{ + "name": "@sparta/scheduler", + "version": "0.1.0", + "type": "commonjs", + "main": "src/lambda.js", + "scripts": { + "dev": "bun run src/local-invoke.js", + "build": "rm -rf dist && esbuild ./src/*.js --entry-names=[dir]/[name]/index --bundle --minify --sourcemap --platform=node --target=node16.14 --outdir=dist && zip -r lambda-package.zip dist" + }, + "dependencies": { + "@sparta/utils": "workspace:*", + "@sparta/ethereum": "workspace:*", + "@sparta/discord": "workspace:*", + "openapi-client-axios": "^7.5.1" + }, + "devDependencies": { + "aws-sdk": "^2.1499.0" + } +} \ No newline at end of file diff --git a/tooling/sparta/packages/scheduler/src/lambda.js b/tooling/sparta/packages/scheduler/src/lambda.js new file mode 100644 index 0000000..638414a --- /dev/null +++ b/tooling/sparta/packages/scheduler/src/lambda.js @@ -0,0 +1,60 @@ +// AWS Lambda handler for validator monitoring +const { logger } = require("@sparta/utils"); +const { ValidatorMonitorService } = require('./validator-monitor'); + +// Singleton validator monitor service instance +let validatorMonitor; + +/** + * Lambda handler for validator monitoring + * Can be triggered by EventBridge scheduled events or manually invoked + */ +exports.handler = async (event, context) => { + // Prevent Lambda from waiting for event loop to empty before returning + // Important for external connections like Discord API + context.callbackWaitsForEmptyEventLoop = false; + + try { + // Initialize service if needed + if (!validatorMonitor) { + validatorMonitor = await ValidatorMonitorService.new(); + } + + logger.info("Starting validator monitoring", { + requestId: context.awsRequestId, + eventSource: event.source || 'manual' + }); + + // Run the validator monitoring process + const reports = await validatorMonitor.monitorValidators(); + + // Return success response + return { + statusCode: 200, + body: JSON.stringify({ + message: "Validator monitoring completed successfully", + timestamp: new Date().toISOString(), + requestId: context.awsRequestId, + reportsCount: reports.length, + summary: reports.length > 0 ? "Issues detected" : "No validator issues detected" + }) + }; + } catch (error) { + // Log the error but don't crash the Lambda + logger.error({ + error: error.message, + stack: error.stack + }, "Error in validator monitoring lambda"); + + // Return error response + return { + statusCode: 500, + body: JSON.stringify({ + message: "Error executing validator monitoring", + error: error.message, + timestamp: new Date().toISOString(), + requestId: context.awsRequestId + }) + }; + } +}; \ No newline at end of file diff --git a/tooling/sparta/packages/scheduler/src/local-invoke.js b/tooling/sparta/packages/scheduler/src/local-invoke.js new file mode 100644 index 0000000..e4f6dca --- /dev/null +++ b/tooling/sparta/packages/scheduler/src/local-invoke.js @@ -0,0 +1,32 @@ +const { handler } = require('./lambda'); +const { logger } = require('@sparta/utils'); + +// Mock AWS Lambda context +const mockContext = { + awsRequestId: `local-${Date.now()}`, + functionName: 'validator-monitor-local', + getRemainingTimeInMillis: () => 300000, // 5 minutes + callbackWaitsForEmptyEventLoop: true +}; + +// Mock scheduled event +const mockEvent = { + source: 'aws.events', + 'detail-type': 'Scheduled Event', + time: new Date().toISOString() +}; + +// Execute the Lambda function locally +async function invokeLocally() { + logger.info('Invoking Lambda function locally...'); + + try { + const result = await handler(mockEvent, mockContext); + console.log('Lambda execution result:', JSON.stringify(result, null, 2)); + } catch (error) { + logger.error('Error invoking Lambda function locally:', error); + } +} + +// Run the local invocation +invokeLocally(); \ No newline at end of file diff --git a/tooling/sparta/packages/scheduler/src/validator-monitor.js b/tooling/sparta/packages/scheduler/src/validator-monitor.js new file mode 100644 index 0000000..01cf95d --- /dev/null +++ b/tooling/sparta/packages/scheduler/src/validator-monitor.js @@ -0,0 +1,194 @@ +const { logger, CHANNELS } = require("@sparta/utils"); +const { l2InfoService } = require("@sparta/ethereum"); +const { clientPromise } = require("@sparta/utils/openapi/api/axios"); +const { discordWebhookService } = require("@sparta/discord"); + +/** + * Service to monitor validator status and alert operators + */ +class ValidatorMonitorService { + constructor(client) { + this.client = client; + this.discordService = discordWebhookService; // Using lightweight webhook service + this.isDev = process.env.NODE_ENV !== "production"; + } + + static async new() { + const client = await clientPromise; + return new ValidatorMonitorService(client); + } + + /** + * Check a single validator's status and send alerts if needed + * @param {string} validator - Validator address + * @param {Array} activeValidators - List of active validators + */ + async processValidator(validator, activeValidators) { + try { + // Check if validator is in active set + const isInValidatorSet = activeValidators.includes(validator); + + // Skip processing if validator is active and attesting + if (isInValidatorSet) { + // Check attestation stats + const validatorStats = await l2InfoService.fetchValidatorStats(validator); + + if (validatorStats.totalSlots && validatorStats.missedAttestationsCount !== undefined) { + const missPercent = (validatorStats.missedAttestationsCount / validatorStats.totalSlots) * 100; + + // Only alert if missing too many attestations (>20%) + if (missPercent < 20) { + return null; // Validator is working well, no alert needed + } + } else { + return null; // No stats available, assume it's working + } + } + + // At this point, we have a validator that either: + // 1. Is not in the active set + // 2. Is missing too many attestations + + // Get validator details to find operator for notification + const { data: { data: validatorData } } = await this.client.getValidator(validator); + + if (!validatorData || !validatorData.operatorInfo?.discordUsername) { + logger.warn(`No operator info found for validator ${validator}`); + return null; + } + + // Calculate miss percentage for reporting + let missPercentage = "N/A"; + let alertReason = ""; + + if (!isInValidatorSet) { + alertReason = "not in active validator set"; + } else { + // We already calculated this earlier but need to do it again + // since we early-returned if everything was fine + const stats = await l2InfoService.fetchValidatorStats(validator); + if (stats.totalSlots && stats.missedAttestationsCount !== undefined) { + missPercentage = ((stats.missedAttestationsCount / stats.totalSlots) * 100).toFixed(2) + "%"; + alertReason = `missing attestations (${missPercentage})`; + } + } + + // Create alert message + const messageContent = `**Validator Alert**\n\nHello ${validatorData.operatorInfo.discordUsername},\n\n` + + `Your validator ${validator} is ${alertReason}. Please check your node status.\n\n` + + `If you need assistance, please reach out in the <#${CHANNELS.OPERATORS_START_HERE.id}> channel.`; + + // Send Discord alert using the lightweight service + const targetDiscordId = this.isDev ? "411954463541166080" : validatorData.operatorId; + let dmSent = false; + let error = null; + + try { + if (targetDiscordId) { + dmSent = await this.discordService.sendDirectMessage(targetDiscordId, messageContent); + + if (dmSent) { + logger.info(`Alert sent to ${validatorData.operatorInfo.discordUsername} for validator ${validator}`); + } else { + error = "Discord webhook service returned false"; + } + } else { + error = "Missing Discord ID"; + } + } catch (dmError) { + error = dmError.message; + logger.error(`Failed to send alert for validator ${validator}: ${error}`); + } + + // Return report of the alert + return { + validatorAddress: validator, + operatorId: validatorData.operatorId, + operatorDiscordUsername: validatorData.operatorInfo.discordUsername, + messageContent: messageContent, + missPercentage: missPercentage, + timestamp: new Date().toISOString(), + dmSent: dmSent, + error: error + }; + } catch (error) { + logger.error(`Error processing validator ${validator}: ${error.message}`); + return null; + } + } + + /** + * Monitor all validators and report issues + */ + async monitorValidators() { + try { + logger.info("Starting validator monitoring..."); + + // Get all validators + const { data: { data: validatorsData } } = await this.client.getAllValidators(); + + if (!validatorsData || !validatorsData.knownValidators?.validators) { + logger.error("Failed to get validators from API"); + return []; + } + + const validators = validatorsData.knownValidators.validators; + logger.info(`Found ${validators.length} validators to check`); + + // Process validators in parallel + const reports = []; + const results = await Promise.allSettled( + validators.map(validator => this.processValidator(validator, validators)) + ); + + // Filter valid reports (removing null/rejected promises) + results.forEach(result => { + if (result.status === 'fulfilled' && result.value) { + reports.push(result.value); + } + }); + + // Send summary report if needed + if (reports.length > 0) { + await this.sendSummaryReport(reports); + } + + logger.info(`Validator monitoring completed. Found ${reports.length} issues.`); + return reports; + } catch (error) { + logger.error(`Error monitoring validators: ${error.message}`); + return []; + } + } + + /** + * Send a summary report to the mod-bot channel using webhook service + */ + async sendSummaryReport(reports) { + try { + const channelId = this.isDev ? CHANNELS.BOT_TEST.id : CHANNELS.MOD_BOT.id; + + // Create summary message + let message = "# Validator Alert Summary\n\n"; + message += `**Time:** ${new Date().toISOString()}\n`; + message += `**Total Alerts:** ${reports.length}\n\n`; + + // Add brief information about each alert + reports.forEach(report => { + message += `- **${report.validatorAddress}** (${report.operatorDiscordUsername}): `; + message += report.messageContent.includes('not in active validator set') ? + 'Not in validator set' : `Missing attestations (${report.missPercentage})`; + message += report.dmSent ? ' - Alert sent' : ` - Alert failed: ${report.error}`; + message += '\n'; + }); + + // Send to Discord channel using webhook service + await this.discordService.sendChannelMessage(channelId, message); + logger.info(`Sent summary report to channel ${channelId}`); + } catch (error) { + logger.error(`Error sending summary report: ${error.message}`); + } + } +} + +module.exports = { ValidatorMonitorService }; \ No newline at end of file diff --git a/tooling/sparta/packages/utils/README.md b/tooling/sparta/packages/utils/README.md new file mode 100644 index 0000000..de52f6e --- /dev/null +++ b/tooling/sparta/packages/utils/README.md @@ -0,0 +1,148 @@ +# @sparta/utils + +Shared utilities for the Sparta Discord bot and supporting services. + +## Overview + +This package provides common utilities and shared functionality used across the Sparta project: + +- Logging with configurable levels and formats +- DynamoDB interactions for session and data storage +- Constants and configuration values +- OpenAPI definitions and client generators + +## Usage + +```typescript +// Import utilities +import { logger, dynamoDB as DynamoDBServiceClass } from '@sparta/utils'; + +// Use logger +logger.info('This is an informational message'); +logger.error({ err: new Error('example') }, 'An error occurred'); + +// Use DynamoDBService +// 1. Instantiate the service for a specific table +const myTableService = new DynamoDBServiceClass('your-table-name'); + +// 2. Get the configured client +const docClient = myTableService.getClient(); + +// 3. Use the client with DynamoDB commands (example) +// async function getItemExample(key: any) { +// const command = new GetCommand({ TableName: myTableService.getTableName(), Key: key }); +// try { +// const data = await docClient.send(command); +// logger.info({ data }, "Item retrieved"); +// return data.Item; +// } catch (err) { +// logger.error({ err }, "Error getting item"); +// } +// } +``` + +## Components + +### Logger + +Configurable logging utility built on Pino: + +```typescript +import { logger } from '@sparta/utils'; + +// Different log levels +logger.trace('Detailed trace information'); +logger.debug('Debug information'); +logger.info('General information'); +logger.warn('Warning'); +logger.error('Error information'); +logger.fatal('Critical error'); +``` + +Configuration via environment variables: +- `LOG_LEVEL`: Set minimum log level (trace, debug, info, warn, error, fatal) +- `LOG_PRETTY_PRINT`: Enable/disable formatted logs (true/false) + +### DynamoDB Client + +The `DynamoDBService` class provides a convenient way to get a configured AWS SDK v3 `DynamoDBDocumentClient` for a specific DynamoDB table. + +**Setup:** + +Import the class from `@sparta/utils`: +```typescript +import { dynamoDB as DynamoDBServiceClass } from '@sparta/utils'; +// or +// import DynamoDBServiceClass from '@sparta/utils/dynamo-db'; // if importing directly +``` + +**Instantiate for your table:** +```typescript +const TABLE_NAME = process.env.MY_DYNAMODB_TABLE || 'my-default-table'; +const dbService = new DynamoDBServiceClass(TABLE_NAME); +``` + +**Get the client:** +The `getClient()` method returns an instance of `DynamoDBDocumentClient`. +```typescript +const docClient = dbService.getClient(); +``` + +**Example: Putting an item:** +```typescript +import { PutCommand } from "@aws-sdk/lib-dynamodb"; + +async function createItem(itemData: Record) { + const command = new PutCommand({ + TableName: dbService.getTableName(), // Use getTableName() for safety + Item: itemData, + }); + + try { + await docClient.send(command); + logger.info({ itemData }, "Successfully put item into table"); + return true; + } catch (err) { + logger.error({ err }, "Error putting item into table"); + return false; + } +} + +// Example usage: +// createItem({ id: 'example-123', name: 'Test Item', value: 100 }); +``` + +The service handles local DynamoDB configuration via `LOCAL_DYNAMO_DB` and `DYNAMODB_LOCAL_ENDPOINT` environment variables. + +### Constants + +Shared constants used across the project: + +```typescript +import { ROLE_NAMES } from '@sparta/utils/const'; + +console.log(ROLE_NAMES.SENTINEL); // "Sentinel" +``` + +### OpenAPI + +OpenAPI schema and client generators: + +```typescript +import { apiDocs } from '@sparta/utils'; +import { ApiProvider } from '@sparta/utils/openapi/api/apiProvider'; + +// Use API docs for documentation +console.log(apiDocs.info.title); + +// Create API client +const apiClient = await ApiProvider.getClient(); +``` + +## Development + +To build types: + +```bash +bun run types +``` \ No newline at end of file diff --git a/tooling/sparta/packages/utils/const/channels.ts b/tooling/sparta/packages/utils/const/channels.ts new file mode 100644 index 0000000..e8965b4 --- /dev/null +++ b/tooling/sparta/packages/utils/const/channels.ts @@ -0,0 +1,45 @@ +/** + * @fileoverview Channel definitions for Discord communication + * @description Provides channel constants for communicating with Discord + * @module sparta/utils/const/channels + */ + +/** + * Interface for channel definition + */ +export interface Channel { + name: string; + id: string; +} + +/** + * Channel definitions used throughout the application + */ +export const CHANNELS = { + MOD_BOT: { name: "mod-bot", id: "1367117045963161685" }, + BOT_TEST: { name: "bot-test", id: "1329081299490570296" }, + OPERATORS_START_HERE: { name: "operators | start-here", id: "1367196595866828982" }, +}; + +/** + * Get allowed channels based on environment + * @returns Array of channel IDs allowed in the current environment + */ +export function getAllowedChannelIds(): string[] { + const environment = process.env.NODE_ENV || "development"; + + return environment === "production" + ? [CHANNELS.MOD_BOT.id, CHANNELS.BOT_TEST.id] + : [CHANNELS.BOT_TEST.id]; +} + +/** + * Gets a string describing the allowed channels based on the current environment + * @returns A formatted string of allowed channel names + */ +export function getAllowedChannelsText(): string { + const environment = process.env.NODE_ENV || "development"; + return environment === "production" + ? `#${CHANNELS.MOD_BOT.name} or #${CHANNELS.BOT_TEST.name}` + : `#${CHANNELS.BOT_TEST.name}`; +} \ No newline at end of file diff --git a/tooling/sparta/packages/utils/const/index.ts b/tooling/sparta/packages/utils/const/index.ts new file mode 100644 index 0000000..2517ec7 --- /dev/null +++ b/tooling/sparta/packages/utils/const/index.ts @@ -0,0 +1,2 @@ +export * from "./verificationStatus.js"; +export * from "./channels.js"; diff --git a/tooling/sparta/packages/utils/const/roles.ts b/tooling/sparta/packages/utils/const/roles.ts new file mode 100644 index 0000000..8180fbc --- /dev/null +++ b/tooling/sparta/packages/utils/const/roles.ts @@ -0,0 +1,28 @@ +export type Role = { + name: string; + id: string; +}; + +/** + * Moderator role definitions mapping role names to their Discord IDs + */ +export const MODERATOR_ROLES: Record = { + AZTEC_LABS_TEAM: { name: "Aztec Labs Team", id: "1144693819015700620" }, + AZMOD: { name: "AzMod", id: "1362901049803018513" }, + ADMIN: { name: "Admin", id: "1146246812299165817" }, +}; + +/** + * Node operator role definitions mapping role names to their Discord IDs + */ +export const NODE_OPERATOR_ROLES: Record = { + APPRENTICE: { name: "Apprentice", id: "1366916508072148992" }, + GUARDIAN: { name: "Guardian", id: "1366921013350371328" }, +}; + +/** + * Developer role definitions mapping role names to their Discord IDs + */ +export const DEVELOPER_ROLES: Record = { + DEVELOPER: { name: "Developer", id: "1367015094638346271" }, +}; diff --git a/tooling/sparta/packages/utils/const/verificationStatus.ts b/tooling/sparta/packages/utils/const/verificationStatus.ts new file mode 100644 index 0000000..835a613 --- /dev/null +++ b/tooling/sparta/packages/utils/const/verificationStatus.ts @@ -0,0 +1,8 @@ +// Removed ADDRESSES_PER_PAGE constant as it's no longer used + +// Command enums have been moved to packages/discord/src/roles/types.ts + +// Verification Message +export const VERIFICATION_MESSAGE = "Verify wallet ownership for Aztec Discord"; + +// Removed old status constants related to background queue diff --git a/tooling/sparta/packages/utils/dynamo-db.ts b/tooling/sparta/packages/utils/dynamo-db.ts new file mode 100644 index 0000000..bf7b93c --- /dev/null +++ b/tooling/sparta/packages/utils/dynamo-db.ts @@ -0,0 +1,61 @@ +/** + * @fileoverview Provides a configured DynamoDB DocumentClient for a specified table. + * @description Service class to interact with AWS DynamoDB. + */ + +import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; +import { + DynamoDBDocumentClient, + // Import specific commands only if this class provides direct helper methods for them. + // GetCommand, PutCommand, UpdateCommand, DeleteCommand, QueryCommand, +} from "@aws-sdk/lib-dynamodb"; +import { logger } from "./logger.js"; + +class DynamoDBService { + private client: DynamoDBDocumentClient; + private tableName: string; + private isLocal: boolean; + + constructor(tableName: string) { + this.tableName = tableName; + this.isLocal = process.env.LOCAL_DYNAMO_DB === "true"; + + // Create the DynamoDB client + const clientOptions: ConstructorParameters[0] = {}; + + // Use local DynamoDB when running locally + if (this.isLocal) { + clientOptions.endpoint = + process.env.DYNAMODB_LOCAL_ENDPOINT || "http://localhost:8000"; + logger.info(`Using local DynamoDB at ${clientOptions.endpoint} for table ${this.tableName}`); + } else { + // Add region if not local and if it's configured, e.g., process.env.AWS_REGION + if (process.env.AWS_REGION) { + clientOptions.region = process.env.AWS_REGION; + } + logger.info(`Using AWS DynamoDB ${clientOptions.region ? 'in region ' + clientOptions.region : ''} for table ${this.tableName}`); + } + + const dynamoClient = new DynamoDBClient(clientOptions); + this.client = DynamoDBDocumentClient.from(dynamoClient); + logger.debug(`DynamoDBService initialized for table: ${this.tableName}`); + } + + /** + * Exposes the underlying DynamoDBDocumentClient for direct use. + * @returns The configured DynamoDBDocumentClient instance. + */ + public getClient(): DynamoDBDocumentClient { + return this.client; + } + + /** + * Gets the table name this service instance is configured for. + * @returns The DynamoDB table name. + */ + public getTableName(): string { + return this.tableName; + } +} + +export default DynamoDBService; diff --git a/tooling/sparta/packages/utils/index.ts b/tooling/sparta/packages/utils/index.ts new file mode 100644 index 0000000..2e45e25 --- /dev/null +++ b/tooling/sparta/packages/utils/index.ts @@ -0,0 +1,13 @@ +/** + * @fileoverview Common utils for Sparta + */ + +// export * from "./ethereum.js"; // Remove export - Server-side specific +// Note: Ethereum functionality has been moved to @sparta/ethereum package +export { logger } from "./logger.js"; +export { default as dynamoDB } from "./dynamo-db.js"; +// export * from "./inputValidator.js"; // Remove export - Discord specific +export * from "./const/index.js"; +export type { OpenAPIV3 } from "openapi-types"; +import apiDocs from "./openapi/api-docs.json"; +export { apiDocs }; diff --git a/tooling/sparta/packages/utils/inputValidator.ts b/tooling/sparta/packages/utils/inputValidator.ts new file mode 100644 index 0000000..f99e1d7 --- /dev/null +++ b/tooling/sparta/packages/utils/inputValidator.ts @@ -0,0 +1,37 @@ +import { ChatInputCommandInteraction, MessageFlags } from "discord.js"; + +/** + * Checks if a string is a valid Ethereum address. + * Browser-safe. + */ +export const isValidEthereumAddress = (address: string | null | undefined): boolean => { + if (!address) return false; + return /^0x[a-fA-F0-9]{40}$/.test(address); +}; + +/** + * Validates an Ethereum address from a Discord command interaction. + * Uses interaction context and replies ephemerally on failure. + * NOT browser-safe. + */ +export const validateAddressFromInteraction = (interaction: ChatInputCommandInteraction): string | null => { + const address = interaction.options.getString("address"); + + if (!address) { + interaction.reply({ + content: "Please provide an address.", + flags: MessageFlags.Ephemeral, + }); + return null; // Indicate failure + } + + if (!isValidEthereumAddress(address)) { // Use the generic validator + interaction.reply({ + content: "Please provide a valid Ethereum address.", + flags: MessageFlags.Ephemeral, + }); + return null; // Indicate failure + } + + return address; // Return the valid address +}; diff --git a/tooling/sparta/packages/utils/logger.ts b/tooling/sparta/packages/utils/logger.ts new file mode 100644 index 0000000..b6cff91 --- /dev/null +++ b/tooling/sparta/packages/utils/logger.ts @@ -0,0 +1,46 @@ +import { pino } from "pino"; + +// Log level hierarchy: trace < debug < info < warn < error < fatal +type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal"; + +// Configuration for the logger +interface LoggerConfig { + level: LogLevel; + prettyPrint: boolean; +} + +// Get log level from environment or default to 'info' +const getLoggerConfig = (): LoggerConfig => { + return { + level: (process.env.LOG_LEVEL as LogLevel) || "info", + prettyPrint: process.env.LOG_PRETTY_PRINT !== "false", // Default to true + }; +}; + +// Create the logger instance +const createLogger = () => { + const config = getLoggerConfig(); + + const transport = config.prettyPrint + ? { + target: "pino-pretty", + options: { + colorize: true, + translateTime: "SYS:standard", + ignore: "pid,hostname", + }, + } + : undefined; + + return pino({ + level: config.level, + transport, + timestamp: pino.stdTimeFunctions.isoTime, + }); +}; + +// Export a singleton logger instance +export const logger = createLogger(); + +// Unused helper functions removed. +// Users can call logger.trace(), logger.debug() etc. directly. diff --git a/tooling/sparta/packages/utils/openapi/api-docs.json b/tooling/sparta/packages/utils/openapi/api-docs.json new file mode 100644 index 0000000..7d8b6b7 --- /dev/null +++ b/tooling/sparta/packages/utils/openapi/api-docs.json @@ -0,0 +1,1594 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Sparta API", + "version": "1.0.0", + "description": "…" + }, + "servers": [ + { + "url": "{serverUrl}", + "description": "Sparta API", + "variables": { + "serverUrl": { + "default": "http://localhost:3000", + "description": "API server URL" + } + } + } + ], + "components": { + "securitySchemes": { + "ApiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key", + "description": "API key for authenticating requests" + } + }, + "schemas": { + "EthereumResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Indicates if the request was successful", + "example": true + }, + "data": { + "type": "array", + "description": "Array of data returned from the endpoint", + "items": { + "type": "string" + }, + "example": [ + "0x1234567890abcdef1234567890abcdef12345678", + "0xabcdef1234567890abcdef1234567890abcdef12" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "RollupStatusResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Indicates if the request was successful", + "example": true + }, + "data": { + "type": "object", + "properties": { + "pendingBlockNum": { + "type": "string", + "description": "Current pending block number", + "example": "123456" + }, + "provenBlockNum": { + "type": "string", + "description": "Current proven block number", + "example": "123450" + }, + "validators": { + "type": "array", + "description": "List of validator addresses", + "items": { + "type": "string" + } + }, + "forwardedValidators": { + "type": "array", + "description": "List of forwarded validator addresses", + "items": { + "type": "string" + } + }, + "committee": { + "type": "array", + "description": "Current committee members", + "items": { + "type": "string" + } + }, + "forwardedCommittee": { + "type": "array", + "description": "Forwarded committee members", + "items": { + "type": "string" + } + }, + "archive": { + "type": "array", + "description": "Archive node addresses", + "items": { + "type": "string" + } + }, + "currentEpoch": { + "type": "string", + "description": "Current epoch number", + "example": "42" + }, + "currentSlot": { + "type": "string", + "description": "Current slot number", + "example": "1024" + }, + "proposerNow": { + "type": "string", + "description": "Current proposer address", + "example": "0x1234567890abcdef1234567890abcdef12345678" + } + } + } + }, + "required": [ + "success", + "data" + ] + }, + "ErrorResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Always false for error responses", + "example": false + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong", + "example": "Failed to retrieve rollup status" + } + }, + "required": [ + "success", + "error" + ] + }, + "NodeOperator": { + "type": "object", + "properties": { + "discordId": { + "type": "string", + "description": "The Discord user ID of the node operator.", + "example": "123456789012345678" + }, + "walletAddress": { + "type": "string", + "description": "The Ethereum wallet address associated with the node operator.", + "example": "0x1234567890abcdef1234567890abcdef12345678" + }, + "discordUsername": { + "type": "string", + "description": "The Discord username of the node operator.", + "example": "user#1234" + }, + "createdAt": { + "type": "number", + "description": "Timestamp (milliseconds since epoch) when the operator was created.", + "example": 1678886400000 + }, + "updatedAt": { + "type": "number", + "description": "Timestamp (milliseconds since epoch) when the operator was last updated.", + "example": 1678887400000 + }, + "validators": { + "type": "array", + "description": "List of validators associated with this operator.", + "items": { + "type": "object", + "properties": { + "validatorAddress": { + "type": "string", + "description": "The Ethereum address of the validator.", + "example": "0x1234567890abcdef1234567890abcdef12345678" + } + } + } + } + }, + "required": [ + "discordId", + "walletAddress", + "createdAt", + "updatedAt" + ] + }, + "OperatorInput": { + "type": "object", + "properties": { + "discordId": { + "type": "string", + "description": "The Discord user ID." + }, + "walletAddress": { + "type": "string", + "description": "The Ethereum wallet address.", + "example": "0x1234567890abcdef1234567890abcdef12345678" + } + }, + "required": [ + "discordId", + "walletAddress" + ] + }, + "OperatorUpdateInput": { + "type": "object", + "properties": { + "walletAddress": { + "type": "string", + "description": "The new Ethereum wallet address.", + "example": "0xabcdef1234567890abcdef1234567890abcdef12" + } + }, + "required": [ + "walletAddress" + ] + }, + "OperatorError": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Error message describing the issue." + } + } + }, + "OperatorResponse": { + "type": "object", + "properties": { + "discordId": { + "type": "string", + "description": "The Discord user ID of the node operator." + }, + "walletAddress": { + "type": "string", + "description": "The Ethereum wallet address associated with the node operator." + }, + "createdAt": { + "type": "number", + "description": "Timestamp when operator was created" + }, + "updatedAt": { + "type": "number", + "description": "Timestamp when operator was last updated" + } + } + }, + "ValidatorResponse": { + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "The Ethereum address of the validator.", + "example": "0x1234567890abcdef1234567890abcdef12345678" + }, + "operatorId": { + "type": "string", + "description": "The Discord ID of the operator who owns this validator.", + "example": "123456789012345678" + }, + "stats": { + "type": "object", + "properties": { + "totalValidators": { + "type": "number", + "description": "Total number of validators in the system.", + "example": 42 + } + } + } + } + } + } + }, + "paths": { + "/api/ethereum/rollup/committee": { + "get": { + "summary": "Get current epoch committee", + "description": "Retrieves the list of committee members for the current epoch", + "tags": [ + "Ethereum" + ], + "operationId": "getCurrentEpochCommittee", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "responses": { + "200": { + "description": "Successfully retrieved committee members", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EthereumResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Server error occurred while retrieving committee data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/ethereum/rollup/validators": { + "get": { + "summary": "Get all validators", + "description": "Retrieves the list of all attesters (validators) in the rollup system", + "tags": [ + "Ethereum" + ], + "operationId": "getAllValidatorsOnChain", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "responses": { + "200": { + "description": "Successfully retrieved validators", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EthereumResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Server error occurred while retrieving validators data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/ethereum/rollup/status": { + "get": { + "summary": "Get comprehensive rollup status", + "description": "Retrieves complete information about the rollup's current state including block numbers, validators, committee members, and other chain data", + "tags": [ + "Ethereum" + ], + "operationId": "getRollupStatus", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "responses": { + "200": { + "description": "Successfully retrieved rollup status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RollupStatusResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Server error occurred while retrieving rollup status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/operator/operators": { + "get": { + "summary": "Get node operators", + "description": "Retrieves a list of registered node operators.", + "tags": [ + "NodeOperator" + ], + "operationId": "getOperators", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "pageToken", + "schema": { + "type": "string" + }, + "required": false, + "description": "Token for pagination to get the next page of results." + } + ], + "responses": { + "200": { + "description": "A list of node operators with pagination token.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "operators": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NodeOperator" + } + }, + "nextPageToken": { + "type": "string", + "description": "Token to retrieve the next page of results. Not present on the last page.", + "example": "eyJsYXN0S2V5IjoiMTIzNDU2Nzg5MCJ9" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + } + }, + "/api/operator": { + "get": { + "summary": "Get a specific node operator", + "description": "Retrieves a specific node operator using either their Discord ID or username.", + "tags": [ + "NodeOperator" + ], + "operationId": "getOperator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "discordId", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord ID of the operator to retrieve." + }, + { + "in": "query", + "name": "discordUsername", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord username of the operator to retrieve." + } + ], + "responses": { + "200": { + "description": "The requested node operator with associated validators.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NodeOperator" + } + } + } + }, + "400": { + "description": "Bad Request - Missing query parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Operator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + }, + "post": { + "summary": "Create a new node operator", + "description": "Registers a new node operator with their Discord ID and wallet address.", + "tags": [ + "NodeOperator" + ], + "operationId": "createOperator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "discordId", + "schema": { + "type": "string" + }, + "required": true, + "description": "The Discord user ID." + }, + { + "in": "query", + "name": "walletAddress", + "schema": { + "type": "string" + }, + "required": true, + "description": "The Ethereum wallet address." + }, + { + "in": "query", + "name": "discordUsername", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord username." + } + ], + "responses": { + "201": { + "description": "Node operator created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NodeOperator" + } + } + } + }, + "400": { + "description": "Bad Request - Missing or invalid body parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "409": { + "description": "Conflict - Operator with this Discord ID already exists", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + }, + "delete": { + "summary": "Delete an operator by Discord ID or username", + "description": "Removes a node operator registration using either their Discord ID or username.", + "tags": [ + "NodeOperator" + ], + "operationId": "deleteOperator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "discordId", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord ID of the operator to delete." + }, + { + "in": "query", + "name": "discordUsername", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord username of the operator to delete." + } + ], + "responses": { + "204": { + "description": "Operator deleted successfully (No Content)." + }, + "400": { + "description": "Bad Request - Missing discordId or discordUsername parameter", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Operator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + }, + "put": { + "summary": "Update operator's wallet address", + "description": "Updates the wallet address for a specific node operator using their Discord ID or username.", + "tags": [ + "NodeOperator" + ], + "operationId": "updateOperator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "discordId", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord ID of the operator to update." + }, + { + "in": "query", + "name": "discordUsername", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord username of the operator to update." + }, + { + "in": "query", + "name": "walletAddress", + "schema": { + "type": "string" + }, + "required": true, + "description": "The new wallet address." + } + ], + "responses": { + "200": { + "description": "Operator updated successfully. Returns the updated operator.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NodeOperator" + } + } + } + }, + "400": { + "description": "Bad Request - Missing parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Operator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + } + }, + "/api/operator/stats": { + "get": { + "summary": "Get node operator statistics", + "description": "Retrieves statistics about registered node operators.", + "tags": [ + "NodeOperator" + ], + "operationId": "getOperatorStats", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "responses": { + "200": { + "description": "Node operator statistics.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "stats": { + "type": "object", + "properties": { + "totalCount": { + "type": "number", + "description": "Total number of registered operators.", + "example": 42 + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + } + }, + "/api/operator/address/{address}": { + "get": { + "summary": "Get operator by wallet address", + "description": "Retrieves a specific node operator using their wallet address.", + "tags": [ + "NodeOperator" + ], + "operationId": "getOperatorByAddress", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "address", + "schema": { + "type": "string" + }, + "required": true, + "description": "The wallet address of the operator to retrieve." + } + ], + "responses": { + "200": { + "description": "The requested node operator.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NodeOperator" + } + } + } + }, + "400": { + "description": "Bad Request - Missing or invalid address parameter", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Operator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + } + }, + "/api/operator/approve": { + "put": { + "summary": "Approve a node operator", + "description": "Approves a node operator using their Discord ID or username.", + "tags": [ + "NodeOperator" + ], + "operationId": "approveOperator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "discordId", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord ID of the operator to approve." + }, + { + "in": "query", + "name": "discordUsername", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord username of the operator to approve." + } + ], + "responses": { + "200": { + "description": "Operator approved successfully. Returns the updated operator.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NodeOperator" + } + } + } + }, + "400": { + "description": "Bad Request - Missing parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Operator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + } + }, + "/api/operator/validators": { + "get": { + "summary": "Get all validators", + "description": "Retrieves a list of all validators in the system.", + "tags": [ + "NodeOperator" + ], + "operationId": "getAllValidators", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "responses": { + "200": { + "description": "A list of validators from blockchain and known validators in the database.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Indicates if the request was successful.", + "example": true + }, + "data": { + "type": "object", + "properties": { + "blockchainValidators": { + "type": "object", + "properties": { + "validators": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of all validator addresses from the blockchain." + }, + "stats": { + "type": "object", + "properties": { + "totalValidators": { + "type": "number", + "description": "Total number of validators in the blockchain." + } + } + } + } + }, + "knownValidators": { + "type": "object", + "properties": { + "validators": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of validator addresses that have matching operators in the database." + }, + "stats": { + "type": "object", + "properties": { + "totalValidators": { + "type": "number", + "description": "Total number of validators with matching operators." + } + } + } + } + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + } + }, + "/api/operator/validator": { + "get": { + "summary": "Get validator information", + "description": "Retrieves validator information either by validator address or by operator (discordId/username).", + "tags": [ + "NodeOperator" + ], + "operationId": "getValidator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "address", + "schema": { + "type": "string" + }, + "required": false, + "description": "The wallet address of the validator to retrieve." + }, + { + "in": "query", + "name": "discordId", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord ID of the operator to get validators for." + }, + { + "in": "query", + "name": "discordUsername", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord username of the operator to get validators for." + } + ], + "responses": { + "200": { + "description": "The requested validator information or validators for an operator.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "data": { + "oneOf": [ + { + "$ref": "#/components/schemas/ValidatorResponse" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidatorResponse" + } + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Missing or invalid query parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Validator or operator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + }, + "post": { + "summary": "Add a new validator", + "description": "Adds a new validator and associates it with an operator.", + "tags": [ + "NodeOperator" + ], + "operationId": "addValidator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "discordId", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord ID of the operator to associate with this validator." + }, + { + "in": "query", + "name": "discordUsername", + "schema": { + "type": "string" + }, + "required": false, + "description": "The Discord username of the operator to associate with this validator." + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "validatorAddress": { + "type": "string", + "description": "The validator address to add.", + "example": "0x1234567890abcdef1234567890abcdef12345678" + } + }, + "required": [ + "validatorAddress" + ] + } + } + } + }, + "responses": { + "201": { + "description": "Validator added successfully.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "data": { + "$ref": "#/components/schemas/ValidatorResponse" + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Missing or invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Operator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + }, + "put": { + "summary": "Update validator's operator", + "description": "Transfers a validator from one operator to another.", + "tags": [ + "NodeOperator" + ], + "operationId": "updateValidator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "validatorAddress": { + "type": "string", + "description": "The validator address to transfer.", + "example": "0x1234567890abcdef1234567890abcdef12345678" + }, + "fromDiscordId": { + "type": "string", + "description": "The Discord ID of the current operator.", + "example": "123456789012345678" + }, + "toDiscordId": { + "type": "string", + "description": "The Discord ID of the new operator to transfer to.", + "example": "987654321098765432" + } + }, + "required": [ + "validatorAddress", + "fromDiscordId", + "toDiscordId" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Validator transferred successfully.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "data": { + "$ref": "#/components/schemas/ValidatorResponse" + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Missing or invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Operator or validator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + }, + "delete": { + "summary": "Remove a validator", + "description": "Removes a validator from an operator's list of validators.", + "tags": [ + "NodeOperator" + ], + "operationId": "removeValidator", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "validatorAddress", + "schema": { + "type": "string" + }, + "required": true, + "description": "The validator address to remove." + }, + { + "in": "query", + "name": "discordId", + "schema": { + "type": "string" + }, + "required": true, + "description": "The Discord ID of the operator." + } + ], + "responses": { + "204": { + "description": "Validator removed successfully." + }, + "400": { + "description": "Bad Request - Missing or invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "404": { + "description": "Operator or validator not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperatorError" + } + } + } + } + } + } + } + }, + "tags": [] +} \ No newline at end of file diff --git a/tooling/sparta/packages/utils/openapi/api/apiProvider.ts b/tooling/sparta/packages/utils/openapi/api/apiProvider.ts new file mode 100644 index 0000000..317d2e3 --- /dev/null +++ b/tooling/sparta/packages/utils/openapi/api/apiProvider.ts @@ -0,0 +1,65 @@ +import { clientPromise } from "./axios"; +import type { Client as ApiClient } from "@sparta/utils/openapi/types"; + +/** + * Singleton class to provide access to the API client + */ +export class ApiProvider { + private static instance: ApiProvider | null = null; + private client: ApiClient | null = null; + private error: Error | null = null; + + private constructor() { + // Private constructor to enforce singleton pattern + } + + /** + * Get the singleton instance of ApiProvider + */ + public static getInstance(): ApiProvider { + if (!ApiProvider.instance) { + ApiProvider.instance = new ApiProvider(); + } + return ApiProvider.instance; + } + + /** + * Initialize the API client + */ + public async init(): Promise { + if (this.client) return; // Already initialized + + try { + this.client = await clientPromise; + this.error = null; + } catch (err) { + this.error = err instanceof Error ? err : new Error(String(err)); + console.error("ApiProvider: Failed to initialize client:", err); + } + } + + /** + * Get the API client + * @throws Error if client is not initialized + */ + public getClient(): ApiClient { + if (!this.client) { + throw new Error("API client not initialized. Call init() first."); + } + return this.client; + } + + /** + * Check if the client is initialized + */ + public isInitialized(): boolean { + return !!this.client; + } + + /** + * Get the initialization error, if any + */ + public getError(): Error | null { + return this.error; + } +} diff --git a/tooling/sparta/packages/utils/openapi/api/axios.ts b/tooling/sparta/packages/utils/openapi/api/axios.ts new file mode 100644 index 0000000..201b5bd --- /dev/null +++ b/tooling/sparta/packages/utils/openapi/api/axios.ts @@ -0,0 +1,39 @@ +// packages/vite/src/api/axios.ts +import { type OpenAPIV3, OpenAPIClientAxios } from "openapi-client-axios"; +import spec from "../api-docs.json"; +import type { Client } from "../types"; + +// Construct API URL from environment variables or use the provided API_URL directly +const apiUrl = process.env.API_URL || + `${process.env.API_PROTOCOL || 'http'}://${process.env.API_HOST || 'localhost'}:${process.env.API_PORT || '3000'}`; + +// Make sure we always have a proper API URL +if (!apiUrl) { + console.warn("API_URL is not set. Defaulting to http://localhost:3000"); +} + +console.log("Initializing API client with baseURL:", apiUrl); + +const apiInstance = new OpenAPIClientAxios({ + definition: spec as OpenAPIV3.Document, + axiosConfigDefaults: { + baseURL: apiUrl, + timeout: 10_000, + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "x-api-key": process.env.BACKEND_API_KEY, + }, + }, +}); + +// Initialize and export the promise directly +export const clientPromise = apiInstance + .init() + .then((client) => { + return client; + }) + .catch((err) => { + console.error("axios.ts: Client init() failed:", err); + throw err; + }); diff --git a/tooling/sparta/packages/utils/openapi/types.d.ts b/tooling/sparta/packages/utils/openapi/types.d.ts new file mode 100644 index 0000000..5cdafe9 --- /dev/null +++ b/tooling/sparta/packages/utils/openapi/types.d.ts @@ -0,0 +1,865 @@ +import type { + OpenAPIClient, + Parameters, + UnknownParamsObject, + OperationResponse, + AxiosRequestConfig, +} from 'openapi-client-axios'; + +declare namespace Components { + namespace Schemas { + export interface ErrorResponse { + /** + * Always false for error responses + * example: + * false + */ + success: boolean; + /** + * Error message describing what went wrong + * example: + * Failed to retrieve rollup status + */ + error: string; + } + export interface EthereumResponse { + /** + * Indicates if the request was successful + * example: + * true + */ + success: boolean; + /** + * Array of data returned from the endpoint + * example: + * [ + * "0x1234567890abcdef1234567890abcdef12345678", + * "0xabcdef1234567890abcdef1234567890abcdef12" + * ] + */ + data: string[]; + } + export interface NodeOperator { + /** + * The Discord user ID of the node operator. + * example: + * 123456789012345678 + */ + discordId: string; + /** + * The Ethereum wallet address associated with the node operator. + * example: + * 0x1234567890abcdef1234567890abcdef12345678 + */ + walletAddress: string; + /** + * The Discord username of the node operator. + * example: + * user#1234 + */ + discordUsername?: string; + /** + * Timestamp (milliseconds since epoch) when the operator was created. + * example: + * 1678886400000 + */ + createdAt: number; + /** + * Timestamp (milliseconds since epoch) when the operator was last updated. + * example: + * 1678887400000 + */ + updatedAt: number; + /** + * List of validators associated with this operator. + */ + validators?: { + /** + * The Ethereum address of the validator. + * example: + * 0x1234567890abcdef1234567890abcdef12345678 + */ + validatorAddress?: string; + }[]; + } + export interface OperatorError { + /** + * Error message describing the issue. + */ + error?: string; + } + export interface OperatorInput { + /** + * The Discord user ID. + */ + discordId: string; + /** + * The Ethereum wallet address. + * example: + * 0x1234567890abcdef1234567890abcdef12345678 + */ + walletAddress: string; + } + export interface OperatorResponse { + /** + * The Discord user ID of the node operator. + */ + discordId?: string; + /** + * The Ethereum wallet address associated with the node operator. + */ + walletAddress?: string; + /** + * Timestamp when operator was created + */ + createdAt?: number; + /** + * Timestamp when operator was last updated + */ + updatedAt?: number; + } + export interface OperatorUpdateInput { + /** + * The new Ethereum wallet address. + * example: + * 0xabcdef1234567890abcdef1234567890abcdef12 + */ + walletAddress: string; + } + export interface RollupStatusResponse { + /** + * Indicates if the request was successful + * example: + * true + */ + success: boolean; + data: { + /** + * Current pending block number + * example: + * 123456 + */ + pendingBlockNum?: string; + /** + * Current proven block number + * example: + * 123450 + */ + provenBlockNum?: string; + /** + * List of validator addresses + */ + validators?: string[]; + /** + * List of forwarded validator addresses + */ + forwardedValidators?: string[]; + /** + * Current committee members + */ + committee?: string[]; + /** + * Forwarded committee members + */ + forwardedCommittee?: string[]; + /** + * Archive node addresses + */ + archive?: string[]; + /** + * Current epoch number + * example: + * 42 + */ + currentEpoch?: string; + /** + * Current slot number + * example: + * 1024 + */ + currentSlot?: string; + /** + * Current proposer address + * example: + * 0x1234567890abcdef1234567890abcdef12345678 + */ + proposerNow?: string; + }; + } + export interface ValidatorResponse { + /** + * The Ethereum address of the validator. + * example: + * 0x1234567890abcdef1234567890abcdef12345678 + */ + address?: string; + /** + * The Discord ID of the operator who owns this validator. + * example: + * 123456789012345678 + */ + operatorId?: string; + stats?: { + /** + * Total number of validators in the system. + * example: + * 42 + */ + totalValidators?: number; + }; + } + } +} +declare namespace Paths { + namespace AddValidator { + namespace Parameters { + export type DiscordId = string; + export type DiscordUsername = string; + } + export interface QueryParameters { + discordId?: Parameters.DiscordId; + discordUsername?: Parameters.DiscordUsername; + } + export interface RequestBody { + /** + * The validator address to add. + * example: + * 0x1234567890abcdef1234567890abcdef12345678 + */ + validatorAddress: string; + } + namespace Responses { + export interface $201 { + success?: boolean; + data?: Components.Schemas.ValidatorResponse; + } + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace ApproveOperator { + namespace Parameters { + export type DiscordId = string; + export type DiscordUsername = string; + } + export interface QueryParameters { + discordId?: Parameters.DiscordId; + discordUsername?: Parameters.DiscordUsername; + } + namespace Responses { + export type $200 = Components.Schemas.NodeOperator; + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace CreateOperator { + namespace Parameters { + export type DiscordId = string; + export type DiscordUsername = string; + export type WalletAddress = string; + } + export interface QueryParameters { + discordId: Parameters.DiscordId; + walletAddress: Parameters.WalletAddress; + discordUsername?: Parameters.DiscordUsername; + } + namespace Responses { + export type $201 = Components.Schemas.NodeOperator; + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $409 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace DeleteOperator { + namespace Parameters { + export type DiscordId = string; + export type DiscordUsername = string; + } + export interface QueryParameters { + discordId?: Parameters.DiscordId; + discordUsername?: Parameters.DiscordUsername; + } + namespace Responses { + export interface $204 { + } + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace GetAllValidators { + namespace Responses { + export interface $200 { + /** + * Indicates if the request was successful. + * example: + * true + */ + success?: boolean; + data?: { + blockchainValidators?: { + /** + * List of all validator addresses from the blockchain. + */ + validators?: string[]; + stats?: { + /** + * Total number of validators in the blockchain. + */ + totalValidators?: number; + }; + }; + knownValidators?: { + /** + * List of validator addresses that have matching operators in the database. + */ + validators?: string[]; + stats?: { + /** + * Total number of validators with matching operators. + */ + totalValidators?: number; + }; + }; + }; + } + export type $401 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace GetAllValidatorsOnChain { + namespace Responses { + export type $200 = Components.Schemas.EthereumResponse; + export type $401 = Components.Schemas.ErrorResponse; + export type $500 = Components.Schemas.ErrorResponse; + } + } + namespace GetCurrentEpochCommittee { + namespace Responses { + export type $200 = Components.Schemas.EthereumResponse; + export type $401 = Components.Schemas.ErrorResponse; + export type $500 = Components.Schemas.ErrorResponse; + } + } + namespace GetOperator { + namespace Parameters { + export type DiscordId = string; + export type DiscordUsername = string; + } + export interface QueryParameters { + discordId?: Parameters.DiscordId; + discordUsername?: Parameters.DiscordUsername; + } + namespace Responses { + export type $200 = Components.Schemas.NodeOperator; + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace GetOperatorByAddress { + namespace Parameters { + export type Address = string; + } + export interface PathParameters { + address: Parameters.Address; + } + namespace Responses { + export type $200 = Components.Schemas.NodeOperator; + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace GetOperatorStats { + namespace Responses { + export interface $200 { + stats?: { + /** + * Total number of registered operators. + * example: + * 42 + */ + totalCount?: number; + }; + } + export type $401 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace GetOperators { + namespace Parameters { + export type PageToken = string; + } + export interface QueryParameters { + pageToken?: Parameters.PageToken; + } + namespace Responses { + export interface $200 { + operators?: Components.Schemas.NodeOperator[]; + /** + * Token to retrieve the next page of results. Not present on the last page. + * example: + * eyJsYXN0S2V5IjoiMTIzNDU2Nzg5MCJ9 + */ + nextPageToken?: string; + } + export type $401 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace GetRollupStatus { + namespace Responses { + export type $200 = Components.Schemas.RollupStatusResponse; + export type $401 = Components.Schemas.ErrorResponse; + export type $500 = Components.Schemas.ErrorResponse; + } + } + namespace GetValidator { + namespace Parameters { + export type Address = string; + export type DiscordId = string; + export type DiscordUsername = string; + } + export interface QueryParameters { + address?: Parameters.Address; + discordId?: Parameters.DiscordId; + discordUsername?: Parameters.DiscordUsername; + } + namespace Responses { + export interface $200 { + success?: boolean; + data?: Components.Schemas.ValidatorResponse | Components.Schemas.ValidatorResponse[]; + } + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace RemoveValidator { + namespace Parameters { + export type DiscordId = string; + export type ValidatorAddress = string; + } + export interface QueryParameters { + validatorAddress: Parameters.ValidatorAddress; + discordId: Parameters.DiscordId; + } + namespace Responses { + export interface $204 { + } + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace UpdateOperator { + namespace Parameters { + export type DiscordId = string; + export type DiscordUsername = string; + export type WalletAddress = string; + } + export interface QueryParameters { + discordId?: Parameters.DiscordId; + discordUsername?: Parameters.DiscordUsername; + walletAddress: Parameters.WalletAddress; + } + namespace Responses { + export type $200 = Components.Schemas.NodeOperator; + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } + namespace UpdateValidator { + export interface RequestBody { + /** + * The validator address to transfer. + * example: + * 0x1234567890abcdef1234567890abcdef12345678 + */ + validatorAddress: string; + /** + * The Discord ID of the current operator. + * example: + * 123456789012345678 + */ + fromDiscordId: string; + /** + * The Discord ID of the new operator to transfer to. + * example: + * 987654321098765432 + */ + toDiscordId: string; + } + namespace Responses { + export interface $200 { + success?: boolean; + data?: Components.Schemas.ValidatorResponse; + } + export type $400 = Components.Schemas.OperatorError; + export type $401 = Components.Schemas.OperatorError; + export type $404 = Components.Schemas.OperatorError; + export type $500 = Components.Schemas.OperatorError; + } + } +} + +export interface OperationMethods { + /** + * getCurrentEpochCommittee - Get current epoch committee + * + * Retrieves the list of committee members for the current epoch + */ + 'getCurrentEpochCommittee'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getAllValidatorsOnChain - Get all validators + * + * Retrieves the list of all attesters (validators) in the rollup system + */ + 'getAllValidatorsOnChain'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getRollupStatus - Get comprehensive rollup status + * + * Retrieves complete information about the rollup's current state including block numbers, validators, committee members, and other chain data + */ + 'getRollupStatus'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getOperators - Get node operators + * + * Retrieves a list of registered node operators. + */ + 'getOperators'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getOperator - Get a specific node operator + * + * Retrieves a specific node operator using either their Discord ID or username. + */ + 'getOperator'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * updateOperator - Update operator's wallet address + * + * Updates the wallet address for a specific node operator using their Discord ID or username. + */ + 'updateOperator'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * createOperator - Create a new node operator + * + * Registers a new node operator with their Discord ID and wallet address. + */ + 'createOperator'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * deleteOperator - Delete an operator by Discord ID or username + * + * Removes a node operator registration using either their Discord ID or username. + */ + 'deleteOperator'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getOperatorStats - Get node operator statistics + * + * Retrieves statistics about registered node operators. + */ + 'getOperatorStats'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getOperatorByAddress - Get operator by wallet address + * + * Retrieves a specific node operator using their wallet address. + */ + 'getOperatorByAddress'( + parameters: Parameters, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * approveOperator - Approve a node operator + * + * Approves a node operator using their Discord ID or username. + */ + 'approveOperator'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getAllValidators - Get all validators + * + * Retrieves a list of all validators in the system. + */ + 'getAllValidators'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getValidator - Get validator information + * + * Retrieves validator information either by validator address or by operator (discordId/username). + */ + 'getValidator'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * updateValidator - Update validator's operator + * + * Transfers a validator from one operator to another. + */ + 'updateValidator'( + parameters?: Parameters | null, + data?: Paths.UpdateValidator.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * addValidator - Add a new validator + * + * Adds a new validator and associates it with an operator. + */ + 'addValidator'( + parameters?: Parameters | null, + data?: Paths.AddValidator.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * removeValidator - Remove a validator + * + * Removes a validator from an operator's list of validators. + */ + 'removeValidator'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse +} + +export interface PathsDictionary { + ['/api/ethereum/rollup/committee']: { + /** + * getCurrentEpochCommittee - Get current epoch committee + * + * Retrieves the list of committee members for the current epoch + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/ethereum/rollup/validators']: { + /** + * getAllValidatorsOnChain - Get all validators + * + * Retrieves the list of all attesters (validators) in the rollup system + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/ethereum/rollup/status']: { + /** + * getRollupStatus - Get comprehensive rollup status + * + * Retrieves complete information about the rollup's current state including block numbers, validators, committee members, and other chain data + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/operator/operators']: { + /** + * getOperators - Get node operators + * + * Retrieves a list of registered node operators. + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/operator']: { + /** + * getOperator - Get a specific node operator + * + * Retrieves a specific node operator using either their Discord ID or username. + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * createOperator - Create a new node operator + * + * Registers a new node operator with their Discord ID and wallet address. + */ + 'post'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * deleteOperator - Delete an operator by Discord ID or username + * + * Removes a node operator registration using either their Discord ID or username. + */ + 'delete'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * updateOperator - Update operator's wallet address + * + * Updates the wallet address for a specific node operator using their Discord ID or username. + */ + 'put'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/operator/stats']: { + /** + * getOperatorStats - Get node operator statistics + * + * Retrieves statistics about registered node operators. + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/operator/address/{address}']: { + /** + * getOperatorByAddress - Get operator by wallet address + * + * Retrieves a specific node operator using their wallet address. + */ + 'get'( + parameters: Parameters, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/operator/approve']: { + /** + * approveOperator - Approve a node operator + * + * Approves a node operator using their Discord ID or username. + */ + 'put'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/operator/validators']: { + /** + * getAllValidators - Get all validators + * + * Retrieves a list of all validators in the system. + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/api/operator/validator']: { + /** + * getValidator - Get validator information + * + * Retrieves validator information either by validator address or by operator (discordId/username). + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * addValidator - Add a new validator + * + * Adds a new validator and associates it with an operator. + */ + 'post'( + parameters?: Parameters | null, + data?: Paths.AddValidator.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * updateValidator - Update validator's operator + * + * Transfers a validator from one operator to another. + */ + 'put'( + parameters?: Parameters | null, + data?: Paths.UpdateValidator.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * removeValidator - Remove a validator + * + * Removes a validator from an operator's list of validators. + */ + 'delete'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } +} + +export type Client = OpenAPIClient diff --git a/tooling/sparta/packages/utils/package.json b/tooling/sparta/packages/utils/package.json new file mode 100644 index 0000000..7543564 --- /dev/null +++ b/tooling/sparta/packages/utils/package.json @@ -0,0 +1,20 @@ +{ + "name": "@sparta/utils", + "version": "0.1.0", + "type": "module", + "scripts": { + "types": "tsc" + }, + "dependencies": { + "@aws-sdk/client-dynamodb": "^3.427.0", + "@aws-sdk/lib-dynamodb": "^3.427.0", + "pino": "^8.16.0" + }, + "devDependencies": { + "@types/bun": "latest", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "typescript": "^5.0.0" + } +} diff --git a/tooling/sparta/packages/utils/tsconfig.json b/tooling/sparta/packages/utils/tsconfig.json new file mode 100644 index 0000000..e220dfe --- /dev/null +++ b/tooling/sparta/packages/utils/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": ".", + "noEmit": false + }, + "include": ["./**/*.ts", "./**/*.json"], + "exclude": ["node_modules", "dist"] +} diff --git a/tooling/sparta/scripts/README.md b/tooling/sparta/scripts/README.md new file mode 100644 index 0000000..bc881ed --- /dev/null +++ b/tooling/sparta/scripts/README.md @@ -0,0 +1,64 @@ +# Sparta Scripts + +This directory contains utility scripts for managing and maintaining the Sparta project. + +## Available Scripts + +### Migrations + +The `migrations/` directory contains database migration scripts that should be run in sequence (based on their numeric prefix). + +- **00_update_node_operators.js**: Adds `isApproved` field and Discord usernames to node operators +- **01_migrate_validators.js**: Migrates validators from being stored as an array in node operators to a separate validators table + +### Running Migrations + +To run all migrations in sequence: + +```bash +./run-migrations.sh +``` + +This script will automatically run each migration in the correct order. If any migration fails, the process will stop. + +To run a specific migration script individually: + +```bash +node migrations/XX_script_name.js +``` + +### Other Utility Scripts + +- **start-local-dynamodb.sh**: Starts a local DynamoDB instance for development and testing +- **test-dynamodb.js**: Tests DynamoDB connectivity and basic operations +- **build_push_get_digest.sh**: Builds and pushes Docker images +- **getStats.js**: Retrieves and displays statistics +- **swagger.js**: Generates Swagger/OpenAPI documentation + +## Environment Variables + +The scripts use the following environment variables: + +- `IS_LOCAL`: Set to "true" to use a local DynamoDB instance (default: true) +- `DYNAMODB_LOCAL_ENDPOINT`: URL of the local DynamoDB instance (default: http://localhost:8000) +- `AWS_REGION`: AWS region to use for AWS services +- `BOT_TOKEN`: Discord bot token (required for migrations that interact with Discord) +- `GUILD_ID`: Discord guild/server ID (required for migrations that interact with Discord) +- `NODE_OPERATORS_TABLE_NAME`: DynamoDB table name for node operators (default: sparta-node-operators-dev) +- `VALIDATORS_TABLE_NAME`: DynamoDB table name for validators (default: sparta-validators-dev) + +## Adding New Migrations + +When adding a new migration: + +1. Create a new file in the `migrations/` directory with a sequential prefix (e.g., `02_migration_name.js`) +2. Add documentation for the migration in this README +3. Test the migration thoroughly before running it in production + +## Migration Structure Best Practices + +- Always handle errors gracefully +- Log each step of the migration process +- Provide a clear summary at the end of the migration +- Make migrations idempotent when possible (can be run multiple times without issues) +- Include a way to verify the migration was successful \ No newline at end of file diff --git a/tooling/sparta/scripts/build_lambda.sh b/tooling/sparta/scripts/build_lambda.sh new file mode 100755 index 0000000..261fb26 --- /dev/null +++ b/tooling/sparta/scripts/build_lambda.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Script to build the Lambda package for validator monitoring + +# Exit on errors +set -e + +# Get paths +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +LAMBDA_PATH="$PROJECT_ROOT/packages/scheduler/lambda-package.zip" + +# Build the Lambda package silently +echo "Building Lambda package..." >&2 +(cd "$PROJECT_ROOT/packages/scheduler" && bun run build > /dev/null 2>&1) + +# Calculate the base64-encoded SHA256 hash of the package +HASH=$(openssl dgst -binary -sha256 "$LAMBDA_PATH" | openssl base64) + +echo "Lambda package built successfully at $LAMBDA_PATH" >&2 +echo "Hash: $HASH" >&2 + +# Output the hash as JSON (and ONLY the hash as JSON) +echo "{\"hash\":\"$HASH\"}" \ No newline at end of file diff --git a/tooling/sparta/scripts/build_push_get_digest.sh b/tooling/sparta/scripts/build_push_get_digest.sh new file mode 100755 index 0000000..5bc3f5b --- /dev/null +++ b/tooling/sparta/scripts/build_push_get_digest.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status. +set -e + +# --- Input Variables (Passed from Terraform) --- +AWS_REGION="$1" +ECR_REPOSITORY_URL="$2" +DOCKERFILE_DIR="$3" # Directory containing the Dockerfile relative to where script runs +# The URL for the frontend, needed at build time by Vite +API_URL="$4" + +# --- Derived Variables --- +# Extract repository name from URL (e.g., 123456789012.dkr.ecr.eu-west-2.amazonaws.com/sparta-development-api -> sparta-development-api) +ECR_REPOSITORY_NAME=$(basename "$ECR_REPOSITORY_URL") + +# --- Script Logic --- + +# 1. Login to ECR (silence stdout) +aws ecr get-login-password --region "${AWS_REGION}" | docker login --username AWS --password-stdin "${ECR_REPOSITORY_URL}" > /dev/null + +# 2. Build Docker image (silence stdout) +# Pass the frontend URL as a build argument +(cd "${DOCKERFILE_DIR}" && docker build \ + --platform linux/amd64 \ + --build-arg API_URL="${API_URL}" \ + -t "${ECR_REPOSITORY_URL}:latest" \ + -f Dockerfile .) > /dev/null + +# 3. Push Docker image (silence stdout) +docker push "${ECR_REPOSITORY_URL}:latest" > /dev/null + +# 4. Retrieve image digest (output needed for variable assignment) +IMAGE_DIGEST=$(aws ecr describe-images --repository-name "${ECR_REPOSITORY_NAME}" --image-ids imageTag=latest --query 'imageDetails[0].imageDigest' --output text --region "${AWS_REGION}") + +# 5. Check if digest was retrieved +if [ -z "$IMAGE_DIGEST" ]; then + echo "Error: Could not retrieve image digest for ${ECR_REPOSITORY_URL}:latest" >&2 + exit 1 +fi + +# --- Output JSON for Terraform --- +# THIS MUST BE THE ONLY THING ON STDOUT +echo "{\"image_digest\":\"${IMAGE_DIGEST}\"}" diff --git a/tooling/sparta/scripts/getStats.js b/tooling/sparta/scripts/getStats.js new file mode 100644 index 0000000..f049b9b --- /dev/null +++ b/tooling/sparta/scripts/getStats.js @@ -0,0 +1,128 @@ +import { EthAddress } from '@aztec/aztec.js'; + +// Define the structure based on the provided TypeScript types using JSDoc for clarity +// Although JavaScript doesn't enforce types, this helps document the expected structure. + +/** + * @typedef {object} SlotInfo + * @property {bigint} timestamp + * @property {bigint} slot + * @property {string} date + */ + +/** + * @typedef {object} MissedStats + * @property {number} currentStreak + * @property {number} rate + * @property {number} count + */ + +/** + * Represents the status of a validator at a specific slot. + * @typedef {object} ValidatorStatus + * @property {bigint} slot + * @property {string} status - e.g., 'block-proposed', 'block-mined', 'attestation-sent', 'block-missed', 'attestation-missed' + * @property {string} [reason] - Optional reason for the status + */ + +/** + * Represents the historical status of a validator. + * @typedef {ValidatorStatus[]} ValidatorStatusHistory + */ + +/** + * @typedef {object} ValidatorStats + * @property {string} address - EthAddress as a string + * @property {SlotInfo} [lastProposal] + * @property {SlotInfo} [lastAttestation] + * @property {number} totalSlots + * @property {MissedStats} missedProposals + * @property {MissedStats} missedAttestations + * @property {ValidatorStatusHistory} history + */ + +/** + * @typedef {object} ValidatorsStatsResponse + * @property {{ [address: string]: ValidatorStats }} stats + * @property {bigint} [lastProcessedSlot] + * @property {bigint} [initialSlot] + * @property {number} slotWindow + */ + +/** + * @typedef {object} JsonRpcResponse + * @property {string} jsonrpc + * @property {ValidatorsStatsResponse} result + * @property {number} id + * @property {object} [error] - Optional error object + */ + +const rpcUrl = 'http://35.230.8.105:8080'; +const methodName = 'node_getValidatorsStats'; + +/** + * Fetches validator stats from the Aztec node RPC. + * @returns {Promise} + */ +async function getValidatorStats() { + console.log(`Fetching validator stats from ${rpcUrl} using method ${methodName}...`); + + try { + const response = await fetch(rpcUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + jsonrpc: '2.0', + method: methodName, + params: [], // Assuming no parameters are needed for getValidatorsStats + id: 67, // Using the ID from the example + }), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`); + } + + /** @type {JsonRpcResponse} */ + const data = await response.json(); + + if (data.error) { + throw new Error(`RPC error! code: ${data.error.code}, message: ${data.error.message}`); + } + + const validatorStats = data.result; + + console.log('Successfully fetched validator stats.'); + console.log(`Last Processed Slot: ${validatorStats.lastProcessedSlot ?? 'N/A'}`); + console.log(`Initial Slot: ${validatorStats.initialSlot ?? 'N/A'}`); + console.log(`Slot Window: ${validatorStats.slotWindow}`); + console.log('\nValidator Attestation Details:'); + + for (const [address, stats] of Object.entries(validatorStats.stats)) { + console.log(`\n Validator: ${address}`); + if (stats.lastAttestation) { + // Convert bigint timestamps/slots if they arrive as strings or numbers + const lastAttestationSlot = BigInt(stats.lastAttestation.slot); + const lastAttestationTimestamp = BigInt(stats.lastAttestation.timestamp); + + console.log(` Last Attestation:`); + console.log(` Slot: ${lastAttestationSlot}`); + console.log(` Timestamp: ${lastAttestationTimestamp}`); + console.log(` Date: ${stats.lastAttestation.date}`); // Assuming date is already a string + } else { + console.log(` Last Attestation: None found in history.`); + } + // Optionally log other stats like missed attestations + // console.log(` Missed Attestations Count: ${stats.missedAttestations.count}`); + // console.log(` Missed Attestations Rate: ${stats.missedAttestations.rate.toFixed(4)}`); + } + + } catch (error) { + console.error('Failed to fetch or process validator stats:', error); + } +} + +// Run the script +getValidatorStats(); diff --git a/tooling/sparta/scripts/migrations/00_update_node_operators.js b/tooling/sparta/scripts/migrations/00_update_node_operators.js new file mode 100644 index 0000000..33543d7 --- /dev/null +++ b/tooling/sparta/scripts/migrations/00_update_node_operators.js @@ -0,0 +1,166 @@ +/** + * Update Node Operators Script + * + * This script updates the "node operators" DynamoDB table by: + * 1. Adding a boolean field "isApproved" (default to false) + * 2. For each operator, fetching their Discord username and adding it as a field + * + * Usage: + * node update-node-operators.js [table-name] + * + * Example: + * node update-node-operators.js sparta-node-operators-dev + * + * Note: This script uses ES Modules. Ensure your package.json has "type": "module" + * or run with: node --input-type=module update-node-operators.js + */ + +import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; +import { + DynamoDBDocumentClient, + ScanCommand, + UpdateCommand, +} from "@aws-sdk/lib-dynamodb"; +import { Client, GatewayIntentBits } from "discord.js"; +import dotenv from "dotenv"; +dotenv.config(); + +// Configuration +const tableName = process.argv[2] || "sparta-node-operators-dev"; +const isLocal = process.env.IS_LOCAL !== "false"; +const endpoint = process.env.DYNAMODB_LOCAL_ENDPOINT || "http://localhost:8000"; +const botToken = process.env.BOT_TOKEN; +const guildId = process.env.GUILD_ID; + +console.log("====== Node Operators Table Update ======"); +console.log(`Table: ${tableName}`); +console.log(`Mode: ${isLocal ? "LOCAL" : "AWS"}`); +if (isLocal) { + console.log(`Endpoint: ${endpoint}`); +} +console.log("=========================================\n"); + +async function updateNodeOperators() { + try { + // Validate Discord bot token + if (!botToken) { + console.error("Error: BOT_TOKEN environment variable is required"); + process.exit(1); + } + + // Validate Guild ID + if (!guildId) { + console.error("Error: GUILD_ID environment variable is required"); + process.exit(1); + } + + // Create DynamoDB client + const clientOptions = isLocal ? { endpoint } : {}; + console.log("Creating DynamoDB client with options:", clientOptions); + const dbClient = new DynamoDBClient(clientOptions); + const docClient = DynamoDBDocumentClient.from(dbClient); + + // Create Discord client with necessary intents + console.log("Initializing Discord client..."); + const discordClient = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMembers, + ], + }); + + // Login to Discord + console.log("Logging in to Discord..."); + await discordClient.login(botToken); + console.log("Discord login successful!"); + + // Fetch the guild + console.log(`Fetching guild with ID: ${guildId}`); + const guild = await discordClient.guilds.fetch(guildId); + console.log(`Guild fetch successful: ${guild.name}`); + + // Scan all items from the table + console.log("Scanning table for node operators..."); + const scanCommand = new ScanCommand({ + TableName: tableName, + }); + + const scanResponse = await docClient.send(scanCommand); + const operators = scanResponse.Items || []; + console.log(`Found ${operators.length} node operators in the table`); + + // Initialize counters + let successCount = 0; + let errorCount = 0; + + // Process each operator + console.log("\nUpdating node operators..."); + for (const operator of operators) { + const { discordId } = operator; + console.log(`\nProcessing operator with Discord ID: ${discordId}`); + + try { + // Fetch Discord user information + let discordUsername = null; + try { + console.log(`Fetching Discord member information for ID: ${discordId}`); + const member = await guild.members.fetch(discordId); + discordUsername = member.user.username; + console.log(`Found username: ${discordUsername}`); + } catch (discordError) { + console.warn(`Could not fetch Discord member for ID ${discordId}: ${discordError.message}`); + } + + // Check if fields already exist before updating + if (operator.isApproved !== undefined && (operator.discordUsername !== undefined || !discordUsername)) { + console.log(`Skipping operator ${discordId} - fields already exist`); + successCount++; // Count as success since no update needed + continue; + } + + // Update the operator record + const updateCommand = new UpdateCommand({ + TableName: tableName, + Key: { discordId }, + UpdateExpression: discordUsername + ? "SET isApproved = :isApproved, discordUsername = :discordUsername, updatedAt = :updatedAt" + : "SET isApproved = :isApproved, updatedAt = :updatedAt", + ExpressionAttributeValues: { + ":isApproved": false, + ...(discordUsername ? { ":discordUsername": discordUsername } : {}), + ":updatedAt": Date.now(), + }, + ReturnValues: "UPDATED_NEW", + }); + + const updateResult = await docClient.send(updateCommand); + console.log(`Update result:`, updateResult.Attributes); + successCount++; + } catch (error) { + console.error(`Error updating operator ${discordId}:`, error.message); + errorCount++; + } + } + + // Log completion summary + console.log("\n===== Update Summary ====="); + console.log(`Total operators: ${operators.length}`); + console.log(`Successfully updated: ${successCount}`); + console.log(`Failed to update: ${errorCount}`); + console.log("=========================="); + + // Cleanup + console.log("Logging out from Discord..."); + discordClient.destroy(); + console.log("Script completed!"); + } catch (error) { + console.error("\n❌ Script failed!"); + console.error("Error:", error.message); + console.error("Error Name:", error.name); + console.error("Error Code:", error.code); + console.error("Full Error:", error); + process.exit(1); + } +} + +updateNodeOperators(); \ No newline at end of file diff --git a/tooling/sparta/scripts/migrations/01_migrate_validators.js b/tooling/sparta/scripts/migrations/01_migrate_validators.js new file mode 100644 index 0000000..d147b7b --- /dev/null +++ b/tooling/sparta/scripts/migrations/01_migrate_validators.js @@ -0,0 +1,137 @@ +/** + * Migration script to create a separate validators table and migrate validators + * from being an array in the node operators table to their own dedicated table + * + * This script: + * 1. Creates a new DynamoDB table for validators if it doesn't exist + * 2. Migrates validators from the node operators table to the validators table + * + * Usage: + * node 01_migrate_validators.js + * + * Note: This script uses ES Modules to match the project structure. + */ + +import { DynamoDBClient, CreateTableCommand } from "@aws-sdk/client-dynamodb"; +import { + DynamoDBDocumentClient, + ScanCommand, + PutCommand, + QueryCommand +} from "@aws-sdk/lib-dynamodb"; +import dotenv from "dotenv"; +dotenv.config(); + +// Configuration +const operatorsTableName = process.argv[2] || "sparta-node-operators-dev"; +const validatorsTableName = process.argv[3] || "sparta-validators-dev"; +const NODE_OPERATOR_INDEX_NAME = "NodeOperatorIndex"; +const isLocal = process.env.IS_LOCAL !== "false"; +const endpoint = process.env.DYNAMODB_LOCAL_ENDPOINT || "http://localhost:8000"; + +console.log("====== Validators Migration ======"); +console.log("Source table (node operators): " + operatorsTableName); +console.log("Target table (validators): " + validatorsTableName); +console.log(`Mode: ${isLocal ? "LOCAL" : "AWS"}`); +if (isLocal) { + console.log(`Endpoint: ${endpoint}`); +} +console.log("================================\n"); + +async function runMigration() { + try { + // Create DynamoDB client + const clientOptions = isLocal ? { endpoint } : {}; + console.log("Creating DynamoDB client with options:", clientOptions); + const client = new DynamoDBClient(clientOptions); + const docClient = DynamoDBDocumentClient.from(client); + + // STEP 1: Create the validators table if it doesn't exist + console.log("\nStep 1: Creating validators table..."); + await createValidatorsTable(client); + + console.log("\n✅ Migration completed successfully!"); + return { success: true }; + } catch (error) { + console.error("\n❌ Migration failed:"); + console.error("Error:", error.message); + console.error("Stack:", error.stack); + return { success: false, error: error.message }; + } +} + +async function createValidatorsTable(client) { + try { + // Define table structure + const tableParams = { + TableName: validatorsTableName, + AttributeDefinitions: [ + { + AttributeName: "validatorAddress", + AttributeType: "S", + }, + { + AttributeName: "nodeOperatorId", + AttributeType: "S", + }, + ], + KeySchema: [ + { + AttributeName: "validatorAddress", + KeyType: "HASH", // Partition key + }, + ], + GlobalSecondaryIndexes: [ + { + IndexName: NODE_OPERATOR_INDEX_NAME, + KeySchema: [ + { + AttributeName: "nodeOperatorId", + KeyType: "HASH", // Partition key + }, + ], + Projection: { + ProjectionType: "ALL", + }, + ProvisionedThroughput: { + ReadCapacityUnits: 5, + WriteCapacityUnits: 5, + }, + }, + ], + ProvisionedThroughput: { + ReadCapacityUnits: 5, + WriteCapacityUnits: 5, + }, + }; + + console.log("Creating table with params:", JSON.stringify(tableParams, null, 2)); + const result = await client.send(new CreateTableCommand(tableParams)); + console.log("✅ Table created successfully:", result.TableDescription.TableName); + + // Wait for table to be active + console.log("Waiting for table to become active..."); + // In a real script, you might want to implement a proper waiter here + await new Promise(resolve => setTimeout(resolve, 5000)); + + return true; + } catch (error) { + if (error.name === "ResourceInUseException") { + console.log("✅ Table already exists, continuing with migration"); + return true; + } + throw error; + } +} + +// Run the migration +runMigration() + .then(result => { + if (!result.success) { + process.exit(1); + } + }) + .catch(error => { + console.error("Unhandled error in migration:", error); + process.exit(1); + }); \ No newline at end of file diff --git a/tooling/sparta/scripts/migrations/02_populate_validators.js b/tooling/sparta/scripts/migrations/02_populate_validators.js new file mode 100644 index 0000000..fee6c18 --- /dev/null +++ b/tooling/sparta/scripts/migrations/02_populate_validators.js @@ -0,0 +1,442 @@ +/** + * Migration script to populate Validators table with validators and associate them with node operators + * + * This script: + * 1. Fetches all node operators from the API + * 2. Fetches all validators from the API + * 3. Matches validators with operators by wallet address + * 4. Populates the validators table with the matched validators + * + * Usage: + * node 02_populate_validators.js [operators-table] [validators-table] + * + * Example: + * node 02_populate_validators.js sparta-node-operators-dev sparta-validators-dev + * + * Note: This script uses ES Modules to match the project structure. + */ + +import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; +import { + DynamoDBDocumentClient, + ScanCommand, + PutCommand, + QueryCommand, + UpdateCommand +} from "@aws-sdk/lib-dynamodb"; +import fetch from 'node-fetch'; +import dotenv from "dotenv"; +dotenv.config(); + +// Configuration +const operatorsTableName = process.env.NODE_OPERATORS_TABLE_NAME || "sparta-node-operators-dev"; +const validatorsTableName = process.env.VALIDATORS_TABLE_NAME || "sparta-validators-dev"; +const endpoint = process.env.DYNAMODB_LOCAL_ENDPOINT || "http://localhost:8000"; +const API_URL = `${process.env.API_URL}/api` || 'http://localhost:3000/api'; +const BACKEND_API_KEY = process.env.BACKEND_API_KEY || 'your-api-key'; // Replace with your API key or use environment variable +const DRY_RUN = process.env.DRY_RUN === 'true'; // Set to true to skip saving to the database + +console.log("====== Validators Population Migration ======"); +console.log("Operators table: " + operatorsTableName); +console.log("Validators table: " + validatorsTableName); +console.log("Dry run mode: " + (DRY_RUN ? "enabled (no database writes)" : "disabled")); +console.log("==========================================\n"); + +/** + * Fetches all node operators from the API + * @param {DynamoDBDocumentClient} docClient The DynamoDB document client (not used, kept for compatibility) + * @returns {Promise} List of all operators + */ +async function getOperatorsFromDB(docClient) { + console.log('Fetching all operators from API...'); + + if (!BACKEND_API_KEY) { + throw new Error('BACKEND_API_KEY environment variable is required'); + } + + let allOperators = []; + let nextPageToken = null; + let pageCount = 0; + + do { + // Build URL with pagination token if available + let url = `${API_URL}/operator/operators`; + if (nextPageToken) { + url += `?pageToken=${encodeURIComponent(nextPageToken)}`; + } + + console.log(`Fetching operators page ${pageCount + 1}...`); + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': BACKEND_API_KEY + } + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + // The response structure includes operators and nextPageToken fields + const operators = data.operators || []; + nextPageToken = data.nextPageToken; + + console.log(`Retrieved ${operators.length} operators from page ${++pageCount}`); + allOperators = [...allOperators, ...operators]; + + } while (nextPageToken); + + console.log(`Successfully fetched a total of ${allOperators.length} operators.`); + return allOperators; +} + +/** + * Fetches all validators from the API + * @returns {Promise} All validators + */ +async function getAllValidators() { + console.log('Fetching all validators from API...'); + + if (!BACKEND_API_KEY) { + throw new Error('BACKEND_API_KEY environment variable is required'); + } + + const url = `${API_URL}/operator/validators`; + console.log("url", url); + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': BACKEND_API_KEY + } + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + + // Based on the updated API response structure + if (data.success && data.data && data.data.blockchainValidators && data.data.blockchainValidators.validators) { + const blockchainValidators = data.data.blockchainValidators.validators; + console.log(`Successfully fetched ${blockchainValidators.length} blockchain validators.`); + + // Also check how many are already known + if (data.data.knownValidators && data.data.knownValidators.validators) { + console.log(`${data.data.knownValidators.validators.length} validators are already known in the database.`); + } + + return blockchainValidators; + } else { + console.error('Unexpected API response format:', data); + throw new Error('API response format was not as expected'); + } +} + +/** + * Matches validators with operators by comparing addresses + * @param {Array} validators List of validators from blockchain + * @param {Array} operators List of operators from DB + * @returns {Promise} Matched validators with operator IDs + */ +async function matchValidatorsWithOperators(validators, operators) { + console.log('Matching blockchain validators with operators by comparing addresses...'); + console.log(`Input: ${validators.length} blockchain validators and ${operators.length} operators`); + + const matches = []; + + // Create a map of operator wallet addresses to operator details for faster lookup + // Note: addresses are stored in lowercase for case-insensitive comparison + const operatorsByWallet = {}; + operators.forEach(operator => { + if (operator.walletAddress) { + operatorsByWallet[operator.walletAddress.toLowerCase()] = operator; + } + }); + + console.log(`Found ${Object.keys(operatorsByWallet).length} unique operator wallet addresses`); + + // Debug: Print first 5 operator wallet addresses + const walletSample = Object.keys(operatorsByWallet).slice(0, 5); + console.log('Sample operator wallet addresses:', walletSample); + + // For each validator address from blockchain, check if it matches any operator's wallet address + let matchCount = 0; + validators.forEach(validatorAddress => { + if (!validatorAddress) return; + + // For comparison, use lowercase + const validatorAddressLower = validatorAddress.toLowerCase(); + + // Check if this validator address matches an operator's wallet address + const operatorWallet = operatorsByWallet[validatorAddressLower]; + if (operatorWallet) { + matchCount++; + // Log the match for debugging + if (matchCount <= 5) { + console.log(`Match found: Validator ${validatorAddress} -> Operator ${operatorWallet.discordId} (${operatorWallet.discordUsername || 'No username'})`); + } + + // Store with the EXACT same case as received from the blockchain API + matches.push({ + validatorAddress: validatorAddress, // Keep original case + nodeOperatorId: operatorWallet.discordId, + createdAt: Date.now(), + updatedAt: Date.now() + }); + } + }); + + console.log(`Found ${matchCount} validators matching operator wallet addresses.`); + console.log(`Total matches: ${matches.length} validators will be saved to the database.`); + + return matches; +} + +/** + * Saves validators to the DynamoDB table + * @param {DynamoDBDocumentClient} docClient The DynamoDB document client + * @param {Array} validators The validators to save + */ +async function saveValidatorsToDB(docClient, validators) { + console.log(`Saving ${validators.length} validators to ${validatorsTableName}...`); + + let successCount = 0; + let errorCount = 0; + + for (const validator of validators) { + try { + const putCommand = new PutCommand({ + TableName: validatorsTableName, + Item: validator, + ConditionExpression: "attribute_not_exists(validatorAddress)" + }); + + await docClient.send(putCommand); + successCount++; + + // Log progress every 10 validators + if (successCount % 10 === 0) { + console.log(`Progress: ${successCount}/${validators.length} validators saved`); + } + } catch (error) { + if (error.name === 'ConditionalCheckFailedException') { + console.log(`Validator ${validator.validatorAddress} already exists, updating instead...`); + + try { + const updateCommand = new UpdateCommand({ + TableName: validatorsTableName, + Key: { validatorAddress: validator.validatorAddress }, + UpdateExpression: "set nodeOperatorId = :operatorId, updatedAt = :updatedAt", + ExpressionAttributeValues: { + ":operatorId": validator.nodeOperatorId, + ":updatedAt": Date.now() + } + }); + + await docClient.send(updateCommand); + successCount++; + } catch (updateError) { + console.error(`Error updating validator ${validator.validatorAddress}:`, updateError); + errorCount++; + } + } else { + console.error(`Error saving validator ${validator.validatorAddress}:`, error); + errorCount++; + } + } + } + + console.log(`\nValidators save complete:`); + console.log(` Success: ${successCount}`); + console.log(` Errors: ${errorCount}`); + + return { successCount, errorCount }; +} + +/** + * Main migration function + */ +async function runMigration() { + try { + // Create DynamoDB client + const clientOptions = { endpoint }; + console.log("Creating DynamoDB client with options:", clientOptions); + const client = new DynamoDBClient(clientOptions); + const docClient = DynamoDBDocumentClient.from(client); + + // 1. Fetch all node operators from API + const operators = await getOperatorsFromDB(docClient); + + // 2. Fetch all validators from API (these are blockchain validators) + const blockchainValidators = await getAllValidators(); + + // Print some samples to debug case sensitivity + if (blockchainValidators.length > 0) { + console.log("\nSample blockchain validator addresses (first 5):"); + blockchainValidators.slice(0, 5).forEach(addr => { + console.log(` ${addr} (lowercase: ${addr.toLowerCase()})`); + }); + } + + // 3. Match blockchain validators with operators by wallet address + const matchedValidators = await matchValidatorsWithOperators(blockchainValidators, operators); + + // 4. Save matched validators to DynamoDB + if (matchedValidators.length > 0) { + if (!DRY_RUN) { + await saveValidatorsToDB(docClient, matchedValidators); + + // 5. Verify data was saved correctly by checking a few examples + console.log("\nVerifying saved validators by direct DB query..."); + + if (matchedValidators.length > 0) { + // Try to verify a few samples + for (let i = 0; i < Math.min(3, matchedValidators.length); i++) { + const sampleValidator = matchedValidators[i]; + const getCommand = new ScanCommand({ + TableName: validatorsTableName, + FilterExpression: "validatorAddress = :address", + ExpressionAttributeValues: { + ":address": sampleValidator.validatorAddress + }, + Limit: 1 + }); + + try { + const response = await docClient.send(getCommand); + if (response.Items && response.Items.length > 0) { + console.log(`Sample ${i+1}: Found validator in database:`, response.Items[0]); + } else { + console.log(`Sample ${i+1}: Could not find validator with exact match: ${sampleValidator.validatorAddress}`); + + // Try case-insensitive match + const scanCommand = new ScanCommand({ + TableName: validatorsTableName, + Limit: 100 + }); + + const scanResponse = await docClient.send(scanCommand); + const allValidators = scanResponse.Items || []; + + const caseInsensitiveMatch = allValidators.find(v => + v.validatorAddress.toLowerCase() === sampleValidator.validatorAddress.toLowerCase() + ); + + if (caseInsensitiveMatch) { + console.log(` But found case-insensitive match:`, caseInsensitiveMatch); + console.log(` Case difference: "${caseInsensitiveMatch.validatorAddress}" vs "${sampleValidator.validatorAddress}"`); + } else { + console.log(` No case-insensitive match found either!`); + } + } + } catch (error) { + console.error(`Error verifying validator ${i+1} in database:`, error); + } + } + + // 6. Call the validators API to check response after update... + console.log("\nCalling validators API to check response after update..."); + try { + const url = `${API_URL}/operator/validators`; + const apiResponse = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': BACKEND_API_KEY + } + }); + + if (!apiResponse.ok) { + throw new Error(`HTTP error! status: ${apiResponse.status} ${apiResponse.statusText}`); + } + + const apiData = await apiResponse.json(); + + // Check how many known validators we have now + if (apiData.success && apiData.data && apiData.data.knownValidators) { + const knownCount = apiData.data.knownValidators.validators.length; + console.log(`API now reports ${knownCount} known validators.`); + + // Check if our sample validators are included + const samplesFound = matchedValidators.slice(0, 3).filter(sample => + apiData.data.knownValidators.validators.some(v => + v.toLowerCase() === sample.validatorAddress.toLowerCase() + ) + ); + + console.log(`${samplesFound.length} out of ${Math.min(3, matchedValidators.length)} sample validators found in API response.`); + + if (samplesFound.length !== Math.min(3, matchedValidators.length)) { + console.log("⚠️ Some sample validators are not included in known validators from API."); + console.log("This may indicate a case sensitivity issue in the API."); + } else { + console.log("✅ All sample validators are included in known validators from API."); + } + } else { + console.log("⚠️ Could not determine number of known validators from API response."); + } + } catch (error) { + console.error("Error calling validators API:", error); + } + + // 7. Do a complete database scan to check how many validators are actually in the database + console.log("\nChecking total validators in database..."); + try { + const scanCommand = new ScanCommand({ + TableName: validatorsTableName, + Select: "COUNT", + }); + + const scanResponse = await docClient.send(scanCommand); + console.log(`Found ${scanResponse.Count || 0} total validators in the database.`); + + // If there are validators, scan a few of them to check + if (scanResponse.Count && scanResponse.Count > 0) { + const detailCommand = new ScanCommand({ + TableName: validatorsTableName, + Limit: 5, + }); + + const detailResponse = await docClient.send(detailCommand); + console.log("Sample validators in database:"); + (detailResponse.Items || []).forEach((item, index) => { + console.log(`Sample ${index + 1}:`, item); + }); + } + } catch (error) { + console.error("Error scanning validators database:", error); + } + } + } else { + console.log("Dry run mode enabled, skipping database writes."); + console.log(`Would have saved ${matchedValidators.length} validators.`); + } + } else { + console.log("No validators matched with operators, nothing to save."); + } + + console.log("\n✅ Migration completed successfully!"); + return { success: true }; + } catch (error) { + console.error("\n❌ Migration failed:"); + console.error("Error:", error.message); + console.error("Stack:", error.stack); + return { success: false, error: error.message }; + } +} + +// Run the migration +runMigration() + .then(result => { + if (!result.success) { + process.exit(1); + } + }) + .catch(error => { + console.error("Unhandled error in migration:", error); + process.exit(1); + }); \ No newline at end of file diff --git a/tooling/sparta/scripts/start-local-dynamodb.sh b/tooling/sparta/scripts/start-local-dynamodb.sh new file mode 100755 index 0000000..faec517 --- /dev/null +++ b/tooling/sparta/scripts/start-local-dynamodb.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# This script sets up a local DynamoDB instance for development testing + +# Check if Docker is running +if ! docker info > /dev/null 2>&1; then + echo "Docker is not running. Please start Docker and try again." + exit 1 +fi + +# Check if the DynamoDB container is already running +if docker ps | grep -q "dynamodb-local"; then + echo "DynamoDB container is already running." +else + echo "Starting DynamoDB local container..." + docker run -d --name dynamodb-local -p 8000:8000 amazon/dynamodb-local:latest -jar DynamoDBLocal.jar -sharedDb + echo "DynamoDB local started on port 8000" +fi + +# Create the node operators table with the required schema +echo "Creating node operators table..." +aws dynamodb create-table \ + --table-name sparta-node-operators-dev \ + --attribute-definitions \ + AttributeName=discordId,AttributeType=S \ + AttributeName=walletAddress,AttributeType=S \ + --key-schema AttributeName=discordId,KeyType=HASH \ + --global-secondary-indexes '[ + { + "IndexName": "WalletAddressIndex", + "KeySchema": [{"AttributeName": "walletAddress", "KeyType": "HASH"}], + "Projection": {"ProjectionType": "ALL"}, + "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5} + } + ]' \ + --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \ + --endpoint-url http://localhost:8000 + +# Check if node operators table creation was successful +if [ $? -eq 0 ]; then + echo "Table sparta-node-operators-dev created successfully" +else + echo "Table sparta-node-operators-dev may already exist, trying to use existing table" +fi + +# Create the validators table with the required schema +echo "Creating validators table..." +aws dynamodb create-table \ + --table-name sparta-validators-dev \ + --attribute-definitions \ + AttributeName=validatorAddress,AttributeType=S \ + AttributeName=nodeOperatorId,AttributeType=S \ + --key-schema AttributeName=validatorAddress,KeyType=HASH \ + --global-secondary-indexes '[ + { + "IndexName": "NodeOperatorIndex", + "KeySchema": [{"AttributeName": "nodeOperatorId", "KeyType": "HASH"}], + "Projection": {"ProjectionType": "ALL"}, + "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5} + } + ]' \ + --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \ + --endpoint-url http://localhost:8000 + +# Check if validators table creation was successful +if [ $? -eq 0 ]; then + echo "Table sparta-validators-dev created successfully" +else + echo "Table sparta-validators-dev may already exist, trying to use existing table" +fi + +# List tables to confirm +echo "Available tables in local DynamoDB:" +aws dynamodb list-tables --endpoint-url http://localhost:8000 + +echo "DynamoDB local setup complete. You can now run your application with:" +echo "LOCAL_DYNAMO_DB=true DYNAMODB_LOCAL_ENDPOINT=http://localhost:8000 NODE_OPERATORS_TABLE_NAME=sparta-node-operators-dev VALIDATORS_TABLE_NAME=sparta-validators-dev npm run dev" diff --git a/tooling/sparta/scripts/swagger.js b/tooling/sparta/scripts/swagger.js new file mode 100644 index 0000000..e736f37 --- /dev/null +++ b/tooling/sparta/scripts/swagger.js @@ -0,0 +1,51 @@ +// generate.js +import swaggerJSDoc from "swagger-jsdoc"; +import fs from "fs"; +import path from "path"; +import dotenv from "dotenv"; + +dotenv.config(); + +// Define default API URL with fallbacks +const apiUrl = process.env.API_URL || + `${process.env.API_PROTOCOL || 'http'}://${process.env.API_HOST || 'localhost'}:${process.env.API_PORT || '3000'}`; + +console.log(`Generating OpenAPI docs with base URL: ${apiUrl}`); + +// swaggerOptions.js +export const swaggerDefinition = { + openapi: "3.0.0", + info: { + title: "Sparta API", + version: "1.0.0", + description: "…", + }, + servers: [ + { + url: "{serverUrl}", + description: "Sparta API", + variables: { + serverUrl: { + default: apiUrl, + description: "API server URL" + } + } + }, + ], + components: { + /* schemas & securitySchemes */ + }, +}; + +export const options = { + definition: swaggerDefinition, + apis: ["packages/express/src/routes/**/*.ts"], // wherever your @openapi JSDoc lives +}; + +const spec = swaggerJSDoc(options); + +console.log(spec); +fs.writeFileSync( + path.resolve("packages/utils/openapi/api-docs.json"), + JSON.stringify(spec, null, 2) +); diff --git a/tooling/sparta/scripts/test-dynamodb.js b/tooling/sparta/scripts/test-dynamodb.js new file mode 100755 index 0000000..f3e102e --- /dev/null +++ b/tooling/sparta/scripts/test-dynamodb.js @@ -0,0 +1,127 @@ +/** + * DynamoDB Test Script + * + * This script tests the DynamoDB connection and performs basic operations + * to verify that DynamoDB is set up correctly. + * + * Usage: + * node test-dynamodb.js [table-name] + * + * Example: + * node test-dynamodb.js sparta-sessions + */ + +const { DynamoDBClient } = require("@aws-sdk/client-dynamodb"); +const { + DynamoDBDocumentClient, + PutCommand, + GetCommand, + DeleteCommand, + ScanCommand, +} = require("@aws-sdk/lib-dynamodb"); + +const tableName = process.argv[2] || "users"; +const isLocal = process.env.IS_LOCAL !== "false"; +const endpoint = process.env.DYNAMODB_LOCAL_ENDPOINT || "http://localhost:8000"; + +console.log("====== DynamoDB Test ======"); +console.log(`Table: ${tableName}`); +console.log(`Mode: ${isLocal ? "LOCAL" : "AWS"}`); +if (isLocal) { + console.log(`Endpoint: ${endpoint}`); +} +console.log("============================\n"); + +async function runTest() { + try { + // Create DynamoDB client + const clientOptions = isLocal ? { endpoint } : {}; + console.log("Creating DynamoDB client with options:", clientOptions); + + const client = new DynamoDBClient(clientOptions); + const docClient = DynamoDBDocumentClient.from(client); + + // Test connection by listing tables + console.log("1. Testing connection..."); + + // Create a test item + const testId = `test-item-${Date.now()}`; + console.log(`2. Creating test item with ID: ${testId}`); + const putCommand = new PutCommand({ + TableName: tableName, + Item: { + sessionId: testId, + discordUserId: "test-user", + verified: false, + roleAssigned: false, + createdAt: Date.now(), + status: "test", + }, + }); + + await docClient.send(putCommand); + console.log(" ✅ Test item created successfully"); + + // Read the item back + console.log(`3. Reading test item with ID: ${testId}`); + const getCommand = new GetCommand({ + TableName: tableName, + Key: { sessionId: testId }, + }); + + const response = await docClient.send(getCommand); + if (response.Item) { + console.log(" ✅ Test item read successfully"); + console.log(" Item:", JSON.stringify(response.Item, null, 2)); + } else { + console.log(" ❌ Failed to read test item"); + } + + // Delete the test item + console.log(`4. Deleting test item with ID: ${testId}`); + const deleteCommand = new DeleteCommand({ + TableName: tableName, + Key: { sessionId: testId }, + }); + + await docClient.send(deleteCommand); + console.log(" ✅ Test item deleted successfully"); + + // Verify deletion + const verifyGet = await docClient.send(getCommand); + if (!verifyGet.Item) { + console.log(" ✅ Verified item was deleted"); + } else { + console.log(" ❌ Item still exists after deletion attempt"); + } + + // List all items in the table + console.log("5. Listing all items in the table (max 10)"); + const scanCommand = new ScanCommand({ + TableName: tableName, + Limit: 10, + }); + + const scanResponse = await docClient.send(scanCommand); + console.log( + ` Found ${scanResponse.Items?.length || 0} items in the table` + ); + if (scanResponse.Items?.length > 0) { + console.log( + " Sample item:", + JSON.stringify(scanResponse.Items[0], null, 2) + ); + } + + console.log("\n✅ All tests passed! DynamoDB is working correctly."); + } catch (error) { + console.error("\n❌ Test failed!"); + console.error("Error:", error.message); + console.error("Error Name:", error.name); + console.error("Error Code:", error.code); + console.error("Full Error:", error); + process.exit(1); + } +} + +runTest(); diff --git a/tooling/sparta/src/.env.example b/tooling/sparta/src/.env.example deleted file mode 100644 index a2837e7..0000000 --- a/tooling/sparta/src/.env.example +++ /dev/null @@ -1,25 +0,0 @@ -# Discord Bot Configuration -BOT_TOKEN=your_bot_token_here -BOT_CLIENT_ID=your_client_id_here -GUILD_ID=your_guild_id_here - -# Ethereum Configuration -ETHEREUM_HOST=http://localhost:8545 -MINTER_PRIVATE_KEY=your_minter_private_key_here -ETHEREUM_REGISTRY_ADDRESS=your_registry_address_here -WITHDRAWER_ADDRESS=your_withdrawer_address_here -ETHEREUM_CHAIN_ID=1337 -ETHEREUM_VALUE=20ether - -MINIMUM_STAKE=100000000000000000000 -APPROVAL_AMOUNT=10000000000000000000000 - -# Google Sheets Configuration -GOOGLE_API_KEY=your_google_api_key_here -SPREADSHEET_ID=your_spreadsheet_id_here - -# Logging Configuration -# Available levels: trace, debug, info, warn, error, fatal -LOG_LEVEL=info -# Enable/disable pretty printing with colors (true/false) -LOG_PRETTY_PRINT=true diff --git a/tooling/sparta/src/README.md b/tooling/sparta/src/README.md deleted file mode 100644 index 3dcb973..0000000 --- a/tooling/sparta/src/README.md +++ /dev/null @@ -1,160 +0,0 @@ -# Sparta Discord Bot - Source Code - -This directory contains the source code for the Sparta Discord bot, which manages Aztec validators and Discord roles. - -## Project Structure - -The project is organized into several directories: - -- **clients/**: API client interfaces for external services (Discord, Ethereum, Google Sheets) -- **roles/**: Command implementations for different Discord roles -- **services/**: Core business logic services -- **utils/**: Utility functions and helpers - -## Key Components - -### Clients - -The `clients/` directory contains interfaces to external services: - -- **discord.ts**: Discord.js client setup and configuration -- **ethereum.ts**: Ethereum blockchain interaction via viem -- **google.ts**: Google Sheets API integration - -### Services - -The `services/` directory contains the core business logic: - -- **chaininfo-service.ts**: Retrieves blockchain state information -- **discord-service.ts**: Manages Discord roles and user identification -- **googlesheet-service.ts**: Monitors Google Sheets for user scores and triggers role assignments -- **validator-service.ts**: Manages validator registration and funding - -### Roles - -The `roles/` directory contains command definitions for different user roles: - -- **nodeOperators/**: Commands available to users with the Node Operator role - - **validator.ts**: Commands for validator registration and checking - - **getChainInfo.ts**: Commands for retrieving chain information -- **admins/**: Commands available only to administrators - -## Key Functionality - -### Role Management - -The bot automatically assigns hierarchical Discord roles based on user scores from Google Sheets: - -1. **Guardian**: Base role (default, requires minimum score of 0) -2. **Defender**: Middle role (requires score > 5) -3. **Sentinel**: Highest role (set manually, but can be removed by this service) - -```typescript -// Example from googlesheet-service.ts -if (score > 10) { - roleName = NodeOperatorRoles.Sentinel; // Highest role -} else if (score > 5) { - roleName = NodeOperatorRoles.Defender; // Middle role -} else { - roleName = NodeOperatorRoles.Guardian; // Default/lowest role -} -``` - -### Validator Management - -The bot provides commands to manage validators on the Ethereum network: - -- Add validators -- Remove validators -- Check validator status -- Fund validators - -```typescript -// Example validator registration -await ValidatorService.addValidator("0x123..."); -``` - -### Chain Information - -The bot provides commands to retrieve blockchain information: - -- Current epoch and slot -- Pending and proven block numbers -- Committee members -- Current proposer - -```typescript -// Example chain info retrieval -const chainInfo = await ChainInfoService.getInfo(); -console.log(`Current epoch: ${chainInfo.currentEpoch}`); -``` - -## Environment Configuration - -The application requires several environment variables to function correctly. Create a `.env` file based on the `.env.example` template with the following variables: - -``` -# Discord Bot Configuration -BOT_TOKEN=your_bot_token -BOT_CLIENT_ID=your_client_id -GUILD_ID=your_guild_id - -# Ethereum Configuration -ETHEREUM_HOST=http://localhost:8545 -MINTER_PRIVATE_KEY=your_private_key -ETHEREUM_REGISTRY_ADDRESS=your_registry_address -WITHDRAWER_ADDRESS=address_to_withdraw_funds_to -ETHEREUM_CHAIN_ID=1337 -ETHEREUM_VALUE=20ether -MINIMUM_STAKE=100000000000000000000 -APPROVAL_AMOUNT=10000000000000000000000 - -# Google Sheets Configuration -GOOGLE_API_KEY=your_api_key -SPREADSHEET_ID=your_spreadsheet_id -``` - -## Development - -### Building and Running - -The project uses Bun for package management and running: - -```bash -# Install dependencies -bun install - -# Run in development mode with hot reloading -bun run dev - -# Build for production -bun run build - -# Run in production mode -bun run start -``` - -### Adding New Commands - -To add a new command: - -1. Create a new command file in the appropriate role directory -2. Define the command using Discord.js slash command builders -3. Export the command and add it to the role's index.ts file - -Example command structure: - -```typescript -import { SlashCommandBuilder } from "discord.js"; - -export default { - data: new SlashCommandBuilder() - .setName("command-name") - .setDescription("Command description"), - - execute: async (interaction) => { - // Command implementation - await interaction.reply("Response message"); - } -}; -``` diff --git a/tooling/sparta/src/clients/README.md b/tooling/sparta/src/clients/README.md deleted file mode 100644 index 2d91ce7..0000000 --- a/tooling/sparta/src/clients/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Clients - -This directory contains client adapters for external services and APIs. - -- `discord.ts` - Discord client for bot interactions -- `google.ts` - Google Sheets client for spreadsheet operations -- `ethereum.ts` - Ethereum blockchain client for interacting with smart contracts -- `aztec.ts` - Aztec client for interacting with Aztec protocol diff --git a/tooling/sparta/src/clients/aztec.ts b/tooling/sparta/src/clients/aztec.ts deleted file mode 100644 index 925a04f..0000000 --- a/tooling/sparta/src/clients/aztec.ts +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @fileoverview Aztec client and utilities - * @description Provides Aztec node interaction methods via JSON-RPC - * @module sparta/utils/aztec - */ -import { logger } from "../utils/logger.js"; - -export class Aztec { - private readonly rpcUrl: string; - - constructor(rpcUrl: string) { - this.rpcUrl = rpcUrl; - } - - static new = async () => { - try { - logger.info("Initializing Aztec client"); - const rpcUrl = process.env.AZTEC_NODE_URL; - - if (!rpcUrl) { - throw new Error("AZTEC_NODE_URL is not set"); - } - - return new Aztec(rpcUrl); - } catch (error) { - logger.error({ error }, "Error initializing Aztec client"); - throw error; - } - }; - - private async sendJsonRpcRequest( - method: string, - params: any[] = [] - ): Promise { - const response = await fetch(this.rpcUrl, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - jsonrpc: "2.0", - method, - params, - id: 67, - }), - }); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const data = await response.json(); - if (data.error) { - throw new Error(`RPC error: ${JSON.stringify(data.error)}`); - } - - return data.result; - } - - getL2Tips = async (): Promise => { - const result = await this.sendJsonRpcRequest("node_getL2Tips"); - return result.proven.number as string; - }; - - getArchiveSiblingPath = async (blockNumber: string): Promise => { - return await this.sendJsonRpcRequest("node_getArchiveSiblingPath", [ - blockNumber, - blockNumber, - ]); - }; -} - -export const aztec = await Aztec.new(); diff --git a/tooling/sparta/src/clients/discord.ts b/tooling/sparta/src/clients/discord.ts deleted file mode 100644 index b300042..0000000 --- a/tooling/sparta/src/clients/discord.ts +++ /dev/null @@ -1,191 +0,0 @@ -/** - * @fileoverview Discord client and utilities - * @description Provides Discord client configuration and event handling - * @module sparta/utils/discord - */ - -import { - Client, - GatewayIntentBits, - Collection, - Interaction, - MessageFlags, - TextChannel, - REST, - Routes, -} from "discord.js"; -import nodeOperatorCommands from "../roles/nodeOperators/index.js"; -import adminsCommands from "../roles/admins/index.js"; -import { logger } from "../utils/logger.js"; -import { subscribe } from "diagnostics_channel"; - -// Extended Discord client interface with commands collection -export interface ExtendedClient extends Client { - commands: Collection; -} - -export class Discord { - private client: ExtendedClient; - - constructor(client: ExtendedClient) { - this.client = client; - } - - /** - * Creates a new Discord instance with initialized client - */ - static new = async () => { - try { - logger.info("Initializing Discord client"); - - // Initialize Discord client with required intents - const client = new Client({ - intents: [ - GatewayIntentBits.Guilds, - GatewayIntentBits.GuildMessages, - ], - }) as ExtendedClient; - - // Initialize commands collection - client.commands = new Collection(); - - // Set up event handlers - Discord.setupEventHandlers(client); - - // Log in to Discord - await client.login(process.env.BOT_TOKEN); - - return new Discord(client); - } catch (error) { - logger.error({ error }, "Error initializing Discord client"); - throw error; - } - }; - - /** - * Sets up the event handlers for the Discord client - * @param client The Discord client - */ - private static setupEventHandlers(client: ExtendedClient): void { - /** - * Error event handler - */ - client.once("error", (error) => { - logger.error({ error }, "Discord client error"); - }); - - /** - * Ready event handler - called when bot is initialized - */ - client.once("ready", async () => { - logger.info("Sparta bot is ready!"); - logger.info( - { clientId: process.env.BOT_CLIENT_ID }, - "Bot connected with Client ID" - ); - Discord.deployCommands(client); - }); - - /** - * Interaction event handler - processes all slash commands - * @param {Interaction} interaction - The interaction object from Discord - */ - client.on("interactionCreate", async (interaction: Interaction) => { - if (!interaction.isChatInputCommand()) return; - - const command = client.commands.get(interaction.commandName); - if (!command) return; - - logger.debug( - { - command: interaction.commandName, - subcommand: interaction.options.getSubcommand(), - }, - "Command" - ); - try { - const channel = interaction.channel as TextChannel; - - logger.debug( - { - channel: channel.name, - user: interaction.user.username, - date: interaction.createdAt, - }, - "Command info" - ); - const reply = await command.execute(interaction); - logger.debug( - { - reply, - }, - "Command reply" - ); - } catch (error) { - logger.error({ error }, "Error executing command"); - await interaction.reply({ - content: "There was an error executing this command!", - flags: MessageFlags.Ephemeral, - }); - } - }); - } - - /** - * Deploys all slash commands to the Discord server - * @param client The Discord client - */ - private static async deployCommands(client: ExtendedClient): Promise { - const rest = new REST({ version: "10" }).setToken( - process.env.BOT_TOKEN as string - ); - - try { - logger.info("Started refreshing application (/) commands"); - - const commandsData = Object.values({ - ...nodeOperatorCommands, - ...adminsCommands, - }).map((command) => command.data.toJSON()); - - await rest.put( - Routes.applicationGuildCommands( - process.env.BOT_CLIENT_ID as string, - process.env.GUILD_ID as string - ), - { - body: commandsData, - } - ); - - for (const command of Object.values({ - ...nodeOperatorCommands, - ...adminsCommands, - })) { - client.commands.set(command.data.name, command); - logger.debug(`Registered command: ${command.data.name}`); - } - - logger.info("Successfully reloaded application (/) commands"); - } catch (error) { - logger.error({ error }, "Error deploying commands"); - } - } - - /** - * Gets the Discord client - */ - getClient = () => { - return this.client; - }; - - /** - * Finds a guild by ID - */ - getGuild = async (guildId: string) => { - return await this.client.guilds.fetch(guildId); - }; -} - -// Create and export a shared Discord instance -export const discord = await Discord.new(); diff --git a/tooling/sparta/src/clients/ethereum.ts b/tooling/sparta/src/clients/ethereum.ts deleted file mode 100644 index 2a842b6..0000000 --- a/tooling/sparta/src/clients/ethereum.ts +++ /dev/null @@ -1,211 +0,0 @@ -/** - * @fileoverview Ethereum client and utilities - * @description Provides Ethereum client configuration and interaction methods - * @module sparta/utils/ethereum - */ - -import { - createPublicClient, - createWalletClient, - encodeDeployData, - getContract, - getCreate2Address, - http, - padHex, - toHex, - TransactionReceipt, - WalletClient, -} from "viem"; - -import { RollupAbi } from "../utils/abis/rollup.js"; -import { TestERC20Abi } from "../utils/abis/testERC20Abi.js"; -import { RegistryAbi } from "../utils/abis/registryAbi.js"; -import { privateKeyToAccount } from "viem/accounts"; -import type { Hex } from "viem"; -import { ForwarderBytecode, ForwarderAbi } from "../utils/abis/forwarder.js"; -import { logger } from "../utils/logger.js"; - -export const DEPLOYER_ADDRESS: Hex = - "0x4e59b44847b379578588920cA78FbF26c0B4956C"; - -/** - * Ethereum chain configuration - * @const {Object} ethereumChain - */ -const ethereumChain = { - id: parseInt(process.env.L1_CHAIN_ID as string), - name: "Sepolia", - network: "sepolia", - nativeCurrency: { - decimals: 18, - name: "Ethereum", - symbol: "ETH", - }, - rpcUrls: { - default: { - http: [process.env.ETHEREUM_HOST as string], - }, - public: { - http: [process.env.ETHEREUM_HOST as string], - }, - }, -} as const; - -export function getExpectedAddress(args: [`0x${string}`], salt: Hex) { - const paddedSalt = padHex(salt, { size: 32 }); - const calldata = encodeDeployData({ - abi: ForwarderAbi, - bytecode: ForwarderBytecode, - args, - }); - const address = getCreate2Address({ - from: DEPLOYER_ADDRESS, - salt: paddedSalt, - bytecode: calldata, - }); - return { - address, - paddedSalt, - calldata, - }; -} - -export class Ethereum { - constructor( - private publicClient: ReturnType, - private walletClient: ReturnType, - private rollup: any, - private stakingAsset: any - ) {} - - static new = async () => { - try { - logger.info("Initializing Ethereum client"); - const rpcUrl = process.env.ETHEREUM_HOST as string; - const privateKey = process.env.MINTER_PRIVATE_KEY as `0x${string}`; - - const publicClient = createPublicClient({ - chain: ethereumChain, - transport: http(rpcUrl), - }); - - const walletClient = createWalletClient({ - account: privateKeyToAccount(privateKey), - chain: ethereumChain, - transport: http(rpcUrl), - }); - - const registry = getContract({ - address: process.env.ETHEREUM_REGISTRY_ADDRESS as `0x${string}`, - abi: RegistryAbi, - client: walletClient, - }); - - const rollupAddress = await registry.read.getRollup(); - - const rollup = getContract({ - address: rollupAddress as `0x${string}`, - abi: RollupAbi, - client: walletClient, - }); - - const stakingAsset = getContract({ - address: (await rollup.read.getStakingAsset()) as `0x${string}`, - abi: TestERC20Abi, - client: walletClient, - }); - - return new Ethereum( - publicClient, - walletClient, - rollup, - stakingAsset - ); - } catch (error) { - logger.error({ error }, "Error initializing Ethereum client"); - throw error; - } - }; - - getPublicClient = () => { - return this.publicClient; - }; - - getWalletClient = () => { - return this.walletClient; - }; - - getRollup = () => { - return this.rollup; - }; - - // TODO: For now, the withdrawer address is managed by the bot - stakingAssetFaucet = async (address: string) => { - const txHash = await this.stakingAsset.write.mint([ - this.walletClient.account?.address as `0x${string}`, - process.env.MINIMUM_STAKE as unknown as string, - ]); - - const receipt = await this.publicClient.waitForTransactionReceipt({ - hash: txHash, - }); - - return receipt; - }; - - addValidator = async (address: string): Promise => { - const expectedAddress = getExpectedAddress( - [address as `0x${string}`], - address as `0x${string}` - ); - const hashes = await Promise.all( - [ - await this.stakingAsset.write.approve([ - this.rollup.address, - process.env.APPROVAL_AMOUNT as unknown as string, - ]), - await this.rollup.write.deposit([ - address, - expectedAddress.address, - process.env.WITHDRAWER_ADDRESS as `0x${string}`, - process.env.MINIMUM_STAKE as unknown as string, - ]), - ].map((txHash) => - this.publicClient.waitForTransactionReceipt({ - hash: txHash, - }) - ) - ); - - return hashes; - }; - - removeValidator = async (address: string): Promise => { - const withdrawerWalletClient = createWalletClient({ - account: privateKeyToAccount( - process.env.WITHDRAWER_PRIVATE_KEY as `0x${string}` - ), - chain: ethereumChain, - transport: http(process.env.ETHEREUM_HOST as string), - }); - - const rollupWithdrawerScoped = getContract({ - address: this.rollup.address as `0x${string}`, - abi: RollupAbi, - client: withdrawerWalletClient, - }); - - const txHash = await rollupWithdrawerScoped.write.initiateWithdraw([ - address as `0x${string}`, - process.env.WITHDRAWER_ADDRESS as `0x${string}`, - ]); - - const receipt = await this.publicClient.waitForTransactionReceipt({ - hash: txHash, - }); - - return receipt; - }; -} - -export const ethereum = await Ethereum.new(); diff --git a/tooling/sparta/src/clients/google.ts b/tooling/sparta/src/clients/google.ts deleted file mode 100644 index f4d3dd1..0000000 --- a/tooling/sparta/src/clients/google.ts +++ /dev/null @@ -1,292 +0,0 @@ -import { sheets, sheets_v4 } from "@googleapis/sheets"; -import { logger } from "../utils/logger.js"; - -export class GoogleSheet { - private sheets: sheets_v4.Sheets; - private watchInterval: NodeJS.Timer | null = null; - private lastValues: Record = {}; - private spreadsheetId: string; - - /** - * Create a new GoogleSheetService - * @param apiKey Google API key - */ - constructor(spreadsheetId: string) { - logger.info("Initializing GoogleSheetService"); - this.spreadsheetId = spreadsheetId; - if (!process.env.GOOGLE_API_KEY) { - logger.error("GOOGLE_API_KEY environment variable is required"); - process.exit(1); - } - this.sheets = sheets({ - version: "v4", - auth: process.env.GOOGLE_API_KEY, - }); - } - - /** - * Start watching a specific sheet for changes - * @param spreadsheetId The ID of the spreadsheet - * @param sheetRange The A1 notation of the range to watch - * @param columnIndex The index of the column to watch for changes (0-based) - * @param callback Function to call when changes are detected - * @param intervalMs How often to check for changes (in milliseconds) - */ - public watchColumn( - sheetRange: string, - columnIndex: number, - callback: ( - newValue: any, - oldValue: any, - row: number, - rowData: any[] - ) => void, - intervalMs: number = 10000 - ): void { - logger.info( - { columnIndex, sheetRange, intervalMs }, - "Watching column for changes" - ); - // Initial fetch to establish baseline - this.fetchData(this.spreadsheetId, sheetRange) - .then((data) => { - // Store initial values - data.forEach((row, rowIndex) => { - if (row && row[columnIndex] !== undefined) { - const key = `${rowIndex}-${columnIndex}`; - this.lastValues[key] = row[columnIndex]; - } - }); - - // Start watching for changes - this.watchInterval = setInterval(async () => { - try { - const newData = await this.fetchData( - this.spreadsheetId, - sheetRange - ); - - // Check for changes - newData.forEach((row, rowIndex) => { - if (row && row[columnIndex] !== undefined) { - const key = `${rowIndex}-${columnIndex}`; - const newValue = row[columnIndex]; - const oldValue = this.lastValues[key]; - - // If value has changed, trigger callback - if (newValue !== oldValue) { - callback(newValue, oldValue, rowIndex, row); - this.lastValues[key] = newValue; - } - } - }); - } catch (error) { - logger.error({ error }, "Error checking for updates"); - } - }, intervalMs); - }) - .catch((error) => { - logger.error({ error }, "Error initializing sheet watcher"); - }); - } - - /** - * Watch multiple columns for changes and execute callback when changes are detected in any watched column - * @param sheetRange The A1 notation of the range to watch - * @param columnIndexes Array of column indexes to watch (0-based) - * @param callback Function to call when changes are detected - * @param intervalMs How often to check for changes (in milliseconds) - */ - public watchColumns( - sheetRange: string, - columnIndexes: number[], - callback: ( - changedColumnIndex: number, - newValue: any, - oldValue: any, - row: number, - rowData: any[] - ) => void, - intervalMs: number = 10000 - ): void { - logger.info( - { columnIndexes, sheetRange, intervalMs }, - "Watching multiple columns for changes" - ); - - // Initial fetch to establish baseline - this.fetchData(this.spreadsheetId, sheetRange) - .then((data) => { - // Store initial values for all specified columns - data.forEach((row, rowIndex) => { - if (row) { - columnIndexes.forEach((colIndex) => { - if (row[colIndex] !== undefined) { - const key = `${rowIndex}-${colIndex}`; - this.lastValues[key] = row[colIndex]; - } - }); - } - }); - - // Start watching for changes - this.watchInterval = setInterval(async () => { - try { - const newData = await this.fetchData( - this.spreadsheetId, - sheetRange - ); - - // Check for changes in any of the watched columns - newData.forEach((row, rowIndex) => { - if (row) { - columnIndexes.forEach((colIndex) => { - if (row[colIndex] !== undefined) { - const key = `${rowIndex}-${colIndex}`; - const newValue = row[colIndex]; - const oldValue = this.lastValues[key]; - - // If value has changed, trigger callback - if (newValue !== oldValue) { - callback( - colIndex, - newValue, - oldValue, - rowIndex, - row - ); - this.lastValues[key] = newValue; - } - } - }); - } - }); - } catch (error) { - logger.error({ error }, "Error checking for updates"); - } - }, intervalMs); - }) - .catch((error) => { - logger.error({ error }, "Error initializing sheet watcher"); - }); - } - - /** - * Stop watching the spreadsheet - */ - public stopWatching(): void { - if (this.watchInterval) { - clearInterval(this.watchInterval); - this.watchInterval = null; - logger.info("Stopped watching spreadsheet"); - } - } - - /** - * Fetch data from the spreadsheet - * @param spreadsheetId The ID of the spreadsheet - * @param range The A1 notation of the range to fetch - */ - private async fetchData( - spreadsheetId: string, - range: string - ): Promise { - try { - const response = await this.sheets.spreadsheets.values.get({ - spreadsheetId, - range, - }); - - return response.data.values || []; - } catch (error) { - logger.error( - { error, spreadsheetId, range }, - "Error fetching sheet data" - ); - throw error; - } - } - - /** - * Fetch a specific cell value from the spreadsheet - * @param spreadsheetId The ID of the spreadsheet - * @param cellRange The A1 notation of the cell to fetch (e.g., "Sheet1!B2") - * @returns The value of the specified cell - */ - public async fetchCellValue( - spreadsheetId: string, - cellRange: string - ): Promise { - try { - logger.debug({ spreadsheetId, cellRange }, "Fetching cell value"); - const response = await this.sheets.spreadsheets.values.get({ - spreadsheetId, - range: cellRange, - }); - - const values = response.data.values; - if (!values || values.length === 0) { - logger.debug({ cellRange }, "Cell value is null"); - return null; - } - - // When fetching a single cell, sheets API returns a 2D array with just that cell - // Get the value directly - return values[0][0]; - } catch (error) { - logger.error( - { error, spreadsheetId, cellRange }, - "Error fetching cell" - ); - throw error; - } - } - - /** - * Convert a column letter (A, B, C, ..., Z, AA, AB, ...) to a zero-based column index - * @param column The column letter(s) - * @returns The zero-based index - */ - private columnLetterToIndex(column: string): number { - let index = 0; - for (let i = 0; i < column.length; i++) { - index = index * 26 + column.charCodeAt(i) - 64; // 'A' is ASCII 65 - } - return index - 1; // Convert to 0-based index - } - - /** - * Update data in the spreadsheet - * @param spreadsheetId The ID of the spreadsheet - * @param range The A1 notation of the range to update - * @param values The values to write - */ - public async updateValues( - spreadsheetId: string, - range: string, - values: any[][] - ): Promise { - try { - logger.debug({ spreadsheetId, range }, "Updating sheet data"); - await this.sheets.spreadsheets.values.update({ - spreadsheetId, - range, - valueInputOption: "USER_ENTERED", - requestBody: { - values, - }, - }); - logger.info({ range }, "Successfully updated sheet data"); - } catch (error) { - logger.error( - { error, spreadsheetId, range }, - "Error updating sheet data" - ); - throw error; - } - } -} - -export const googleSheet = new GoogleSheet( - process.env.SPREADSHEET_ID as string -); diff --git a/tooling/sparta/src/const.ts b/tooling/sparta/src/const.ts deleted file mode 100644 index c4699d3..0000000 --- a/tooling/sparta/src/const.ts +++ /dev/null @@ -1,35 +0,0 @@ -export const ADDRESSES_PER_PAGE = 20; - -export enum AdminSubcommandGroups { - Admin = "admin", -} - -export enum AdminSubcommands { - Get = "get", - Committee = "committee", - Validators = "validators", - Remove = "remove", - Fund = "fund", -} - -export enum NodeOperatorSubcommandGroups { - Operator = "operator", -} - -export enum NodeOperatorSubcommands { - ChainInfo = "chain-info", -} - -export enum ValidatorSubcommandGroups { - Validator = "validator", -} - -export enum ValidatorSubcommands { - Check = "check", -} - -export enum NodeOperatorRoles { - Guardian = "Guardian", // lowest level, requires minimum score of 0 - Defender = "Defender", // mid level, requires over 5 - Sentinel = "Sentinel", // set manually, but can be removed by this service -} diff --git a/tooling/sparta/src/index.ts b/tooling/sparta/src/index.ts deleted file mode 100644 index 6cd45ff..0000000 --- a/tooling/sparta/src/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @fileoverview Main entry point for the Sparta Discord bot - * @description Initializes the Ethereum client and Discord bot services - * @module sparta/index - */ - -import { - ChainInfoService, - ValidatorService, - GoogleSheetService, -} from "./services/index.js"; -import "./clients/discord.js"; // Import to ensure Discord client is initialized -import { logger } from "./utils/logger.js"; - -// Log application startup -logger.info("Sparta bot starting up"); - -// Initialize services -logger.debug("Initializing services"); -export const chainInfoService = new ChainInfoService(); -export const validatorService = new ValidatorService(); -export const googleSheetService = new GoogleSheetService(); - -// Start services -logger.info("Starting services..."); -googleSheetService.watchColumn("Sheet1", "A:B"); - -// Log configuration -logger.debug( - { - logLevel: process.env.LOG_LEVEL || "info", - prettyPrint: process.env.LOG_PRETTY_PRINT !== "false", - environment: process.env.NODE_ENV || "development", - }, - "Current configuration" -); diff --git a/tooling/sparta/src/package.json b/tooling/sparta/src/package.json deleted file mode 100644 index 0bd3f34..0000000 --- a/tooling/sparta/src/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "sparta-bot", - "version": "1.0.0", - "type": "module", - "scripts": { - "build": "FOUNDRY_DISABLE_NIGHTLY_WARNING=true bun build index.ts --target bun --minify --outdir=dist", - "dev": "LOG_LEVEL=debug FOUNDRY_DISABLE_NIGHTLY_WARNING=true bun run --watch index.ts", - "start": "FOUNDRY_DISABLE_NIGHTLY_WARNING=true bun run index.ts", - "watch": "FOUNDRY_DISABLE_NIGHTLY_WARNING=true tsc -w", - "lint": "eslint . --ext .ts", - "format": "prettier --write \"src/**/*.ts\"" - }, - "dependencies": { - "@googleapis/sheets": "^9.6.0", - "discord.js": "^14.14.1", - "dotenv": "^16.4.7", - "pino": "^9.6.0", - "pino-pretty": "^13.0.0", - "viem": "^2.22.15" - }, - "devDependencies": { - "@types/bun": "latest", - "@types/node": "^20.10.5", - "typescript": "^5.3.3" - }, - "module": "index.ts", - "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" -} diff --git a/tooling/sparta/src/roles/admins/README.md b/tooling/sparta/src/roles/admins/README.md deleted file mode 100644 index 6936c27..0000000 --- a/tooling/sparta/src/roles/admins/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# Admin Role Commands - -The Admin role provides advanced management capabilities for users with administrator permissions in the Sparta Discord bot system. This role is designed for system administrators who need to manage validators and view detailed system information. - -## Available Commands - -| Command | Subcommand | Arguments | Description | -| -------- | ---------------- | --------- | ---------------------------------------------------------- | -| `/admin` | `get validators` | | Get a list of all validators and their forwarder addresses | -| | `get committee` | | Get the current committee members and their forwarders | -| | `remove` | `address` | Remove a validator from the system | -| | `fund` | `address` | Fund a validator with Sepolia ETH | - -## Command Details - -### `/admin get validators` - -Retrieves a list of all validators in the system and their corresponding forwarder addresses. - -**Usage**: `/admin get validators` - -**Returns**: -- Paginated list of validator addresses and their associated forwarder addresses - -**Example Response**: -``` -Validators (Forwarders): -0x1234...5678 -> 0xabcd...efgh -0x5678...1234 -> 0xefgh...abcd -... -``` - -### `/admin get committee` - -Retrieves the current committee members and their forwarder addresses. - -**Usage**: `/admin get committee` - -**Returns**: -- Paginated list of committee member addresses and their associated forwarder addresses - -**Example Response**: -``` -Committee (Forwarders): -0x1234...5678 -> 0xabcd...efgh -0x5678...1234 -> 0xefgh...abcd -... -``` - -### `/admin remove` - -Removes a validator from the system. - -**Usage**: `/admin remove address:0x1234...5678` - -**Arguments**: -- `address`: The Ethereum address of the validator to remove - -**Returns**: -- Confirmation message indicating successful removal or error message - -**Example Response**: -``` -Removed validator 0x1234...5678 -``` - -### `/admin fund` - -Funds a validator with Sepolia ETH. - -**Usage**: `/admin fund address:0x1234...5678` - -**Arguments**: -- `address`: The Ethereum address of the validator to fund - -**Returns**: -- Confirmation message indicating successful funding or error message - -**Example Response**: -``` -Successfully funded validator 0x1234...5678 -``` - -## Permission Requirements - -- Only users with Discord Administrator permissions can access these commands -- These commands are intended for system administrators responsible for maintaining the validator network - -## Technical Implementation - -These commands are implemented in: -- `getValidators.ts`: Handles retrieving the list of validators -- `getCommittee.ts`: Handles retrieving the committee members -- `remove.ts`: Handles removing validators -- `fund.ts`: Handles funding validators - -The commands interact with the Ethereum blockchain using the ChainInfoService and ValidatorService. diff --git a/tooling/sparta/src/roles/admins/index.ts b/tooling/sparta/src/roles/admins/index.ts deleted file mode 100644 index 22efeb4..0000000 --- a/tooling/sparta/src/roles/admins/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import manageValidators from "./manageValidators/index.js"; - -export default { manageValidators }; diff --git a/tooling/sparta/src/roles/admins/manageValidators/fund.ts b/tooling/sparta/src/roles/admins/manageValidators/fund.ts deleted file mode 100644 index 238ef7f..0000000 --- a/tooling/sparta/src/roles/admins/manageValidators/fund.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ChatInputCommandInteraction } from "discord.js"; -import { ValidatorService } from "../../../services/validator-service.js"; -import { validateAddress } from "../../../utils/inputValidator.js"; - -export const fund = async (interaction: ChatInputCommandInteraction) => { - const address = validateAddress(interaction); - if (typeof address !== "string") { - return `Invalid address`; - } - await ValidatorService.fundValidator(address); - await interaction.editReply({ - content: `Successfully funded validator ${address}`, - }); - return "Funded validator"; -}; diff --git a/tooling/sparta/src/roles/admins/manageValidators/getCommittee.ts b/tooling/sparta/src/roles/admins/manageValidators/getCommittee.ts deleted file mode 100644 index b108052..0000000 --- a/tooling/sparta/src/roles/admins/manageValidators/getCommittee.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ChatInputCommandInteraction } from "discord.js"; -import { paginate } from "../../../utils/pagination.js"; -import { ChainInfoService } from "../../../services/chaininfo-service.js"; -import { ADDRESSES_PER_PAGE } from "../../../const.js"; - -export const getCommittee = async ( - interaction: ChatInputCommandInteraction -) => { - const { committee, forwardedCommittee } = await ChainInfoService.getInfo(); - - await paginate( - committee.map((c, i) => `${c} -> ${forwardedCommittee[i]}`) as string[], - committee.length, - ADDRESSES_PER_PAGE, - interaction, - "Committee (Forwarders)" - ); - return "Checked committee"; -}; diff --git a/tooling/sparta/src/roles/admins/manageValidators/getValidators.ts b/tooling/sparta/src/roles/admins/manageValidators/getValidators.ts deleted file mode 100644 index b069b47..0000000 --- a/tooling/sparta/src/roles/admins/manageValidators/getValidators.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ChatInputCommandInteraction } from "discord.js"; -import { paginate } from "../../../utils/pagination.js"; -import { ADDRESSES_PER_PAGE } from "../../../const.js"; -import { ChainInfoService } from "../../../services/chaininfo-service.js"; - -export const getValidators = async ( - interaction: ChatInputCommandInteraction -) => { - const { validators, forwardedValidators } = - await ChainInfoService.getInfo(); - await paginate( - validators.map( - (v, i) => `${v} -> ${forwardedValidators[i]}` - ) as string[], - validators.length, - ADDRESSES_PER_PAGE, - interaction, - "Validators (Forwarders)" - ); - return "Checked validators"; -}; diff --git a/tooling/sparta/src/roles/admins/manageValidators/index.ts b/tooling/sparta/src/roles/admins/manageValidators/index.ts deleted file mode 100644 index 9a97860..0000000 --- a/tooling/sparta/src/roles/admins/manageValidators/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { - SlashCommandBuilder, - ChatInputCommandInteraction, - MessageFlags, - PermissionFlagsBits, -} from "discord.js"; -import { getCommittee } from "./getCommittee.js"; -import { getValidators } from "./getValidators.js"; -import { fund } from "./fund.js"; -import { remove } from "./remove.js"; -import { AdminSubcommands } from "../../../const.js"; - -export default { - data: new SlashCommandBuilder() - .setName("admin") - .setDescription("Admin commands") - .setDefaultMemberPermissions(PermissionFlagsBits.Administrator) - .addSubcommandGroup((group) => - group - .setName(AdminSubcommands.Get) - .setDescription("Get info about validators") - .addSubcommand((subcommand) => - subcommand - .setName(AdminSubcommands.Validators) - .setDescription("Get validators") - ) - .addSubcommand((subcommand) => - subcommand - .setName(AdminSubcommands.Committee) - .setDescription("Get committee") - ) - ) - .addSubcommand((subcommand) => - subcommand - .setName(AdminSubcommands.Remove) - .setDescription("Remove a validator") - .addStringOption((option) => - option - .setName("address") - .setDescription("The validator to remove") - .setRequired(true) - ) - ) - .addSubcommand((subcommand) => - subcommand - .setName(AdminSubcommands.Fund) - .setDescription("Fund a validator with Sepolia ETH") - .addStringOption((option) => - option - .setName("address") - .setDescription("The validator to fund") - .setRequired(true) - ) - ), - execute: async (interaction: ChatInputCommandInteraction) => { - await interaction.deferReply({ - flags: MessageFlags.Ephemeral, - }); - - try { - const subcommand = interaction.options.getSubcommand(); - switch (subcommand) { - case AdminSubcommands.Committee: - await getCommittee(interaction); - break; - case AdminSubcommands.Validators: - await getValidators(interaction); - break; - case AdminSubcommands.Remove: - await remove(interaction); - break; - case AdminSubcommands.Fund: - await fund(interaction); - break; - default: - await interaction.editReply({ - content: `Invalid subcommand: ${subcommand}`, - }); - return; - } - } catch (error) { - await interaction.editReply({ - content: `Failed with error: ${error}`, - }); - return `Failed with error: ${ - error instanceof Error && error.message - }`; - } - }, -}; diff --git a/tooling/sparta/src/roles/admins/manageValidators/remove.ts b/tooling/sparta/src/roles/admins/manageValidators/remove.ts deleted file mode 100644 index 683d944..0000000 --- a/tooling/sparta/src/roles/admins/manageValidators/remove.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ChatInputCommandInteraction } from "discord.js"; -import { ValidatorService } from "../../../services/validator-service.js"; - -export const remove = async (interaction: ChatInputCommandInteraction) => { - const address = interaction.options.getString("address"); - if (!address) { - await interaction.editReply({ - content: "Please provide an address to remove", - }); - return `Failed`; - } - await ValidatorService.removeValidator(address); - await interaction.editReply({ - content: `Removed validator ${address}`, - }); - return "Removed validator"; -}; diff --git a/tooling/sparta/src/roles/nodeOperators/README.md b/tooling/sparta/src/roles/nodeOperators/README.md deleted file mode 100644 index 28113dd..0000000 --- a/tooling/sparta/src/roles/nodeOperators/README.md +++ /dev/null @@ -1,120 +0,0 @@ -# Node Operator Role Commands - -The Node Operator role is the base role for users in the Sparta Discord bot system. Users who have successfully verified in Discord receive this role and can access the following commands. - -## Available Commands - -| Command | Subcommand | Arguments | Description | -| ------------ | ---------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------ | -| `/get-info` | | | Get chain information including pending block, proven block, current epoch, current slot, and proposer | -| `/validator` | `check` | `address` | Check if an address is a validator | -| | `register` | `address`, `block-number`, `merkle-proof` | Register a validator address | -| | `help` | `subcommand` | Get help for a specific validator subcommand | - -## Command Details - -### `/get-info` - -Retrieves current blockchain state information. - -**Usage**: `/get-info` - -**Returns**: -- Pending block number: The latest block being processed -- Proven block number: The latest block that has been cryptographically proven -- Current epoch: The current epoch number -- Current slot: The current slot number -- Current proposer: The address of the current block proposer -- Validators: List of current validators -- Committee members: Current committee members for the epoch - -**Example Response**: -``` -Chain Information: -Pending Block: 1234 -Proven Block: 1230 -Current Epoch: 45 -Current Slot: 3 -Current Proposer: 0x1234...5678 -``` - -### `/validator check` - -Checks if a given Ethereum address is a registered validator. - -**Usage**: `/validator check address:0x1234...5678` - -**Arguments**: -- `address`: The Ethereum address to check - -**Returns**: -- Validation status (is/is not a validator) -- If a validator, additional information such as: - - Date registered - - Stake amount - - Current status - -**Example Response**: -``` -Address 0x1234...5678 is a registered validator. -Registered since: Jan 15, 2023 -Stake: 100 ETH -Status: Active -``` - -### `/validator register` - -Registers a new validator address on the blockchain. - -**Usage**: `/validator register address:0x1234...5678 block-number:123456 merkle-proof:0xabcd...1234` - -**Arguments**: -- `address`: The Ethereum address to register as a validator -- `block-number`: The block number for the merkle proof -- `merkle-proof`: Cryptographic proof of eligibility - -**Returns**: -- Registration status (success/failure) -- Transaction hash if successful -- Error message if failed - -**Example Response**: -``` -Successfully registered validator 0x1234...5678. -Transaction: 0xabcd...1234 -Block: 7654321 -``` - -### `/validator help` - -Provides help information for validator commands. - -**Usage**: `/validator help subcommand:check` - -**Arguments**: -- `subcommand`: The validator subcommand to get help for (`check`, `register`) - -**Returns**: -- Detailed help information for the specified subcommand - -**Example Response**: -``` -Validator Check Command Help: -The check command verifies if an address is a registered validator. -Usage: /validator check address:0x1234...5678 -The address should be a valid Ethereum address. -``` - -## Permission Requirements - -- All users with the Node Operator role can access these commands -- The `/validator register` command requires additional verification that the user controls the address being registered - -## Technical Implementation - -These commands are implemented in: -- `getChainInfo.ts`: Handles the `/get-info` command -- `validator.ts`: Handles all validator-related commands - -The commands interact with the Ethereum blockchain using the ChainInfoService and ValidatorService. - diff --git a/tooling/sparta/src/roles/nodeOperators/chainInfo/get.ts b/tooling/sparta/src/roles/nodeOperators/chainInfo/get.ts deleted file mode 100644 index f23aef5..0000000 --- a/tooling/sparta/src/roles/nodeOperators/chainInfo/get.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { - ChatInputCommandInteraction, - DiscordAPIError, - MessageFlags, - TextChannel, -} from "discord.js"; -import { ChainInfoService } from "../../../services/chaininfo-service.js"; -export const get = async ( - interaction: ChatInputCommandInteraction -): Promise => { - const { - pendingBlockNum, - provenBlockNum, - currentEpoch, - currentSlot, - proposerNow, - } = await ChainInfoService.getInfo(); - const channel = interaction.channel as TextChannel; - const messages = await channel.messages.fetch({ - limit: 15, - }); - - // Filter for bot messages that look like chain info responses - // and aren't the current interaction's response - const botMessages = messages.filter( - (m) => - m.author.id === interaction.client.user?.id && - m.content.includes("Pending block:") && - m.content.includes("Proven block:") && - m.content.includes("Current epoch:") && - !m.flags.has(MessageFlags.Ephemeral) && - // Ensure we don't delete the message we're about to send - m.id !== interaction.id - ); - - if (botMessages.size > 0) { - try { - // Try bulk delete first (only works for messages less than 14 days old) - await channel.bulkDelete(botMessages); - } catch (error) { - // If bulk delete fails (e.g., messages are too old), delete individually - if (error instanceof DiscordAPIError && error.code === 50034) { - for (const message of botMessages.values()) { - try { - await message.delete(); - } catch (deleteError) { - console.error( - "Error deleting individual message:", - deleteError - ); - } - } - } else { - throw error; - } - } - } - - await interaction.reply({ - content: `Pending block: ${pendingBlockNum}\nProven block: ${provenBlockNum}\nCurrent epoch: ${currentEpoch}\nCurrent slot: ${currentSlot}\nProposer now: ${proposerNow}`, - }); - return `Pending block: ${pendingBlockNum}\nProven block: ${provenBlockNum}\nCurrent epoch: ${currentEpoch}\nCurrent slot: ${currentSlot}\nProposer now: ${proposerNow}`; -}; diff --git a/tooling/sparta/src/roles/nodeOperators/chainInfo/index.ts b/tooling/sparta/src/roles/nodeOperators/chainInfo/index.ts deleted file mode 100644 index da34ea2..0000000 --- a/tooling/sparta/src/roles/nodeOperators/chainInfo/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { - SlashCommandBuilder, - ChatInputCommandInteraction, - MessageFlags, -} from "discord.js"; -import { - NodeOperatorSubcommandGroups, - NodeOperatorSubcommands, -} from "../../../const.js"; -import { get } from "./get.js"; - -export default { - data: new SlashCommandBuilder() - .setName(NodeOperatorSubcommandGroups.Operator) - .setDescription("Node operator commands") - .addSubcommand((subcommand) => - subcommand - .setName(NodeOperatorSubcommands.ChainInfo) - .setDescription("Get chain information") - ), - execute: async (interaction: ChatInputCommandInteraction) => { - try { - const subcommand = interaction.options.getSubcommand(); - switch (subcommand) { - case NodeOperatorSubcommands.ChainInfo: - await get(interaction); - break; - default: - await interaction.editReply({ - content: `Invalid subcommand: ${subcommand}`, - }); - return; - } - } catch (error) { - await interaction.editReply({ - content: `Failed with error: ${error}`, - }); - return `Failed with error: ${ - error instanceof Error && error.message - }`; - } - }, -}; diff --git a/tooling/sparta/src/roles/nodeOperators/index.ts b/tooling/sparta/src/roles/nodeOperators/index.ts deleted file mode 100644 index 5e38841..0000000 --- a/tooling/sparta/src/roles/nodeOperators/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import validator from "./validator/index.js"; -import chainInfo from "./chainInfo/index.js"; - -export default { validator, chainInfo }; diff --git a/tooling/sparta/src/roles/nodeOperators/validator/check.ts b/tooling/sparta/src/roles/nodeOperators/validator/check.ts deleted file mode 100644 index b277851..0000000 --- a/tooling/sparta/src/roles/nodeOperators/validator/check.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ChatInputCommandInteraction, MessageFlags } from "discord.js"; -import { validateAddress } from "../../../utils/inputValidator.js"; -import { ChainInfoService } from "../../../services/chaininfo-service.js"; -import { getExpectedAddress } from "../../../clients/ethereum.js"; - -export const check = async ( - interaction: ChatInputCommandInteraction -): Promise => { - const address = validateAddress(interaction); - if (typeof address !== "string") { - await interaction.editReply({ - content: "Please provide a valid address", - }); - return; - } - - const forwarder = getExpectedAddress( - [address as `0x${string}`], - address as `0x${string}` - ).address; - - const info = await ChainInfoService.getInfo(); - const { validators, committee } = info; - - let reply = "Your forwarder contract is: " + forwarder + "\n"; - reply += `It is ${!validators.includes(address) && "not"} a validator\n`; - reply += `It is ${ - !committee.includes(address) && "not" - } a committee member\n`; - - await interaction.editReply({ - content: reply, - }); -}; diff --git a/tooling/sparta/src/roles/nodeOperators/validator/index.ts b/tooling/sparta/src/roles/nodeOperators/validator/index.ts deleted file mode 100644 index 8d20be4..0000000 --- a/tooling/sparta/src/roles/nodeOperators/validator/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { - SlashCommandBuilder, - ChatInputCommandInteraction, - MessageFlags, -} from "discord.js"; -import { - ValidatorSubcommandGroups, - ValidatorSubcommands, -} from "../../../const.js"; -import { check } from "./check.js"; - -export default { - data: new SlashCommandBuilder() - .setName(ValidatorSubcommandGroups.Validator) - .setDescription("Validator commands for Node Operator users") - .addSubcommand((subcommand) => - subcommand - .setName(ValidatorSubcommands.Check) - .setDescription("Check if you are a validator") - .addStringOption((option) => - option - .setName("address") - .setDescription("The validator address to check") - .setRequired(true) - ) - ), - execute: async ( - interaction: ChatInputCommandInteraction - ): Promise => { - try { - await interaction.deferReply({ flags: MessageFlags.Ephemeral }); - - const subcommand = interaction.options.getSubcommand(); - switch (subcommand) { - case ValidatorSubcommands.Check: - await check(interaction); - return `Checked validator`; - default: - await interaction.editReply({ - content: `Unknown subcommand: ${subcommand}`, - }); - return `Unknown subcommand`; - } - } catch (error) { - await interaction.editReply({ - content: `Failed with error: ${ - error instanceof Error ? error.message : "Unknown error" - }`, - }); - return `Failed with error: ${ - error instanceof Error ? error.message : "Unknown error" - }`; - } - }, -}; diff --git a/tooling/sparta/src/services/chaininfo-service.ts b/tooling/sparta/src/services/chaininfo-service.ts deleted file mode 100644 index d02f04e..0000000 --- a/tooling/sparta/src/services/chaininfo-service.ts +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @fileoverview Chain Information service for Ethereum blockchain data - * @description Provides methods for retrieving blockchain state and validator information - * @module sparta/services/chaininfo-service - */ - -import { ethereum } from "../clients/ethereum.js"; -import { getExpectedAddress } from "../clients/ethereum.js"; -import { logger } from "../utils/logger.js"; - -/** - * Interface for blockchain information data - * - * @property {string} pendingBlockNum - The current pending block number - * @property {string} provenBlockNum - The current proven block number - * @property {string[]} validators - Array of validator addresses - * @property {string[]} forwardedValidators - Array of forwarded validator addresses - * @property {string[]} committee - Array of committee member addresses - * @property {string[]} forwardedCommittee - Array of forwarded committee addresses - * @property {string[]} archive - Array of archived addresses - * @property {string} currentEpoch - The current epoch number - * @property {string} currentSlot - The current slot number - * @property {string} proposerNow - The current proposer address - */ -type ChainInfo = { - pendingBlockNum: string; - provenBlockNum: string; - validators: string[]; - forwardedValidators: string[]; - committee: string[]; - forwardedCommittee: string[]; - archive: string[]; - currentEpoch: string; - currentSlot: string; - proposerNow: string; -}; - -/** - * Service for retrieving blockchain information and validator data - * - * This service provides methods to: - * - Get current block information (pending, proven) - * - Get validator and committee lists - * - Get epoch and slot information - * - Get current proposer information - */ -export class ChainInfoService { - /** - * Retrieves comprehensive information about the current blockchain state - * - * This method gathers blockchain data from multiple sources and returns - * a consolidated view of the current chain state, including: - * - Block numbers (pending and proven) - * - Validator lists - * - Committee information - * - Epoch and slot data - * - Current proposer - * - * @returns {Promise} A promise that resolves to an object containing chain information - * - * @example - * // Get chain information - * const chainInfo = await ChainInfoService.getInfo(); - * console.log(`Current epoch: ${chainInfo.currentEpoch}`); - * console.log(`Current slot: ${chainInfo.currentSlot}`); - * console.log(`Pending block: ${chainInfo.pendingBlockNum}`); - * - * @throws Will throw an error if retrieving chain information fails - */ - static async getInfo(): Promise { - try { - const rollup = ethereum.getRollup(); - const [ - pendingNum, - provenNum, - validators, - committee, - archive, - epochNum, - slot, - nextBlockTS, - ] = await Promise.all([ - rollup.read.getPendingBlockNumber(), - rollup.read.getProvenBlockNumber(), - rollup.read.getAttesters(), - rollup.read.getCurrentEpochCommittee(), - rollup.read.archive(), - rollup.read.getCurrentEpoch(), - rollup.read.getCurrentSlot(), - rollup.read.getCurrentProposer(), - (async () => { - const block = await ethereum.getPublicClient().getBlock(); - return BigInt(block.timestamp + BigInt(12)); - })(), - ]); - - const proposer = await rollup.read.getProposerAt([nextBlockTS]); - - return { - pendingBlockNum: pendingNum as string, - provenBlockNum: provenNum as string, - validators: validators, - forwardedValidators: validators.map( - (e: `0x${string}`) => getExpectedAddress([e], e).address - ), - committee: committee, - forwardedCommittee: committee.map( - (e: `0x${string}`) => getExpectedAddress([e], e).address - ), - archive: archive as string[], - currentEpoch: epochNum as string, - currentSlot: slot as string, - proposerNow: proposer as string, - }; - } catch (error) { - logger.error({ error }, "Error getting chain info"); - throw error; - } - } -} diff --git a/tooling/sparta/src/services/discord-service.ts b/tooling/sparta/src/services/discord-service.ts deleted file mode 100644 index dd25cd4..0000000 --- a/tooling/sparta/src/services/discord-service.ts +++ /dev/null @@ -1,529 +0,0 @@ -/** - * @fileoverview Discord service for role management - * @description Provides methods for managing Discord roles and finding users - * @module sparta/services/discord-service - */ - -import { discord } from "../clients/discord.js"; -import { logger } from "../utils/logger.js"; -import { NodeOperatorRoles } from "../const.js"; - -/** - * Discord service class for role management and user operations - * - * This service provides methods to: - * - Assign roles to Discord users - * - Find Discord users by username or tag - * - Manage role hierarchies - * - * @example - * // Get the service instance - * const service = DiscordService.getInstance(); - * - * // Assign a role to a user - * await service.assignRole("1234567890", NodeOperatorRoles.Guardian); - * - * // Find a user by username - * const userId = await service.findUserIdByUsername("username"); - */ -export class DiscordService { - private static instance: DiscordService; - - /** - * Gets the singleton instance of DiscordService - * - * @returns {DiscordService} The singleton instance - * - * @example - * const service = DiscordService.getInstance(); - */ - public static getInstance(): DiscordService { - if (!DiscordService.instance) { - DiscordService.instance = new DiscordService(); - } - return DiscordService.instance; - } - - /** - * Assigns a role to a Discord user - * - * This method: - * 1. Finds the guild (Discord server) - * 2. Finds the role by name - * 3. Gets the member by their Discord ID - * 4. Removes any conflicting roles from the hierarchy - * 5. Assigns the new role - * - * @param {string} userId - The Discord user ID to assign the role to - * @param {string} roleName - The name of the role to assign - * @returns {Promise} A promise that resolves to true if the role was assigned, false otherwise - * - * @example - * // Assign the Guardian role to a user - * const success = await discordService.assignRole("1234567890", NodeOperatorRoles.Guardian); - * - * if (success) { - * logger.info("Role assigned successfully"); - * } else { - * logger.error("Failed to assign role"); - * } - */ - public async assignRole( - userId: string, - roleName: string - ): Promise { - try { - // Get the guild (server) - const guildId = process.env.GUILD_ID; - if (!guildId) { - logger.error("GUILD_ID not set in environment variables"); - return false; - } - - const guild = await discord.getGuild(guildId); - if (!guild) { - logger.error({ guildId }, "Guild not found"); - return false; - } - - // Find the role - const role = guild.roles.cache.find((r) => r.name === roleName); - if (!role) { - logger.error( - { roleName, guildName: guild.name }, - "Role not found in guild" - ); - return false; - } - - // Get the member - const member = await guild.members.fetch(userId); - if (!member) { - logger.error( - { userId, guildName: guild.name }, - "Member not found in guild" - ); - return false; - } - - // First check and remove all hierarchy roles (regardless of target role) - const rolesToRemove = member.roles.cache.filter((r) => - Object.values(NodeOperatorRoles).includes( - r.name as NodeOperatorRoles - ) - ); - - if (rolesToRemove.size > 0) { - logger.info( - { - roles: rolesToRemove.map((r) => r.name).join(", "), - username: member.user.username, - }, - "Removing existing roles" - ); - try { - await member.roles.remove(rolesToRemove); - logger.debug( - { - count: rolesToRemove.size, - username: member.user.username, - }, - "Successfully removed roles" - ); - } catch (error: any) { - logger.error( - { error: error.message }, - "Error removing roles" - ); - logger.error( - "Bot might not have sufficient permissions or role hierarchy issue" - ); - } - - // Refresh member data after removing roles - try { - await member.fetch(); - logger.debug( - { - roles: member.roles.cache - .map((r) => r.name) - .join(", "), - username: member.user.username, - }, - "Member data refreshed" - ); - } catch (error: any) { - logger.error( - { error: error.message }, - "Error refreshing member data" - ); - } - } - - // Now add the new role - try { - await member.roles.add(role); - logger.info( - { - roleName, - username: member.user.username, - }, - "Successfully added role" - ); - - // Verify role was added - const updatedMember = await guild.members.fetch(userId); - const hasRole = updatedMember.roles.cache.has(role.id); - await member.fetch(); - - logger.debug( - { - username: member.user.username, - roleName, - hasRole, - }, - "Role verification" - ); - } catch (error: any) { - logger.error({ error: error.message }, "Error adding role"); - logger.error( - "Bot might not have sufficient permissions or role hierarchy issue" - ); - return false; - } - - return true; - } catch (error) { - logger.error({ error }, "Error assigning role"); - return false; - } - } - - /** - * Finds a Discord user by username or username#discriminator - * - * This method attempts to find a user through multiple strategies: - * 1. First checks the cache for the user - * 2. Tries using Discord's search functionality - * 3. Attempts a limited fetch of members - * 4. Tries a direct user lookup if the input looks like an ID - * - * @param {string} usernameOrTag - The Discord username (e.g., "username") or tag (e.g., "username#1234") - * @returns {Promise} A promise that resolves to the user ID if found, null otherwise - * - * @example - * // Find a user by username - * const userId = await discordService.findUserIdByUsername("username"); - * - * // Find a user by tag (legacy format) - * const userId = await discordService.findUserIdByUsername("username#1234"); - * - * if (userId) { - * logger.info(`Found user with ID: ${userId}`); - * } else { - * logger.info("User not found"); - * } - */ - public async findUserIdByUsername( - usernameOrTag: string - ): Promise { - try { - logger.debug({ username: usernameOrTag }, "Starting user lookup"); - - // Get the guild (server) - const guildId = process.env.GUILD_ID; - if (!guildId) { - logger.error("GUILD_ID not set in environment variables"); - return null; - } - - const guild = await discord.getGuild(guildId); - if (!guild) { - logger.error({ guildId }, "Guild not found"); - return null; - } - - logger.debug( - { guildName: guild.name, guildId: guild.id }, - "Guild found" - ); - - // Instead of loading all members at once, which can be slow and cause timeouts, - // we'll use search functionality if available or limit the fetch - - // First try with currently cached members - logger.debug("Checking cached members first"); - const cachedMember = this.findMemberInCache(guild, usernameOrTag); - if (cachedMember) { - logger.info( - { - username: cachedMember.user.username, - userId: cachedMember.id, - }, - "Found user in cache" - ); - return cachedMember.id; - } - - logger.debug("User not found in cache, attempting limited fetch"); - - // Try different strategies to find the user - let userId = null; - - // Strategy 1: Try search if available - userId = await this.trySearchByUsername(guild, usernameOrTag); - if (userId) return userId; - - // Strategy 2: Try limited fetch with timeout - userId = await this.tryLimitedFetch(guild, usernameOrTag); - if (userId) return userId; - - // Strategy 3: Try direct user lookup if it might be an ID already - if (/^\d+$/.test(usernameOrTag)) { - try { - logger.debug( - { username: usernameOrTag }, - "Username looks like an ID, trying direct fetch" - ); - const member = await guild.members - .fetch(usernameOrTag) - .catch(() => null); - if (member) { - logger.info( - { - username: member.user.username, - userId: member.id, - }, - "Found user directly" - ); - return member.id; - } - } catch (error: any) { - logger.debug( - { error: error.message }, - "Direct fetch failed" - ); - } - } - - logger.info( - { username: usernameOrTag }, - "Could not find user with username after trying all strategies" - ); - return null; - } catch (error) { - logger.error({ error }, "Error finding user by username"); - return null; - } - } - - /** - * Attempts to search for a user by username using Discord's search feature - * - * @param {any} guild - The Discord guild object - * @param {string} username - The username to search for - * @returns {Promise} A promise that resolves to the user ID if found, null otherwise - * - * @private - */ - private async trySearchByUsername( - guild: any, - username: string - ): Promise { - if (!guild.members.search) { - logger.debug("Search capability not available"); - return null; - } - - logger.debug({ username }, "Attempting to search for username"); - try { - const searchResults = await guild.members.search({ - query: username, - limit: 5, - }); - - if (searchResults && searchResults.size > 0) { - const member = searchResults.first(); - if (member && member.user) { - logger.info( - { - username: member.user.username, - userId: member.id, - }, - "Found user via search" - ); - return member.id; - } - } - logger.debug("Search returned no results"); - return null; - } catch (searchError) { - logger.error({ searchError }, "Error using member search"); - return null; - } - } - - /** - * Attempts to find a user by fetching a limited number of members - * Uses a timeout to prevent hanging - * - * This method: - * 1. First tries with a small batch (25 members) for speed - * 2. If unsuccessful, tries with a larger batch (100 members) - * 3. Uses an abort controller to prevent hanging - * - * @param {any} guild - The Discord guild object - * @param {string} username - The username to search for - * @returns {Promise} A promise that resolves to the user ID if found, null otherwise - * - * @private - */ - private async tryLimitedFetch( - guild: any, - username: string - ): Promise { - logger.debug("Attempting limited fetch with timeout protection"); - try { - // Create a controller to allow aborting the fetch - const controller = new AbortController(); - const timeoutId = setTimeout(() => { - controller.abort(); - logger.debug("Fetch operation aborted due to timeout"); - }, 5000); - - // Try a smaller batch first (faster) - try { - logger.debug("Trying fetch with limit 25"); - const members = await guild.members.fetch({ - limit: 25, - signal: controller.signal, - }); - - const match = this.findMatchingMember(members, username); - if (match) { - clearTimeout(timeoutId); - return match; - } - } catch (error: any) { - if (error.name === "AbortError") { - logger.debug("First fetch attempt aborted"); - } else { - logger.error( - { error: error.message }, - "Error in first fetch attempt" - ); - } - } - - // Try a larger batch if first attempt failed but not timed out - if (!controller.signal.aborted) { - try { - logger.debug("Trying fetch with limit 100"); - const members = await guild.members.fetch({ - limit: 100, - signal: controller.signal, - }); - - const match = this.findMatchingMember(members, username); - if (match) { - clearTimeout(timeoutId); - return match; - } - } catch (error: any) { - if (error.name === "AbortError") { - logger.debug("Second fetch attempt aborted"); - } else { - logger.error( - { error: error.message }, - "Error in second fetch attempt" - ); - } - } - } - - clearTimeout(timeoutId); - logger.debug( - "Limited fetch attempts completed without finding user" - ); - return null; - } catch (error) { - logger.error({ error }, "Error in limited fetch process"); - return null; - } - } - - /** - * Find a matching member from a collection of Discord members - * - * @param {any} members - Collection of Discord members - * @param {string} username - The username to find - * @returns {string|null} The user ID if found, null otherwise - * - * @private - */ - private findMatchingMember(members: any, username: string): string | null { - if (!members || typeof members.forEach !== "function") { - logger.debug("Invalid members data received"); - return null; - } - - for (const [_, member] of members) { - if (this.isUserMatch(member, username)) { - logger.info( - { - username: member.user.username, - userId: member.id, - }, - "Found user" - ); - return member.id; - } - } - - logger.debug(`No matching user found among ${members.size} members`); - return null; - } - - /** - * Checks if a Discord member matches the given username or tag - * - * Supports both modern username format and legacy username#discriminator format - * - * @param {any} member - The Discord member object - * @param {string} usernameOrTag - The username or tag to check against - * @returns {boolean} True if the member matches, false otherwise - * - * @private - */ - private isUserMatch(member: any, usernameOrTag: string): boolean { - // Check if the input includes a discriminator (#) - const isTag = usernameOrTag.includes("#"); - - if (isTag) { - // For legacy username#discriminator format - const fullTag = `${member.user.username}#${member.user.discriminator}`; - return fullTag === usernameOrTag; - } else { - // For regular username - return member.user.username === usernameOrTag; - } - } - - /** - * Finds a Discord member in the currently cached members - * - * @param {any} guild - The Discord guild object - * @param {string} usernameOrTag - The username or tag to find - * @returns {any} The member object if found, undefined otherwise - * - * @private - */ - private findMemberInCache(guild: any, usernameOrTag: string): any { - return guild.members.cache.find((member: any) => - this.isUserMatch(member, usernameOrTag) - ); - } -} - -// Export a default instance -export const discordService = DiscordService.getInstance(); diff --git a/tooling/sparta/src/services/googlesheet-service.ts b/tooling/sparta/src/services/googlesheet-service.ts deleted file mode 100644 index e314642..0000000 --- a/tooling/sparta/src/services/googlesheet-service.ts +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @fileoverview Google Sheets service for integration with Discord - * @description Provides methods to monitor Google Sheets and assign Discord roles based on sheet data - * @module sparta/services/googlesheet-service - */ - -import { GoogleSheet, googleSheet } from "../clients/google.js"; -import { discordService } from "./discord-service.js"; -import { logger } from "../utils/logger.js"; -import { ADDRESSES_PER_PAGE, NodeOperatorRoles } from "../const.js"; - -/** - * Service for integrating with Google Sheets and assigning Discord roles based on sheet data - * - * This service: - * - Monitors specific columns in Google Sheets - * - Detects changes to user scores - * - Assigns Discord roles based on score thresholds - * - * @example - * // Create an instance and watch a sheet - * const service = new GoogleSheetService(); - * service.watchColumn("Sheet1", "A:B"); - */ -export class GoogleSheetService { - /** - * Watches specified columns in a Google Sheet for changes - * - * This method sets up a watch on column A (scores) and column B (Discord usernames). - * When changes are detected, it triggers the role assignment process if both - * a score and username are present. - * - * @param {string} sheetName - The name of the sheet to watch (e.g., "Sheet1") - * @param {string} range - The range of cells to watch (e.g., "A:B") - * - * @example - * // Watch columns A and B in Sheet1 - * googleSheetService.watchColumn("Sheet1", "A:B"); - */ - watchColumn(sheetName: string, range: string) { - // Watch both columns A and B at the same time - googleSheet.watchColumns( - `${sheetName}!${range}`, - [0, 1], // Watch columns A (index 0) and B (index 1) - (changedColumnIndex, newValue, oldValue, row, rowData) => { - const columnLetter = changedColumnIndex === 0 ? "A" : "B"; - logger.info( - { - cell: `${columnLetter}${row + 2}`, - oldValue, - newValue, - }, - "Cell value changed" - ); - - // Only execute if both columns have values - const scoreValue = rowData[0]; - const discordUsername = rowData[1]; - - if (scoreValue && discordUsername) { - // Handle the promise without blocking - this.assignRoleBasedOnScore( - scoreValue, - discordUsername, - row - ).catch((error) => { - logger.error( - { error, scoreValue, discordUsername, row }, - "Error in role assignment process" - ); - }); - } - } - ); - } - - /** - * Assigns a Discord role based on a user's score - * - * This method: - * 1. Validates and parses the score - * 2. Finds the Discord user ID by username - * 3. Determines the appropriate role based on score thresholds: - * - Score > 10: NodeOperatorRoles.Sentinel (highest role) - * - Score > 5: NodeOperatorRoles.Defender (middle role) - * - Default: NodeOperatorRoles.Guardian (lowest role) - * 4. Assigns the role to the user - * - * @param {string} scoreString - The user's score as a string (will be converted to number) - * @param {string} discordUsername - The Discord username to assign the role to - * @param {number} row - The row number in the spreadsheet (for logging purposes) - * @returns {Promise} A promise that resolves when the role assignment is complete - * - * @private - */ - private async assignRoleBasedOnScore( - scoreString: string, - discordUsername: string, - row: number - ): Promise { - logger.debug(`Processing role assignment for row ${row + 2}`); - logger.debug( - { score: scoreString, username: discordUsername }, - "Processing score for role assignment" - ); - - // Parse score as a number - const score = Number(scoreString); - - // Validate score is a number - if (isNaN(score)) { - logger.error( - { score: scoreString }, - "Invalid score value, expected a number" - ); - return; - } - - logger.debug(`Finding Discord ID for username: ${discordUsername}`); - // Find the Discord ID by username - const discordUserId = await discordService.findUserIdByUsername( - discordUsername - ); - - logger.debug({ userId: discordUserId }, "Discord ID lookup completed"); - - if (!discordUserId) { - logger.error( - { username: discordUsername }, - "Could not find Discord user" - ); - return; - } - - // Determine role based on score threshold using the hierarchy: - // Guardian (lowest) -> Defender -> Sentinel (highest) - let roleName = NodeOperatorRoles.Guardian; // Default/lowest role - - if (score > 10) { - roleName = NodeOperatorRoles.Sentinel; // Highest role - } else if (score > 5) { - roleName = NodeOperatorRoles.Defender; // Middle role - } - - // Assign the appropriate role to the Discord user - try { - const success = await discordService.assignRole( - discordUserId, - roleName - ); - - if (success) { - logger.info( - { - username: discordUsername, - userId: discordUserId, - role: roleName, - }, - "Successfully assigned role" - ); - } else { - logger.error( - { - username: discordUsername, - userId: discordUserId, - role: roleName, - }, - "Failed to assign role" - ); - } - } catch (error) { - logger.error( - { - error, - username: discordUsername, - userId: discordUserId, - role: roleName, - }, - "Error assigning role" - ); - } - } -} diff --git a/tooling/sparta/src/services/index.ts b/tooling/sparta/src/services/index.ts deleted file mode 100644 index 7d69fb6..0000000 --- a/tooling/sparta/src/services/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @fileoverview Service module exports - * @description Centralizes exports for all Sparta service modules - * @module sparta/services - */ - -import { GoogleSheetService } from "./googlesheet-service.js"; -import { ChainInfoService } from "./chaininfo-service.js"; -import { ValidatorService } from "./validator-service.js"; -import { DiscordService, discordService } from "./discord-service.js"; - -/** - * Export all service classes and instances - * - * - GoogleSheetService: Monitors Google Sheets and assigns roles based on scores - * - ChainInfoService: Retrieves blockchain state information - * - ValidatorService: Manages Ethereum validators - * - DiscordService: Manages Discord roles and user interactions - * - discordService: Singleton instance of DiscordService - */ -export { - GoogleSheetService, - ChainInfoService, - ValidatorService, - DiscordService, - discordService, -}; diff --git a/tooling/sparta/src/services/validator-service.ts b/tooling/sparta/src/services/validator-service.ts deleted file mode 100644 index 8e9f8de..0000000 --- a/tooling/sparta/src/services/validator-service.ts +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @fileoverview Validator service for Ethereum validator management - * @description Provides methods for managing validators on the Ethereum network - * @module sparta/services/validator-service - */ - -import { exec } from "child_process"; -import { promisify } from "util"; -import { ethereum } from "../clients/ethereum.js"; -import { Transaction, TransactionReceipt } from "viem"; -import { logger } from "../utils/logger.js"; - -const execAsync = promisify(exec); - -/** - * Service for managing Ethereum validators - * - * This service provides methods to: - * - Request tokens from a faucet for validators - * - Add validators to the network - * - Remove validators from the network - * - Fund validators with ETH - */ -export class ValidatorService { - /** - * Requests staking asset tokens from a faucet for a validator address - * - * This method calls the Ethereum client to distribute staking tokens - * to the specified address, which can then be used for staking. - * - * @param {string} address - The Ethereum address to receive staking tokens - * @returns {Promise} A promise that resolves to the transaction receipt - * - * @example - * // Request staking tokens for a validator - * const receipt = await ValidatorService.stakingAssetFaucet("0x123..."); - * logger.info({ transactionHash: receipt.transactionHash }, "Staking asset faucet transaction completed"); - * - * @throws Will throw an error if the faucet transaction fails - */ - static async stakingAssetFaucet( - address: string - ): Promise { - try { - return await ethereum.stakingAssetFaucet(address); - } catch (error) { - logger.error({ error, address }, "Error adding validator"); - throw error; - } - } - - /** - * Adds a new validator to the Ethereum network - * - * This method registers the provided address as a validator - * in the validator registry contract. - * - * @param {string} address - The Ethereum address to add as a validator - * @returns {Promise} A promise that resolves to an array of transaction receipts - * - * @example - * // Add a new validator - * const receipts = await ValidatorService.addValidator("0x123..."); - * logger.info({ transactionCount: receipts.length }, "Added validator"); - * - * @throws Will throw an error if adding the validator fails - */ - static async addValidator(address: string): Promise { - try { - return await ethereum.addValidator(address); - } catch (error) { - logger.error({ error, address }, "Error adding validator"); - throw error; - } - } - - /** - * Removes a validator from the Ethereum network - * - * This method deregisters the provided address from the - * validator registry contract. - * - * @param {string} address - The Ethereum address to remove as a validator - * @returns {Promise} A promise that resolves to the transaction receipt - * - * @example - * // Remove a validator - * const receipt = await ValidatorService.removeValidator("0x123..."); - * logger.info({ transactionHash: receipt.transactionHash }, "Removed validator"); - * - * @throws Will throw an error if removing the validator fails - */ - static async removeValidator(address: string): Promise { - try { - return await ethereum.removeValidator(address); - } catch (error) { - logger.error({ error, address }, "Error removing validator"); - throw error; - } - } - - /** - * Funds a validator address with ETH - * - * This method sends ETH to the specified address using the cast command - * from the Foundry toolkit. The amount sent is specified in the FUNDER_AMOUNT - * environment variable. - * - * @param {string} address - The Ethereum address to fund with ETH - * @returns {Promise} A promise that resolves to the command output - * - * @example - * // Fund a validator with ETH - * const output = await ValidatorService.fundValidator("0x123..."); - * logger.info({ output }, "Funded validator with ETH"); - * - * @throws Will throw an error if funding the validator fails - */ - static async fundValidator(address: string): Promise { - try { - const command = `cast send --value ${process.env.FUNDER_AMOUNT} --rpc-url ${process.env.ETHEREUM_HOST} --chain-id ${process.env.L1_CHAIN_ID} --private-key ${process.env.FUNDER_ADDRESS_PRIVATE_KEY} ${address}`; - - logger.debug( - { address, amount: process.env.FUNDER_AMOUNT }, - "Funding validator" - ); - const { stdout, stderr } = await execAsync(command); - - if (stderr) { - throw new Error(stderr); - } - - return stdout; - } catch (error) { - logger.error({ error, address }, "Error funding validator"); - throw error; - } - } -} diff --git a/tooling/sparta/src/test/README.md b/tooling/sparta/src/test/README.md deleted file mode 100644 index d2dadc3..0000000 --- a/tooling/sparta/src/test/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Tests - -This directory contains test files for the codebase. - -- `aztec.test.ts` - Tests for Aztec client functionality diff --git a/tooling/sparta/src/test/aztec.test.ts b/tooling/sparta/src/test/aztec.test.ts deleted file mode 100644 index 1a00025..0000000 --- a/tooling/sparta/src/test/aztec.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { expect, test, beforeAll, describe } from "bun:test"; -import { Aztec } from "../clients/aztec.js"; -import { config } from "dotenv"; - -config({ path: ".env.local" }); - -// Set the RPC URL for tests -const TEST_RPC_URL = process.env.AZTEC_NODE_URL || "http://localhost:8080"; -let aztec: Aztec; -let isNodeAvailable = false; - -// Verify node is available before tests -beforeAll(async () => { - aztec = new Aztec(TEST_RPC_URL); - - try { - // Try to get L2 tips to check if node is available - await aztec.getL2Tips(); - isNodeAvailable = true; - console.log(`Connected to Aztec node at ${TEST_RPC_URL}`); - } catch (error: any) { - console.warn( - `⚠️ Aztec node at ${TEST_RPC_URL} is not available. Some tests will be skipped.` - ); - console.warn(`Error: ${error.message}`); - throw new Error("Aztec node is not available"); - } -}); - -describe("Aztec Integration Tests", () => { - test("Aztec.new() initializes client with correct URL", async () => { - // This test doesn't need the node to be available - process.env.AZTEC_NODE_URL = TEST_RPC_URL; - const instance = await Aztec.new(); - // @ts-expect-error - accessing private property for test - expect(instance.rpcUrl).toBe(TEST_RPC_URL); - }); - - test("getL2Tips returns the proven block number", async () => { - if (!isNodeAvailable) { - console.log("Skipping test: getL2Tips - node not available"); - return; - } - - const blockNumber = await aztec.getL2Tips(); - console.log(`Current proven block: ${blockNumber}`); - expect(typeof blockNumber).toBe("number"); - expect(blockNumber).toBeGreaterThan(0); - }); - - test("getArchiveSiblingPath returns sibling path data", async () => { - if (!isNodeAvailable) { - console.log( - "Skipping test: getArchiveSiblingPath - node not available" - ); - return; - } - - // Get the current proven block - const provenBlock = await aztec.getL2Tips(); - console.log(`Using proven block: ${provenBlock}`); - - const siblingPath = await aztec.getArchiveSiblingPath(provenBlock); - - // Check if we got a valid response format - expect(siblingPath).toBeDefined(); - - // console.log("Sibling path:", JSON.stringify(siblingPath, null, 2)); - }); - - test("handles RPC errors gracefully", async () => { - // Create an instance with an invalid URL to force an error - const badAztec = new Aztec("http://nonexistent-url:9999"); - - // This should throw an error when trying to connect - await expect(badAztec.getL2Tips()).rejects.toThrow(); - }); -}); diff --git a/tooling/sparta/src/test/discord.test.ts b/tooling/sparta/src/test/discord.test.ts deleted file mode 100644 index 97dbeef..0000000 --- a/tooling/sparta/src/test/discord.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { expect, test, beforeAll, describe, mock, Mock } from "bun:test"; -import { Discord } from "../clients/discord.js"; -import { - Client, - Collection, - GatewayIntentBits, - MessageFlags, - REST, - Routes, -} from "discord.js"; -import { config } from "dotenv"; - -config({ path: ".env.local" }); - -// Mock Discord.js components -mock.module("discord.js", () => { - // Create mock client class - const mockClient = { - login: mock(() => Promise.resolve("token")), - once: mock(), - on: mock(), - commands: new Collection(), - guilds: { - fetch: mock(() => Promise.resolve({ id: "mock-guild" })), - }, - }; - - return { - Client: mock(() => mockClient), - Collection, - GatewayIntentBits: { - Guilds: 1, - GuildMessages: 2, - }, - MessageFlags: { - Ephemeral: 64, - }, - REST: mock(() => ({ - setToken: mock().mockReturnThis(), - put: mock(() => Promise.resolve()), - })), - Routes: { - applicationGuildCommands: mock( - (clientId, guildId) => - `/applications/${clientId}/guilds/${guildId}/commands` - ), - }, - }; -}); - -describe("Discord Client Tests", () => { - // Keep reference to any mock clients created during tests - let mockDiscordClient: any; - - test("Discord.new() initializes client with correct configuration", async () => { - // Store original environment variables - const originalToken = process.env.BOT_TOKEN; - const originalClientId = process.env.BOT_CLIENT_ID; - const originalGuildId = process.env.GUILD_ID; - - // Set test environment variables - process.env.BOT_TOKEN = "test-token"; - process.env.BOT_CLIENT_ID = "test-client-id"; - process.env.GUILD_ID = "test-guild-id"; - - try { - const discord = await Discord.new(); - expect(discord).toBeInstanceOf(Discord); - - // Verify the client was initialized - mockDiscordClient = discord.getClient(); - expect(mockDiscordClient).toBeDefined(); - expect(mockDiscordClient.login).toHaveBeenCalledWith("test-token"); - expect(mockDiscordClient.once).toHaveBeenCalledWith( - "ready", - expect.any(Function) - ); - expect(mockDiscordClient.once).toHaveBeenCalledWith( - "error", - expect.any(Function) - ); - expect(mockDiscordClient.on).toHaveBeenCalledWith( - "interactionCreate", - expect.any(Function) - ); - } finally { - // Restore original environment variables - process.env.BOT_TOKEN = originalToken; - process.env.BOT_CLIENT_ID = originalClientId; - process.env.GUILD_ID = originalGuildId; - } - }); - - test("getClient() returns the Discord client instance", async () => { - const discord = await Discord.new(); - const client = discord.getClient(); - expect(client).toBeDefined(); - expect(client.commands).toBeInstanceOf(Collection); - }); - - test("getGuild() retrieves guild by ID", async () => { - const discord = await Discord.new(); - const guild = await discord.getGuild("test-guild-id"); - expect(guild).toBeDefined(); - expect(mockDiscordClient.guilds.fetch).toHaveBeenCalledWith( - "test-guild-id" - ); - }); - - test("handles errors gracefully during initialization", async () => { - // Force an error condition by removing the token - const originalToken = process.env.BOT_TOKEN; - process.env.BOT_TOKEN = undefined; - - try { - // Get a reference to the login function so we can modify it - const client = new Client({ intents: [] }); - const loginSpy = mock(() => - Promise.reject(new Error("Invalid token")) - ); - client.login = loginSpy; - - // @ts-expect-error - accessing private property for test - Client.mockImplementationOnce(() => client); - - await expect(Discord.new()).rejects.toThrow(); - expect(loginSpy).toHaveBeenCalled(); - } finally { - // Restore original token - process.env.BOT_TOKEN = originalToken; - } - }); -}); diff --git a/tooling/sparta/src/test/ethereum.test.ts b/tooling/sparta/src/test/ethereum.test.ts deleted file mode 100644 index 0af1406..0000000 --- a/tooling/sparta/src/test/ethereum.test.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { expect, test, beforeAll, describe, mock } from "bun:test"; -import { Ethereum, getExpectedAddress } from "../clients/ethereum.js"; -import { config } from "dotenv"; - -config({ path: ".env.local" }); - -// Mock viem and its functions -mock.module("viem", () => { - const mockPublicClient = { - waitForTransactionReceipt: mock(({ hash }) => - Promise.resolve({ - blockHash: "0xblock123", - blockNumber: 123456n, - transactionHash: hash, - status: "success", - }) - ), - }; - - const mockContract = { - address: "0xcontract123" as `0x${string}`, - write: { - mint: mock(() => "0xtxhash123"), - approve: mock(() => "0xtxhash456"), - deposit: mock(() => "0xtxhash789"), - initiateWithdraw: mock(() => "0xtxhash000"), - }, - read: { - getRollup: mock(() => "0xrollup123"), - getStakingAsset: mock(() => "0xstaking123"), - }, - }; - - const mockWalletClient = { - account: { - address: "0xwallet123" as `0x${string}`, - }, - }; - - return { - createPublicClient: mock((config) => mockPublicClient), - createWalletClient: mock(() => mockWalletClient), - encodeDeployData: mock(() => "0xencoded123"), - getContract: mock(() => mockContract), - getCreate2Address: mock(() => "0xcreated123"), - http: mock(() => "http-transport"), - padHex: mock(() => "0xpadded123"), - }; -}); - -// Mock viem/accounts -mock.module("viem/accounts", () => { - return { - privateKeyToAccount: mock(() => ({ - address: "0xaccount123" as `0x${string}`, - })), - }; -}); - -describe("Ethereum Integration Tests", () => { - let ethereum: Ethereum; - - // Set environment variables for tests - const testEnv = { - ETHEREUM_HOST: "https://test-rpc-url", - ETHEREUM_REGISTRY_ADDRESS: "0xregistry123", - MINTER_PRIVATE_KEY: "0xprivkey123", - MINIMUM_STAKE: "1000000", - APPROVAL_AMOUNT: "2000000", - WITHDRAWER_ADDRESS: "0xwithdrawer123", - WITHDRAWER_PRIVATE_KEY: "0xwithdrawerprivkey123", - L1_CHAIN_ID: "11155111", - }; - - beforeAll(() => { - // Save original env variables - const originalEnv = { ...process.env }; - - // Set test env variables - Object.entries(testEnv).forEach(([key, value]) => { - process.env[key] = value; - }); - - return () => { - // Restore original env variables - process.env = originalEnv; - }; - }); - - test("Ethereum.new() initializes client with correct configuration", async () => { - const ethereum = await Ethereum.new(); - expect(ethereum).toBeInstanceOf(Ethereum); - - // Check if required clients were initialized - const viem = await import("viem"); - expect(viem.createPublicClient).toHaveBeenCalled(); - expect(viem.createWalletClient).toHaveBeenCalled(); - expect(viem.getContract).toHaveBeenCalled(); - }); - - test("getPublicClient() returns the public client", async () => { - ethereum = await Ethereum.new(); - const client = ethereum.getPublicClient(); - expect(client).toBeDefined(); - expect(client.waitForTransactionReceipt).toBeDefined(); - }); - - test("getWalletClient() returns the wallet client", async () => { - ethereum = await Ethereum.new(); - const client = ethereum.getWalletClient(); - expect(client).toBeDefined(); - expect(client.account).toBeDefined(); - }); - - test("getRollup() returns the rollup contract", async () => { - ethereum = await Ethereum.new(); - const rollup = ethereum.getRollup(); - expect(rollup).toBeDefined(); - expect(rollup.address).toBe("0xcontract123"); - }); - - test("stakingAssetFaucet() mints tokens", async () => { - ethereum = await Ethereum.new(); - const receipt = await ethereum.stakingAssetFaucet("0xrecipient123"); - - expect(receipt).toBeDefined(); - expect(receipt.transactionHash).toBe("0xtxhash123"); - expect(receipt.status).toBe("success"); - }); - - test("addValidator() deposits stake for a validator", async () => { - ethereum = await Ethereum.new(); - const receipts = await ethereum.addValidator("0xvalidator123"); - - expect(receipts).toBeInstanceOf(Array); - expect(receipts.length).toBe(2); - expect(receipts[0].transactionHash).toBe("0xtxhash456"); - expect(receipts[1].transactionHash).toBe("0xtxhash789"); - }); - - test("removeValidator() initiates withdrawal for a validator", async () => { - ethereum = await Ethereum.new(); - const receipt = await ethereum.removeValidator("0xvalidator123"); - - expect(receipt).toBeDefined(); - expect(receipt.transactionHash).toBe("0xtxhash000"); - expect(receipt.status).toBe("success"); - }); - - test("getExpectedAddress calculates the correct address", () => { - const result = getExpectedAddress( - ["0xarg123"] as [`0x${string}`], - "0xsalt123" as `0x${string}` - ); - - expect(result).toBeDefined(); - expect(result.address).toBe("0xcreated123"); - expect(result.paddedSalt).toBe("0xpadded123"); - expect(result.calldata).toBe("0xencoded123"); - }); - - test("handles errors gracefully", async () => { - // Mock waitForTransactionReceipt to throw an error - const viem = await import("viem"); - - // Create a mock chain object with required properties - const mockChain = { - id: 11155111, - name: "Sepolia", - nativeCurrency: { - decimals: 18, - name: "Ethereum", - symbol: "ETH", - }, - rpcUrls: { - default: { - http: ["https://test-rpc-url"], - }, - public: { - http: ["https://test-rpc-url"], - }, - }, - }; - - // Create a mock http transport - const httpTransport = viem.http(); - - const mockPublicClient = viem.createPublicClient({ - chain: mockChain, - transport: httpTransport, - }); - - mockPublicClient.waitForTransactionReceipt = mock(() => { - throw new Error("Transaction failed"); - }); - - ethereum = await Ethereum.new(); - - // @ts-expect-error - accessing private property for test - ethereum.publicClient = mockPublicClient; - - await expect( - ethereum.stakingAssetFaucet("0xrecipient123") - ).rejects.toThrow("Transaction failed"); - }); -}); diff --git a/tooling/sparta/src/test/google.test.ts b/tooling/sparta/src/test/google.test.ts deleted file mode 100644 index d6ee860..0000000 --- a/tooling/sparta/src/test/google.test.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { expect, test, beforeAll, describe, mock } from "bun:test"; -import { GoogleSheet } from "../clients/google.js"; -import { config } from "dotenv"; - -config({ path: ".env.local" }); - -// Mock test data for our spreadsheet -const testData = [ - ["header1", "header2", "header3"], - ["value1", "value2", "value3"], - ["value4", "value5", "value6"], -]; - -// Mock Google Sheets API -mock.module("@googleapis/sheets", () => { - const mockSheetsGet = mock((params) => { - const range = params.range; - - // Handle single cell requests (e.g., Sheet1!B2) - const cellMatch = range.match(/.*!([A-Z])([0-9]+)$/); - if (cellMatch) { - const col = cellMatch[1].charCodeAt(0) - 65; // Convert A->0, B->1, etc. - const row = parseInt(cellMatch[2]) - 1; // Convert to 0-based index - - // Return just the value at that position in a 2D array - // This is how the real API would respond for a cell request - if ( - row >= 0 && - row < testData.length && - col >= 0 && - col < testData[row].length - ) { - return { - data: { - values: [[testData[row][col]]], - }, - }; - } - } - - // Default case: return all data - return { - data: { - values: testData, - }, - }; - }); - - const mockSheetsUpdate = mock(() => ({ - data: { - updatedCells: 3, - updatedRange: "Sheet1!A1:C2", - }, - })); - - return { - sheets: mock((options) => ({ - spreadsheets: { - values: { - get: mockSheetsGet, - update: mockSheetsUpdate, - }, - }, - })), - }; -}); - -describe("Google Sheets Integration Tests", () => { - let googleSheet: GoogleSheet; - - beforeAll(() => { - // Set environment variable for tests - process.env.GOOGLE_API_KEY = "test-api-key"; - - // Create an instance with a test spreadsheet ID - googleSheet = new GoogleSheet("test-spreadsheet-id"); - }); - - test("GoogleSheet constructor initializes with correct spreadsheet ID", () => { - // @ts-expect-error - accessing private property for test - expect(googleSheet.spreadsheetId).toBe("test-spreadsheet-id"); - }); - - test("fetchData retrieves values from the spreadsheet", async () => { - // @ts-expect-error - accessing private method for test - const values = await googleSheet.fetchData( - "test-spreadsheet-id", - "Sheet1!A1:C3" - ); - - expect(values).toBeDefined(); - expect(values.length).toBe(3); - expect(values[0][0]).toBe("header1"); - expect(values[1][0]).toBe("value1"); - }); - - test("fetchCellValue retrieves a specific cell value", async () => { - const value = await googleSheet.fetchCellValue( - "test-spreadsheet-id", - "Sheet1!B2" - ); - expect(value).toBe("value2"); - }); - - test("updateValues updates data in the spreadsheet", async () => { - const newValues = [ - ["newValue1", "newValue2", "newValue3"], - ["newValue4", "newValue5", "newValue6"], - ]; - - await googleSheet.updateValues( - "test-spreadsheet-id", - "Sheet1!A1:C2", - newValues - ); - - // The update verification is handled by the mock system automatically - }); - - test("watchColumn correctly sets up watching for changes", async () => { - // Mock setTimeout for testing interval setting - const originalSetInterval = global.setInterval; - const mockSetInterval = mock(() => 123); - global.setInterval = mockSetInterval as any; - - // Mock fetchData to resolve immediately - // @ts-expect-error - accessing private method for test - const originalFetchData = googleSheet.fetchData; - // @ts-expect-error - accessing private method for test - googleSheet.fetchData = mock(() => Promise.resolve([["data"]])); - - try { - // Define a callback function - const callback = mock( - (newVal: any, oldVal: any, row: number, rowData: any[]) => {} - ); - - // Set up watching a column - googleSheet.watchColumn("Sheet1!A1:C10", 1, callback, 5000); - - // Allow any pending promises to resolve - await new Promise(process.nextTick); - - // Verify setInterval was called with the correct interval - expect(mockSetInterval).toHaveBeenCalledWith( - expect.any(Function), - 5000 - ); - - // @ts-expect-error - accessing private property for test - expect(googleSheet.watchInterval).toBe(123); - } finally { - // Restore original functions - global.setInterval = originalSetInterval; - // @ts-expect-error - accessing private method for test - googleSheet.fetchData = originalFetchData; - } - }); - - test("stopWatching clears the interval", () => { - // Mock clearInterval - const originalClearInterval = global.clearInterval; - const mockClearInterval = mock((id: number) => {}); - global.clearInterval = mockClearInterval as any; - - try { - // @ts-expect-error - accessing private property for test - googleSheet.watchInterval = 123; - - // Call stopWatching - googleSheet.stopWatching(); - - // Verify clearInterval was called with the correct ID - expect(mockClearInterval).toHaveBeenCalledWith(123); - - // @ts-expect-error - accessing private property for test - expect(googleSheet.watchInterval).toBeNull(); - } finally { - // Restore original clearInterval - global.clearInterval = originalClearInterval; - } - }); - - test("handles API errors gracefully", async () => { - // Save original fetchCellValue implementation - const originalFetchCellValue = googleSheet.fetchCellValue; - - try { - // Replace fetchCellValue with a version that returns a rejected promise - googleSheet.fetchCellValue = mock(() => { - return Promise.reject(new Error("API Error")); - }); - - // Test that the rejected promise is properly caught - await expect( - googleSheet.fetchCellValue("test-spreadsheet-id", "Sheet1!A1") - ).rejects.toThrow("API Error"); - } finally { - // Restore original method - googleSheet.fetchCellValue = originalFetchCellValue; - } - }); -}); diff --git a/tooling/sparta/src/tsconfig.json b/tooling/sparta/src/tsconfig.json deleted file mode 100644 index f1ae592..0000000 --- a/tooling/sparta/src/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "NodeNext", - "moduleResolution": "nodenext", - "outDir": "./dist", - "rootDir": "./", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "dist"] -} diff --git a/tooling/sparta/src/utils/README.md b/tooling/sparta/src/utils/README.md deleted file mode 100644 index 707b113..0000000 --- a/tooling/sparta/src/utils/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Utils - -This directory contains utility functions and helpers that are used across the codebase. - -- `inputValidator.ts` - Input validation utilities -- `pagination.ts` - Pagination helpers -- `abis/` - Ethereum contract ABIs (Application Binary Interfaces) diff --git a/tooling/sparta/src/utils/abis/forwarder.ts b/tooling/sparta/src/utils/abis/forwarder.ts deleted file mode 100644 index 7f63d6f..0000000 --- a/tooling/sparta/src/utils/abis/forwarder.ts +++ /dev/null @@ -1,1608 +0,0 @@ -/** - * Forwarder ABI. - */ -export const ForwarderAbi = [ - { - type: "constructor", - inputs: [ - { - name: "__owner", - type: "address", - internalType: "address", - }, - ], - stateMutability: "nonpayable", - }, - { - type: "error", - name: "AddressEmptyCode", - inputs: [ - { - name: "target", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "CoinIssuer__InsufficientMintAvailable", - inputs: [ - { - name: "available", - type: "uint256", - internalType: "uint256", - }, - { - name: "needed", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "DevNet__InvalidProposer", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "DevNet__NoPruningAllowed", - inputs: [], - }, - { - type: "error", - name: "FailedCall", - inputs: [], - }, - { - type: "error", - name: "FeeJuicePortal__AlreadyInitialized", - inputs: [], - }, - { - type: "error", - name: "FeeJuicePortal__InvalidInitialization", - inputs: [], - }, - { - type: "error", - name: "FeeJuicePortal__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "FeeLib__InvalidFeeAssetPriceModifier", - inputs: [], - }, - { - type: "error", - name: "ForwarderLengthMismatch", - inputs: [ - { - name: "toLength", - type: "uint256", - internalType: "uint256", - }, - { - name: "dataLength", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__CanOnlyExecuteProposalInPast", - inputs: [], - }, - { - type: "error", - name: "GovernanceProposer__FailedToPropose", - inputs: [ - { - name: "proposal", - type: "address", - internalType: "contract IPayload", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InstanceHaveNoCode", - inputs: [ - { - name: "instance", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InsufficientVotes", - inputs: [ - { - name: "votesCast", - type: "uint256", - internalType: "uint256", - }, - { - name: "votesNeeded", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InvalidNAndMValues", - inputs: [ - { - name: "n", - type: "uint256", - internalType: "uint256", - }, - { - name: "m", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__NCannotBeLargerTHanM", - inputs: [ - { - name: "n", - type: "uint256", - internalType: "uint256", - }, - { - name: "m", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__OnlyProposerCanVote", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalAlreadyExecuted", - inputs: [ - { - name: "roundNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalCannotBeAddressZero", - inputs: [], - }, - { - type: "error", - name: "GovernanceProposer__ProposalHaveNoCode", - inputs: [ - { - name: "proposal", - type: "address", - internalType: "contract IPayload", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalTooOld", - inputs: [ - { - name: "roundNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "currentRoundNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__VoteAlreadyCastForSlot", - inputs: [ - { - name: "slot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Governance__CallFailed", - inputs: [ - { - name: "target", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CallerNotGovernanceProposer", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "governanceProposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CallerNotSelf", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "self", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CannotCallAsset", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__DifferentialTooBig", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__DifferentialTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__InvalidMinimumVotes", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__LockAmountTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__QuorumTooBig", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__QuorumTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__TimeTooBig", - inputs: [ - { - name: "name", - type: "string", - internalType: "string", - }, - ], - }, - { - type: "error", - name: "Governance__ConfigurationLib__TimeTooSmall", - inputs: [ - { - name: "name", - type: "string", - internalType: "string", - }, - ], - }, - { - type: "error", - name: "Governance__InsufficientPower", - inputs: [ - { - name: "voter", - type: "address", - internalType: "address", - }, - { - name: "have", - type: "uint256", - internalType: "uint256", - }, - { - name: "required", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Governance__InvalidConfiguration", - inputs: [], - }, - { - type: "error", - name: "Governance__NoCheckpointsFound", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalAlreadyDropped", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalCannotBeDropped", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalDoesNotExists", - inputs: [ - { - name: "proposalId", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Governance__ProposalLib__MoreVoteThanExistNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__MoreYeaVoteThanExistNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroMinimum", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroVotesNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroYeaVotesNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalNotActive", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalNotExecutable", - inputs: [], - }, - { - type: "error", - name: "Governance__UserLib__NotInPast", - inputs: [], - }, - { - type: "error", - name: "Governance__WithdrawalAlreadyclaimed", - inputs: [], - }, - { - type: "error", - name: "Governance__WithdrawalNotUnlockedYet", - inputs: [ - { - name: "currentTime", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "unlocksAt", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "HeaderLib__InvalidHeaderSize", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "HeaderLib__InvalidSlotNumber", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Slot", - }, - { - name: "actual", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Inbox__ActorTooLarge", - inputs: [ - { - name: "actor", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__ContentTooLarge", - inputs: [ - { - name: "content", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__MustBuildBeforeConsume", - inputs: [], - }, - { - type: "error", - name: "Inbox__SecretHashTooLarge", - inputs: [ - { - name: "secretHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "InsufficientBalance", - inputs: [ - { - name: "balance", - type: "uint256", - internalType: "uint256", - }, - { - name: "needed", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "MerkleLib__InvalidRoot", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "leaf", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "leafIndex", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__AlreadyNullified", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "leafIndex", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__BlockNotProven", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__IncompatibleEntryArguments", - inputs: [ - { - name: "messageHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "storedFee", - type: "uint64", - internalType: "uint64", - }, - { - name: "feePassed", - type: "uint64", - internalType: "uint64", - }, - { - name: "storedVersion", - type: "uint32", - internalType: "uint32", - }, - { - name: "versionPassed", - type: "uint32", - internalType: "uint32", - }, - { - name: "storedDeadline", - type: "uint32", - internalType: "uint32", - }, - { - name: "deadlinePassed", - type: "uint32", - internalType: "uint32", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidChainId", - inputs: [], - }, - { - type: "error", - name: "Outbox__InvalidPathLength", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidRecipient", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidVersion", - inputs: [ - { - name: "entry", - type: "uint256", - internalType: "uint256", - }, - { - name: "message", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__NothingToConsume", - inputs: [ - { - name: "messageHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Outbox__NothingToConsumeAtBlock", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__RootAlreadySetAtBlock", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "OwnableInvalidOwner", - inputs: [ - { - name: "owner", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "OwnableUnauthorizedAccount", - inputs: [ - { - name: "account", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "event", - name: "OwnershipTransferred", - inputs: [ - { - name: "previousOwner", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "newOwner", - type: "address", - indexed: true, - internalType: "address", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "ProofCommitmentEscrow__InsufficientBalance", - inputs: [ - { - name: "balance", - type: "uint256", - internalType: "uint256", - }, - { - name: "requested", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ProofCommitmentEscrow__NotOwner", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ProofCommitmentEscrow__WithdrawRequestNotReady", - inputs: [ - { - name: "current", - type: "uint256", - internalType: "uint256", - }, - { - name: "readyAt", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "Registry__RollupAlreadyRegistered", - inputs: [ - { - name: "rollup", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Registry__RollupNotRegistered", - inputs: [ - { - name: "rollup", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "RewardDistributor__InvalidCaller", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "canonical", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Rollup__AlreadyClaimed", - inputs: [ - { - name: "prover", - type: "address", - internalType: "address", - }, - { - name: "epoch", - type: "uint256", - internalType: "Epoch", - }, - ], - }, - { - type: "error", - name: "Rollup__InsufficientBondAmount", - inputs: [ - { - name: "minimum", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InsufficientFundsInEscrow", - inputs: [ - { - name: "required", - type: "uint256", - internalType: "uint256", - }, - { - name: "available", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBasisPointFee", - inputs: [ - { - name: "basisPointFee", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobHash", - inputs: [ - { - name: "blobHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobProof", - inputs: [ - { - name: "blobHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobPublicInputsHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlockHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlockNumber", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidChainId", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidInHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidManaBaseFee", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidPreviousArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidPreviousBlockHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidProof", - inputs: [], - }, - { - type: "error", - name: "Rollup__InvalidProposedArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidTimestamp", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "actual", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidVersion", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__ManaLimitExceeded", - inputs: [], - }, - { - type: "error", - name: "Rollup__NoEpochToProve", - inputs: [], - }, - { - type: "error", - name: "Rollup__NonSequentialProving", - inputs: [], - }, - { - type: "error", - name: "Rollup__NonZeroDaFee", - inputs: [], - }, - { - type: "error", - name: "Rollup__NotPastDeadline", - inputs: [ - { - name: "deadline", - type: "uint256", - internalType: "Slot", - }, - { - name: "currentSlot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Rollup__NothingToPrune", - inputs: [], - }, - { - type: "error", - name: "Rollup__PastDeadline", - inputs: [ - { - name: "deadline", - type: "uint256", - internalType: "Slot", - }, - { - name: "currentSlot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Rollup__ProverHaveAlreadySubmitted", - inputs: [ - { - name: "prover", - type: "address", - internalType: "address", - }, - { - name: "epoch", - type: "uint256", - internalType: "Epoch", - }, - ], - }, - { - type: "error", - name: "Rollup__SlotAlreadyInChain", - inputs: [ - { - name: "lastSlot", - type: "uint256", - internalType: "Slot", - }, - { - name: "proposedSlot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Rollup__StartAndEndNotSameEpoch", - inputs: [ - { - name: "start", - type: "uint256", - internalType: "Epoch", - }, - { - name: "end", - type: "uint256", - internalType: "Epoch", - }, - ], - }, - { - type: "error", - name: "Rollup__StartIsNotBuildingOnProven", - inputs: [], - }, - { - type: "error", - name: "Rollup__StartIsNotFirstBlockOfEpoch", - inputs: [], - }, - { - type: "error", - name: "Rollup__TimestampInFuture", - inputs: [ - { - name: "max", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "actual", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "Rollup__TimestampTooOld", - inputs: [], - }, - { - type: "error", - name: "Rollup__TryingToProveNonExistingBlock", - inputs: [], - }, - { - type: "error", - name: "Rollup__UnavailableTxs", - inputs: [ - { - name: "txsHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "SampleLib__IndexOutOfBounds", - inputs: [ - { - name: "requested", - type: "uint256", - internalType: "uint256", - }, - { - name: "bound", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "SignatureLib__CannotVerifyEmpty", - inputs: [], - }, - { - type: "error", - name: "SignatureLib__InvalidSignature", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "recovered", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__AlreadyActive", - inputs: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__AlreadyRegistered", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__CannotSlashExitedStake", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__FailedToRemove", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__InsufficientStake", - inputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Staking__InvalidDeposit", - inputs: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NoOneToSlash", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotExiting", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotSlasher", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotWithdrawer", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NothingToExit", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__WithdrawalNotUnlockedYet", - inputs: [ - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__EpochNotSetup", - inputs: [], - }, - { - type: "error", - name: "ValidatorSelection__InsufficientAttestations", - inputs: [ - { - name: "minimumNeeded", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InsufficientAttestationsProvided", - inputs: [ - { - name: "minimumNeeded", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InvalidDeposit", - inputs: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InvalidProposer", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "function", - name: "forward", - inputs: [ - { - name: "_to", - type: "address[]", - internalType: "address[]", - }, - { - name: "_data", - type: "bytes[]", - internalType: "bytes[]", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "owner", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "renounceOwnership", - inputs: [], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "transferOwnership", - inputs: [ - { - name: "newOwner", - type: "address", - internalType: "address", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, -] as const; - -export const ForwarderBytecode = - "0x6080604052348015600e575f5ffd5b506040516105f13803806105f1833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b610505806100ec5f395ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c8063715018a61461004e5780638da5cb5b14610058578063b028e60714610076578063f2fde38b14610089575b5f5ffd5b61005661009c565b005b5f54604080516001600160a01b039092168252519081900360200190f35b6100566100843660046103d0565b6100af565b61005661009736600461043c565b610197565b6100a46101d4565b6100ad5f610200565b565b6100b76101d4565b82818181146100e757604051633a2aeb4d60e01b8152600481019290925260248201526044015b60405180910390fd5b505f90505b838110156101905761018783838381811061010957610109610462565b905060200281019061011b9190610476565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525089925088915085905081811061016357610163610462565b9050602002016020810190610178919061043c565b6001600160a01b03169061024f565b506001016100ec565b5050505050565b61019f6101d4565b6001600160a01b0381166101c857604051631e4fbdf760e01b81525f60048201526024016100de565b6101d181610200565b50565b5f546001600160a01b031633146100ad5760405163118cdaa760e01b81523360048201526024016100de565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b606061025c83835f610263565b9392505050565b60608147101561028f5760405163cf47918160e01b8152476004820152602481018390526044016100de565b5f5f856001600160a01b031684866040516102aa91906104b9565b5f6040518083038185875af1925050503d805f81146102e4576040519150601f19603f3d011682016040523d82523d5f602084013e6102e9565b606091505b50915091506102f9868383610303565b9695505050505050565b606082610318576103138261035f565b61025c565b815115801561032f57506001600160a01b0384163b155b1561035857604051639996b31560e01b81526001600160a01b03851660048201526024016100de565b508061025c565b80511561036f5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f5f83601f840112610398575f5ffd5b50813567ffffffffffffffff8111156103af575f5ffd5b6020830191508360208260051b85010111156103c9575f5ffd5b9250929050565b5f5f5f5f604085870312156103e3575f5ffd5b843567ffffffffffffffff8111156103f9575f5ffd5b61040587828801610388565b909550935050602085013567ffffffffffffffff811115610424575f5ffd5b61043087828801610388565b95989497509550505050565b5f6020828403121561044c575f5ffd5b81356001600160a01b038116811461025c575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e1984360301811261048b575f5ffd5b83018035915067ffffffffffffffff8211156104a5575f5ffd5b6020019150368190038213156103c9575f5ffd5b5f82518060208501845e5f92019182525091905056fea26469706673582212201094da15988f4705d58503cdbc19677b21e89966fdc614400045372c2317a21b64736f6c634300081b0033"; diff --git a/tooling/sparta/src/utils/abis/rollup.ts b/tooling/sparta/src/utils/abis/rollup.ts deleted file mode 100644 index 7892cb0..0000000 --- a/tooling/sparta/src/utils/abis/rollup.ts +++ /dev/null @@ -1,3648 +0,0 @@ -/** - * Rollup ABI. - */ -export const RollupAbi = [ - { - type: "constructor", - inputs: [ - { - name: "_fpcJuicePortal", - type: "address", - internalType: "contract IFeeJuicePortal", - }, - { - name: "_rewardDistributor", - type: "address", - internalType: "contract IRewardDistributor", - }, - { - name: "_stakingAsset", - type: "address", - internalType: "contract IERC20", - }, - { - name: "_governance", - type: "address", - internalType: "address", - }, - { - name: "_genesisState", - type: "tuple", - internalType: "struct GenesisState", - components: [ - { - name: "vkTreeRoot", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "protocolContractTreeRoot", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "genesisArchiveRoot", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "genesisBlockHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - name: "_config", - type: "tuple", - internalType: "struct RollupConfigInput", - components: [ - { - name: "aztecSlotDuration", - type: "uint256", - internalType: "uint256", - }, - { - name: "aztecEpochDuration", - type: "uint256", - internalType: "uint256", - }, - { - name: "targetCommitteeSize", - type: "uint256", - internalType: "uint256", - }, - { - name: "aztecProofSubmissionWindow", - type: "uint256", - internalType: "uint256", - }, - { - name: "minimumStake", - type: "uint256", - internalType: "uint256", - }, - { - name: "slashingQuorum", - type: "uint256", - internalType: "uint256", - }, - { - name: "slashingRoundSize", - type: "uint256", - internalType: "uint256", - }, - { - name: "manaTarget", - type: "uint256", - internalType: "uint256", - }, - { - name: "provingCostPerMana", - type: "uint256", - internalType: "EthValue", - }, - ], - }, - ], - stateMutability: "nonpayable", - }, - { - type: "error", - name: "CoinIssuer__InsufficientMintAvailable", - inputs: [ - { - name: "available", - type: "uint256", - internalType: "uint256", - }, - { - name: "needed", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "event", - name: "Deposit", - inputs: [ - { - name: "attester", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "proposer", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "withdrawer", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "amount", - type: "uint256", - indexed: false, - internalType: "uint256", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "DevNet__InvalidProposer", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "DevNet__NoPruningAllowed", - inputs: [], - }, - { - type: "event", - name: "EIP712DomainChanged", - inputs: [], - anonymous: false, - }, - { - type: "error", - name: "FeeJuicePortal__AlreadyInitialized", - inputs: [], - }, - { - type: "error", - name: "FeeJuicePortal__InvalidInitialization", - inputs: [], - }, - { - type: "error", - name: "FeeJuicePortal__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "FeeLib__InvalidFeeAssetPriceModifier", - inputs: [], - }, - { - type: "error", - name: "GovernanceProposer__CanOnlyExecuteProposalInPast", - inputs: [], - }, - { - type: "error", - name: "GovernanceProposer__FailedToPropose", - inputs: [ - { - name: "proposal", - type: "address", - internalType: "contract IPayload", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InstanceHaveNoCode", - inputs: [ - { - name: "instance", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InsufficientVotes", - inputs: [ - { - name: "votesCast", - type: "uint256", - internalType: "uint256", - }, - { - name: "votesNeeded", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InvalidNAndMValues", - inputs: [ - { - name: "n", - type: "uint256", - internalType: "uint256", - }, - { - name: "m", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__NCannotBeLargerTHanM", - inputs: [ - { - name: "n", - type: "uint256", - internalType: "uint256", - }, - { - name: "m", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__OnlyProposerCanVote", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalAlreadyExecuted", - inputs: [ - { - name: "roundNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalCannotBeAddressZero", - inputs: [], - }, - { - type: "error", - name: "GovernanceProposer__ProposalHaveNoCode", - inputs: [ - { - name: "proposal", - type: "address", - internalType: "contract IPayload", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalTooOld", - inputs: [ - { - name: "roundNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "currentRoundNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__VoteAlreadyCastForSlot", - inputs: [ - { - name: "slot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Governance__CallFailed", - inputs: [ - { - name: "target", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CallerNotGovernanceProposer", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "governanceProposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CallerNotSelf", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "self", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CannotCallAsset", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__DifferentialTooBig", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__DifferentialTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__InvalidMinimumVotes", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__LockAmountTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__QuorumTooBig", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__QuorumTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__TimeTooBig", - inputs: [ - { - name: "name", - type: "string", - internalType: "string", - }, - ], - }, - { - type: "error", - name: "Governance__ConfigurationLib__TimeTooSmall", - inputs: [ - { - name: "name", - type: "string", - internalType: "string", - }, - ], - }, - { - type: "error", - name: "Governance__InsufficientPower", - inputs: [ - { - name: "voter", - type: "address", - internalType: "address", - }, - { - name: "have", - type: "uint256", - internalType: "uint256", - }, - { - name: "required", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Governance__InvalidConfiguration", - inputs: [], - }, - { - type: "error", - name: "Governance__NoCheckpointsFound", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalAlreadyDropped", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalCannotBeDropped", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalDoesNotExists", - inputs: [ - { - name: "proposalId", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Governance__ProposalLib__MoreVoteThanExistNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__MoreYeaVoteThanExistNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroMinimum", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroVotesNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroYeaVotesNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalNotActive", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalNotExecutable", - inputs: [], - }, - { - type: "error", - name: "Governance__UserLib__NotInPast", - inputs: [], - }, - { - type: "error", - name: "Governance__WithdrawalAlreadyclaimed", - inputs: [], - }, - { - type: "error", - name: "Governance__WithdrawalNotUnlockedYet", - inputs: [ - { - name: "currentTime", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "unlocksAt", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "HeaderLib__InvalidHeaderSize", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "HeaderLib__InvalidSlotNumber", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Slot", - }, - { - name: "actual", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Inbox__ActorTooLarge", - inputs: [ - { - name: "actor", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__ContentTooLarge", - inputs: [ - { - name: "content", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__MustBuildBeforeConsume", - inputs: [], - }, - { - type: "error", - name: "Inbox__SecretHashTooLarge", - inputs: [ - { - name: "secretHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "InvalidShortString", - inputs: [], - }, - { - type: "function", - name: "L1_BLOCK_AT_GENESIS", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "event", - name: "L2BlockProposed", - inputs: [ - { - name: "blockNumber", - type: "uint256", - indexed: true, - internalType: "uint256", - }, - { - name: "archive", - type: "bytes32", - indexed: true, - internalType: "bytes32", - }, - { - name: "versionedBlobHashes", - type: "bytes32[]", - indexed: false, - internalType: "bytes32[]", - }, - ], - anonymous: false, - }, - { - type: "event", - name: "L2ProofVerified", - inputs: [ - { - name: "blockNumber", - type: "uint256", - indexed: true, - internalType: "uint256", - }, - { - name: "proverId", - type: "address", - indexed: true, - internalType: "address", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "MerkleLib__InvalidRoot", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "leaf", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "leafIndex", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__AlreadyNullified", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "leafIndex", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__BlockNotProven", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__IncompatibleEntryArguments", - inputs: [ - { - name: "messageHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "storedFee", - type: "uint64", - internalType: "uint64", - }, - { - name: "feePassed", - type: "uint64", - internalType: "uint64", - }, - { - name: "storedVersion", - type: "uint32", - internalType: "uint32", - }, - { - name: "versionPassed", - type: "uint32", - internalType: "uint32", - }, - { - name: "storedDeadline", - type: "uint32", - internalType: "uint32", - }, - { - name: "deadlinePassed", - type: "uint32", - internalType: "uint32", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidChainId", - inputs: [], - }, - { - type: "error", - name: "Outbox__InvalidPathLength", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidRecipient", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidVersion", - inputs: [ - { - name: "entry", - type: "uint256", - internalType: "uint256", - }, - { - name: "message", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__NothingToConsume", - inputs: [ - { - name: "messageHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Outbox__NothingToConsumeAtBlock", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__RootAlreadySetAtBlock", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "OwnableInvalidOwner", - inputs: [ - { - name: "owner", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "OwnableUnauthorizedAccount", - inputs: [ - { - name: "account", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "event", - name: "OwnershipTransferred", - inputs: [ - { - name: "previousOwner", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "newOwner", - type: "address", - indexed: true, - internalType: "address", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "ProofCommitmentEscrow__InsufficientBalance", - inputs: [ - { - name: "balance", - type: "uint256", - internalType: "uint256", - }, - { - name: "requested", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ProofCommitmentEscrow__NotOwner", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ProofCommitmentEscrow__WithdrawRequestNotReady", - inputs: [ - { - name: "current", - type: "uint256", - internalType: "uint256", - }, - { - name: "readyAt", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "event", - name: "PrunedPending", - inputs: [ - { - name: "provenBlockNumber", - type: "uint256", - indexed: false, - internalType: "uint256", - }, - { - name: "pendingBlockNumber", - type: "uint256", - indexed: false, - internalType: "uint256", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "Registry__RollupAlreadyRegistered", - inputs: [ - { - name: "rollup", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Registry__RollupNotRegistered", - inputs: [ - { - name: "rollup", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "RewardDistributor__InvalidCaller", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "canonical", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Rollup__AlreadyClaimed", - inputs: [ - { - name: "prover", - type: "address", - internalType: "address", - }, - { - name: "epoch", - type: "uint256", - internalType: "Epoch", - }, - ], - }, - { - type: "error", - name: "Rollup__InsufficientBondAmount", - inputs: [ - { - name: "minimum", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InsufficientFundsInEscrow", - inputs: [ - { - name: "required", - type: "uint256", - internalType: "uint256", - }, - { - name: "available", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBasisPointFee", - inputs: [ - { - name: "basisPointFee", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobHash", - inputs: [ - { - name: "blobHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobProof", - inputs: [ - { - name: "blobHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobPublicInputsHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlockHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlockNumber", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidChainId", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidInHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidManaBaseFee", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidPreviousArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidPreviousBlockHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidProof", - inputs: [], - }, - { - type: "error", - name: "Rollup__InvalidProposedArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidTimestamp", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "actual", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidVersion", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__ManaLimitExceeded", - inputs: [], - }, - { - type: "error", - name: "Rollup__NoEpochToProve", - inputs: [], - }, - { - type: "error", - name: "Rollup__NonSequentialProving", - inputs: [], - }, - { - type: "error", - name: "Rollup__NonZeroDaFee", - inputs: [], - }, - { - type: "error", - name: "Rollup__NotPastDeadline", - inputs: [ - { - name: "deadline", - type: "uint256", - internalType: "Slot", - }, - { - name: "currentSlot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Rollup__NothingToPrune", - inputs: [], - }, - { - type: "error", - name: "Rollup__PastDeadline", - inputs: [ - { - name: "deadline", - type: "uint256", - internalType: "Slot", - }, - { - name: "currentSlot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Rollup__ProverHaveAlreadySubmitted", - inputs: [ - { - name: "prover", - type: "address", - internalType: "address", - }, - { - name: "epoch", - type: "uint256", - internalType: "Epoch", - }, - ], - }, - { - type: "error", - name: "Rollup__SlotAlreadyInChain", - inputs: [ - { - name: "lastSlot", - type: "uint256", - internalType: "Slot", - }, - { - name: "proposedSlot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Rollup__StartAndEndNotSameEpoch", - inputs: [ - { - name: "start", - type: "uint256", - internalType: "Epoch", - }, - { - name: "end", - type: "uint256", - internalType: "Epoch", - }, - ], - }, - { - type: "error", - name: "Rollup__StartIsNotBuildingOnProven", - inputs: [], - }, - { - type: "error", - name: "Rollup__StartIsNotFirstBlockOfEpoch", - inputs: [], - }, - { - type: "error", - name: "Rollup__TimestampInFuture", - inputs: [ - { - name: "max", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "actual", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "Rollup__TimestampTooOld", - inputs: [], - }, - { - type: "error", - name: "Rollup__TryingToProveNonExistingBlock", - inputs: [], - }, - { - type: "error", - name: "Rollup__UnavailableTxs", - inputs: [ - { - name: "txsHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "SafeCastOverflowedIntToUint", - inputs: [ - { - name: "value", - type: "int256", - internalType: "int256", - }, - ], - }, - { - type: "error", - name: "SampleLib__IndexOutOfBounds", - inputs: [ - { - name: "requested", - type: "uint256", - internalType: "uint256", - }, - { - name: "bound", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "SignatureLib__CannotVerifyEmpty", - inputs: [], - }, - { - type: "error", - name: "SignatureLib__InvalidSignature", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "recovered", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "event", - name: "Slashed", - inputs: [ - { - name: "attester", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "amount", - type: "uint256", - indexed: false, - internalType: "uint256", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "Staking__AlreadyActive", - inputs: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__AlreadyRegistered", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__CannotSlashExitedStake", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__FailedToRemove", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__InsufficientStake", - inputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Staking__InvalidDeposit", - inputs: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NoOneToSlash", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotExiting", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotSlasher", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotWithdrawer", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NothingToExit", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__WithdrawalNotUnlockedYet", - inputs: [ - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "StringTooLong", - inputs: [ - { - name: "str", - type: "string", - internalType: "string", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__EpochNotSetup", - inputs: [], - }, - { - type: "error", - name: "ValidatorSelection__InsufficientAttestations", - inputs: [ - { - name: "minimumNeeded", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InsufficientAttestationsProvided", - inputs: [ - { - name: "minimumNeeded", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InvalidDeposit", - inputs: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InvalidProposer", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "event", - name: "WithdrawFinalised", - inputs: [ - { - name: "attester", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "recipient", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "amount", - type: "uint256", - indexed: false, - internalType: "uint256", - }, - ], - anonymous: false, - }, - { - type: "event", - name: "WithdrawInitiated", - inputs: [ - { - name: "attester", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "recipient", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "amount", - type: "uint256", - indexed: false, - internalType: "uint256", - }, - ], - anonymous: false, - }, - { - type: "function", - name: "archive", - inputs: [], - outputs: [ - { - name: "", - type: "bytes32", - internalType: "bytes32", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "archiveAt", - inputs: [ - { - name: "_blockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "bytes32", - internalType: "bytes32", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "canProposeAtTime", - inputs: [ - { - name: "_ts", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "_archive", - type: "bytes32", - internalType: "bytes32", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Slot", - }, - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "canPruneAtTime", - inputs: [ - { - name: "_ts", - type: "uint256", - internalType: "Timestamp", - }, - ], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "cheat__InitialiseValidatorSet", - inputs: [ - { - name: "_args", - type: "tuple[]", - internalType: "struct CheatDepositArgs[]", - components: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - { - name: "withdrawer", - type: "address", - internalType: "address", - }, - { - name: "amount", - type: "uint256", - internalType: "uint256", - }, - ], - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "checkBlob", - inputs: [], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "claimProverRewards", - inputs: [ - { - name: "_recipient", - type: "address", - internalType: "address", - }, - { - name: "_epochs", - type: "uint256[]", - internalType: "Epoch[]", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "claimSequencerRewards", - inputs: [ - { - name: "_recipient", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "deposit", - inputs: [ - { - name: "_attester", - type: "address", - internalType: "address", - }, - { - name: "_proposer", - type: "address", - internalType: "address", - }, - { - name: "_withdrawer", - type: "address", - internalType: "address", - }, - { - name: "_amount", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "eip712Domain", - inputs: [], - outputs: [ - { - name: "fields", - type: "bytes1", - internalType: "bytes1", - }, - { - name: "name", - type: "string", - internalType: "string", - }, - { - name: "version", - type: "string", - internalType: "string", - }, - { - name: "chainId", - type: "uint256", - internalType: "uint256", - }, - { - name: "verifyingContract", - type: "address", - internalType: "address", - }, - { - name: "salt", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "extensions", - type: "uint256[]", - internalType: "uint256[]", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "finaliseWithdraw", - inputs: [ - { - name: "_attester", - type: "address", - internalType: "address", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "getActiveAttesterCount", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getAttesterAtIndex", - inputs: [ - { - name: "_index", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getAttesters", - inputs: [], - outputs: [ - { - name: "", - type: "address[]", - internalType: "address[]", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getBlobPublicInputsHash", - inputs: [ - { - name: "_blockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "bytes32", - internalType: "bytes32", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getBlock", - inputs: [ - { - name: "_blockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct BlockLog", - components: [ - { - name: "archive", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "blockHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "slotNumber", - type: "uint256", - internalType: "Slot", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getBurnAddress", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "pure", - }, - { - type: "function", - name: "getCollectiveProverRewardsForEpoch", - inputs: [ - { - name: "_epoch", - type: "uint256", - internalType: "Epoch", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getCommitteeAt", - inputs: [ - { - name: "_ts", - type: "uint256", - internalType: "Timestamp", - }, - ], - outputs: [ - { - name: "", - type: "address[]", - internalType: "address[]", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getCurrentEpoch", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Epoch", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getCurrentEpochCommittee", - inputs: [], - outputs: [ - { - name: "", - type: "address[]", - internalType: "address[]", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getCurrentProposer", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getCurrentSampleSeed", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getCurrentSlot", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Slot", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getEpochAt", - inputs: [ - { - name: "_ts", - type: "uint256", - internalType: "Timestamp", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Epoch", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getEpochAtSlot", - inputs: [ - { - name: "_slotNumber", - type: "uint256", - internalType: "Slot", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Epoch", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getEpochCommittee", - inputs: [ - { - name: "_epoch", - type: "uint256", - internalType: "Epoch", - }, - ], - outputs: [ - { - name: "", - type: "address[]", - internalType: "address[]", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getEpochDuration", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getEpochForBlock", - inputs: [ - { - name: "_blockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Epoch", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getEpochProofPublicInputs", - inputs: [ - { - name: "_start", - type: "uint256", - internalType: "uint256", - }, - { - name: "_end", - type: "uint256", - internalType: "uint256", - }, - { - name: "_args", - type: "tuple", - internalType: "struct PublicInputArgs", - components: [ - { - name: "previousArchive", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "endArchive", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "previousBlockHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "endBlockHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "endTimestamp", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "outHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "proverId", - type: "address", - internalType: "address", - }, - ], - }, - { - name: "_fees", - type: "bytes32[]", - internalType: "bytes32[]", - }, - { - name: "_blobPublicInputs", - type: "bytes", - internalType: "bytes", - }, - { - name: "_aggregationObject", - type: "bytes", - internalType: "bytes", - }, - ], - outputs: [ - { - name: "", - type: "bytes32[]", - internalType: "bytes32[]", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getExit", - inputs: [ - { - name: "_attester", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct Exit", - components: [ - { - name: "exitableAt", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "recipient", - type: "address", - internalType: "address", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getExitDelay", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getFeeAsset", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "contract IERC20", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getFeeAssetPerEth", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "FeeAssetPerEthE9", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getFeeAssetPortal", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "contract IFeeJuicePortal", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getFeeHeader", - inputs: [ - { - name: "_blockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct FeeHeader", - components: [ - { - name: "excessMana", - type: "uint256", - internalType: "uint256", - }, - { - name: "manaUsed", - type: "uint256", - internalType: "uint256", - }, - { - name: "feeAssetPriceNumerator", - type: "uint256", - internalType: "uint256", - }, - { - name: "congestionCost", - type: "uint256", - internalType: "uint256", - }, - { - name: "provingCost", - type: "uint256", - internalType: "uint256", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getGenesisTime", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getHasSubmitted", - inputs: [ - { - name: "_epoch", - type: "uint256", - internalType: "Epoch", - }, - { - name: "_length", - type: "uint256", - internalType: "uint256", - }, - { - name: "_prover", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getInbox", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "contract IInbox", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getInfo", - inputs: [ - { - name: "_attester", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct ValidatorInfo", - components: [ - { - name: "stake", - type: "uint256", - internalType: "uint256", - }, - { - name: "withdrawer", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - { - name: "status", - type: "uint8", - internalType: "enum Status", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getL1FeesAt", - inputs: [ - { - name: "_timestamp", - type: "uint256", - internalType: "Timestamp", - }, - ], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct L1FeeData", - components: [ - { - name: "baseFee", - type: "uint256", - internalType: "uint256", - }, - { - name: "blobFee", - type: "uint256", - internalType: "uint256", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getManaBaseFeeAt", - inputs: [ - { - name: "_timestamp", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "_inFeeAsset", - type: "bool", - internalType: "bool", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getManaBaseFeeComponentsAt", - inputs: [ - { - name: "_timestamp", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "_inFeeAsset", - type: "bool", - internalType: "bool", - }, - ], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct ManaBaseFeeComponents", - components: [ - { - name: "congestionCost", - type: "uint256", - internalType: "uint256", - }, - { - name: "congestionMultiplier", - type: "uint256", - internalType: "uint256", - }, - { - name: "dataCost", - type: "uint256", - internalType: "uint256", - }, - { - name: "gasCost", - type: "uint256", - internalType: "uint256", - }, - { - name: "provingCost", - type: "uint256", - internalType: "uint256", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getManaLimit", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getManaTarget", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getMinimumStake", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getOperatorAtIndex", - inputs: [ - { - name: "_index", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct OperatorInfo", - components: [ - { - name: "proposer", - type: "address", - internalType: "address", - }, - { - name: "attester", - type: "address", - internalType: "address", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getOutbox", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "contract IOutbox", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getPendingBlockNumber", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getProofSubmissionWindow", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getProposerAt", - inputs: [ - { - name: "_ts", - type: "uint256", - internalType: "Timestamp", - }, - ], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getProposerAtIndex", - inputs: [ - { - name: "_index", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getProposerForAttester", - inputs: [ - { - name: "_attester", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getProvenBlockNumber", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getProvingCostPerManaInEth", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "EthValue", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getProvingCostPerManaInFeeAsset", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "FeeAssetValue", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getRewardDistributor", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "contract IRewardDistributor", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getSampleSeedAt", - inputs: [ - { - name: "_ts", - type: "uint256", - internalType: "Timestamp", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getSequencerRewards", - inputs: [ - { - name: "_sequencer", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getSlasher", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getSlotAt", - inputs: [ - { - name: "_ts", - type: "uint256", - internalType: "Timestamp", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Slot", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getSlotDuration", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getSpecificProverRewardsForEpoch", - inputs: [ - { - name: "_epoch", - type: "uint256", - internalType: "Epoch", - }, - { - name: "_prover", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getStakingAsset", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "contract IERC20", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getTargetCommitteeSize", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getTimestampForSlot", - inputs: [ - { - name: "_slotNumber", - type: "uint256", - internalType: "Slot", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getTips", - inputs: [], - outputs: [ - { - name: "", - type: "tuple", - internalType: "struct ChainTips", - components: [ - { - name: "pendingBlockNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "provenBlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "getVersion", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "initiateWithdraw", - inputs: [ - { - name: "_attester", - type: "address", - internalType: "address", - }, - { - name: "_recipient", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", - }, - ], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "owner", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "propose", - inputs: [ - { - name: "_args", - type: "tuple", - internalType: "struct ProposeArgs", - components: [ - { - name: "archive", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "blockHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "oracleInput", - type: "tuple", - internalType: "struct OracleInput", - components: [ - { - name: "feeAssetPriceModifier", - type: "int256", - internalType: "int256", - }, - ], - }, - { - name: "header", - type: "bytes", - internalType: "bytes", - }, - { - name: "txHashes", - type: "bytes32[]", - internalType: "bytes32[]", - }, - ], - }, - { - name: "_signatures", - type: "tuple[]", - internalType: "struct Signature[]", - components: [ - { - name: "isEmpty", - type: "bool", - internalType: "bool", - }, - { - name: "v", - type: "uint8", - internalType: "uint8", - }, - { - name: "r", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "s", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - name: "_blobInput", - type: "bytes", - internalType: "bytes", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "prune", - inputs: [], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "renounceOwnership", - inputs: [], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "setEpochVerifier", - inputs: [ - { - name: "_verifier", - type: "address", - internalType: "address", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "setProtocolContractTreeRoot", - inputs: [ - { - name: "_protocolContractTreeRoot", - type: "bytes32", - internalType: "bytes32", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "setProvingCostPerMana", - inputs: [ - { - name: "_provingCostPerMana", - type: "uint256", - internalType: "EthValue", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "setVkTreeRoot", - inputs: [ - { - name: "_vkTreeRoot", - type: "bytes32", - internalType: "bytes32", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "setupEpoch", - inputs: [], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "slash", - inputs: [ - { - name: "_attester", - type: "address", - internalType: "address", - }, - { - name: "_amount", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "status", - inputs: [ - { - name: "_myHeaderBlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "provenBlockNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "provenArchive", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "pendingBlockNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "pendingArchive", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "archiveOfMyBlock", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "provenEpochNumber", - type: "uint256", - internalType: "Epoch", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "submitEpochRootProof", - inputs: [ - { - name: "_args", - type: "tuple", - internalType: "struct SubmitEpochRootProofArgs", - components: [ - { - name: "start", - type: "uint256", - internalType: "uint256", - }, - { - name: "end", - type: "uint256", - internalType: "uint256", - }, - { - name: "args", - type: "tuple", - internalType: "struct PublicInputArgs", - components: [ - { - name: "previousArchive", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "endArchive", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "previousBlockHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "endBlockHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "endTimestamp", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "outHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "proverId", - type: "address", - internalType: "address", - }, - ], - }, - { - name: "fees", - type: "bytes32[]", - internalType: "bytes32[]", - }, - { - name: "blobPublicInputs", - type: "bytes", - internalType: "bytes", - }, - { - name: "aggregationObject", - type: "bytes", - internalType: "bytes", - }, - { - name: "proof", - type: "bytes", - internalType: "bytes", - }, - ], - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "transferOwnership", - inputs: [ - { - name: "newOwner", - type: "address", - internalType: "address", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "updateL1GasFeeOracle", - inputs: [], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "validateBlobs", - inputs: [ - { - name: "_blobsInput", - type: "bytes", - internalType: "bytes", - }, - ], - outputs: [ - { - name: "", - type: "bytes32[]", - internalType: "bytes32[]", - }, - { - name: "", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "", - type: "bytes32", - internalType: "bytes32", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "validateHeader", - inputs: [ - { - name: "_header", - type: "bytes", - internalType: "bytes", - }, - { - name: "_signatures", - type: "tuple[]", - internalType: "struct Signature[]", - components: [ - { - name: "isEmpty", - type: "bool", - internalType: "bool", - }, - { - name: "v", - type: "uint8", - internalType: "uint8", - }, - { - name: "r", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "s", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - name: "_digest", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "_currentTime", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "_blobsHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "_flags", - type: "tuple", - internalType: "struct BlockHeaderValidationFlags", - components: [ - { - name: "ignoreDA", - type: "bool", - internalType: "bool", - }, - { - name: "ignoreSignatures", - type: "bool", - internalType: "bool", - }, - ], - }, - ], - outputs: [], - stateMutability: "view", - }, -] as const; diff --git a/tooling/sparta/src/utils/abis/testERC20Abi.ts b/tooling/sparta/src/utils/abis/testERC20Abi.ts deleted file mode 100644 index da6350c..0000000 --- a/tooling/sparta/src/utils/abis/testERC20Abi.ts +++ /dev/null @@ -1,1869 +0,0 @@ -/** - * TestERC20 ABI. - */ -export const TestERC20Abi = [ - { - type: "constructor", - inputs: [ - { - name: "_name", - type: "string", - internalType: "string", - }, - { - name: "_symbol", - type: "string", - internalType: "string", - }, - { - name: "_owner", - type: "address", - internalType: "address", - }, - ], - stateMutability: "nonpayable", - }, - { - type: "event", - name: "Approval", - inputs: [ - { - name: "owner", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "spender", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "value", - type: "uint256", - indexed: false, - internalType: "uint256", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "CoinIssuer__InsufficientMintAvailable", - inputs: [ - { - name: "available", - type: "uint256", - internalType: "uint256", - }, - { - name: "needed", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "DevNet__InvalidProposer", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "DevNet__NoPruningAllowed", - inputs: [], - }, - { - type: "error", - name: "ERC20InsufficientAllowance", - inputs: [ - { - name: "spender", - type: "address", - internalType: "address", - }, - { - name: "allowance", - type: "uint256", - internalType: "uint256", - }, - { - name: "needed", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ERC20InsufficientBalance", - inputs: [ - { - name: "sender", - type: "address", - internalType: "address", - }, - { - name: "balance", - type: "uint256", - internalType: "uint256", - }, - { - name: "needed", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ERC20InvalidApprover", - inputs: [ - { - name: "approver", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ERC20InvalidReceiver", - inputs: [ - { - name: "receiver", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ERC20InvalidSender", - inputs: [ - { - name: "sender", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ERC20InvalidSpender", - inputs: [ - { - name: "spender", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "FeeJuicePortal__AlreadyInitialized", - inputs: [], - }, - { - type: "error", - name: "FeeJuicePortal__InvalidInitialization", - inputs: [], - }, - { - type: "error", - name: "FeeJuicePortal__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "FeeMath__InvalidFeeAssetPriceModifier", - inputs: [], - }, - { - type: "error", - name: "FeeMath__InvalidProvingCostModifier", - inputs: [], - }, - { - type: "error", - name: "GovernanceProposer__CanOnlyExecuteProposalInPast", - inputs: [], - }, - { - type: "error", - name: "GovernanceProposer__FailedToPropose", - inputs: [ - { - name: "proposal", - type: "address", - internalType: "contract IPayload", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InstanceHaveNoCode", - inputs: [ - { - name: "instance", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InsufficientVotes", - inputs: [ - { - name: "votesCast", - type: "uint256", - internalType: "uint256", - }, - { - name: "votesNeeded", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__InvalidNAndMValues", - inputs: [ - { - name: "n", - type: "uint256", - internalType: "uint256", - }, - { - name: "m", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__NCannotBeLargerTHanM", - inputs: [ - { - name: "n", - type: "uint256", - internalType: "uint256", - }, - { - name: "m", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__OnlyProposerCanVote", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalAlreadyExecuted", - inputs: [ - { - name: "roundNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalCannotBeAddressZero", - inputs: [], - }, - { - type: "error", - name: "GovernanceProposer__ProposalHaveNoCode", - inputs: [ - { - name: "proposal", - type: "address", - internalType: "contract IPayload", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__ProposalTooOld", - inputs: [ - { - name: "roundNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "currentRoundNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "GovernanceProposer__VoteAlreadyCastForSlot", - inputs: [ - { - name: "slot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Governance__CallFailed", - inputs: [ - { - name: "target", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CallerNotGovernanceProposer", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "governanceProposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CallerNotSelf", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "self", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Governance__CannotCallAsset", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__DifferentialTooBig", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__DifferentialTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__InvalidMinimumVotes", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__LockAmountTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__QuorumTooBig", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__QuorumTooSmall", - inputs: [], - }, - { - type: "error", - name: "Governance__ConfigurationLib__TimeTooBig", - inputs: [ - { - name: "name", - type: "string", - internalType: "string", - }, - ], - }, - { - type: "error", - name: "Governance__ConfigurationLib__TimeTooSmall", - inputs: [ - { - name: "name", - type: "string", - internalType: "string", - }, - ], - }, - { - type: "error", - name: "Governance__InsufficientPower", - inputs: [ - { - name: "voter", - type: "address", - internalType: "address", - }, - { - name: "have", - type: "uint256", - internalType: "uint256", - }, - { - name: "required", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Governance__InvalidConfiguration", - inputs: [], - }, - { - type: "error", - name: "Governance__NoCheckpointsFound", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalAlreadyDropped", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalCannotBeDropped", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalDoesNotExists", - inputs: [ - { - name: "proposalId", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Governance__ProposalLib__MoreVoteThanExistNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__MoreYeaVoteThanExistNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroMinimum", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroVotesNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalLib__ZeroYeaVotesNeeded", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalNotActive", - inputs: [], - }, - { - type: "error", - name: "Governance__ProposalNotExecutable", - inputs: [], - }, - { - type: "error", - name: "Governance__UserLib__NotInPast", - inputs: [], - }, - { - type: "error", - name: "Governance__WithdrawalAlreadyclaimed", - inputs: [], - }, - { - type: "error", - name: "Governance__WithdrawalNotUnlockedYet", - inputs: [ - { - name: "currentTime", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "unlocksAt", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "HeaderLib__InvalidHeaderSize", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "HeaderLib__InvalidSlotNumber", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Slot", - }, - { - name: "actual", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Inbox__ActorTooLarge", - inputs: [ - { - name: "actor", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__ContentTooLarge", - inputs: [ - { - name: "content", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__MustBuildBeforeConsume", - inputs: [], - }, - { - type: "error", - name: "Inbox__SecretHashTooLarge", - inputs: [ - { - name: "secretHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Inbox__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "MerkleLib__InvalidRoot", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "leaf", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "leafIndex", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__AlreadyNullified", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - { - name: "leafIndex", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__BlockNotProven", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__IncompatibleEntryArguments", - inputs: [ - { - name: "messageHash", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "storedFee", - type: "uint64", - internalType: "uint64", - }, - { - name: "feePassed", - type: "uint64", - internalType: "uint64", - }, - { - name: "storedVersion", - type: "uint32", - internalType: "uint32", - }, - { - name: "versionPassed", - type: "uint32", - internalType: "uint32", - }, - { - name: "storedDeadline", - type: "uint32", - internalType: "uint32", - }, - { - name: "deadlinePassed", - type: "uint32", - internalType: "uint32", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidChainId", - inputs: [], - }, - { - type: "error", - name: "Outbox__InvalidPathLength", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidRecipient", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Outbox__InvalidVersion", - inputs: [ - { - name: "entry", - type: "uint256", - internalType: "uint256", - }, - { - name: "message", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__NothingToConsume", - inputs: [ - { - name: "messageHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Outbox__NothingToConsumeAtBlock", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__RootAlreadySetAtBlock", - inputs: [ - { - name: "l2BlockNumber", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Outbox__Unauthorized", - inputs: [], - }, - { - type: "error", - name: "OwnableInvalidOwner", - inputs: [ - { - name: "owner", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "OwnableUnauthorizedAccount", - inputs: [ - { - name: "account", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "event", - name: "OwnershipTransferred", - inputs: [ - { - name: "previousOwner", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "newOwner", - type: "address", - indexed: true, - internalType: "address", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "ProofCommitmentEscrow__InsufficientBalance", - inputs: [ - { - name: "balance", - type: "uint256", - internalType: "uint256", - }, - { - name: "requested", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ProofCommitmentEscrow__NotOwner", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ProofCommitmentEscrow__WithdrawRequestNotReady", - inputs: [ - { - name: "current", - type: "uint256", - internalType: "uint256", - }, - { - name: "readyAt", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "Registry__RollupAlreadyRegistered", - inputs: [ - { - name: "rollup", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Registry__RollupNotRegistered", - inputs: [ - { - name: "rollup", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "RewardDistributor__InvalidCaller", - inputs: [ - { - name: "caller", - type: "address", - internalType: "address", - }, - { - name: "canonical", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Rollup__InsufficientBondAmount", - inputs: [ - { - name: "minimum", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InsufficientFundsInEscrow", - inputs: [ - { - name: "required", - type: "uint256", - internalType: "uint256", - }, - { - name: "available", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBasisPointFee", - inputs: [ - { - name: "basisPointFee", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobHash", - inputs: [ - { - name: "blobHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobProof", - inputs: [ - { - name: "blobHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlobPublicInputsHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlockHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidBlockNumber", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidChainId", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidEpoch", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Epoch", - }, - { - name: "actual", - type: "uint256", - internalType: "Epoch", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidInHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidManaBaseFee", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidPreviousArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidPreviousBlockHash", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidProof", - inputs: [], - }, - { - type: "error", - name: "Rollup__InvalidProposedArchive", - inputs: [ - { - name: "expected", - type: "bytes32", - internalType: "bytes32", - }, - { - name: "actual", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidTimestamp", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "actual", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "Rollup__InvalidVersion", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "uint256", - }, - { - name: "actual", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__NoEpochToProve", - inputs: [], - }, - { - type: "error", - name: "Rollup__NonSequentialProving", - inputs: [], - }, - { - type: "error", - name: "Rollup__NonZeroDaFee", - inputs: [], - }, - { - type: "error", - name: "Rollup__NonZeroL2Fee", - inputs: [], - }, - { - type: "error", - name: "Rollup__NotClaimingCorrectEpoch", - inputs: [ - { - name: "expected", - type: "uint256", - internalType: "Epoch", - }, - { - name: "actual", - type: "uint256", - internalType: "Epoch", - }, - ], - }, - { - type: "error", - name: "Rollup__NotInClaimPhase", - inputs: [ - { - name: "currentSlotInEpoch", - type: "uint256", - internalType: "uint256", - }, - { - name: "claimDuration", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Rollup__NothingToPrune", - inputs: [], - }, - { - type: "error", - name: "Rollup__ProofRightAlreadyClaimed", - inputs: [], - }, - { - type: "error", - name: "Rollup__QuoteExpired", - inputs: [ - { - name: "currentSlot", - type: "uint256", - internalType: "Slot", - }, - { - name: "quoteSlot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Rollup__SlotAlreadyInChain", - inputs: [ - { - name: "lastSlot", - type: "uint256", - internalType: "Slot", - }, - { - name: "proposedSlot", - type: "uint256", - internalType: "Slot", - }, - ], - }, - { - type: "error", - name: "Rollup__TimestampInFuture", - inputs: [ - { - name: "max", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "actual", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "error", - name: "Rollup__TimestampTooOld", - inputs: [], - }, - { - type: "error", - name: "Rollup__TryingToProveNonExistingBlock", - inputs: [], - }, - { - type: "error", - name: "Rollup__UnavailableTxs", - inputs: [ - { - name: "txsHash", - type: "bytes32", - internalType: "bytes32", - }, - ], - }, - { - type: "error", - name: "SampleLib__IndexOutOfBounds", - inputs: [ - { - name: "requested", - type: "uint256", - internalType: "uint256", - }, - { - name: "bound", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "SignatureLib__CannotVerifyEmpty", - inputs: [], - }, - { - type: "error", - name: "SignatureLib__InvalidSignature", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "recovered", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__AlreadyActive", - inputs: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__AlreadyRegistered", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__CannotSlashExitedStake", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__FailedToRemove", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__InsufficientStake", - inputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "Staking__NoOneToSlash", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotExiting", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotSlasher", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NotWithdrawer", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__NothingToExit", - inputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "Staking__WithdrawalNotUnlockedYet", - inputs: [ - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - { - name: "", - type: "uint256", - internalType: "Timestamp", - }, - ], - }, - { - type: "event", - name: "Transfer", - inputs: [ - { - name: "from", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "to", - type: "address", - indexed: true, - internalType: "address", - }, - { - name: "value", - type: "uint256", - indexed: false, - internalType: "uint256", - }, - ], - anonymous: false, - }, - { - type: "error", - name: "ValidatorSelection__EpochNotSetup", - inputs: [], - }, - { - type: "error", - name: "ValidatorSelection__InsufficientAttestations", - inputs: [ - { - name: "minimumNeeded", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InsufficientAttestationsProvided", - inputs: [ - { - name: "minimumNeeded", - type: "uint256", - internalType: "uint256", - }, - { - name: "provided", - type: "uint256", - internalType: "uint256", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InvalidDeposit", - inputs: [ - { - name: "attester", - type: "address", - internalType: "address", - }, - { - name: "proposer", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "error", - name: "ValidatorSelection__InvalidProposer", - inputs: [ - { - name: "expected", - type: "address", - internalType: "address", - }, - { - name: "actual", - type: "address", - internalType: "address", - }, - ], - }, - { - type: "function", - name: "allowance", - inputs: [ - { - name: "owner", - type: "address", - internalType: "address", - }, - { - name: "spender", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "approve", - inputs: [ - { - name: "spender", - type: "address", - internalType: "address", - }, - { - name: "value", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", - }, - ], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "balanceOf", - inputs: [ - { - name: "account", - type: "address", - internalType: "address", - }, - ], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "decimals", - inputs: [], - outputs: [ - { - name: "", - type: "uint8", - internalType: "uint8", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "freeForAll", - inputs: [], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "mint", - inputs: [ - { - name: "_to", - type: "address", - internalType: "address", - }, - { - name: "_amount", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "name", - inputs: [], - outputs: [ - { - name: "", - type: "string", - internalType: "string", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "owner", - inputs: [], - outputs: [ - { - name: "", - type: "address", - internalType: "address", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "renounceOwnership", - inputs: [], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "setFreeForAll", - inputs: [ - { - name: "_freeForAll", - type: "bool", - internalType: "bool", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "symbol", - inputs: [], - outputs: [ - { - name: "", - type: "string", - internalType: "string", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "totalSupply", - inputs: [], - outputs: [ - { - name: "", - type: "uint256", - internalType: "uint256", - }, - ], - stateMutability: "view", - }, - { - type: "function", - name: "transfer", - inputs: [ - { - name: "to", - type: "address", - internalType: "address", - }, - { - name: "value", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", - }, - ], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "transferFrom", - inputs: [ - { - name: "from", - type: "address", - internalType: "address", - }, - { - name: "to", - type: "address", - internalType: "address", - }, - { - name: "value", - type: "uint256", - internalType: "uint256", - }, - ], - outputs: [ - { - name: "", - type: "bool", - internalType: "bool", - }, - ], - stateMutability: "nonpayable", - }, - { - type: "function", - name: "transferOwnership", - inputs: [ - { - name: "newOwner", - type: "address", - internalType: "address", - }, - ], - outputs: [], - stateMutability: "nonpayable", - }, -] as const; diff --git a/tooling/sparta/src/utils/inputValidator.ts b/tooling/sparta/src/utils/inputValidator.ts deleted file mode 100644 index c9d8ac3..0000000 --- a/tooling/sparta/src/utils/inputValidator.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ChatInputCommandInteraction, MessageFlags } from "discord.js"; - -export const validateAddress = (interaction: ChatInputCommandInteraction) => { - const address = interaction.options.getString("address"); - if (!address) { - return interaction.reply({ - content: "Please provide an address.", - flags: MessageFlags.Ephemeral, - }); - } - if (!address.match(/^0x[a-fA-F0-9]{40}$/)) { - return interaction.reply({ - content: "Please provide a valid Ethereum address.", - flags: MessageFlags.Ephemeral, - }); - } - return address; -}; diff --git a/tooling/sparta/src/utils/logger.ts b/tooling/sparta/src/utils/logger.ts deleted file mode 100644 index b4ec3d6..0000000 --- a/tooling/sparta/src/utils/logger.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { pino } from "pino"; - -// Log level hierarchy: trace < debug < info < warn < error < fatal -type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal"; - -// Configuration for the logger -interface LoggerConfig { - level: LogLevel; - prettyPrint: boolean; -} - -// Get log level from environment or default to 'info' -const getLoggerConfig = (): LoggerConfig => { - return { - level: (process.env.LOG_LEVEL as LogLevel) || "info", - prettyPrint: process.env.LOG_PRETTY_PRINT !== "false", // Default to true - }; -}; - -// Create the logger instance -const createLogger = () => { - const config = getLoggerConfig(); - - const transport = config.prettyPrint - ? { - target: "pino-pretty", - options: { - colorize: true, - translateTime: "SYS:standard", - ignore: "pid,hostname", - }, - } - : undefined; - - return pino({ - level: config.level, - transport, - timestamp: pino.stdTimeFunctions.isoTime, - }); -}; - -// Export a singleton logger instance -export const logger = createLogger(); - -// Log HTTP requests -export const requestLogger = (req: any, res: any, next?: () => void) => { - logger.debug( - { - method: req.method, - url: req.url, - query: req.query, - params: req.params, - body: req.body, - headers: req.headers, - }, - "Incoming request" - ); - - if (next) next(); -}; - -// Re-export log methods for convenience -export const trace = (obj: object | string, msg?: string) => { - if (typeof obj === "string") { - logger.trace(obj); - } else { - logger.trace(obj, msg); - } -}; - -export const debug = (obj: object | string, msg?: string) => { - if (typeof obj === "string") { - logger.debug(obj); - } else { - logger.debug(obj, msg); - } -}; - -export const info = (obj: object | string, msg?: string) => { - if (typeof obj === "string") { - logger.info(obj); - } else { - logger.info(obj, msg); - } -}; - -export const warn = (obj: object | string, msg?: string) => { - if (typeof obj === "string") { - logger.warn(obj); - } else { - logger.warn(obj, msg); - } -}; - -export const error = (obj: object | string, msg?: string) => { - if (typeof obj === "string") { - logger.error(obj); - } else { - logger.error(obj, msg); - } -}; - -export const fatal = (obj: object | string, msg?: string) => { - if (typeof obj === "string") { - logger.fatal(obj); - } else { - logger.fatal(obj, msg); - } -}; diff --git a/tooling/sparta/src/utils/pagination.ts b/tooling/sparta/src/utils/pagination.ts deleted file mode 100644 index d7ccd5b..0000000 --- a/tooling/sparta/src/utils/pagination.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { MessageFlags } from "discord.js"; - -import { ChatInputCommandInteraction } from "discord.js"; - -export const paginate = async ( - array: string[], - total: number, - perMessage: number, - interaction: ChatInputCommandInteraction, - message: string -) => { - const numMessages = Math.ceil(array.length / perMessage); - if (!numMessages) { - await interaction.followUp({ - content: "No validators present", - flags: MessageFlags.Ephemeral, - }); - } - - for (let i = 0; i < numMessages; i++) { - const start = i * perMessage; - const end = Math.min(start + perMessage, array.length); - const validatorSlice = array.slice(start, end) as string[]; - - if (i === 0) { - await interaction.editReply({ - content: `${message} total: ${total}.\n${message} (excl. Aztec Labs) (${ - start + 1 - }-${end} of ${array.length}):\n${validatorSlice.join("\n")}`, - }); - } else { - await interaction.followUp({ - content: `${message} total: ${total}.\n${message} (excl. Aztec Labs) (${ - start + 1 - }-${end} of ${array.length}):\n${validatorSlice.join("\n")}`, - flags: MessageFlags.Ephemeral, - }); - } - } -}; diff --git a/tooling/sparta/terraform/README.md b/tooling/sparta/terraform/README.md index 43ccbee..4a51d61 100644 --- a/tooling/sparta/terraform/README.md +++ b/tooling/sparta/terraform/README.md @@ -28,22 +28,26 @@ Before deploying, ensure you have: The deployment is configured using the following variables: -| Variable | Description | Default | -| --------------------------- | -------------------------------------------------------------------------- | ------------ | -| `aws_region` | AWS region to deploy to | `us-west-2` | -| `environment` | Environment name (e.g., production, staging) | `production` | -| `bot_token` | Discord bot token | Required | -| `bot_client_id` | Discord bot client ID | Required | -| `guild_id` | Discord server/guild ID | Required | -| `ethereum_host` | Ethereum RPC endpoint | Required | -| `ethereum_registry_address` | Address of validator registry contract | Required | -| `minter_private_key` | Private key for minting/transactions | Required | -| `withdrawer_address` | Address for withdrawing funds | Required | -| `ethereum_chain_id` | Ethereum chain ID | Required | -| `google_api_key` | Google API key for Sheets access | Required | -| `spreadsheet_id` | Google Spreadsheet ID to monitor | Required | -| `log_level` | The log level for the application (trace, debug, info, warn, error, fatal) | `string` | `"info"` | -| `log_pretty_print` | Enable or disable colorful, pretty-printed logs | `bool` | `true` | +| Name | Description | Required? | +| ------------------------------- | ----------------------------------------------- | --------- | +| `aws_region` | AWS region | Required | +| `environment` | Deployment environment (development/production) | Required | +| `bot_token` | Discord bot token | Required | +| `bot_client_id` | Discord client ID | Required | +| `guild_id` | Discord server ID | Required | +| `ethereum_host` | Ethereum node URL | Required | +| `staking_asset_handler_address` | Contract address | Required | +| `l1_chain_id` | Ethereum chain ID | Required | +| `log_level` | Log level (debug, info, warn, error) | Optional | +| `log_pretty_print` | Enable pretty printing for logs | Optional | +| `availability_zones` | List of Availability Zones | Optional | +| `public_subnet_cidrs` | List of CIDR blocks for public subnets | Optional | +| `private_subnet_cidrs` | List of CIDR blocks for private subnets | Optional | +| `api_port` | Port for the API container | Optional | +| `api_desired_count` | Desired number of API tasks | Optional | +| `api_cpu` | CPU units for API task | Optional | +| `api_memory` | Memory for API task | Optional | +| `vpc_cidr` | CIDR block for the VPC | Optional | ## Deployment Steps diff --git a/tooling/sparta/terraform/main.tf b/tooling/sparta/terraform/main.tf index fa6f801..0bfed48 100644 --- a/tooling/sparta/terraform/main.tf +++ b/tooling/sparta/terraform/main.tf @@ -2,335 +2,836 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 5.0" # Using AWS Provider version 5.x for latest features + version = "~> 5.0" } } + required_version = ">= 1.0" # Specify minimum Terraform version backend "s3" { - bucket = "sparta-tf-state" - key = "sparta/terraform" + bucket = "sparta-terraf-state" # Ensure this bucket exists region = "eu-west-2" + key = "production/terraform.tfstate" } } + provider "aws" { - profile = "default" - region = var.aws_region + region = var.aws_region + # Assuming credentials are configured via environment variables, IAM instance profile, or AWS config/credentials file +} + +locals { + resource_prefix = "sparta-${var.environment}" + common_tags = { + Environment = var.environment + Project = "sparta" + ManagedBy = "Terraform" + } +} + +# ============================================================================= +# Networking +# ============================================================================= + +# Create a VPC +resource "aws_vpc" "sparta_vpc" { + cidr_block = var.vpc_cidr + enable_dns_hostnames = true + enable_dns_support = true + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-vpc" + }) +} + +# Create public subnets across multiple AZs +resource "aws_subnet" "sparta_public_subnets" { + count = length(var.availability_zones) + vpc_id = aws_vpc.sparta_vpc.id + cidr_block = var.public_subnet_cidrs[count.index] + availability_zone = var.availability_zones[count.index] + map_public_ip_on_launch = true # Needed for NAT Gateway and potential bastion hosts + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-public-subnet-${var.availability_zones[count.index]}" + Tier = "public" + }) +} + +# Create private subnets across multiple AZs +resource "aws_subnet" "sparta_private_subnets" { + count = length(var.availability_zones) + vpc_id = aws_vpc.sparta_vpc.id + cidr_block = var.private_subnet_cidrs[count.index] + availability_zone = var.availability_zones[count.index] + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-private-subnet-${var.availability_zones[count.index]}" + Tier = "private" + }) +} + +# Create an Internet Gateway (IGW) +resource "aws_internet_gateway" "sparta_igw" { + vpc_id = aws_vpc.sparta_vpc.id + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-igw" + }) +} + +# Allocate an Elastic IP for the NAT Gateway +resource "aws_eip" "nat_eip" { + domain = "vpc" # Changed from `vpc = true` for newer provider versions + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-nat-eip" + }) +} + +# Create a NAT Gateway in the first public subnet +resource "aws_nat_gateway" "sparta_nat_gw" { + allocation_id = aws_eip.nat_eip.id + subnet_id = aws_subnet.sparta_public_subnets[0].id # Place NAT GW in the first public subnet + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-nat-gw" + }) + + depends_on = [aws_internet_gateway.sparta_igw] } +# Create a public route table +resource "aws_route_table" "sparta_public_rt" { + vpc_id = aws_vpc.sparta_vpc.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.sparta_igw.id + } + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-public-rt" + }) +} + +# Associate public subnets with the public route table +resource "aws_route_table_association" "sparta_public_rta" { + count = length(var.availability_zones) + subnet_id = aws_subnet.sparta_public_subnets[count.index].id + route_table_id = aws_route_table.sparta_public_rt.id +} + +# Create a private route table +resource "aws_route_table" "sparta_private_rt" { + vpc_id = aws_vpc.sparta_vpc.id + + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.sparta_nat_gw.id + } + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-private-rt" + }) +} + +# Associate private subnets with the private route table +resource "aws_route_table_association" "sparta_private_rta" { + count = length(var.availability_zones) + subnet_id = aws_subnet.sparta_private_subnets[count.index].id + route_table_id = aws_route_table.sparta_private_rt.id +} + + +# ============================================================================= +# Security Groups +# ============================================================================= + +# Security Group for the Application Load Balancer (ALB) +resource "aws_security_group" "alb_sg" { + name = "${local.resource_prefix}-alb-sg" + description = "Allow HTTP/HTTPS inbound traffic to ALB" + vpc_id = aws_vpc.sparta_vpc.id + + ingress { + description = "Allow HTTP from anywhere" + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + description = "Allow HTTPS from anywhere" + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + description = "Allow all outbound traffic" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-alb-sg" + }) +} + +# Security Group for the API ECS Service (Fargate) +resource "aws_security_group" "api_service_sg" { + name = "${local.resource_prefix}-api-service-sg" + description = "Allow inbound traffic from ALB to API service" + vpc_id = aws_vpc.sparta_vpc.id + + ingress { + description = "Allow traffic from ALB" + from_port = var.api_port # Port the container listens on (e.g., 3000) + to_port = var.api_port + protocol = "tcp" + security_groups = [aws_security_group.alb_sg.id] # Only allow traffic from the ALB SG + } + + egress { + description = "Allow all outbound traffic (for NAT GW)" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-api-service-sg" + }) +} + +# ============================================================================= +# IAM Roles & Policies +# ============================================================================= + +# IAM Role for ECS Task Execution (used by ECS Agent to pull images, write logs) resource "aws_iam_role" "ecs_task_execution_role" { - name = "ecs_task_execution_role-${var.environment}" + name = "${local.resource_prefix}-ecs-task-execution-role" assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [{ - Action = "sts:AssumeRole", - Principal = { - Service = "ecs-tasks.amazonaws.com", - }, - Effect = "Allow", - Sid = "", + Action = "sts:AssumeRole", + Effect = "Allow", + Principal = { Service = "ecs-tasks.amazonaws.com" }, }] }) + tags = local.common_tags } resource "aws_iam_role_policy_attachment" "ecs_task_execution_policy" { role = aws_iam_role.ecs_task_execution_role.name + # Standard AWS managed policy for basic ECS task execution needs policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" } -# Add CloudWatch logs permissions -resource "aws_iam_role_policy" "cloudwatch_logs_policy" { - name = "cloudwatch-logs-policy-${var.environment}" - role = aws_iam_role.ecs_task_execution_role.id +# IAM Role for API ECS Task (used by the application container) +resource "aws_iam_role" "api_task_role" { + name = "${local.resource_prefix}-api-task-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [{ + Action = "sts:AssumeRole", + Effect = "Allow", + Principal = { Service = "ecs-tasks.amazonaws.com" }, + }] + }) + tags = local.common_tags +} + +# IAM Policy allowing API Task Role to access DynamoDB +resource "aws_iam_policy" "dynamodb_access_policy" { + name = "${local.resource_prefix}-dynamodb-access-policy" + description = "Policy for accessing DynamoDB node operators table" policy = jsonencode({ - Version = "2012-10-17" + Version = "2012-10-17", Statement = [ { - Effect = "Allow" + Effect = "Allow", Action = [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents", - "logs:DescribeLogStreams" - ] + "dynamodb:GetItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchWriteItem" + ], + # Grant access to both tables and their indexes Resource = [ - "arn:aws:logs:${var.aws_region}:*:log-group:/fargate/service/${var.environment}/sparta-discord-bot:*", - "arn:aws:logs:${var.aws_region}:*:log-group:/fargate/service/${var.environment}/sparta-discord-bot:*:*" + # Node Operators table + aws_dynamodb_table.sparta_node_operators.arn, + "${aws_dynamodb_table.sparta_node_operators.arn}/index/*", + # Validators table + aws_dynamodb_table.sparta_validators.arn, + "${aws_dynamodb_table.sparta_validators.arn}/index/*" ] } + # Add statements here if the API needs access to other AWS resources ] }) + tags = local.common_tags } -# Add ECR pull permissions -resource "aws_iam_role_policy" "ecr_pull_policy" { - name = "ecr_pull_policy-${var.environment}" - role = aws_iam_role.ecs_task_execution_role.id +# Attach DynamoDB policy to the API Task Role +resource "aws_iam_role_policy_attachment" "api_dynamodb_policy_attachment" { + role = aws_iam_role.api_task_role.name + policy_arn = aws_iam_policy.dynamodb_access_policy.arn +} - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Action = [ - "ecr:GetAuthorizationToken", - "ecr:BatchCheckLayerAvailability", - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage" - ] - Resource = "*" - } - ] +# ============================================================================= +# Database (DynamoDB) +# ============================================================================= + +# Add the 'node operators' table definition +resource "aws_dynamodb_table" "sparta_node_operators" { + name = "${local.resource_prefix}-node-operators" # Use prefix for consistency + billing_mode = "PAY_PER_REQUEST" # Use pay-per-request + + # Define attributes used in keys/indexes + attribute { + name = "discordId" + type = "S" + } + attribute { + name = "walletAddress" + type = "S" + } + + # Define the primary hash key + hash_key = "discordId" + + # Define Global Secondary Indexes + global_secondary_index { + name = "WalletAddressIndex" + hash_key = "walletAddress" + projection_type = "ALL" # Project all attributes + # PAY_PER_REQUEST billing mode applies to GSIs as well + } + + # Enable Point-in-Time Recovery for backups (Recommended) + point_in_time_recovery { + enabled = true + } + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-node-operators-table" + }) +} + +# Add the 'validators' table definition +resource "aws_dynamodb_table" "sparta_validators" { + name = "${local.resource_prefix}-validators" # Use prefix for consistency + billing_mode = "PAY_PER_REQUEST" # Use pay-per-request + + # Define attributes used in keys/indexes + attribute { + name = "validatorAddress" + type = "S" + } + attribute { + name = "nodeOperatorId" + type = "S" + } + + # Define the primary hash key + hash_key = "validatorAddress" + + # Define Global Secondary Indexes + global_secondary_index { + name = "NodeOperatorIndex" + hash_key = "nodeOperatorId" + projection_type = "ALL" # Project all attributes + # PAY_PER_REQUEST billing mode applies to GSIs as well + } + + # Enable Point-in-Time Recovery for backups (Recommended) + point_in_time_recovery { + enabled = true + } + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-validators-table" }) } -# Create ECR Repository -resource "aws_ecr_repository" "sparta_bot" { - name = "sparta-bot-${var.environment}" - image_tag_mutability = "MUTABLE" - force_delete = true + + + + +# ============================================================================= +# Backend Service (API - Express App) +# ============================================================================= + +# ECR Repository for the API Docker image +resource "aws_ecr_repository" "sparta_api" { + name = "${local.resource_prefix}-api" + image_tag_mutability = "MUTABLE" # Or IMMUTABLE for better versioning control + force_delete = true # Use with caution in production image_scanning_configuration { scan_on_push = true } + + tags = merge(local.common_tags, { + Name = "${local.resource_prefix}-api-ecr" + }) } -# Build and push Docker image -resource "null_resource" "docker_build" { - triggers = { - always_run = "${timestamp()}" # This ensures it runs on every apply - } +# --- Use external data source to build, push, and get image digest --- +data "external" "api_docker_build_push_digest" { + program = ["bash", "${path.module}/../scripts/build_push_get_digest.sh", + var.aws_region, + aws_ecr_repository.sparta_api.repository_url, + "${path.module}/../", + "http://${aws_lb.sparta_alb.dns_name}" + ] # Pass region, repo url, Dockerfile dir, frontend URL, and VITE variables - provisioner "local-exec" { - command = <