From 6b8b68117a041be21485396807881cec9d75efac Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 29 Dec 2023 10:35:13 +0300 Subject: [PATCH 01/50] indexer draft --- .gitignore | 1 + indexer/.dockerignore | 4 + indexer/.env | 16 + indexer/.env.example | 16 + indexer/.eslintrc.js | 25 + indexer/.github/ISSUE_TEMPLATE/bug_report.md | 45 + indexer/.gitignore | 10 + indexer/.npmrc | 1 + indexer/.prettierrc | 4 + indexer/README.md | 224 + indexer/assets/README.MD | 3 + indexer/assets/nft.meta.txt | 1 + indexer/assets/nft_marketplace.meta.txt | 1 + indexer/commands.json | 84 + indexer/db/migrations/1703490897133-Data.js | 45 + indexer/docker-compose.yml | 15 + indexer/package-lock.json | 10714 ++++++++++++++++ indexer/package.json | 42 + indexer/renovate.json | 29 + indexer/schema.graphql | 68 + indexer/scripts/docker-run.sh | 5 + indexer/scripts/sub-client.js | 42 + indexer/squid.yaml | 18 + indexer/src/config.ts | 4 + indexer/src/main.ts | 33 + .../src/model/generated/collection.model.ts | 75 + .../model/generated/collectionType.model.ts | 34 + indexer/src/model/generated/index.ts | 6 + .../src/model/generated/marketplace.model.ts | 23 + indexer/src/model/generated/marshal.ts | 167 + indexer/src/model/generated/nft.model.ts | 55 + indexer/src/model/generated/sale.model.ts | 41 + indexer/src/model/generated/transfer.model.ts | 37 + indexer/src/model/index.ts | 1 + indexer/src/processing/entities.storage.ts | 119 + indexer/src/processing/events.processing.ts | 135 + .../marketplace/auction-canceled.handler.ts | 29 + .../marketplace/auction-created.handler.ts | 45 + .../marketplace/collection-created.handler.ts | 35 + .../marketplace/collection-deleted.handler.ts | 22 + .../new-collection-added.handler.ts | 31 + .../marketplace/nft-marketplace.handler.ts | 11 + .../marketplace/nft-sold.handler.ts | 57 + .../src/processing/nft/initialized.handler.ts | 55 + .../src/processing/nft/nft-minted.handler.ts | 35 + indexer/src/processing/nft/nft.handler.ts | 12 + indexer/src/processor.ts | 45 + indexer/src/types/marketplace.events.ts | 316 + indexer/src/types/nft.events.ts | 299 + indexer/tsconfig.json | 19 + indexer/typegen.json | 14 + 51 files changed, 13168 insertions(+) create mode 100644 indexer/.dockerignore create mode 100644 indexer/.env create mode 100644 indexer/.env.example create mode 100644 indexer/.eslintrc.js create mode 100644 indexer/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 indexer/.gitignore create mode 100644 indexer/.npmrc create mode 100644 indexer/.prettierrc create mode 100644 indexer/README.md create mode 100644 indexer/assets/README.MD create mode 100644 indexer/assets/nft.meta.txt create mode 100644 indexer/assets/nft_marketplace.meta.txt create mode 100644 indexer/commands.json create mode 100644 indexer/db/migrations/1703490897133-Data.js create mode 100644 indexer/docker-compose.yml create mode 100644 indexer/package-lock.json create mode 100644 indexer/package.json create mode 100644 indexer/renovate.json create mode 100644 indexer/schema.graphql create mode 100644 indexer/scripts/docker-run.sh create mode 100644 indexer/scripts/sub-client.js create mode 100644 indexer/squid.yaml create mode 100644 indexer/src/config.ts create mode 100644 indexer/src/main.ts create mode 100644 indexer/src/model/generated/collection.model.ts create mode 100644 indexer/src/model/generated/collectionType.model.ts create mode 100644 indexer/src/model/generated/index.ts create mode 100644 indexer/src/model/generated/marketplace.model.ts create mode 100644 indexer/src/model/generated/marshal.ts create mode 100644 indexer/src/model/generated/nft.model.ts create mode 100644 indexer/src/model/generated/sale.model.ts create mode 100644 indexer/src/model/generated/transfer.model.ts create mode 100644 indexer/src/model/index.ts create mode 100644 indexer/src/processing/entities.storage.ts create mode 100644 indexer/src/processing/events.processing.ts create mode 100644 indexer/src/processing/marketplace/auction-canceled.handler.ts create mode 100644 indexer/src/processing/marketplace/auction-created.handler.ts create mode 100644 indexer/src/processing/marketplace/collection-created.handler.ts create mode 100644 indexer/src/processing/marketplace/collection-deleted.handler.ts create mode 100644 indexer/src/processing/marketplace/new-collection-added.handler.ts create mode 100644 indexer/src/processing/marketplace/nft-marketplace.handler.ts create mode 100644 indexer/src/processing/marketplace/nft-sold.handler.ts create mode 100644 indexer/src/processing/nft/initialized.handler.ts create mode 100644 indexer/src/processing/nft/nft-minted.handler.ts create mode 100644 indexer/src/processing/nft/nft.handler.ts create mode 100644 indexer/src/processor.ts create mode 100644 indexer/src/types/marketplace.events.ts create mode 100644 indexer/src/types/nft.events.ts create mode 100644 indexer/tsconfig.json create mode 100644 indexer/typegen.json diff --git a/.gitignore b/.gitignore index 1f03125..fd383c3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /Cargo.lock .binpath .DS_Store +.idea diff --git a/indexer/.dockerignore b/indexer/.dockerignore new file mode 100644 index 0000000..27c983b --- /dev/null +++ b/indexer/.dockerignore @@ -0,0 +1,4 @@ +/.git +/node_modules +/lib +/*Versions.jsonl diff --git a/indexer/.env b/indexer/.env new file mode 100644 index 0000000..119eb7f --- /dev/null +++ b/indexer/.env @@ -0,0 +1,16 @@ +DB_NAME=squid +DB_HOST=localhost +DB_PORT=5432 +GQL_PORT=4350 + +# JSON-RPC node endpoints (wss or https) +# Use private endpoints in production! +# Set urls via secrets if deploying to Cloud: https://docs.subsquid.io/deploy-squid/env-variables/ +# OR use the RPC proxy service: https://docs.subsquid.io/deploy-squid/rpc-proxy +RPC_ENDPOINT=wss://testnet-archive.vara.network +MARKETPLACE_PROGRAM=0x9d1f3a81c636d59decc2c4336bca2480aa4fea7cecd742e5792799c0637baad9 +# NFT_PROGRAM=0x9d1f3a81c636d59decc2c4336bca2480aa4fea7cecd742e5792799c0637baad9 + +# Uncommenting this line enables the debug mode +# More info at https://docs.subsquid.io/basics/logging/ +# SQD_DEBUG=* diff --git a/indexer/.env.example b/indexer/.env.example new file mode 100644 index 0000000..119eb7f --- /dev/null +++ b/indexer/.env.example @@ -0,0 +1,16 @@ +DB_NAME=squid +DB_HOST=localhost +DB_PORT=5432 +GQL_PORT=4350 + +# JSON-RPC node endpoints (wss or https) +# Use private endpoints in production! +# Set urls via secrets if deploying to Cloud: https://docs.subsquid.io/deploy-squid/env-variables/ +# OR use the RPC proxy service: https://docs.subsquid.io/deploy-squid/rpc-proxy +RPC_ENDPOINT=wss://testnet-archive.vara.network +MARKETPLACE_PROGRAM=0x9d1f3a81c636d59decc2c4336bca2480aa4fea7cecd742e5792799c0637baad9 +# NFT_PROGRAM=0x9d1f3a81c636d59decc2c4336bca2480aa4fea7cecd742e5792799c0637baad9 + +# Uncommenting this line enables the debug mode +# More info at https://docs.subsquid.io/basics/logging/ +# SQD_DEBUG=* diff --git a/indexer/.eslintrc.js b/indexer/.eslintrc.js new file mode 100644 index 0000000..8f5aedb --- /dev/null +++ b/indexer/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir : __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/indexer/.github/ISSUE_TEMPLATE/bug_report.md b/indexer/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..bf3db9c --- /dev/null +++ b/indexer/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,45 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Environment (please complete the following information):** + - specify the version of the core packages (@subsquid/cli, @subsquid/substrate-processor, ...) + - node.js version + - npm version + - OS version + - Reproducible example or a repo link + +**Applicable to decoding issues:** + - chain name + - typesBundle (if it's not built-in) +optional: + - block + - extrinsic + - call + - event + - spec version + - endpoint + +**Additional context** +Add any other context about the problem here. diff --git a/indexer/.gitignore b/indexer/.gitignore new file mode 100644 index 0000000..79667bb --- /dev/null +++ b/indexer/.gitignore @@ -0,0 +1,10 @@ +/node_modules +/lib +/builds + +/**Versions.json +/**Versions.jsonl + +# IDE files +/.idea +.env diff --git a/indexer/.npmrc b/indexer/.npmrc new file mode 100644 index 0000000..4fd0219 --- /dev/null +++ b/indexer/.npmrc @@ -0,0 +1 @@ +engine-strict=true \ No newline at end of file diff --git a/indexer/.prettierrc b/indexer/.prettierrc new file mode 100644 index 0000000..dcb7279 --- /dev/null +++ b/indexer/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/indexer/README.md b/indexer/README.md new file mode 100644 index 0000000..ceb677d --- /dev/null +++ b/indexer/README.md @@ -0,0 +1,224 @@ +# Squid template project + +A starter [Squid](https://subsquid.io) project to demonstrate its structure and conventions. +It accumulates [kusama](https://kusama.network) account transfers and serves them via GraphQL API. + +## Summary + +- [Quickstart](#quickly-running-the-sample) +- [Public archives for Parachains](#public-archives-for-parachains) +- [Self-hosted archive](#self-hosted-archive) +- [Development flow](#dev-flow) + - [Database Schema](#1-define-database-schema) + - [Entity classes](#2-generate-typeorm-classes) + - [DB migrations](#3-generate-database-migration) + - [Typegen for Events, Extrinsics and Storage Calls](#4-generate-typescript-definitions-for-substrate-events-calls-and-storage) +- [Deploy the Squid](#deploy-the-squid) +- [Conventions](#project-conventions) +- [Type Bundles](#types-bundle) + +## Prerequisites + +* node 16.x +* docker +* npm -- note that `yarn` package manager is not supported + +## Quickly running the sample + +Example commands below use [sqd](https://docs.subsquid.io/squid-cli/). +Please [install](https://docs.subsquid.io/squid-cli/installation/) it before proceeding. + +```bash +# 1. Install dependencies +npm ci + +# 2. Start target Postgres database and detach +sqd up + +# 3. Build the project +sqd build + +# 4. Start both the squid processor and the GraphQL server +sqd run . +``` +A GraphiQL playground will be available at [localhost:4350/graphql](http://localhost:4350/graphql). + +## Public archives for Parachains + +Subsquid provides archive data sources [for most parachains](https://docs.subsquid.io/substrate-indexing/supported-networks/). Use `lookupArchive(, )` from `@subsquid/archive-registry` to look up the archive endpoint by the network name, e.g. + +```typescript +processor.setDataSource({ + archive: lookupArchive("kusama", { release: "ArrowSquid" }) + //... +}); +``` + +To make sure you're indexing the right chain one can additionally filter by the genesis block hash: + +```typescript +processor.setDataSource({ + archive: lookupArchive("kusama", { + release: "ArrowSquid", + genesis: "0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe" + }), + //... +}); +``` + +If the chain is not yet supported, you can still index it using [RPC ingestion](https://docs.subsquid.io/substrate-indexing/setup/general/#set-data-source). If you take this route, use [metadata exporer](https://github.com/subsquid/squid-sdk/tree/master/substrate/substrate-metadata-explorer) with [Substrate typegen](https://docs.subsquid.io/substrate-indexing/squid-substrate-typegen/) for help with decoding. + +You can also fill out this [form](https://forms.gle/Vhr3exPs4HrF4Zt36) to submit a request for an Archive/Subsquid Network dataset. + +## Self-hosted archive + +Self-hosted Archives are deprecated by the ArrowSquid release. Keep an eye on updates on [Subsquid Network](https://docs.subsquid.io/subsquid-network/) and use it instead once it is released. + +## Dev flow + +### 1. Define database schema + +Start development by defining the schema of the target database via `schema.graphql`. +Schema definition consists of regular graphql type declarations annotated with custom directives. +Full description of `schema.graphql` dialect is available [here](https://docs.subsquid.io/store/postgres/schema-file/). + +### 2. Generate TypeORM classes + +Mapping developers use [TypeORM](https://typeorm.io) entities +to interact with the target database during data processing. All necessary entity classes are +[generated](https://docs.subsquid.io/store/postgres/schema-file/intro/) by the squid framework from `schema.graphql`. This is done by running `npx squid-typeorm-codegen` +or (equivalently) `sqd codegen` command. + +### 3. Generate database migration + +All database changes are applied through migration files located at `db/migrations`. +`squid-typeorm-migration(1)` tool provides several commands to drive the process. +It is all [TypeORM](https://typeorm.io/#/migrations) under the hood. + +```bash +# Connect to database, analyze its state and generate migration to match the target schema. +# The target schema is derived from entity classes generated earlier. +# Don't forget to compile your entity classes beforehand! +npx squid-typeorm-migration generate + +# Create template file for custom database changes +npx squid-typeorm-migration create + +# Apply database migrations from `db/migrations` +npx squid-typeorm-migration apply + +# Revert the last performed migration +npx squid-typeorm-migration revert +``` +Available `sqd` shortcuts: +```bash +# Build the project, remove any old migrations, then run `npx squid-typeorm-migration generate` +sqd migration:generate + +# Run npx squid-typeorm-migration apply +sqd migration:apply +``` + +### 4. Generate TypeScript definitions for substrate events, calls and storage + +This is an optional part, but it is very advisable. + +Event, call and runtime storage data come to mapping handlers as raw untyped json. +While it is possible to work with raw untyped json data, +it's extremely error-prone and the json structure may change over time due to runtime upgrades. + +Squid framework provides a tool for generating type-safe wrappers around events, calls and runtime storage items for +each historical change in the spec version. See the [Substrate typegen](https://docs.subsquid.io/substrate-indexing/squid-substrate-typegen/) documentation page. + +## Deploy the Squid + +After a local run, obtain a deployment key by signing into [Subsquid Cloud](https://app.subsquid.io) and run + +```sh +npx sqd auth -k YOUR_DEPLOYMENT_KEY +``` + +Next, inspect the Squid CLI help to deploy and manage your squid: + +```sh +npx sqd squid --help +``` + +For more information, consult the [Deployment Guide](https://docs.subsquid.io/deploy-squid/). + +## Project conventions + +Squid tools assume a certain project layout. + +* All compiled js files must reside in `lib` and all TypeScript sources in `src`. +The layout of `lib` must reflect `src`. +* All TypeORM classes must be exported by `src/model/index.ts` (`lib/model` module). +* Database schema must be defined in `schema.graphql`. +* Database migrations must reside in `db/migrations` and must be plain js files. +* `squid-*(1)` executables consult `.env` file for a number of environment variables. + +See the [full desription](https://docs.subsquid.io/basics/squid-structure/) in the documentation. + +## Types bundle + +Substrate chains that have blocks with metadata versions below 14 don't provide enough +information to decode their data. For those chains, external [type](https://polkadot.js.org/docs/api/start/types.extend) [definitions](https://polkadot.js.org/docs/api/start/types.extend) are required. + +Subsquid tools include definitions for many chains, however sometimes external +definitions are still required. + +You can pass them as a special json file (types bundle) of the following structure: + +```json5 +{ + "types": { + "AccountId": "[u8; 32]" + }, + "typesAlias": { + "assets": { + "Balance": "u64" + } + }, + "versions": [ + { + "minmax": [0, 1000], // spec version range with inclusive boundaries + "types": { + "AccountId": "[u8; 16]" + }, + "typesAlias": { + "assets": { + "Balance": "u32" + } + } + } + ] +} +``` + +* `.types` - scale type definitions similar to [polkadot.js types](https://polkadot.js.org/docs/api/start/types.extend#extension) +* `.typesAlias` - similar to [polkadot.js type aliases](https://polkadot.js.org/docs/api/start/types.extend#type-clashes) +* `.versions` - per-block range overrides/patches for above fields. + +All fields in the type bundle are optional and applied on top of a fixed set of well-known frame types. + +Note, that although the structure of subsquid types bundle is very similar to the one from polkadot.js, +those two are not fully compatible. + +## Differences from polkadot.js + +Polkadot.js provides lots of [specialized classes](https://polkadot.js.org/docs/api/start/types.basics) for various types of data. +Even primitives like `u32` are exposed through special classes. +In contrast, the squid framework works only with plain js primitives and objects. +For instance, account data is passed to the handler context as a plain byte array. To convert it into a standard human-readable format one should explicitly use a utility lib `@subsquid/ss58`: + +```typescript + // ... + from: ss58.codec('kusama').encode(rec.from), + to: ss58.codec('kusama').encode(rec.to), +``` + +## Graphql server extensions + +It is possible to extend `squid-graphql-server(1)` with custom +[type-graphql](https://typegraphql.com) resolvers and to add request validation. +For more details, consult [docs](https://docs.subsquid.io/graphql-api/). diff --git a/indexer/assets/README.MD b/indexer/assets/README.MD new file mode 100644 index 0000000..23a55ab --- /dev/null +++ b/indexer/assets/README.MD @@ -0,0 +1,3 @@ +# Assets + +`assets` is the designated folder for any additional files to be used by the squid, for example a static data file. The folder is added by default to `Dockerfile` and is kept when the squid is deployed to the Aquairum. \ No newline at end of file diff --git a/indexer/assets/nft.meta.txt b/indexer/assets/nft.meta.txt new file mode 100644 index 0000000..6445168 --- /dev/null +++ b/indexer/assets/nft.meta.txt @@ -0,0 +1 @@ +0002000100000000000117000000011800000000000000011e000000011f000000f52ca00008186e66745f696f1c4e6674496e697400000c0140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000118636f6e666967100118436f6e666967000124696d675f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e00000410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004000801205b75383b2033325d000008000003200000000c000c00000503001008186e66745f696f18436f6e66696700002c01106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e6700013c636f6c6c656374696f6e5f7461677318012c5665633c537472696e673e000144636f6c6c656374696f6e5f62616e6e6572140118537472696e6700013c636f6c6c656374696f6e5f6c6f676f140118537472696e6700013c757365725f6d696e745f6c696d69741c012c4f7074696f6e3c7533323e0001406164646974696f6e616c5f6c696e6b7324015c4f7074696f6e3c4164646974696f6e616c4c696e6b733e00011c726f79616c747930010c7531360001407061796d656e745f666f725f6d696e74340110753132380001307472616e7366657261626c6538012c4f7074696f6e3c7536343e00012073656c6c61626c6538012c4f7074696f6e3c7536343e00001400000502001800000214001c04184f7074696f6e04045401200108104e6f6e6500000010536f6d6504002000000100002000000505002404184f7074696f6e04045401280108104e6f6e6500000010536f6d6504002800000100002808186e66745f696f3c4164646974696f6e616c4c696e6b73000014013065787465726e616c5f75726c2c01384f7074696f6e3c537472696e673e00012074656c656772616d2c01384f7074696f6e3c537472696e673e00011078636f6d2c01384f7074696f6e3c537472696e673e0001186d656469756d2c01384f7074696f6e3c537472696e673e00011c646973636f72642c01384f7074696f6e3c537472696e673e00002c04184f7074696f6e04045401140108104e6f6e6500000010536f6d6504001400000100003000000504003400000507003804184f7074696f6e040454013c0108104e6f6e6500000010536f6d6504003c00000100003c000005060040000002440044000004081448004808186e66745f696f24496d6167654461746100000801306c696d69745f636f7069657320010c75333200014c6175746f5f6368616e67696e675f72756c65734c01784f7074696f6e3c5665633c2854696d655365632c20416374696f6e293e3e00004c04184f7074696f6e04045401500108104e6f6e6500000010536f6d65040050000001000050000002540054000004082058005808186e66745f696f18416374696f6e000108244368616e6765496d670400140118537472696e670000001c4164644d6574610400140118537472696e67000100005c08186e66745f696f244e6674416374696f6e00012c205472616e73666572080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000000305472616e7366657246726f6d0c011066726f6d04011c4163746f724964000108746f04011c4163746f724964000120746f6b656e5f69643c01144e6674496400010030476574546f6b656e496e666f040120746f6b656e5f69643c01144e667449640002002443616e44656c657465000300104d696e740004001c417070726f7665080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000500385265766f6b65417070726f76616c040120746f6b656e5f69643c01144e6674496400060018457870616e640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000700304368616e6765436f6e666967040118636f6e666967100118436f6e666967000800244368616e6765496d67080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e670009002c4164644d65746164617461080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a0000600418526573756c740804540164044501740108084f6b040064000000000c45727204007400000100006408186e66745f696f204e66744576656e7400012c2c5472616e736665727265640c01146f776e657204011c4163746f724964000124726563697069656e7404011c4163746f724964000120746f6b656e5f69643c01144e6674496400000044546f6b656e496e666f526563656976656414012c746f6b656e5f6f776e657204011c4163746f724964000120617070726f76616c68013c4f7074696f6e3c4163746f7249643e00012073656c6c61626c656c0110626f6f6c000140636f6c6c656374696f6e5f6f776e657204011c4163746f72496400011c726f79616c747930010c7531360001002443616e44656c65746504006c0110626f6f6c0002002c496e697469616c697a6564040118636f6e666967100118436f6e666967000300184d696e746564080120746f6b656e5f69643c01144e667449640001206e66745f6461746170010c4e667400040020417070726f766564080108746f04011c4163746f724964000120746f6b656e5f69643c01144e667449640005003c417070726f76616c5265766f6b6564040120746f6b656e5f69643c01144e6674496400060020457870616e6465640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e00070034436f6e6669674368616e676564040118636f6e666967100118436f6e66696700080030496d6167654368616e676564080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e67000900344d657461646174614164646564080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a00006804184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100006c00000500007008186e66745f696f0c4e667400001801146f776e657204011c4163746f7249640001106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e670001206d6574616461746118012c5665633c537472696e673e0001246d656469615f75726c140118537472696e670001246d696e745f74696d653c010c75363400007408186e66745f696f204e66744572726f7200000400140118537472696e6700007808186e66745f696f2853746174655175657279000110104e616d650000002c4465736372697074696f6e00010018436f6e6669670002000c416c6c000300007c08186e66745f696f2853746174655265706c79000110104e616d650400140118537472696e670000002c4465736372697074696f6e0400140118537472696e6700010018436f6e6669670400100118436f6e6669670002000c416c6c04008001204e66745374617465000300008008186e66745f696f204e6674537461746500001c0118746f6b656e738401445665633c284e667449642c204e6674293e0001186f776e6572738c01685665633c284163746f7249642c205665633c4e667449643e293e00013c746f6b656e5f617070726f76616c739801545665633c284e667449642c204163746f724964293e000118636f6e666967100118436f6e6669670001146e6f6e63653c01144e66744964000124696d675f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000084000002880088000004083c70008c00000290009000000408049400940000023c00980000029c009c000004083c0400 \ No newline at end of file diff --git a/indexer/assets/nft_marketplace.meta.txt b/indexer/assets/nft_marketplace.meta.txt new file mode 100644 index 0000000..a143e5c --- /dev/null +++ b/indexer/assets/nft_marketplace.meta.txt @@ -0,0 +1 @@ +0002000100000000000103000000010e0000000000000001110000000112000000793f940008486e66745f6d61726b6574706c6163655f696f484e66744d61726b6574706c616365496e697400000c01406761735f666f725f6372656174696f6e04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001586d696e696d756d5f7472616e736665725f76616c75650801107531323800000400000506000800000507000c08486e66745f6d61726b6574706c6163655f696f504e66744d61726b6574706c616365416374696f6e000140404164644e6577436f6c6c656374696f6e10011c636f64655f6964100118436f646549640001246d6574615f6c696e6b1c0118537472696e67000124747970655f6e616d651c0118537472696e67000140747970655f6465736372697074696f6e1c0118537472696e6700000040437265617465436f6c6c656374696f6e080124747970655f6e616d651c0118537472696e6700011c7061796c6f616420011c5665633c75383e0001001c53616c654e66740c0148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380002003443616e63656c53616c654e6674080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000300184275794e6674080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340004003443726561746541756374696f6e100148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d7328010c75333200050018416464426964080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c75363400060030436c6f736541756374696f6e080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340007003443616e63656c41756374696f6e080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340008002c4372656174654f66666572080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340009002c43616e63656c4f66666572080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000a002c4163636570744f666665720401146f666665722c01144f66666572000b004044656c657465436f6c6c656374696f6e040148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000c002441646441646d696e7304011475736572733001305665633c4163746f7249643e000d002c44656c65746541646d696e0401107573657224011c4163746f724964000e0030557064617465436f6e6669670801406761735f666f725f6372656174696f6e34012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7334012c4f7074696f6e3c7536343e000f00001010106773746418636f6d6d6f6e287072696d69746976657318436f64654964000004001401205b75383b2033325d0000140000032000000018001800000503001c00000502002000000218002410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004001401205b75383b2033325d00002800000505002c08486e66745f6d61726b6574706c6163655f696f144f6666657200000c0148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c75363400011c63726561746f7224011c4163746f72496400003000000224003404184f7074696f6e04045401040108104e6f6e6500000010536f6d650400040000010000380418526573756c74080454013c044501400108084f6b04003c000000000c45727204004000000100003c08486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654576656e74000140484e6577436f6c6c656374696f6e416464656410011c636f64655f6964100118436f646549640001246d6574615f6c696e6b1c0118537472696e67000124747970655f6e616d651c0118537472696e67000140747970655f6465736372697074696f6e1c0118537472696e6700000044436f6c6c656374696f6e43726561746564080124747970655f6e616d651c0118537472696e67000148636f6c6c656374696f6e5f6164647265737324011c4163746f7249640001001c53616c654e6674100148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380001146f776e657224011c4163746f7249640002003c53616c654e667443616e63656c6564080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340003001c4e6674536f6c640c013463757272656e745f6f776e657224011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380004003841756374696f6e43726561746564100148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d7328010c7533320005003441756374696f6e436c6f736564100148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c75363400011470726963650801107531323800013463757272656e745f6f776e657224011c4163746f724964000600204269644164646564080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340007003c41756374696f6e43616e63656c6564080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000800304f66666572437265617465640c0148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000114707269636508011075313238000900344f6666657243616e63656c6564080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000a00344f6666657241636365707465640401146f666665722c01144f66666572000b0044436f6c6c656374696f6e44656c65746564040148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000c002c41646d696e73416464656404011475736572733001305665633c4163746f7249643e000d003041646d696e44656c657465640401107573657224011c4163746f724964000e0034436f6e666967557064617465640801406761735f666f725f6372656174696f6e34012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7334012c4f7074696f6e3c7536343e000f00004008486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654572726f72000004001c0118537472696e6700004408486e66745f6d61726b6574706c6163655f696f28537461746551756572790001140c416c6c0000001841646d696e730001003c436f6c6c656374696f6e73496e666f00020018436f6e66696700030038416c6c436f6c6c656374696f6e73000400004808486e66745f6d61726b6574706c6163655f696f2853746174655265706c790001140c416c6c04004c011453746174650000001841646d696e7304003001305665633c4163746f7249643e0001003c436f6c6c656374696f6e73496e666f04006001745665633c28537472696e672c20436f6c6c656374696f6e496e666f293e00020018436f6e6669670400900118436f6e66696700030038416c6c436f6c6c656374696f6e73040050015c5665633c284163746f7249642c204163746f724964293e000400004c08486e66745f6d61726b6574706c6163655f696f145374617465000020011861646d696e733001305665633c4163746f7249643e00014c636f6c6c656374696f6e5f746f5f6f776e657250015c5665633c284163746f7249642c204163746f724964293e00013474696d655f6372656174696f6e58014c5665633c284163746f7249642c20753634293e000140747970655f636f6c6c656374696f6e736001745665633c28537472696e672c20436f6c6c656374696f6e496e666f293e00011473616c65736c01945665633c28284163746f7249642c20753634292c204e6674496e666f466f7253616c65293e00012061756374696f6e737c01785665633c28284163746f7249642c20753634292c2041756374696f6e293e0001186f66666572738801485665633c284f666665722c2075313238293e000118636f6e666967900118436f6e66696700005000000254005400000408242400580000025c005c0000040824040060000002640064000004081c68006808486e66745f6d61726b6574706c6163655f696f38436f6c6c656374696f6e496e666f00000c011c636f64655f6964100118436f646549640001246d6574615f6c696e6b1c0118537472696e67000140747970655f6465736372697074696f6e1c0118537472696e6700006c000002700070000004085c74007408486e66745f6d61726b6574706c6163655f696f384e6674496e666f466f7253616c65000010011470726963650801107531323800012c746f6b656e5f6f776e657224011c4163746f724964000140636f6c6c656374696f6e5f6f776e657224011c4163746f72496400011c726f79616c747978010c75313600007800000504007c000002800080000004085c84008408486e66745f6d61726b6574706c6163655f696f1c41756374696f6e00001c01146f776e657224011c4163746f724964000128737461727465645f617404010c753634000120656e6465645f617404010c75363400013463757272656e745f70726963650801107531323800013863757272656e745f77696e6e657224011c4163746f724964000140636f6c6c656374696f6e5f6f776e657224011c4163746f72496400011c726f79616c747978010c7531360000880000028c008c000004082c08009008486e66745f6d61726b6574706c6163655f696f18436f6e66696700000c01406761735f666f725f6372656174696f6e04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001586d696e696d756d5f7472616e736665725f76616c7565080110753132380000 diff --git a/indexer/commands.json b/indexer/commands.json new file mode 100644 index 0000000..ac21a21 --- /dev/null +++ b/indexer/commands.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://cdn.subsquid.io/schemas/commands.json", + "commands": { + "clean": { + "description": "delete all build artifacts", + "cmd": ["npx", "--yes", "rimraf", "lib"] + }, + "build": { + "description": "Build the squid project", + "deps": ["clean"], + "cmd": ["tsc"] + }, + "up": { + "description": "Start a PG database", + "cmd": ["docker", "compose", "up", "-d"] + }, + "down": { + "description": "Drop a PG database", + "cmd": ["docker", "compose", "down"] + }, + "migration:apply": { + "description": "Apply the DB migrations", + "cmd": ["squid-typeorm-migration", "apply"] + }, + "migration:generate": { + "description": "Generate a DB migration matching the TypeORM entities", + "deps": ["build", "migration:clean"], + "cmd": ["squid-typeorm-migration", "generate"] + }, + "migration:clean": { + "description": "Clean the migrations folder", + "cmd": ["npx", "--yes", "rimraf", "./db/migrations"] + }, + "migration": { + "deps": ["build"], + "cmd": ["squid-typeorm-migration", "generate"], + "hidden": true + }, + "codegen": { + "description": "Generate TypeORM entities from the schema file", + "cmd": ["squid-typeorm-codegen"] + }, + "typegen": { + "description": "Generate data access classes for an substrate metadata", + "cmd": ["squid-substrate-typegen", "./typegen.json"] + }, + "process": { + "description": "Load .env and start the squid processor", + "deps": ["build", "migration:apply"], + "cmd": ["node", "--require=dotenv/config", "lib/main.js"] + }, + "process:prod": { + "description": "Start the squid processor", + "deps": ["migration:apply"], + "cmd": ["node", "lib/main.js"], + "hidden": true + }, + "serve": { + "description": "Start the GraphQL API server", + "cmd": ["squid-graphql-server"] + }, + "serve:prod": { + "description": "Start the GraphQL API server with caching and limits", + "cmd": ["squid-graphql-server", + "--dumb-cache", "in-memory", + "--dumb-cache-ttl", "1000", + "--dumb-cache-size", "100", + "--dumb-cache-max-age", "1000" ] + }, + "check-updates": { + "cmd": ["npx", "--yes", "npm-check-updates", "--filter=/subsquid/", "--upgrade"], + "hidden": true + }, + "bump": { + "description": "Bump @subsquid packages to the latest versions", + "deps": ["check-updates"], + "cmd": ["npm", "i", "-f"] + }, + "open": { + "description": "Open a local browser window", + "cmd": ["npx", "--yes", "opener"] + } + } +} diff --git a/indexer/db/migrations/1703490897133-Data.js b/indexer/db/migrations/1703490897133-Data.js new file mode 100644 index 0000000..6f4ec57 --- /dev/null +++ b/indexer/db/migrations/1703490897133-Data.js @@ -0,0 +1,45 @@ +module.exports = class Data1703490897133 { + name = 'Data1703490897133' + + async up(db) { + await db.query(`CREATE TABLE "collection_type" ("id" character varying NOT NULL, "description" text NOT NULL, "type" text NOT NULL, "meta_url" text NOT NULL, "meta_str" text NOT NULL, "marketplace_id" character varying, CONSTRAINT "PK_75c673f46e25c52205fae22130c" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_be423ee528eb245b57165bd597" ON "collection_type" ("marketplace_id") `) + await db.query(`CREATE TABLE "transfer" ("id" character varying NOT NULL, "from" text NOT NULL, "to" text NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" text NOT NULL, "tx_hash" text NOT NULL, "nft_id" character varying, CONSTRAINT "PK_fd9ddbdd49a17afcbe014401295" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_52fc453ba5ff660f331db4b359" ON "transfer" ("nft_id") `) + await db.query(`CREATE TABLE "sale" ("id" character varying NOT NULL, "owner" text NOT NULL, "price" numeric NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" text NOT NULL, "is_sold" boolean NOT NULL, "nft_id" character varying, CONSTRAINT "PK_d03891c457cbcd22974732b5de2" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_8524438f82167bcb795bcb8663" ON "sale" ("nft_id") `) + await db.query(`CREATE TABLE "nft" ("id" character varying NOT NULL, "owner" text NOT NULL, "id_in_collection" text NOT NULL, "media_url" text NOT NULL, "minted_at" TIMESTAMP WITH TIME ZONE NOT NULL, "approved_account" text, "on_sale" boolean NOT NULL, "collection_id" character varying, CONSTRAINT "PK_8f46897c58e23b0e7bf6c8e56b0" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_ffe58aa05707db77c2f20ecdbc" ON "nft" ("collection_id") `) + await db.query(`CREATE TABLE "collection" ("id" character varying NOT NULL, "admin" text NOT NULL, "name" text NOT NULL, "description" text NOT NULL, "user_mint_limit" numeric, "tokens_limit" numeric, "collection_image" text NOT NULL, "transferable" boolean NOT NULL, "approvable" boolean NOT NULL, "burnable" boolean NOT NULL, "sellable" boolean NOT NULL, "attandable" boolean NOT NULL, "tags" text array NOT NULL, "marketplace_id" character varying, "type_id" character varying, CONSTRAINT "PK_ad3f485bbc99d875491f44d7c85" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_4698f01445e4833a95f214f862" ON "collection" ("marketplace_id") `) + await db.query(`CREATE INDEX "IDX_75c673f46e25c52205fae22130" ON "collection" ("type_id") `) + await db.query(`CREATE TABLE "marketplace" ("id" character varying NOT NULL, CONSTRAINT "PK_d9c9a956a1a45b27b56db53bfc8" PRIMARY KEY ("id"))`) + await db.query(`ALTER TABLE "collection_type" ADD CONSTRAINT "FK_be423ee528eb245b57165bd597b" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "transfer" ADD CONSTRAINT "FK_52fc453ba5ff660f331db4b3591" FOREIGN KEY ("nft_id") REFERENCES "nft"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "sale" ADD CONSTRAINT "FK_8524438f82167bcb795bcb86637" FOREIGN KEY ("nft_id") REFERENCES "nft"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "nft" ADD CONSTRAINT "FK_ffe58aa05707db77c2f20ecdbc3" FOREIGN KEY ("collection_id") REFERENCES "collection"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "collection" ADD CONSTRAINT "FK_4698f01445e4833a95f214f862b" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "collection" ADD CONSTRAINT "FK_75c673f46e25c52205fae22130c" FOREIGN KEY ("type_id") REFERENCES "collection_type"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + } + + async down(db) { + await db.query(`DROP TABLE "collection_type"`) + await db.query(`DROP INDEX "public"."IDX_be423ee528eb245b57165bd597"`) + await db.query(`DROP TABLE "transfer"`) + await db.query(`DROP INDEX "public"."IDX_52fc453ba5ff660f331db4b359"`) + await db.query(`DROP TABLE "sale"`) + await db.query(`DROP INDEX "public"."IDX_8524438f82167bcb795bcb8663"`) + await db.query(`DROP TABLE "nft"`) + await db.query(`DROP INDEX "public"."IDX_ffe58aa05707db77c2f20ecdbc"`) + await db.query(`DROP TABLE "collection"`) + await db.query(`DROP INDEX "public"."IDX_4698f01445e4833a95f214f862"`) + await db.query(`DROP INDEX "public"."IDX_75c673f46e25c52205fae22130"`) + await db.query(`DROP TABLE "marketplace"`) + await db.query(`ALTER TABLE "collection_type" DROP CONSTRAINT "FK_be423ee528eb245b57165bd597b"`) + await db.query(`ALTER TABLE "transfer" DROP CONSTRAINT "FK_52fc453ba5ff660f331db4b3591"`) + await db.query(`ALTER TABLE "sale" DROP CONSTRAINT "FK_8524438f82167bcb795bcb86637"`) + await db.query(`ALTER TABLE "nft" DROP CONSTRAINT "FK_ffe58aa05707db77c2f20ecdbc3"`) + await db.query(`ALTER TABLE "collection" DROP CONSTRAINT "FK_4698f01445e4833a95f214f862b"`) + await db.query(`ALTER TABLE "collection" DROP CONSTRAINT "FK_75c673f46e25c52205fae22130c"`) + } +} diff --git a/indexer/docker-compose.yml b/indexer/docker-compose.yml new file mode 100644 index 0000000..3f22ae1 --- /dev/null +++ b/indexer/docker-compose.yml @@ -0,0 +1,15 @@ +version: "3" + +services: + db: + image: postgres:15 + environment: + POSTGRES_DB: squid + POSTGRES_PASSWORD: postgres + shm_size: 1gb + ports: + - "${DB_PORT}:5432" + # command: ["postgres", "-c", "log_statement=all"] +# volumes: +# - ./data/db:/var/lib/postgresql/data + diff --git a/indexer/package-lock.json b/indexer/package-lock.json new file mode 100644 index 0000000..d68e3c9 --- /dev/null +++ b/indexer/package-lock.json @@ -0,0 +1,10714 @@ +{ + "name": "nft-marketplace-indexer", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "nft-marketplace-indexer", + "dependencies": { + "@gear-js/api": "^0.35.2", + "@polkadot/types": "^10.11.2", + "@subsquid/archive-registry": "^3.3.0", + "@subsquid/graphql-server": "^4.3.1", + "@subsquid/ss58": "^2.0.1", + "@subsquid/substrate-processor": "^7.2.1", + "@subsquid/typeorm-migration": "^1.2.2", + "@subsquid/typeorm-store": "^1.2.4", + "dotenv": "^16.3.1", + "pg": "8.11.3", + "typeorm": "^0.3.17" + }, + "devDependencies": { + "@subsquid/substrate-metadata-explorer": "^3.1.1", + "@subsquid/substrate-typegen": "^8.0.1", + "@subsquid/typeorm-codegen": "^1.3.2", + "@types/node": "^20.8.4", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^27.2.5", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@apollo/protobufjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.7.tgz", + "integrity": "sha512-Lahx5zntHPZia35myYDBRuF58tlwPskwHc5CWBZC/4bMKB6siTBWwtMrkqXcsNwQiFSzSx5hKdRPUmemrEp3Gg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "long": "^4.0.0" + }, + "bin": { + "apollo-pbjs": "bin/pbjs", + "apollo-pbts": "bin/pbts" + } + }, + "node_modules/@apollo/usage-reporting-protobuf": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@apollo/usage-reporting-protobuf/-/usage-reporting-protobuf-4.1.1.tgz", + "integrity": "sha512-u40dIUePHaSKVshcedO7Wp+mPiZsaU6xjv9J+VyxpoU/zL6Jle+9zWeG98tr/+SZ0nZ4OXhrbb8SNr0rAPpIDA==", + "dependencies": { + "@apollo/protobufjs": "1.2.7" + } + }, + "node_modules/@apollo/utils.dropunuseddefinitions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.dropunuseddefinitions/-/utils.dropunuseddefinitions-1.1.0.tgz", + "integrity": "sha512-jU1XjMr6ec9pPoL+BFWzEPW7VHHulVdGKMkPAMiCigpVIT11VmCbnij0bWob8uS3ODJ65tZLYKAh/55vLw2rbg==", + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.keyvadapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvadapter/-/utils.keyvadapter-1.1.2.tgz", + "integrity": "sha512-vPC5e97uwHuZ2iMHVrEeRsV4dLw0lNx2UY9APhb7StC/RMR3BdnuPwS/+5yR9tUF5IUut+iJZocHkS4y6mR9aA==", + "dependencies": { + "@apollo/utils.keyvaluecache": "^1.0.1", + "dataloader": "^2.1.0", + "keyv": "^4.4.0" + } + }, + "node_modules/@apollo/utils.keyvaluecache": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-1.0.2.tgz", + "integrity": "sha512-p7PVdLPMnPzmXSQVEsy27cYEjVON+SH/Wb7COyW3rQN8+wJgT1nv9jZouYtztWW8ZgTkii5T6tC9qfoDREd4mg==", + "dependencies": { + "@apollo/utils.logger": "^1.0.0", + "lru-cache": "7.10.1 - 7.13.1" + } + }, + "node_modules/@apollo/utils.logger": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-1.0.1.tgz", + "integrity": "sha512-XdlzoY7fYNK4OIcvMD2G94RoFZbzTQaNP0jozmqqMudmaGo2I/2Jx71xlDJ801mWA/mbYRihyaw6KJii7k5RVA==" + }, + "node_modules/@apollo/utils.printwithreducedwhitespace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.printwithreducedwhitespace/-/utils.printwithreducedwhitespace-1.1.0.tgz", + "integrity": "sha512-GfFSkAv3n1toDZ4V6u2d7L4xMwLA+lv+6hqXicMN9KELSJ9yy9RzuEXaX73c/Ry+GzRsBy/fdSUGayGqdHfT2Q==", + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.removealiases": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.removealiases/-/utils.removealiases-1.0.0.tgz", + "integrity": "sha512-6cM8sEOJW2LaGjL/0vHV0GtRaSekrPQR4DiywaApQlL9EdROASZU5PsQibe2MWeZCOhNrPRuHh4wDMwPsWTn8A==", + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.sortast": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.sortast/-/utils.sortast-1.1.0.tgz", + "integrity": "sha512-VPlTsmUnOwzPK5yGZENN069y6uUHgeiSlpEhRnLFYwYNoJHsuJq2vXVwIaSmts015WTPa2fpz1inkLYByeuRQA==", + "dependencies": { + "lodash.sortby": "^4.7.0" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.stripsensitiveliterals": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.stripsensitiveliterals/-/utils.stripsensitiveliterals-1.2.0.tgz", + "integrity": "sha512-E41rDUzkz/cdikM5147d8nfCFVKovXxKBcjvLEQ7bjZm/cg9zEcXvS6vFY8ugTubI3fn6zoqo0CyU8zT+BGP9w==", + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.usagereporting": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@apollo/utils.usagereporting/-/utils.usagereporting-1.0.1.tgz", + "integrity": "sha512-6dk+0hZlnDbahDBB2mP/PZ5ybrtCJdLMbeNJD+TJpKyZmSY6bA3SjI8Cr2EM9QA+AdziywuWg+SgbWUF3/zQqQ==", + "dependencies": { + "@apollo/usage-reporting-protobuf": "^4.0.0", + "@apollo/utils.dropunuseddefinitions": "^1.1.0", + "@apollo/utils.printwithreducedwhitespace": "^1.1.0", + "@apollo/utils.removealiases": "1.0.0", + "@apollo/utils.sortast": "^1.1.0", + "@apollo/utils.stripsensitiveliterals": "^1.2.0" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollographql/apollo-tools": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.4.tgz", + "integrity": "sha512-shM3q7rUbNyXVVRkQJQseXv6bnYM3BUma/eZhwXR4xsuM+bqWnJKvW7SAfRjP7LuSCocrexa5AXhjjawNHrIlw==", + "engines": { + "node": ">=8", + "npm": ">=6" + }, + "peerDependencies": { + "graphql": "^14.2.1 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@apollographql/graphql-playground-html": { + "version": "1.6.29", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.29.tgz", + "integrity": "sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA==", + "dependencies": { + "xss": "^1.0.8" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", + "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.6", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", + "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", + "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "dev": true + }, + "node_modules/@gear-js/api": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@gear-js/api/-/api-0.35.2.tgz", + "integrity": "sha512-mgbBH16qOsSkv1grkQeGxfhIG29C4WBepo1VogJvTAi1mnqcY8XqrOq5T9ilx7CMAi0ENMRDSTIA7usMRUdA7w==", + "peerDependencies": { + "@polkadot/api": "10.10.1", + "@polkadot/wasm-crypto": "7.2.2", + "rxjs": "7.8.1" + } + }, + "node_modules/@graphql-tools/merge": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", + "integrity": "sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q==", + "dependencies": { + "@graphql-tools/utils": "^10.0.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/mock": { + "version": "8.7.20", + "resolved": "https://registry.npmjs.org/@graphql-tools/mock/-/mock-8.7.20.tgz", + "integrity": "sha512-ljcHSJWjC/ZyzpXd5cfNhPI7YljRVvabKHPzKjEs5ElxWu2cdlLGvyNYepApXDsM/OJG/2xuhGM+9GWu5gEAPQ==", + "dependencies": { + "@graphql-tools/schema": "^9.0.18", + "@graphql-tools/utils": "^9.2.1", + "fast-json-stable-stringify": "^2.1.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/mock/node_modules/@graphql-tools/merge": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", + "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/mock/node_modules/@graphql-tools/schema": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", + "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "dependencies": { + "@graphql-tools/merge": "^8.4.1", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/mock/node_modules/@graphql-tools/utils": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", + "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/schema": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.0.tgz", + "integrity": "sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==", + "dependencies": { + "@graphql-tools/merge": "^9.0.0", + "@graphql-tools/utils": "^10.0.0", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/utils": { + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", + "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "dset": "^3.1.2", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@josephg/resolvable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz", + "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@keyv/redis": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/@keyv/redis/-/redis-2.5.8.tgz", + "integrity": "sha512-WweuUZqZN2ETcseV6r1AEum1qG6eR5poNhkZ4CIpWBOjMasT2ArTKWyIPxxYllKUS2A8wKv1l8+AqH6Jpzk7Ug==", + "dependencies": { + "ioredis": "^5.3.2" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@polkadot/api": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.10.1.tgz", + "integrity": "sha512-YHVkmNvjGF4Eg3thAbVhj9UX3SXx+Yxk6yVuzsEcckEudIRHzL2ikIWGCfUprfzSeFNpUCKdJIi1tsxVHtA7Tg==", + "peer": true, + "dependencies": { + "@polkadot/api-augment": "10.10.1", + "@polkadot/api-base": "10.10.1", + "@polkadot/api-derive": "10.10.1", + "@polkadot/keyring": "^12.5.1", + "@polkadot/rpc-augment": "10.10.1", + "@polkadot/rpc-core": "10.10.1", + "@polkadot/rpc-provider": "10.10.1", + "@polkadot/types": "10.10.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/types-known": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "eventemitter3": "^5.0.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-augment": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-10.10.1.tgz", + "integrity": "sha512-J0r1DT1M5y75iO1iwcpUBokKD3q6b22kWlPfiHEDNFydVw5vm7OTRBk9Njjl8rOnlSzcW/Ya8qWfV/wkrqHxUQ==", + "peer": true, + "dependencies": { + "@polkadot/api-base": "10.10.1", + "@polkadot/rpc-augment": "10.10.1", + "@polkadot/types": "10.10.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/util": "^12.5.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-augment/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-base": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.10.1.tgz", + "integrity": "sha512-joH2Ywxnn+AStkw+JWAdF3i3WJy4NcBYp0SWJM/WqGafWR/FuHnati2pcj/MHzkHT8JkBippmSSJFvsqRhlwcQ==", + "peer": true, + "dependencies": { + "@polkadot/rpc-core": "10.10.1", + "@polkadot/types": "10.10.1", + "@polkadot/util": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-base/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-derive": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.10.1.tgz", + "integrity": "sha512-Q9Ibs4eRPqdV8qnRzFPD3dlWNbLHxRqMqNTNPmNQwKPo5m6fcQbZ0UZy3yJ+PI9S4AQHGhsWtfoi5qW8006GHQ==", + "peer": true, + "dependencies": { + "@polkadot/api": "10.10.1", + "@polkadot/api-augment": "10.10.1", + "@polkadot/api-base": "10.10.1", + "@polkadot/rpc-core": "10.10.1", + "@polkadot/types": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-derive/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/keyring": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.6.2.tgz", + "integrity": "sha512-O3Q7GVmRYm8q7HuB3S0+Yf/q/EB2egKRRU3fv9b3B7V+A52tKzA+vIwEmNVaD1g5FKW9oB97rmpggs0zaKFqHw==", + "dependencies": { + "@polkadot/util": "12.6.2", + "@polkadot/util-crypto": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "12.6.2", + "@polkadot/util-crypto": "12.6.2" + } + }, + "node_modules/@polkadot/networks": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-12.6.2.tgz", + "integrity": "sha512-1oWtZm1IvPWqvMrldVH6NI2gBoCndl5GEwx7lAuQWGr7eNL+6Bdc5K3Z9T0MzFvDGoi2/CBqjX9dRKo39pDC/w==", + "dependencies": { + "@polkadot/util": "12.6.2", + "@substrate/ss58-registry": "^1.44.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/rpc-augment": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-10.10.1.tgz", + "integrity": "sha512-PcvsX8DNV8BNDXXnY2K8F4mE7cWz7fKg8ykXNZTN8XUN6MrI4k/ohv7itYic7X5LaP25ZmQt5UiGyjKDGIELow==", + "peer": true, + "dependencies": { + "@polkadot/rpc-core": "10.10.1", + "@polkadot/types": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/util": "^12.5.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-augment/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-core": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.10.1.tgz", + "integrity": "sha512-awfFfJYsVF6W4DrqTj5RP00SSDRNB770FIoe1QE1Op4NcSrfeLpwh54HUJS716f4l5mOSYuvMp+zCbKzt8zKow==", + "peer": true, + "dependencies": { + "@polkadot/rpc-augment": "10.10.1", + "@polkadot/rpc-provider": "10.10.1", + "@polkadot/types": "10.10.1", + "@polkadot/util": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-core/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-provider": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.10.1.tgz", + "integrity": "sha512-VMDWoJgx6/mPHAOT66Sq+Jf2lJABfV/ZUIXtT2k8HjOndbm6oKrFqGEOSSLvB2q4olDee3FkFFxkyW1s6k4JaQ==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types": "10.10.1", + "@polkadot/types-support": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "@polkadot/x-fetch": "^12.5.1", + "@polkadot/x-global": "^12.5.1", + "@polkadot/x-ws": "^12.5.1", + "eventemitter3": "^5.0.1", + "mock-socket": "^9.3.1", + "nock": "^13.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@substrate/connect": "0.7.33" + } + }, + "node_modules/@polkadot/rpc-provider/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.11.2.tgz", + "integrity": "sha512-d52j3xXni+C8GdYZVTSfu8ROAnzXFMlyRvXtor0PudUc8UQHOaC4+mYAkTBGA2gKdmL8MHSfRSbhcxHhsikY6Q==", + "dependencies": { + "@polkadot/keyring": "^12.6.2", + "@polkadot/types-augment": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/types-create": "10.11.2", + "@polkadot/util": "^12.6.2", + "@polkadot/util-crypto": "^12.6.2", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/types-augment": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.10.1.tgz", + "integrity": "sha512-XRHE75IocXfFE6EADYov3pqXCyBk5SWbiHoZ0+4WYWP9SwMuzsBaAy84NlhLBlkG3+ehIqi0HpAd/qrljJGZbg==", + "peer": true, + "dependencies": { + "@polkadot/types": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/util": "^12.5.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-augment/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-codec": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.10.1.tgz", + "integrity": "sha512-ETPG0wzWzt/bDKRQmYbO7CLe/0lUt8VrG6/bECdv+Kye+8Qedba2LZyTWm/9f2ngms8TZ82yI8mPv/mozdtfnw==", + "peer": true, + "dependencies": { + "@polkadot/util": "^12.5.1", + "@polkadot/x-bigint": "^12.5.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-create": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.10.1.tgz", + "integrity": "sha512-7OiLzd+Ter5zrpjP7fDwA1m89kd38VvMVixfOSv8x7ld2pDT+yyyKl14TCwRSWrKWCMtIb6M3iasPhq5cUa7cw==", + "peer": true, + "dependencies": { + "@polkadot/types-codec": "10.10.1", + "@polkadot/util": "^12.5.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-known": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-10.10.1.tgz", + "integrity": "sha512-yRa1lbDRqg3V/zoa0vSwdGOiYTIWktILW8OfkaLDExTu0GZBSbVHZlLAta52XVpA9Zww7mrUUC9+iernOwk//w==", + "peer": true, + "dependencies": { + "@polkadot/networks": "^12.5.1", + "@polkadot/types": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-known/node_modules/@polkadot/types": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", + "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", + "peer": true, + "dependencies": { + "@polkadot/keyring": "^12.5.1", + "@polkadot/types-augment": "10.10.1", + "@polkadot/types-codec": "10.10.1", + "@polkadot/types-create": "10.10.1", + "@polkadot/util": "^12.5.1", + "@polkadot/util-crypto": "^12.5.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-support": { + "version": "10.10.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.10.1.tgz", + "integrity": "sha512-Cd2mwk9RG6LlX8X3H0bRY7wCTbZPqU3z38CMFhvNkFDAyjqKjtn8hpS4n8mMrZK2EwCs/MjQH1wb7rtFkaWmJw==", + "peer": true, + "dependencies": { + "@polkadot/util": "^12.5.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types/node_modules/@polkadot/types-augment": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.11.2.tgz", + "integrity": "sha512-8eB8ew04wZiE5GnmFvEFW1euJWmF62SGxb1O+8wL3zoUtB9Xgo1vB6w6xbTrd+HLV6jNSeXXnbbF1BEUvi9cNg==", + "dependencies": { + "@polkadot/types": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/util": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/types/node_modules/@polkadot/types-codec": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.11.2.tgz", + "integrity": "sha512-3xjOQL+LOOMzYqlgP9ROL0FQnzU8lGflgYewzau7AsDlFziSEtb49a9BpYo6zil4koC+QB8zQ9OHGFumG08T8w==", + "dependencies": { + "@polkadot/util": "^12.6.2", + "@polkadot/x-bigint": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/types/node_modules/@polkadot/types-create": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.11.2.tgz", + "integrity": "sha512-SJt23NxYvefRxVZZm6mT9ed1pR6FDoIGQ3xUpbjhTLfU2wuhpKjekMVorYQ6z/gK2JLMu2kV92Ardsz+6GX5XQ==", + "dependencies": { + "@polkadot/types-codec": "10.11.2", + "@polkadot/util": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/util": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.6.2.tgz", + "integrity": "sha512-l8TubR7CLEY47240uki0TQzFvtnxFIO7uI/0GoWzpYD/O62EIAMRsuY01N4DuwgKq2ZWD59WhzsLYmA5K6ksdw==", + "dependencies": { + "@polkadot/x-bigint": "12.6.2", + "@polkadot/x-global": "12.6.2", + "@polkadot/x-textdecoder": "12.6.2", + "@polkadot/x-textencoder": "12.6.2", + "@types/bn.js": "^5.1.5", + "bn.js": "^5.2.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/util-crypto": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-12.6.2.tgz", + "integrity": "sha512-FEWI/dJ7wDMNN1WOzZAjQoIcCP/3vz3wvAp5QQm+lOrzOLj0iDmaIGIcBkz8HVm3ErfSe/uKP0KS4jgV/ib+Mg==", + "dependencies": { + "@noble/curves": "^1.3.0", + "@noble/hashes": "^1.3.3", + "@polkadot/networks": "12.6.2", + "@polkadot/util": "12.6.2", + "@polkadot/wasm-crypto": "^7.3.2", + "@polkadot/wasm-util": "^7.3.2", + "@polkadot/x-bigint": "12.6.2", + "@polkadot/x-randomvalues": "12.6.2", + "@scure/base": "^1.1.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "12.6.2" + } + }, + "node_modules/@polkadot/util-crypto/node_modules/@polkadot/wasm-bridge": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.3.2.tgz", + "integrity": "sha512-AJEXChcf/nKXd5Q/YLEV5dXQMle3UNT7jcXYmIffZAo/KI394a+/24PaISyQjoNC0fkzS1Q8T5pnGGHmXiVz2g==", + "dependencies": { + "@polkadot/wasm-util": "7.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/util-crypto/node_modules/@polkadot/wasm-crypto": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.3.2.tgz", + "integrity": "sha512-+neIDLSJ6jjVXsjyZ5oLSv16oIpwp+PxFqTUaZdZDoA2EyFRQB8pP7+qLsMNk+WJuhuJ4qXil/7XiOnZYZ+wxw==", + "dependencies": { + "@polkadot/wasm-bridge": "7.3.2", + "@polkadot/wasm-crypto-asmjs": "7.3.2", + "@polkadot/wasm-crypto-init": "7.3.2", + "@polkadot/wasm-crypto-wasm": "7.3.2", + "@polkadot/wasm-util": "7.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/util-crypto/node_modules/@polkadot/wasm-crypto-asmjs": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.3.2.tgz", + "integrity": "sha512-QP5eiUqUFur/2UoF2KKKYJcesc71fXhQFLT3D4ZjG28Mfk2ZPI0QNRUfpcxVQmIUpV5USHg4geCBNuCYsMm20Q==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/util-crypto/node_modules/@polkadot/wasm-crypto-init": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.3.2.tgz", + "integrity": "sha512-FPq73zGmvZtnuJaFV44brze3Lkrki3b4PebxCy9Fplw8nTmisKo9Xxtfew08r0njyYh+uiJRAxPCXadkC9sc8g==", + "dependencies": { + "@polkadot/wasm-bridge": "7.3.2", + "@polkadot/wasm-crypto-asmjs": "7.3.2", + "@polkadot/wasm-crypto-wasm": "7.3.2", + "@polkadot/wasm-util": "7.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/util-crypto/node_modules/@polkadot/wasm-crypto-wasm": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.3.2.tgz", + "integrity": "sha512-15wd0EMv9IXs5Abp1ZKpKKAVyZPhATIAHfKsyoWCEFDLSOA0/K0QGOxzrAlsrdUkiKZOq7uzSIgIDgW8okx2Mw==", + "dependencies": { + "@polkadot/wasm-util": "7.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-bridge": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.2.2.tgz", + "integrity": "sha512-CgNENd65DVYtackOVXXRA0D1RPoCv5+77IdBCf7kNqu6LeAnR4nfTI6qjaApUdN1xRweUsQjSH7tu7VjkMOA0A==", + "peer": true, + "dependencies": { + "@polkadot/wasm-util": "7.2.2", + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-bridge/node_modules/@polkadot/wasm-util": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.2.tgz", + "integrity": "sha512-N/25960ifCc56sBlJZ2h5UBpEPvxBmMLgwYsl7CUuT+ea2LuJW9Xh8VHDN/guYXwmm92/KvuendYkEUykpm/JQ==", + "peer": true, + "dependencies": { + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-crypto": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.2.2.tgz", + "integrity": "sha512-1ZY1rxUTawYm0m1zylvBMFovNIHYgG2v/XoASNp/EMG5c8FQIxCbhJRaTBA983GVq4lN/IAKREKEp9ZbLLqssA==", + "peer": true, + "dependencies": { + "@polkadot/wasm-bridge": "7.2.2", + "@polkadot/wasm-crypto-asmjs": "7.2.2", + "@polkadot/wasm-crypto-init": "7.2.2", + "@polkadot/wasm-crypto-wasm": "7.2.2", + "@polkadot/wasm-util": "7.2.2", + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-asmjs": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.2.2.tgz", + "integrity": "sha512-wKg+cpsWQCTSVhjlHuNeB/184rxKqY3vaklacbLOMbUXieIfuDBav5PJdzS3yeiVE60TpYaHW4iX/5OYHS82gg==", + "peer": true, + "dependencies": { + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-init": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.2.2.tgz", + "integrity": "sha512-vD4iPIp9x+SssUIWUenxWLPw4BVIwhXHNMpsV81egK990tvpyIxL205/EF5QRb1mKn8WfWcNFm5tYwwh9NdnnA==", + "peer": true, + "dependencies": { + "@polkadot/wasm-bridge": "7.2.2", + "@polkadot/wasm-crypto-asmjs": "7.2.2", + "@polkadot/wasm-crypto-wasm": "7.2.2", + "@polkadot/wasm-util": "7.2.2", + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-init/node_modules/@polkadot/wasm-util": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.2.tgz", + "integrity": "sha512-N/25960ifCc56sBlJZ2h5UBpEPvxBmMLgwYsl7CUuT+ea2LuJW9Xh8VHDN/guYXwmm92/KvuendYkEUykpm/JQ==", + "peer": true, + "dependencies": { + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-wasm": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.2.2.tgz", + "integrity": "sha512-3efoIB6jA3Hhv6k0YIBwCtlC8gCSWCk+R296yIXRLLr3cGN415KM/PO/d1JIXYI64lbrRzWRmZRhllw3jf6Atg==", + "peer": true, + "dependencies": { + "@polkadot/wasm-util": "7.2.2", + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-wasm/node_modules/@polkadot/wasm-util": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.2.tgz", + "integrity": "sha512-N/25960ifCc56sBlJZ2h5UBpEPvxBmMLgwYsl7CUuT+ea2LuJW9Xh8VHDN/guYXwmm92/KvuendYkEUykpm/JQ==", + "peer": true, + "dependencies": { + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-crypto/node_modules/@polkadot/wasm-util": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.2.tgz", + "integrity": "sha512-N/25960ifCc56sBlJZ2h5UBpEPvxBmMLgwYsl7CUuT+ea2LuJW9Xh8VHDN/guYXwmm92/KvuendYkEUykpm/JQ==", + "peer": true, + "dependencies": { + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-util": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.3.2.tgz", + "integrity": "sha512-bmD+Dxo1lTZyZNxbyPE380wd82QsX+43mgCm40boyKrRppXEyQmWT98v/Poc7chLuskYb6X8IQ6lvvK2bGR4Tg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/x-bigint": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-12.6.2.tgz", + "integrity": "sha512-HSIk60uFPX4GOFZSnIF7VYJz7WZA7tpFJsne7SzxOooRwMTWEtw3fUpFy5cYYOeLh17/kHH1Y7SVcuxzVLc74Q==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-fetch": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-12.6.2.tgz", + "integrity": "sha512-8wM/Z9JJPWN1pzSpU7XxTI1ldj/AfC8hKioBlUahZ8gUiJaOF7K9XEFCrCDLis/A1BoOu7Ne6WMx/vsJJIbDWw==", + "peer": true, + "dependencies": { + "@polkadot/x-global": "12.6.2", + "node-fetch": "^3.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-global": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-12.6.2.tgz", + "integrity": "sha512-a8d6m+PW98jmsYDtAWp88qS4dl8DyqUBsd0S+WgyfSMtpEXu6v9nXDgPZgwF5xdDvXhm+P0ZfVkVTnIGrScb5g==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-randomvalues": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-12.6.2.tgz", + "integrity": "sha512-Vr8uG7rH2IcNJwtyf5ebdODMcr0XjoCpUbI91Zv6AlKVYOGKZlKLYJHIwpTaKKB+7KPWyQrk4Mlym/rS7v9feg==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "12.6.2", + "@polkadot/wasm-util": "*" + } + }, + "node_modules/@polkadot/x-textdecoder": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-12.6.2.tgz", + "integrity": "sha512-M1Bir7tYvNappfpFWXOJcnxUhBUFWkUFIdJSyH0zs5LmFtFdbKAeiDXxSp2Swp5ddOZdZgPac294/o2TnQKN1w==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-textencoder": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-12.6.2.tgz", + "integrity": "sha512-4N+3UVCpI489tUJ6cv3uf0PjOHvgGp9Dl+SZRLgFGt9mvxnvpW/7+XBADRMtlG4xi5gaRK7bgl5bmY6OMDsNdw==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-ws": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-12.6.2.tgz", + "integrity": "sha512-cGZWo7K5eRRQCRl2LrcyCYsrc3lRbTlixZh3AzgU8uX4wASVGRlNWi/Hf4TtHNe1ExCDmxabJzdIsABIfrr7xw==", + "peer": true, + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2", + "ws": "^8.15.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@scure/base": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", + "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" + }, + "node_modules/@subsquid/archive-registry": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@subsquid/archive-registry/-/archive-registry-3.3.0.tgz", + "integrity": "sha512-moXnGNOSmKMHyuDvUiOHbpL7IePSo4XZOW9OnzESIND64eGxlKusIsCi8Nth1DgzbE/UTTFeNJvYKu0v7SOIqw==", + "dependencies": { + "@subsquid/util-internal": "^1.0.0", + "commander": "^10.0.0", + "easy-table": "^1.2.0", + "sync-fetch": "^0.5.2" + }, + "bin": { + "squid-archive-registry": "bin/run.js" + } + }, + "node_modules/@subsquid/graphiql-console": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@subsquid/graphiql-console/-/graphiql-console-0.3.0.tgz", + "integrity": "sha512-C89mus6IXnNi0xMQrZqUFBZwLj8tbuq9lye8Gq/lHmmERAUpi6UsWEyLdJLx2mneZzF3JtY8eNiiZ16jmjtvfw==" + }, + "node_modules/@subsquid/graphql-server": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@subsquid/graphql-server/-/graphql-server-4.3.1.tgz", + "integrity": "sha512-EEZXaZf3TSK0JD+kcBgr+ENf2WOAjb7EREQP28+9NRWQhtn1s1w3XQNMjjurfyeb5Us/pRODAmfl8jOcXj3CAQ==", + "dependencies": { + "@apollo/utils.keyvadapter": "~1.1.2", + "@apollo/utils.keyvaluecache": "~1.0.2", + "@graphql-tools/merge": "^9.0.0", + "@graphql-tools/schema": "^10.0.0", + "@graphql-tools/utils": "^10.0.6", + "@keyv/redis": "~2.5.8", + "@subsquid/logger": "^1.3.1", + "@subsquid/openreader": "^4.4.1", + "@subsquid/typeorm-config": "^3.3.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-commander": "^1.3.1", + "@subsquid/util-internal-http-server": "^1.2.1", + "apollo-server-core": "^3.12.1", + "apollo-server-express": "^3.12.1", + "apollo-server-plugin-response-cache": "~3.7.1", + "commander": "^11.0.0", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "graphql": "^15.8.0", + "graphql-ws": "^5.14.1", + "keyv": "~4.5.3", + "pg": "^8.11.3", + "ws": "^8.14.2" + }, + "bin": { + "squid-graphql-server": "bin/run.js" + }, + "peerDependencies": { + "@subsquid/big-decimal": "^1.0.0", + "class-validator": "^0.14.0", + "type-graphql": "^1.2.0-rc.1", + "typeorm": "^0.3.17" + }, + "peerDependenciesMeta": { + "@subsquid/big-decimal": { + "optional": true + }, + "class-validator": { + "optional": true + }, + "type-graphql": { + "optional": true + }, + "typeorm": { + "optional": true + } + } + }, + "node_modules/@subsquid/graphql-server/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/graphql-server/node_modules/@subsquid/util-internal-commander": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-commander/-/util-internal-commander-1.3.1.tgz", + "integrity": "sha512-KeGsOghBU20tM1BzqryOf3MKvrDFSfPuhnl9LhhEC00ysp8rRPyejlw6jIJhO2NRJ+oaUi5jHRdf64/o21N7Lw==", + "peerDependencies": { + "commander": "^11.0.0" + } + }, + "node_modules/@subsquid/graphql-server/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@subsquid/http-client": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@subsquid/http-client/-/http-client-1.3.1.tgz", + "integrity": "sha512-ZBuYNW9IOvigvpntZvM0tzAY5Llr44NYswOzGwJpCjOnWF7EotzeJRMwDH0Zv5hXSMFvX3UBACP+PxmwDvma5A==", + "dependencies": { + "@subsquid/logger": "^1.3.1", + "@subsquid/util-internal": "^2.5.2", + "node-fetch": "^3.3.2" + } + }, + "node_modules/@subsquid/http-client/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/logger": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@subsquid/logger/-/logger-1.3.1.tgz", + "integrity": "sha512-OBhelb0HbhqSygq/IxEm9PPX8thQSDiCPV45UlCqWOoQ9UpiROiQLL+2nwt+HAHQq+LlHTzQmGXV43eabrTfwQ==", + "dependencies": { + "@subsquid/util-internal-hex": "^1.2.1", + "@subsquid/util-internal-json": "^1.2.1", + "supports-color": "^8.1.1" + } + }, + "node_modules/@subsquid/openreader": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@subsquid/openreader/-/openreader-4.4.1.tgz", + "integrity": "sha512-Z2M+scuoJx1H3U+KttIEjrSvZ+5K3ioNdWatUS42k9xgOIEMJzDCJM8ZxhqgP/fMTrR9RPjeFqjy6NBS0kgwtg==", + "dependencies": { + "@graphql-tools/merge": "^9.0.0", + "@subsquid/graphiql-console": "^0.3.0", + "@subsquid/logger": "^1.3.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-commander": "^1.3.1", + "@subsquid/util-internal-hex": "^1.2.1", + "@subsquid/util-internal-http-server": "^1.2.1", + "@subsquid/util-naming": "^1.2.1", + "apollo-server-core": "^3.12.1", + "apollo-server-express": "^3.12.1", + "commander": "^11.0.0", + "deep-equal": "^2.2.2", + "express": "^4.18.2", + "graphql": "^15.8.0", + "graphql-parse-resolve-info": "^4.13.0", + "graphql-ws": "^5.14.1", + "pg": "^8.11.3", + "ws": "^8.14.2" + }, + "bin": { + "openreader": "bin/main.js" + }, + "peerDependencies": { + "@subsquid/big-decimal": "^1.0.0" + }, + "peerDependenciesMeta": { + "@subsquid/big-decimal": { + "optional": true + } + } + }, + "node_modules/@subsquid/openreader/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/openreader/node_modules/@subsquid/util-internal-commander": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-commander/-/util-internal-commander-1.3.1.tgz", + "integrity": "sha512-KeGsOghBU20tM1BzqryOf3MKvrDFSfPuhnl9LhhEC00ysp8rRPyejlw6jIJhO2NRJ+oaUi5jHRdf64/o21N7Lw==", + "peerDependencies": { + "commander": "^11.0.0" + } + }, + "node_modules/@subsquid/openreader/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@subsquid/rpc-client": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@subsquid/rpc-client/-/rpc-client-4.4.2.tgz", + "integrity": "sha512-Zo/KuFNiwKblKCUDpXUNbeshxEpCX44CtBKbzr4f5zFNdwxuH7FjwFnZk4X5YZUVnbcTF6cmqhH5RwRkKBgPfQ==", + "dependencies": { + "@subsquid/http-client": "^1.3.1", + "@subsquid/logger": "^1.3.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-binary-heap": "^1.0.0", + "@subsquid/util-internal-counters": "^1.3.1", + "websocket": "^1.0.34" + } + }, + "node_modules/@subsquid/rpc-client/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/scale-codec": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@subsquid/scale-codec/-/scale-codec-4.0.0.tgz", + "integrity": "sha512-aVqcy1KeQiYhL3lRLZJcRVuBOmh88zQKqEdxU/7gJCj/gvBF9+Isd16oE0xuA5xwlGcFHbRfUFSON5EP2Lv8Eg==", + "dependencies": { + "@subsquid/util-internal-hex": "^1.2.1", + "@subsquid/util-internal-json": "^1.2.1" + } + }, + "node_modules/@subsquid/scale-type-system": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@subsquid/scale-type-system/-/scale-type-system-1.0.1.tgz", + "integrity": "sha512-CjY5nBzGrbRcOH//lOwNHbBjHtHD0t27SirdIAFre/Mp4fLIiv6gEkIgNYu+lwAjMvuFkLkcw7JGmwXvLNepNw==", + "peer": true, + "dependencies": { + "@subsquid/util-internal": "^2.5.2" + }, + "peerDependencies": { + "@subsquid/scale-codec": "^4.0.0" + } + }, + "node_modules/@subsquid/scale-type-system/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==", + "peer": true + }, + "node_modules/@subsquid/ss58": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@subsquid/ss58/-/ss58-2.0.1.tgz", + "integrity": "sha512-VmVgR6E8cwpYiQtL+ZbdW0RCguNmwunbX4JYI08vHErxWdLhX4o6v9LClq3L9+5LcKgspzOci9DNt0xzR1keYQ==", + "dependencies": { + "@subsquid/ss58-codec": "^1.2.2", + "@subsquid/util-internal-hex": "^1.2.1" + } + }, + "node_modules/@subsquid/ss58-codec": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@subsquid/ss58-codec/-/ss58-codec-1.2.2.tgz", + "integrity": "sha512-hNYKWqfKd92l2xFSgSiSfK6dHLE/hwWWJ6FIlZ3mS/tgUsEUqTHJabqZ1p+pt0US9P8h+J4Dd58eujPI03peqA==", + "dependencies": { + "base-x": "^4.0.0", + "blake2b": "^2.1.4" + } + }, + "node_modules/@subsquid/substrate-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@subsquid/substrate-data/-/substrate-data-3.0.1.tgz", + "integrity": "sha512-zmZGtwYwNi50siU5k0r8YRXlJPNsls1E6y1N+Yv7driNdsolKhXdcHKLoRIaiXRlV/QGkuSh/vNaLxebxiL1TQ==", + "dependencies": { + "@subsquid/scale-codec": "^4.0.0", + "@subsquid/substrate-data-raw": "^0.1.0", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-hex": "^1.2.1", + "@subsquid/util-internal-ingest-tools": "^0.0.2", + "@subsquid/util-internal-range": "^0.0.1", + "@subsquid/util-xxhash": "^1.2.1", + "@substrate/calc": "^0.2.8", + "blake2b": "^2.1.4" + }, + "peerDependencies": { + "@subsquid/rpc-client": "^4.4.2", + "@subsquid/substrate-runtime": "^1.0.1" + } + }, + "node_modules/@subsquid/substrate-data-raw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@subsquid/substrate-data-raw/-/substrate-data-raw-0.1.0.tgz", + "integrity": "sha512-0540hjZzUgeVjqy7UqKcTPKBsun2eisv9JR0ks3WDHPLabyWy4TolbE1WWqCo4B8wBmLEm5+vTL/BtM/AkHrYg==", + "dependencies": { + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-ingest-tools": "^0.0.2", + "@subsquid/util-internal-range": "^0.0.1" + }, + "peerDependencies": { + "@subsquid/rpc-client": "^4.4.2" + } + }, + "node_modules/@subsquid/substrate-data-raw/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/substrate-data/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/substrate-metadata-explorer": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@subsquid/substrate-metadata-explorer/-/substrate-metadata-explorer-3.1.1.tgz", + "integrity": "sha512-GzlgUMEIcJvtiEYXxPqC6onncbmPKoBdINuyQSNmU7hVVOn5MEJhXAj2kzOnTztCGhM8GnBDebmLf/f7RndgiQ==", + "dev": true, + "dependencies": { + "@subsquid/logger": "^1.3.1", + "@subsquid/rpc-client": "^4.4.2", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-commander": "^1.3.1", + "@subsquid/util-internal-hex": "^1.2.1", + "@subsquid/util-internal-read-lines": "^1.2.1", + "commander": "^11.0.0" + }, + "bin": { + "squid-substrate-metadata-explorer": "bin/run.js", + "substrate-metadata-explorer": "bin/run.js" + } + }, + "node_modules/@subsquid/substrate-metadata-explorer/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==", + "dev": true + }, + "node_modules/@subsquid/substrate-metadata-explorer/node_modules/@subsquid/util-internal-commander": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-commander/-/util-internal-commander-1.3.1.tgz", + "integrity": "sha512-KeGsOghBU20tM1BzqryOf3MKvrDFSfPuhnl9LhhEC00ysp8rRPyejlw6jIJhO2NRJ+oaUi5jHRdf64/o21N7Lw==", + "dev": true, + "peerDependencies": { + "commander": "^11.0.0" + } + }, + "node_modules/@subsquid/substrate-metadata-explorer/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@subsquid/substrate-processor": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/substrate-processor/-/substrate-processor-7.2.1.tgz", + "integrity": "sha512-9T/wQIaDt4HfkioFQ8nGMc+/N/mEskiYFhQdvT0FYwdKxr3qbyvsbT2qoZfDS/i9J/d2y/39YKrtCMBKOwf65w==", + "dependencies": { + "@subsquid/http-client": "^1.3.1", + "@subsquid/logger": "^1.3.1", + "@subsquid/rpc-client": "^4.4.2", + "@subsquid/substrate-data": "^3.0.1", + "@subsquid/substrate-data-raw": "^0.1.0", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-archive-client": "^0.0.1", + "@subsquid/util-internal-hex": "^1.2.1", + "@subsquid/util-internal-json": "^1.2.1", + "@subsquid/util-internal-processor-tools": "^3.1.0" + }, + "peerDependencies": { + "@subsquid/substrate-runtime": "^1.0.1" + } + }, + "node_modules/@subsquid/substrate-processor/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/substrate-runtime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@subsquid/substrate-runtime/-/substrate-runtime-1.0.1.tgz", + "integrity": "sha512-L7ln2EaIfl99uAbkz3Nw6oIXdpj2yfBk5qUyOJ/nOm5WHGBE3NKw0nIfgnC6EbbsNJKZZfJT0Tm+eRZZlUakug==", + "peer": true, + "dependencies": { + "@subsquid/scale-codec": "^4.0.0", + "@subsquid/scale-type-system": "^1.0.0", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-hex": "^1.2.1", + "@subsquid/util-naming": "^1.2.1", + "@subsquid/util-xxhash": "^1.2.1", + "blake2b": "^2.1.4" + } + }, + "node_modules/@subsquid/substrate-runtime/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==", + "peer": true + }, + "node_modules/@subsquid/substrate-typegen": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@subsquid/substrate-typegen/-/substrate-typegen-8.0.1.tgz", + "integrity": "sha512-/Mx6ITDbVVjgPuhW3/JUvEDzN01hrz0lSmjTzX46L2JGamPeCxZfX/HdbwDUb0Ns7zn+Q3e1JOtQoRkC6MVEhA==", + "dev": true, + "dependencies": { + "@subsquid/http-client": "^1.3.1", + "@subsquid/logger": "^1.3.1", + "@subsquid/substrate-metadata-explorer": "^3.1.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-code-printer": "^1.2.1", + "@subsquid/util-internal-config": "^2.2.1", + "@subsquid/util-internal-read-lines": "^1.2.1", + "@subsquid/util-naming": "^1.2.1", + "commander": "^11.0.0" + }, + "bin": { + "squid-substrate-typegen": "bin/run.js" + }, + "peerDependencies": { + "@subsquid/substrate-runtime": "^1.0.0" + } + }, + "node_modules/@subsquid/substrate-typegen/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==", + "dev": true + }, + "node_modules/@subsquid/substrate-typegen/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@subsquid/typeorm-codegen": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@subsquid/typeorm-codegen/-/typeorm-codegen-1.3.2.tgz", + "integrity": "sha512-jSDrMjcCa1NiEQICFXHyYENEnjJxmFd2vmyiSXm+CTyqQRMJutqLcZFHx38CHwz15kyCxKK8whDYQglmLvx0cQ==", + "dev": true, + "dependencies": { + "@subsquid/openreader": "^4.4.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-code-printer": "^1.2.1", + "@subsquid/util-naming": "^1.2.1", + "commander": "^11.0.0" + }, + "bin": { + "squid-typeorm-codegen": "bin/run.js" + } + }, + "node_modules/@subsquid/typeorm-codegen/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==", + "dev": true + }, + "node_modules/@subsquid/typeorm-codegen/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@subsquid/typeorm-config": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@subsquid/typeorm-config/-/typeorm-config-3.3.1.tgz", + "integrity": "sha512-d8n+GHAr05A1cQXBr+kbaU0WeSD7oQk+t7KwkGbC9hh80tkYiweKzQwS4+fJcJCbrpZe+B6mV8WY5eVR9ebZMw==", + "dependencies": { + "@subsquid/util-naming": "^1.2.1" + }, + "peerDependencies": { + "typeorm": "^0.3.17" + }, + "peerDependenciesMeta": { + "typeorm": { + "optional": true + } + } + }, + "node_modules/@subsquid/typeorm-migration": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@subsquid/typeorm-migration/-/typeorm-migration-1.2.2.tgz", + "integrity": "sha512-G22Eh7AuPHjLB7C30XNT+fVe2bGYmYI2EB/8Sf5kYfS0yCKvev2YWJNcvkyD6eswv8HgrekwEoj3BKjR5wH6yg==", + "dependencies": { + "@subsquid/typeorm-config": "^3.3.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-code-printer": "^1.2.1", + "commander": "^11.0.0", + "dotenv": "^16.3.1" + }, + "bin": { + "squid-typeorm-migration": "bin/squid-typeorm-migration", + "squid-typeorm-migration-apply": "bin/squid-typeorm-migration-apply", + "squid-typeorm-migration-create": "bin/squid-typeorm-migration-create", + "squid-typeorm-migration-generate": "bin/squid-typeorm-migration-generate", + "squid-typeorm-migration-revert": "bin/squid-typeorm-migration-revert" + }, + "peerDependencies": { + "typeorm": "^0.3.17" + } + }, + "node_modules/@subsquid/typeorm-migration/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/typeorm-migration/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@subsquid/typeorm-store": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@subsquid/typeorm-store/-/typeorm-store-1.2.4.tgz", + "integrity": "sha512-fcHp9cHEe1T1tVjV125CLbNjs/NIQKFW8bdK/stDn9prxuuwfiAGKvpztU52dKVuyQCUFL+8YTtFt2y1i7ZEBA==", + "dependencies": { + "@subsquid/typeorm-config": "^3.3.1", + "@subsquid/util-internal": "^2.5.2" + }, + "peerDependencies": { + "typeorm": "^0.3.17" + } + }, + "node_modules/@subsquid/typeorm-store/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/util-internal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-1.1.0.tgz", + "integrity": "sha512-O6m666RDcWEw4vb3bmeNZKlAa1rGOHQvS0nhZFTBXnxZpqK/pU5N0jrQ7X/3is0pY2RKxFoxTurZjhv4QdxtqA==" + }, + "node_modules/@subsquid/util-internal-archive-client": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-archive-client/-/util-internal-archive-client-0.0.1.tgz", + "integrity": "sha512-Sr+m1vxAArPIdsjyKVOpjU57JlVujBpI8NEeHqeA6twSb40wasOLAeq775WyYFynucltNRSgIiwXBIo0t02D6g==", + "dependencies": { + "@subsquid/http-client": "^1.3.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-range": "^0.0.1" + }, + "peerDependencies": { + "@subsquid/logger": "^1.3.1" + }, + "peerDependenciesMeta": { + "@subsquid/logger": { + "optional": true + } + } + }, + "node_modules/@subsquid/util-internal-archive-client/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/util-internal-binary-heap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-binary-heap/-/util-internal-binary-heap-1.0.0.tgz", + "integrity": "sha512-88auuc8yNFmCZugmJSTYzS7WM/nN2obKGQCgrl8Jty5rJUFbqazGSi8icqftKhv6MPtUMJ3PSTRLiTFXAUGnAA==" + }, + "node_modules/@subsquid/util-internal-code-printer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-code-printer/-/util-internal-code-printer-1.2.1.tgz", + "integrity": "sha512-9l0kCm50hQfRjzplIZs9kHooqxczG82fzAexlD6x1SjdLDU1NfYA0uGxgE6pweKydgd7LCb9ICc5gfDvbWtdaw==" + }, + "node_modules/@subsquid/util-internal-config": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-config/-/util-internal-config-2.2.1.tgz", + "integrity": "sha512-yOyIzn5Gx4aawtOEkY/Bxvo57WBqU/vRvpG/nsyFWOEEC/opmxH5Tl3hDPdoeF+/+AN6a9AEprGAMK2Wesj8LQ==", + "dev": true, + "dependencies": { + "@exodus/schemasafe": "^1.3.0", + "jsonc-parser": "^3.2.0" + } + }, + "node_modules/@subsquid/util-internal-counters": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-counters/-/util-internal-counters-1.3.1.tgz", + "integrity": "sha512-bc22t8lEvoCBn31F+B763E81+ZDaL7ufpwr0VLXZzcA5wZ6NEqqRfs4bJtPeBNGEjyeLLrItXWxfjSkR7sGKAg==" + }, + "node_modules/@subsquid/util-internal-hex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-hex/-/util-internal-hex-1.2.1.tgz", + "integrity": "sha512-R7TYDsftjguapzWia97WGvcF4s65VKArzSga5i1i4aZSq9Z330kPYpgAUkqDGsJqD/Ki3PTE4cXhuKLRyMHPvg==" + }, + "node_modules/@subsquid/util-internal-http-server": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-http-server/-/util-internal-http-server-1.2.1.tgz", + "integrity": "sha512-aQIodM3xWDu8wxllOONU5Fy6hmYYAZzS2PglC2FfdUi6HUxaZ8aCUkjFisG56tglhsoAh/TQSQX1YhCX00MCcg==", + "dependencies": { + "stoppable": "^1.1.0" + } + }, + "node_modules/@subsquid/util-internal-ingest-tools": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-ingest-tools/-/util-internal-ingest-tools-0.0.2.tgz", + "integrity": "sha512-Nx5LDWq9B1sVAXg6qDI0zVmzfwP1Mk5Rrn79OJc4eKLvZTrTIk2vyM5SB4n1kwQk6KRuQYI9dfiNWdcm+9rGfA==", + "dependencies": { + "@subsquid/logger": "^1.3.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-range": "^0.0.1" + } + }, + "node_modules/@subsquid/util-internal-ingest-tools/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/util-internal-json": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-json/-/util-internal-json-1.2.1.tgz", + "integrity": "sha512-Jtbhur/QaRk727fiZ/w8so0M0o4BIkfvnT6zBnC3s1mQ9fKve0Q6aj22gbimpX7Whj6tAGF0Bz8LFhbAethbkA==", + "dependencies": { + "@subsquid/util-internal-hex": "^1.2.1" + } + }, + "node_modules/@subsquid/util-internal-processor-tools": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-processor-tools/-/util-internal-processor-tools-3.1.0.tgz", + "integrity": "sha512-uEa8Bw/xvSfiagbK8IFt1OEgR7hacfblPZXH5EV4cAIKoIVOonhnkJEPRWqI3ZaDHl+8Z9p909tlsEd46sXenw==", + "dependencies": { + "@subsquid/logger": "^1.3.1", + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-counters": "^1.3.1", + "@subsquid/util-internal-prometheus-server": "^1.2.1", + "@subsquid/util-internal-range": "^0.0.1", + "prom-client": "^14.2.0" + } + }, + "node_modules/@subsquid/util-internal-processor-tools/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/util-internal-prometheus-server": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-prometheus-server/-/util-internal-prometheus-server-1.2.1.tgz", + "integrity": "sha512-GhbsEmv0xAkaBaxwZGRavMIO0h68V6LctZIvxsrrPr695bI1mrXKSYDvVvUwLXQ3aDPy9PIQiKdbSjNa60JW6Q==", + "dependencies": { + "@subsquid/util-internal-http-server": "^1.2.1" + }, + "peerDependencies": { + "prom-client": "^14.2.0" + } + }, + "node_modules/@subsquid/util-internal-range": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-range/-/util-internal-range-0.0.1.tgz", + "integrity": "sha512-9hqlPdTJeR9j9+1L3ymOPC0/qJ2IemGkrHmkTq+gwkjtGKmiXuXw4WLgt0Ps5aeupWKfP7UFy1hDE9DZQFseog==", + "dependencies": { + "@subsquid/util-internal": "^2.5.2", + "@subsquid/util-internal-binary-heap": "^1.0.0" + } + }, + "node_modules/@subsquid/util-internal-range/node_modules/@subsquid/util-internal": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", + "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + }, + "node_modules/@subsquid/util-internal-read-lines": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-read-lines/-/util-internal-read-lines-1.2.1.tgz", + "integrity": "sha512-Fh7lGlIwFr88pJ39UdkDeQ2z8JEDk13OuoHJHTmgLtThI4kvmDSpVgMdIUUh9nrzFrP/rzlDsvjACTw4D/mTHw==", + "dev": true + }, + "node_modules/@subsquid/util-naming": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-naming/-/util-naming-1.2.1.tgz", + "integrity": "sha512-l5rvAXG7TxMPeB5kFTTZWisgN0DNe1mVBHT2V2/nxUx4sOfYfneWIN/+02YqJI/GHX9FoOTB6ru7WLfQEMhvhg==", + "dependencies": { + "camelcase": "^6.3.0", + "inflected": "^2.1.0" + } + }, + "node_modules/@subsquid/util-xxhash": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@subsquid/util-xxhash/-/util-xxhash-1.2.1.tgz", + "integrity": "sha512-wobgbKK0fd+3ufUVjxcx4zaYII9JY7hbIStyO9M9Q5xrdihiWM5APX27sRuoO8X8oSj34v44JpIMxC8Rbpy3xQ==", + "dependencies": { + "xxhash-wasm": "^1.0.2", + "xxhashjs": "^0.2.2" + } + }, + "node_modules/@substrate/calc": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@substrate/calc/-/calc-0.2.8.tgz", + "integrity": "sha512-1c3mxf35FBeOswduhy0Wil9s4exHahXFo974qa0Ci2AORX8JTxmwhBb10+3Ls9iWoTFwvgOaFr9v1HeRL5tCig==" + }, + "node_modules/@substrate/connect": { + "version": "0.7.33", + "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.33.tgz", + "integrity": "sha512-1B984/bmXVQvTT9oV3c3b7215lvWmulP9rfP3T3Ri+OU3uIsyCzYw0A+XG6J8/jgO2FnroeNIBWlgoLaUM1uzw==", + "hasInstallScript": true, + "optional": true, + "peer": true, + "dependencies": { + "@substrate/connect-extension-protocol": "^1.0.1", + "smoldot": "2.0.1" + } + }, + "node_modules/@substrate/connect-extension-protocol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz", + "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==", + "optional": true, + "peer": true + }, + "node_modules/@substrate/ss58-registry": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.44.0.tgz", + "integrity": "sha512-7lQ/7mMCzVNSEfDS4BCqnRnKCFKpcOaPrxMeGTXHX1YQzM/m2BBHjbK2C3dJvjv7GYxMiaTq/HdWQj1xS6ss+A==" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/accepts": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.6.tgz", + "integrity": "sha512-6+qlUg57yfE9OO63wnsJXLeq9cG3gSHBBIxNMOjNrbDRlDnm/NaR7RctfYcVCPq+j7d+MwOxqVEludH5+FKrlg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/bn.js": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", + "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.37", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", + "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + }, + "node_modules/@types/express": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", + "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, + "node_modules/@types/mime": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.3.tgz", + "integrity": "sha512-i8MBln35l856k5iOhKk2XJ4SeAWg75mLIpZB4v6imOagKL6twsukBZGDMNhdOVk7yRFTMPpfILocMos59Q1otQ==" + }, + "node_modules/@types/node": { + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", + "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", + "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==" + }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", + "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/apollo-datasource": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-3.3.2.tgz", + "integrity": "sha512-L5TiS8E2Hn/Yz7SSnWIVbZw0ZfEIXZCa5VUiVxD9P53JvSrf4aStvsFDlGWPvpIdCR+aly2CfoB79B9/JjKFqg==", + "deprecated": "The `apollo-datasource` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/utils.keyvaluecache": "^1.0.1", + "apollo-server-env": "^4.2.1" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/apollo-reporting-protobuf": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-3.4.0.tgz", + "integrity": "sha512-h0u3EbC/9RpihWOmcSsvTW2O6RXVaD/mPEjfrPkxRPTEPWqncsgOoRJw+wih4OqfH3PvTJvoEIf4LwKrUaqWog==", + "deprecated": "The `apollo-reporting-protobuf` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/usage-reporting-protobuf` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/protobufjs": "1.2.6" + } + }, + "node_modules/apollo-reporting-protobuf/node_modules/@apollo/protobufjs": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.6.tgz", + "integrity": "sha512-Wqo1oSHNUj/jxmsVp4iR3I480p6qdqHikn38lKrFhfzcDJ7lwd7Ck7cHRl4JE81tWNArl77xhnG/OkZhxKBYOw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + }, + "bin": { + "apollo-pbjs": "bin/pbjs", + "apollo-pbts": "bin/pbts" + } + }, + "node_modules/apollo-reporting-protobuf/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" + }, + "node_modules/apollo-server-core": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-3.12.1.tgz", + "integrity": "sha512-9SF5WAkkV0FZQ2HVUWI9Jada1U0jg7e8NCN9EklbtvaCeUlOLyXyM+KCWuZ7+dqHxjshbtcwylPHutt3uzoNkw==", + "deprecated": "The `apollo-server-core` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/utils.keyvaluecache": "^1.0.1", + "@apollo/utils.logger": "^1.0.0", + "@apollo/utils.usagereporting": "^1.0.0", + "@apollographql/apollo-tools": "^0.5.3", + "@apollographql/graphql-playground-html": "1.6.29", + "@graphql-tools/mock": "^8.1.2", + "@graphql-tools/schema": "^8.0.0", + "@josephg/resolvable": "^1.0.0", + "apollo-datasource": "^3.3.2", + "apollo-reporting-protobuf": "^3.4.0", + "apollo-server-env": "^4.2.1", + "apollo-server-errors": "^3.3.1", + "apollo-server-plugin-base": "^3.7.2", + "apollo-server-types": "^3.8.0", + "async-retry": "^1.2.1", + "fast-json-stable-stringify": "^2.1.0", + "graphql-tag": "^2.11.0", + "loglevel": "^1.6.8", + "lru-cache": "^6.0.0", + "node-abort-controller": "^3.0.1", + "sha.js": "^2.4.11", + "uuid": "^9.0.0", + "whatwg-mimetype": "^3.0.0" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-core/node_modules/@graphql-tools/merge": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.3.1.tgz", + "integrity": "sha512-BMm99mqdNZbEYeTPK3it9r9S6rsZsQKtlqJsSBknAclXq2pGEfOxjcIZi+kBSkHZKPKCRrYDd5vY0+rUmIHVLg==", + "dependencies": { + "@graphql-tools/utils": "8.9.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/apollo-server-core/node_modules/@graphql-tools/schema": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.5.1.tgz", + "integrity": "sha512-0Esilsh0P/qYcB5DKQpiKeQs/jevzIadNTaT0jeWklPMwNbT7yMX4EqZany7mbeRRlSRwMzNzL5olyFdffHBZg==", + "dependencies": { + "@graphql-tools/merge": "8.3.1", + "@graphql-tools/utils": "8.9.0", + "tslib": "^2.4.0", + "value-or-promise": "1.0.11" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/apollo-server-core/node_modules/@graphql-tools/utils": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.9.0.tgz", + "integrity": "sha512-pjJIWH0XOVnYGXCqej8g/u/tsfV4LvLlj0eATKQu5zwnxd/TiTHq7Cg313qUPTFFHZ3PP5wJ15chYVtLDwaymg==", + "dependencies": { + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/apollo-server-core/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/apollo-server-core/node_modules/value-or-promise": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", + "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/apollo-server-env": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-4.2.1.tgz", + "integrity": "sha512-vm/7c7ld+zFMxibzqZ7SSa5tBENc4B0uye9LTfjJwGoQFY5xsUPH5FpO5j0bMUDZ8YYNbrF9SNtzc5Cngcr90g==", + "deprecated": "The `apollo-server-env` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/utils.fetcher` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/apollo-server-env/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/apollo-server-errors": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-3.3.1.tgz", + "integrity": "sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA==", + "deprecated": "The `apollo-server-errors` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-express": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-3.12.1.tgz", + "integrity": "sha512-5A9efrhEXqDx08BnORWf0zPYCABENqur47VZZW8osQpSSnMINqzJiV5RMrzz8wIznecRRhEcz+BqLdiexqZdgg==", + "deprecated": "The `apollo-server-express` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@types/accepts": "^1.3.5", + "@types/body-parser": "1.19.2", + "@types/cors": "2.8.12", + "@types/express": "4.17.14", + "@types/express-serve-static-core": "4.17.31", + "accepts": "^1.3.5", + "apollo-server-core": "^3.12.1", + "apollo-server-types": "^3.8.0", + "body-parser": "^1.19.0", + "cors": "^2.8.5", + "parseurl": "^1.3.3" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "express": "^4.17.1", + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-plugin-base": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-3.7.2.tgz", + "integrity": "sha512-wE8dwGDvBOGehSsPTRZ8P/33Jan6/PmL0y0aN/1Z5a5GcbFhDaaJCjK5cav6npbbGL2DPKK0r6MPXi3k3N45aw==", + "deprecated": "The `apollo-server-plugin-base` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "apollo-server-types": "^3.8.0" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-plugin-response-cache": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/apollo-server-plugin-response-cache/-/apollo-server-plugin-response-cache-3.7.1.tgz", + "integrity": "sha512-3FHwwySf1kQl8dGC+2E08LtDeFGUOeqckLchAD1REYx1vwMZbGhmEIwaNezjXwxkTM5Y7l38n0vQTka6YoQN7w==", + "deprecated": "The `apollo-server-plugin-response-cache` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server-plugin-response-cache` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/utils.keyvaluecache": "^1.0.1", + "apollo-server-plugin-base": "^3.6.3", + "apollo-server-types": "^3.6.3" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-types": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-3.8.0.tgz", + "integrity": "sha512-ZI/8rTE4ww8BHktsVpb91Sdq7Cb71rdSkXELSwdSR0eXu600/sY+1UXhTWdiJvk+Eq5ljqoHLwLbY2+Clq2b9A==", + "deprecated": "The `apollo-server-types` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/utils.keyvaluecache": "^1.0.1", + "@apollo/utils.logger": "^1.0.0", + "apollo-reporting-protobuf": "^3.4.0", + "apollo-server-env": "^4.2.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bintrees": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" + }, + "node_modules/blake2b": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/blake2b/-/blake2b-2.1.4.tgz", + "integrity": "sha512-AyBuuJNI64gIvwx13qiICz6H6hpmjvYS5DGkG6jbXMOT8Z3WUJ3V1X0FlhIoT1b/5JtHE3ki+xjtMvu1nn+t9A==", + "dependencies": { + "blake2b-wasm": "^2.4.0", + "nanoassert": "^2.0.0" + } + }, + "node_modules/blake2b-wasm": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/blake2b-wasm/-/blake2b-wasm-2.4.0.tgz", + "integrity": "sha512-S1kwmW2ZhZFFFOghcx73+ZajEfKBqhP82JMssxtLVMxlaPea1p9uoLiUZ5WYyHn0KddwbLc+0vh4wR0KBNoT5w==", + "dependencies": { + "b4a": "^1.0.1", + "nanoassert": "^2.0.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "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.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/bufferutil": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", + "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001571", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001571.tgz", + "integrity": "sha512-tYq/6MoXhdezDLFZuCO/TKboTzuQ/xR5cFdgXPfDtM7/kchBO3b4VWghE/OAi/DV7tTdhmLjZiZBZi1fA/GheQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==" + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/data-urls/node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/dataloader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", + "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/deep-equal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.1", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "optional": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/dset": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", + "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/easy-table": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", + "integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "optionalDependencies": { + "wcwidth": "^1.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.616", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.616.tgz", + "integrity": "sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "peer": true + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "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.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/graphql": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", + "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/graphql-parse-resolve-info": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/graphql-parse-resolve-info/-/graphql-parse-resolve-info-4.13.0.tgz", + "integrity": "sha512-VVJ1DdHYcR7hwOGQKNH+QTzuNgsLA8l/y436HtP9YHoX6nmwXRWq3xWthU3autMysXdm0fQUbhTZCx0W9ICozw==", + "dependencies": { + "debug": "^4.1.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=8.6" + }, + "peerDependencies": { + "graphql": ">=0.9 <0.14 || ^14.0.2 || ^15.4.0 || ^16.3.0" + } + }, + "node_modules/graphql-parse-resolve-info/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/graphql-parse-resolve-info/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/graphql-ws": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.14.2.tgz", + "integrity": "sha512-LycmCwhZ+Op2GlHz4BZDsUYHKRiiUz+3r9wbhBATMETNlORQJAaFlAgTFoeRh6xQoQegwYwIylVD1Qns9/DA3w==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": ">=0.11 <=16" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflected": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/inflected/-/inflected-2.1.0.tgz", + "integrity": "sha512-hAEKNxvHf2Iq3H60oMBHkB4wl5jn3TPF3+fXek/sRwAB5gP9xWs4r7aweSF95f99HFoz69pnZTcu8f0SIHV18w==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "dependencies": { + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ioredis": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", + "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/ioredis/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ioredis/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/jsdom/node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "peer": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/loglevel": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", + "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/lru-cache": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.1.tgz", + "integrity": "sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mock-socket": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz", + "integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==", + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoassert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz", + "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node_modules/nock": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.4.0.tgz", + "integrity": "sha512-W8NVHjO/LCTNA64yxAPHV/K47LpGYcVzgKd3Q0n6owhwvD0Dgoterc25R4rnZbckJEb6Loxz1f5QMuJpJnbSyQ==", + "peer": true, + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, + "node_modules/nock/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nock/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "peer": true + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-gyp-build": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prom-client": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.2.0.tgz", + "integrity": "sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA==", + "dependencies": { + "tdigest": "^0.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smoldot": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.1.tgz", + "integrity": "sha512-Wqw2fL/sELQByLSeeTX1Z/d0H4McmphPMx8vh6UZS/bIIDx81oU7s/drmx2iL/ME36uk++YxpRuJey8/MOyfOA==", + "optional": true, + "peer": true, + "dependencies": { + "ws": "^8.8.1" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/sync-fetch": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.5.2.tgz", + "integrity": "sha512-6gBqqkHrYvkH65WI2bzrDwrIKmt3U10s4Exnz3dYuE5Ah62FIfNv/F63inrNhu2Nyh3GH5f42GKU3RrSJoaUyQ==", + "dependencies": { + "node-fetch": "^2.6.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/sync-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/tdigest": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", + "dependencies": { + "bintrees": "1.0.2" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", + "dev": true + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typeorm": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.17.tgz", + "integrity": "sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==", + "dependencies": { + "@sqltools/formatter": "^1.2.5", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "chalk": "^4.1.2", + "cli-highlight": "^2.1.11", + "date-fns": "^2.29.3", + "debug": "^4.3.4", + "dotenv": "^16.0.3", + "glob": "^8.1.0", + "mkdirp": "^2.1.3", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.5.0", + "uuid": "^9.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, + "engines": { + "node": ">= 12.9.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0", + "@sap/hana-client": "^2.12.25", + "better-sqlite3": "^7.1.2 || ^8.0.0", + "hdb-pool": "^0.1.6", + "ioredis": "^5.0.4", + "mongodb": "^5.2.0", + "mssql": "^9.1.1", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^5.1.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/value-or-promise": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", + "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", + "engines": { + "node": ">=12" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "optional": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/websocket": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", + "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.15.1.tgz", + "integrity": "sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/xss": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.14.tgz", + "integrity": "sha512-og7TEJhXvn1a7kzZGQ7ETjdQVS2UfZyTlsEdDOqvQF7GoxNfY+0YLCzBy1kPdsDDx4QuNAonQPddpsn6Xl/7sw==", + "dependencies": { + "commander": "^2.20.3", + "cssfilter": "0.0.10" + }, + "bin": { + "xss": "bin/xss" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/xss/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/xxhash-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz", + "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==" + }, + "node_modules/xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dependencies": { + "cuint": "^0.2.2" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", + "engines": { + "node": ">=0.10.32" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/indexer/package.json b/indexer/package.json new file mode 100644 index 0000000..87cba11 --- /dev/null +++ b/indexer/package.json @@ -0,0 +1,42 @@ +{ + "name": "nft-marketplace-indexer", + "private": true, + "engines": { + "node": ">=16" + }, + "scripts": { + "build": "rm -rf lib && tsc", + "run": "sqd process", + "migrations:generate": "sqd migration:generate", + "migrations:apply": "sqd migration:apply", + "format": "prettier --write \"src/**/*.ts\"" + }, + "dependencies": { + "@gear-js/api": "^0.35.2", + "@polkadot/types": "^10.11.2", + "@subsquid/archive-registry": "^3.3.0", + "@subsquid/graphql-server": "^4.3.1", + "@subsquid/ss58": "^2.0.1", + "@subsquid/substrate-processor": "^7.2.1", + "@subsquid/typeorm-migration": "^1.2.2", + "@subsquid/typeorm-store": "^1.2.4", + "dotenv": "^16.3.1", + "pg": "8.11.3", + "typeorm": "^0.3.17" + }, + "devDependencies": { + "@subsquid/substrate-metadata-explorer": "^3.1.1", + "@subsquid/substrate-typegen": "^8.0.1", + "@subsquid/typeorm-codegen": "^1.3.2", + "@types/node": "^20.8.4", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^27.2.5", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "typescript": "^5.2.2" + } +} diff --git a/indexer/renovate.json b/indexer/renovate.json new file mode 100644 index 0000000..202c130 --- /dev/null +++ b/indexer/renovate.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ], + "packageRules": [ + { + "groupName": "@subsquid", + "matchPackagePatterns": [ + "^@subsquid/" + ], + "matchUpdateTypes": [ + "minor", + "patch", + "pin", + "digest" + ] + }, + { + "matchPackagePatterns": ["*"], + "excludePackagePatterns": ["^@subsquid/"], + "enabled": false + } + ], + // "automerge": true, + "automergeType": "pr", + "automergeStrategy": "squash", + "ignoreTests": true +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql new file mode 100644 index 0000000..29ca1c2 --- /dev/null +++ b/indexer/schema.graphql @@ -0,0 +1,68 @@ +type Marketplace @entity { + id: ID! + collections: [Collection!]! @derivedFrom(field: "marketplace") + collectionTypes: [CollectionType!]! @derivedFrom(field: "marketplace") +} + +type CollectionType @entity { + id: ID! + description: String! + type: String! + metaUrl: String! + metaStr: String! + marketplace: Marketplace! +} + +type Collection @entity { + id: ID! + marketplace: Marketplace! + type: CollectionType! + admin: String! + name: String! + description: String! + userMintLimit: BigInt + tokensLimit: BigInt + collectionImage: String! + transferable: Boolean! + approvable: Boolean! + burnable: Boolean! + sellable: Boolean! + attandable: Boolean! + nfts: [Nft!]! @derivedFrom(field: "collection") + tags: [String!]! +} + +type Nft @entity { + id: ID! + owner: String! + name: String! + description: String! + idInCollection: Int! + collection: Collection! + mediaUrl: String! + mintedAt: DateTime! + approvedAccount: String + onSale: Boolean! + transfers: [Transfer!]! @derivedFrom(field: "nft") + sales: [Sale!]! @derivedFrom(field: "nft") +} + +type Transfer @entity { + id: ID! + nft: Nft! + from: String! + to: String! + timestamp: DateTime! + blockNumber: String! + txHash: String! +} + +type Sale @entity { + id: ID! + nft: Nft! + owner: String! + price: BigInt! + timestamp: DateTime! + blockNumber: String! + isSold: Boolean! +} diff --git a/indexer/scripts/docker-run.sh b/indexer/scripts/docker-run.sh new file mode 100644 index 0000000..1947733 --- /dev/null +++ b/indexer/scripts/docker-run.sh @@ -0,0 +1,5 @@ +set -e +docker build . --target processor -t squid-processor +# make sure the port matches .env. +# For Linux, add --add-host=host.docker.internal:host-gateway +docker run --rm -e DB_HOST=host.docker.internal --env-file=.env squid-processor \ No newline at end of file diff --git a/indexer/scripts/sub-client.js b/indexer/scripts/sub-client.js new file mode 100644 index 0000000..87ba38a --- /dev/null +++ b/indexer/scripts/sub-client.js @@ -0,0 +1,42 @@ +const WebSocket = require('ws') +const { createClient } = require('graphql-ws'); + +const port = process.env.GQL_PORT || 4350 +const host = process.env.GQL_HOST || 'localhost' +const proto = process.env.GQL_PROTO || 'ws' + + +const client = createClient({ + webSocketImpl: WebSocket, + url: `${proto}://${host}:${port}/graphql`, +}); + +client.subscribe( + { + query: ` + subscription { + transfers(limit: 5, orderBy: timestamp_DESC) { + amount + blockNumber + from { + id + } + to { + id + } + } + } + `, + }, + { + next: (data) => { + console.log(`New transfers: ${JSON.stringify(data)}`); + }, + error: (error) => { + console.error('error', error); + }, + complete: () => { + console.log('done!'); + }, + } +); \ No newline at end of file diff --git a/indexer/squid.yaml b/indexer/squid.yaml new file mode 100644 index 0000000..8abf491 --- /dev/null +++ b/indexer/squid.yaml @@ -0,0 +1,18 @@ +manifestVersion: subsquid.io/v0.1 +name: sqd-nft-marketplace +version: 1 +description: Substrate squid template +build: +deploy: + addons: + postgres: + processor: + cmd: + - sqd + - process:prod + env: + RPC_ENDPOINT: ${{ secrets.RPC_ENDPOINT }} + api: + cmd: + - sqd + - serve:prod diff --git a/indexer/src/config.ts b/indexer/src/config.ts new file mode 100644 index 0000000..ec95b28 --- /dev/null +++ b/indexer/src/config.ts @@ -0,0 +1,4 @@ +export const config = { + marketplaceProgram: process.env.MARKETPLACE_PROGRAM, + nftProgram: process.env.NFT_PROGRAM, +}; diff --git a/indexer/src/main.ts b/indexer/src/main.ts new file mode 100644 index 0000000..45817ce --- /dev/null +++ b/indexer/src/main.ts @@ -0,0 +1,33 @@ +import { TypeormDatabase } from '@subsquid/typeorm-store'; + +import { processor } from './processor'; +import { config } from './config'; +import { EventsProcessing } from './processing/events.processing'; + +processor.run(new TypeormDatabase(), async (ctx) => { + const processing = new EventsProcessing(ctx.store); + for (const block of ctx.blocks) { + const events = [ + ...block.events, + ...block.extrinsics.flatMap((e) => e.events), + ].filter((e) => e.args && e.args.message); + for (const item of events) { + const { + message: { source, payload, details }, + } = item.args; + if (payload === '0x') { + continue; + } + if (details && details.code.__kind !== 'Success') { + continue; + } + if (config.nftProgram && config.nftProgram === source) { + await processing.handleNftEvent(block, payload, source); + } + if (config.marketplaceProgram && config.marketplaceProgram === source) { + await processing.handleMarketplaceEvent(block, payload, source); + } + } + } + await processing.saveAll(); +}); diff --git a/indexer/src/model/generated/collection.model.ts b/indexer/src/model/generated/collection.model.ts new file mode 100644 index 0000000..bd98a06 --- /dev/null +++ b/indexer/src/model/generated/collection.model.ts @@ -0,0 +1,75 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, + OneToMany as OneToMany_, +} from 'typeorm'; +import * as marshal from './marshal'; +import { Marketplace } from './marketplace.model'; +import { CollectionType } from './collectionType.model'; +import { Nft } from './nft.model'; + +@Entity_() +export class Collection { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Index_() + @ManyToOne_(() => Marketplace, { nullable: true }) + marketplace!: Marketplace; + + @Index_() + @ManyToOne_(() => CollectionType, { nullable: true }) + type!: CollectionType; + + @Column_('text', { nullable: false }) + admin!: string; + + @Column_('text', { nullable: false }) + name!: string; + + @Column_('text', { nullable: false }) + description!: string; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: true, + }) + userMintLimit!: bigint | undefined | null; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: true, + }) + tokensLimit!: bigint | undefined | null; + + @Column_('text', { nullable: false }) + collectionImage!: string; + + @Column_('bool', { nullable: false }) + transferable!: boolean; + + @Column_('bool', { nullable: false }) + approvable!: boolean; + + @Column_('bool', { nullable: false }) + burnable!: boolean; + + @Column_('bool', { nullable: false }) + sellable!: boolean; + + @Column_('bool', { nullable: false }) + attandable!: boolean; + + @OneToMany_(() => Nft, (e) => e.collection) + nfts!: Nft[]; + + @Column_('text', { array: true, nullable: false }) + tags!: string[]; +} diff --git a/indexer/src/model/generated/collectionType.model.ts b/indexer/src/model/generated/collectionType.model.ts new file mode 100644 index 0000000..394ba06 --- /dev/null +++ b/indexer/src/model/generated/collectionType.model.ts @@ -0,0 +1,34 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm'; +import { Marketplace } from './marketplace.model'; + +@Entity_() +export class CollectionType { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Column_('text', { nullable: false }) + description!: string; + + @Column_('text', { nullable: false }) + type!: string; + + @Column_('text', { nullable: false }) + metaUrl!: string; + + @Column_('text', { nullable: false }) + metaStr!: string; + + @Index_() + @ManyToOne_(() => Marketplace, { nullable: true }) + marketplace!: Marketplace; +} diff --git a/indexer/src/model/generated/index.ts b/indexer/src/model/generated/index.ts new file mode 100644 index 0000000..935528e --- /dev/null +++ b/indexer/src/model/generated/index.ts @@ -0,0 +1,6 @@ +export * from './marketplace.model'; +export * from './collectionType.model'; +export * from './collection.model'; +export * from './nft.model'; +export * from './transfer.model'; +export * from './sale.model'; diff --git a/indexer/src/model/generated/marketplace.model.ts b/indexer/src/model/generated/marketplace.model.ts new file mode 100644 index 0000000..a25bdf8 --- /dev/null +++ b/indexer/src/model/generated/marketplace.model.ts @@ -0,0 +1,23 @@ +import { + Entity as Entity_, + PrimaryColumn as PrimaryColumn_, + OneToMany as OneToMany_, +} from 'typeorm'; +import { Collection } from './collection.model'; +import { CollectionType } from './collectionType.model'; + +@Entity_() +export class Marketplace { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @OneToMany_(() => Collection, (e) => e.marketplace) + collections!: Collection[]; + + @OneToMany_(() => CollectionType, (e) => e.marketplace) + collectionTypes!: CollectionType[]; +} diff --git a/indexer/src/model/generated/marshal.ts b/indexer/src/model/generated/marshal.ts new file mode 100644 index 0000000..7f3d828 --- /dev/null +++ b/indexer/src/model/generated/marshal.ts @@ -0,0 +1,167 @@ +import assert from 'assert'; + +export interface Marshal { + fromJSON(value: unknown): T; + toJSON(value: T): S; +} + +export const string: Marshal = { + fromJSON(value: unknown): string { + assert(typeof value === 'string', 'invalid String'); + return value; + }, + toJSON(value) { + return value; + }, +}; + +export const id = string; + +export const int: Marshal = { + fromJSON(value: unknown): number { + assert(Number.isInteger(value), 'invalid Int'); + return value as number; + }, + toJSON(value) { + return value; + }, +}; + +export const float: Marshal = { + fromJSON(value: unknown): number { + assert(typeof value === 'number', 'invalid Float'); + return value as number; + }, + toJSON(value) { + return value; + }, +}; + +export const boolean: Marshal = { + fromJSON(value: unknown): boolean { + assert(typeof value === 'boolean', 'invalid Boolean'); + return value; + }, + toJSON(value: boolean): boolean { + return value; + }, +}; + +export const bigint: Marshal = { + fromJSON(value: unknown): bigint { + assert(typeof value === 'string', 'invalid BigInt'); + return BigInt(value); + }, + toJSON(value: bigint): string { + return value.toString(); + }, +}; + +export const bigdecimal: Marshal = { + fromJSON(value: unknown): bigint { + assert(typeof value === 'string', 'invalid BigDecimal'); + return decimal.BigDecimal(value); + }, + toJSON(value: any): string { + return value.toString(); + }, +}; + +// credit - https://github.com/Urigo/graphql-scalars/blob/91b4ea8df891be8af7904cf84751930cc0c6613d/src/scalars/iso-date/validator.ts#L122 +const RFC_3339_REGEX = + /^(\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60))(\.\d{1,})?([Z])$/; + +function isIsoDateTimeString(s: string): boolean { + return RFC_3339_REGEX.test(s); +} + +export const datetime: Marshal = { + fromJSON(value: unknown): Date { + assert(typeof value === 'string', 'invalid DateTime'); + assert(isIsoDateTimeString(value), 'invalid DateTime'); + return new Date(value); + }, + toJSON(value: Date): string { + return value.toISOString(); + }, +}; + +export const bytes: Marshal = { + fromJSON(value: unknown): Buffer { + assert(typeof value === 'string', 'invalid Bytes'); + assert(value.length % 2 === 0, 'invalid Bytes'); + assert(/^0x[0-9a-f]+$/i.test(value), 'invalid Bytes'); + return Buffer.from(value.slice(2), 'hex'); + }, + toJSON(value: Uint8Array): string { + if (Buffer.isBuffer(value)) { + return '0x' + value.toString('hex'); + } else { + return ( + '0x' + + Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString( + 'hex', + ) + ); + } + }, +}; + +export function fromList(list: unknown, f: (val: unknown) => T): T[] { + assert(Array.isArray(list)); + return list.map((val) => f(val)); +} + +export function nonNull(val: T | undefined | null): T { + assert(val != null, 'non-nullable value is null'); + return val; +} + +export const bigintTransformer = { + to(x?: bigint) { + return x?.toString(); + }, + from(s?: string): bigint | undefined { + return s == null ? undefined : BigInt(s); + }, +}; + +export const floatTransformer = { + to(x?: number) { + return x?.toString(); + }, + from(s?: string): number | undefined { + return s == null ? undefined : Number(s); + }, +}; + +export const bigdecimalTransformer = { + to(x?: any) { + return x?.toString(); + }, + from(s?: any): any | undefined { + return s == null ? undefined : decimal.BigDecimal(s); + }, +}; + +export function enumFromJson( + json: unknown, + enumObject: E, +): E[keyof E] { + assert(typeof json == 'string', 'invalid enum value'); + let val = (enumObject as any)[json]; + assert(typeof val == 'string', `invalid enum value`); + return val as any; +} + +const decimal = { + get BigDecimal(): any { + throw new Error('Package `@subsquid/big-decimal` is not installed'); + }, +}; + +try { + Object.defineProperty(decimal, 'BigDecimal', { + value: require('@subsquid/big-decimal').BigDecimal, + }); +} catch (e) {} diff --git a/indexer/src/model/generated/nft.model.ts b/indexer/src/model/generated/nft.model.ts new file mode 100644 index 0000000..bc0ac3f --- /dev/null +++ b/indexer/src/model/generated/nft.model.ts @@ -0,0 +1,55 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, + OneToMany as OneToMany_, +} from 'typeorm'; +import { Collection } from './collection.model'; +import { Transfer } from './transfer.model'; +import { Sale } from './sale.model'; + +@Entity_() +export class Nft { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Column_('text', { nullable: false }) + owner!: string; + + @Column_('text', { nullable: false }) + name!: string; + + @Column_('text', { nullable: false }) + description!: string; + + @Column_('int', { nullable: false }) + idInCollection!: number; + + @Index_() + @ManyToOne_(() => Collection, { nullable: true }) + collection!: Collection; + + @Column_('text', { nullable: false }) + mediaUrl!: string; + + @Column_('timestamp with time zone', { nullable: false }) + mintedAt!: Date; + + @Column_('text', { nullable: true }) + approvedAccount!: string | undefined | null; + + @Column_('bool', { nullable: false }) + onSale!: boolean; + + @OneToMany_(() => Transfer, (e) => e.nft) + transfers!: Transfer[]; + + @OneToMany_(() => Sale, (e) => e.nft) + sales!: Sale[]; +} diff --git a/indexer/src/model/generated/sale.model.ts b/indexer/src/model/generated/sale.model.ts new file mode 100644 index 0000000..725a94c --- /dev/null +++ b/indexer/src/model/generated/sale.model.ts @@ -0,0 +1,41 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm'; +import * as marshal from './marshal'; +import { Nft } from './nft.model'; + +@Entity_() +export class Sale { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Index_() + @ManyToOne_(() => Nft, { nullable: true }) + nft!: Nft; + + @Column_('text', { nullable: false }) + owner!: string; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + price!: bigint; + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date; + + @Column_('text', { nullable: false }) + blockNumber!: string; + + @Column_('bool', { nullable: false }) + isSold!: boolean; +} diff --git a/indexer/src/model/generated/transfer.model.ts b/indexer/src/model/generated/transfer.model.ts new file mode 100644 index 0000000..0f40ed6 --- /dev/null +++ b/indexer/src/model/generated/transfer.model.ts @@ -0,0 +1,37 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm'; +import { Nft } from './nft.model'; + +@Entity_() +export class Transfer { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Index_() + @ManyToOne_(() => Nft, { nullable: true }) + nft!: Nft; + + @Column_('text', { nullable: false }) + from!: string; + + @Column_('text', { nullable: false }) + to!: string; + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date; + + @Column_('text', { nullable: false }) + blockNumber!: string; + + @Column_('text', { nullable: false }) + txHash!: string; +} diff --git a/indexer/src/model/index.ts b/indexer/src/model/index.ts new file mode 100644 index 0000000..69e4e4e --- /dev/null +++ b/indexer/src/model/index.ts @@ -0,0 +1 @@ +export * from './generated'; diff --git a/indexer/src/processing/entities.storage.ts b/indexer/src/processing/entities.storage.ts new file mode 100644 index 0000000..bf73ee3 --- /dev/null +++ b/indexer/src/processing/entities.storage.ts @@ -0,0 +1,119 @@ +import { + Collection, + CollectionType, + Marketplace, + Nft, + Sale, + Transfer, +} from '../model'; +import { Store } from '@subsquid/typeorm-store'; + +export class EntitiesStorage { + // typeName -> CollectionType + private collectionTypes: Record = {}; + // collectionAddress -> Collection + private collections: Record = {}; + // // collectionAddress-tokenId -> Nft + private nfts: Record = {}; + private transfers: Transfer[] = []; + private sale: Record = {}; + private marketplace: Marketplace = new Marketplace(); + + constructor(private readonly store: Store) {} + + async saveAll() { + await Promise.all([ + this.store.save(Object.values(this.collectionTypes)), + this.store.save(Object.values(this.collections)), + this.store.save(Object.values(this.nfts)), + this.store.save(this.transfers), + this.store.save(Object.values(this.sale)), + ]); + } + + async getCollection(collectionAddress: string) { + if (this.collections[collectionAddress] !== undefined) { + return this.collections[collectionAddress]; + } + return this.store.findOne(Collection, { where: { id: collectionAddress } }); + } + + async getNft(collectionAddress: string, tokenId: number) { + const key = this.getNftKey(collectionAddress, tokenId); + if (this.nfts[key] !== undefined) { + return this.nfts[key]; + } + return this.store.findOne(Nft, { + where: { + collection: { + id: 'collectionAddress', + }, + idInCollection: tokenId, + }, + }); + } + + setCollection(collection: Collection) { + this.collections[collection.id] = collection; + } + + getSale(nft: Nft) { + const key = this.getNftKey(nft.collection.id, nft.idInCollection); + if (this.sale[key] !== undefined) { + return this.sale[key]; + } + return this.store.findOne(Sale, { + where: { + nft: { + collection: { + id: nft.collection.id, + }, + idInCollection: nft.idInCollection, + }, + isSold: false, + }, + }); + } + + setSale(sale: Sale) { + this.sale[this.getNftKey(sale.nft.collection.id, sale.nft.idInCollection)] = + sale; + } + + async deleteSale(sale: Sale) { + delete this.sale[ + this.getNftKey(sale.nft.collection.id, sale.nft.idInCollection) + ]; + await this.store.remove(sale); + } + + async deleteCollection(collection: Collection) { + delete this.collections[collection.id]; + await this.store.remove(collection); + } + + async getCollectionType( + typeName: string, + ): Promise { + if (this.collectionTypes[typeName] !== undefined) { + return this.collectionTypes[typeName]; + } + return this.store.findOne(CollectionType, { where: { type: typeName } }); + } + + setCollectionType(collectionType: CollectionType) { + this.collectionTypes[collectionType.type] = collectionType; + } + + setNft(nft: Nft) { + this.nfts[this.getNftKey(nft.collection.id, nft.idInCollection)] = nft; + } + + setTransfer(transfer: Transfer) { + this.transfers.push(transfer); + } + + private getNftKey(collectionAddress: string, idInCollection: number) { + return `${collectionAddress}-${idInCollection}`; + } +} diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts new file mode 100644 index 0000000..d54a317 --- /dev/null +++ b/indexer/src/processing/events.processing.ts @@ -0,0 +1,135 @@ +import { readFileSync } from 'fs'; +import { ProgramMetadata } from '@gear-js/api'; +import { + getMarketplaceEvent, + NftMarketplaceEventPlain, + NftMarketplaceEventType, +} from '../types/marketplace.events'; +import { getNftEvent, NftEventPlain, NftEventType } from '../types/nft.events'; +import { EntitiesStorage } from './entities.storage'; +import { INftMarketplaceEventHandler } from './marketplace/nft-marketplace.handler'; +import { NewCollectionAddedHandler } from './marketplace/new-collection-added.handler'; +import { Store } from '@subsquid/typeorm-store'; +import { Block } from '@subsquid/substrate-processor'; +import { AuctionCreatedHandler } from './marketplace/auction-created.handler'; +import { AuctionCanceledHandler } from './marketplace/auction-canceled.handler'; +import { CollectionDeletedHandler } from './marketplace/collection-deleted.handler'; +import { NftSoldHandler } from './marketplace/nft-sold.handler'; +import { InitializedHandler } from './nft/initialized.handler'; +import { INftEventHandler } from './nft/nft.handler'; +import { NftMintedHandler } from './nft/nft-minted.handler'; + +const marketplaceMeta = ProgramMetadata.from( + readFileSync('./assets/nft_marketplace.meta.txt', 'utf8'), +); +const nftMeta = ProgramMetadata.from( + readFileSync('./assets/nft.meta.txt', 'utf8'), +); + +const marketplaceEventsToHandler: Record< + NftMarketplaceEventType, + INftMarketplaceEventHandler | undefined +> = { + [NftMarketplaceEventType.NewCollectionAdded]: new NewCollectionAddedHandler(), + [NftMarketplaceEventType.CollectionCreated]: new NewCollectionAddedHandler(), + [NftMarketplaceEventType.AuctionCreated]: new AuctionCreatedHandler(), + [NftMarketplaceEventType.AuctionCanceled]: new AuctionCanceledHandler(), + [NftMarketplaceEventType.CollectionDeleted]: new CollectionDeletedHandler(), + [NftMarketplaceEventType.NftSold]: new NftSoldHandler(), + // TODO: handle marketplace and admin events + [NftMarketplaceEventType.AdminDeleted]: undefined, + [NftMarketplaceEventType.AdminsAdded]: undefined, + [NftMarketplaceEventType.ConfigUpdated]: undefined, + [NftMarketplaceEventType.OfferCreated]: undefined, + [NftMarketplaceEventType.OfferCanceled]: undefined, + [NftMarketplaceEventType.OfferAccepted]: undefined, + [NftMarketplaceEventType.BidAdded]: undefined, + [NftMarketplaceEventType.SaleNft]: undefined, + [NftMarketplaceEventType.SaleNftCanceled]: undefined, +}; + +const nftEventsToHandler: Record = { + [NftEventType.Initialized]: new InitializedHandler(), + [NftEventType.Minted]: new NftMintedHandler(), + [NftEventType.Approved]: undefined, + [NftEventType.ApprovalRevoked]: undefined, + [NftEventType.Expanded]: undefined, + [NftEventType.ConfigChanged]: undefined, + [NftEventType.ImageChanged]: undefined, + [NftEventType.MetadataAdded]: undefined, + [NftEventType.TokenInfoReceived]: undefined, + [NftEventType.Transferred]: undefined, +}; + +export class EventsProcessing { + private readonly entitiesStorage: EntitiesStorage; + + constructor(private readonly store: Store) { + this.entitiesStorage = new EntitiesStorage(store); + } + + saveAll() { + return this.entitiesStorage.saveAll(); + } + + async handleMarketplaceEvent(block: Block, payload: string, source: string) { + try { + console.log(`${block.header.hash}: handling marketplace event`); + const data = marketplaceMeta.createType( + marketplaceMeta.types.handle.output!, + payload, + ); + const parsed = data.toJSON() as { ok: NftMarketplaceEventPlain } | null; + if (!parsed || !parsed.ok) { + return; + } + const event = getMarketplaceEvent(parsed.ok); + if (!event) { + console.warn(`${block.header.hash}: unknown event type`, parsed); + return; + } + const eventHandler = marketplaceEventsToHandler[event.type]; + if (!eventHandler) { + console.warn( + `${block.header.hash}: no event handlers found for ${event.type}`, + ); + return; + } + await eventHandler.handle(block, event, this.entitiesStorage); + } catch (e) { + console.error( + `${block.header.hash}: error handling marketplace event`, + e, + ); + } + } + + async handleNftEvent(block: Block, payload: string, source: string) { + try { + console.log(`${block.header.hash}: handling nft event`); + const data = marketplaceMeta.createType( + nftMeta.types.handle.output!, + payload, + ); + const parsed = data.toJSON() as { ok: NftEventPlain } | null; + if (!parsed || !parsed.ok) { + return; + } + const event = getNftEvent(data); + if (!event) { + console.warn(`${block.header.hash}: unknown event type`, parsed); + return; + } + const eventHandler = nftEventsToHandler[event.type]; + if (!eventHandler) { + console.warn( + `${block.header.hash}: no nft event handlers found for ${event.type}`, + ); + return; + } + await eventHandler.handle(block, source, event, this.entitiesStorage); + } catch (e) { + console.error(`${block.header.hash}: error handling nft event`, e); + } + } +} diff --git a/indexer/src/processing/marketplace/auction-canceled.handler.ts b/indexer/src/processing/marketplace/auction-canceled.handler.ts new file mode 100644 index 0000000..0fb7742 --- /dev/null +++ b/indexer/src/processing/marketplace/auction-canceled.handler.ts @@ -0,0 +1,29 @@ +import { AuctionCanceled } from '../../types/marketplace.events'; +import { EntitiesStorage } from '../entities.storage'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Block } from '@subsquid/substrate-processor'; + +export class AuctionCanceledHandler implements INftMarketplaceEventHandler { + async handle( + block: Block, + event: AuctionCanceled, + storage: EntitiesStorage, + ): Promise { + const { collectionAddress, tokenId } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[AuctionCanceledHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const sale = await storage.getSale(nft); + if (sale === undefined) { + console.warn( + `[AuctionCanceledHandler] ${collectionAddress}-${tokenId}: sale is not found`, + ); + return; + } + await storage.deleteSale(sale); + } +} diff --git a/indexer/src/processing/marketplace/auction-created.handler.ts b/indexer/src/processing/marketplace/auction-created.handler.ts new file mode 100644 index 0000000..7d37e04 --- /dev/null +++ b/indexer/src/processing/marketplace/auction-created.handler.ts @@ -0,0 +1,45 @@ +import { AuctionCreated } from '../../types/marketplace.events'; +import { EntitiesStorage } from '../entities.storage'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Sale } from '../../model'; +import { Block } from '@subsquid/substrate-processor'; + +export class AuctionCreatedHandler implements INftMarketplaceEventHandler { + async handle( + block: Block, + event: AuctionCreated, + storage: EntitiesStorage, + ): Promise { + const { collectionAddress, tokenId, price, currentOwner } = event; + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[AuctionCreatedHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[AuctionCreatedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const sale = await storage.getSale(nft); + if (sale !== undefined) { + console.warn( + `[AuctionCreatedHandler] ${collectionAddress}-${tokenId}: sale is already exists`, + ); + return; + } + storage.setSale( + new Sale({ + nft, + price, + owner: currentOwner, + isSold: false, + blockNumber: block.header.hash, + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/collection-created.handler.ts b/indexer/src/processing/marketplace/collection-created.handler.ts new file mode 100644 index 0000000..e235382 --- /dev/null +++ b/indexer/src/processing/marketplace/collection-created.handler.ts @@ -0,0 +1,35 @@ +import { CollectionCreated } from '../../types/marketplace.events'; +import { EntitiesStorage } from '../entities.storage'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Collection } from '../../model'; +import { Block } from '@subsquid/substrate-processor'; + +export class CollectionCreatedHandler implements INftMarketplaceEventHandler { + async handle( + block: Block, + event: CollectionCreated, + storage: EntitiesStorage, + ): Promise { + const { typeName, collectionAddress } = event; + const existingCollection = await storage.getCollection(collectionAddress); + if (existingCollection !== undefined) { + console.warn( + `[CollectionCreatedHandler] ${collectionAddress}: collection already exists`, + ); + return; + } + const collectionType = await storage.getCollectionType(typeName); + if (collectionType === undefined) { + console.warn( + `[CollectionCreatedHandler] ${collectionAddress}: collection type ${typeName} does not exist`, + ); + return; + } + storage.setCollection( + new Collection({ + id: collectionAddress, + type: collectionType, + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/collection-deleted.handler.ts b/indexer/src/processing/marketplace/collection-deleted.handler.ts new file mode 100644 index 0000000..4a0bbce --- /dev/null +++ b/indexer/src/processing/marketplace/collection-deleted.handler.ts @@ -0,0 +1,22 @@ +import { CollectionDeleted } from '../../types/marketplace.events'; +import { EntitiesStorage } from '../entities.storage'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Block } from '@subsquid/substrate-processor'; + +export class CollectionDeletedHandler implements INftMarketplaceEventHandler { + async handle( + block: Block, + event: CollectionDeleted, + storage: EntitiesStorage, + ): Promise { + const { collectionAddress } = event; + const existingCollection = await storage.getCollection(collectionAddress); + if (existingCollection === undefined) { + console.warn( + `[CollectionDeletedHandler] ${collectionAddress}: collection not exists`, + ); + return; + } + await storage.deleteCollection(existingCollection); + } +} diff --git a/indexer/src/processing/marketplace/new-collection-added.handler.ts b/indexer/src/processing/marketplace/new-collection-added.handler.ts new file mode 100644 index 0000000..a6eb8ca --- /dev/null +++ b/indexer/src/processing/marketplace/new-collection-added.handler.ts @@ -0,0 +1,31 @@ +import { NewCollectionAdded } from '../../types/marketplace.events'; +import { EntitiesStorage } from '../entities.storage'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { CollectionType } from '../../model'; +import { Block } from '@subsquid/substrate-processor'; + +export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { + async handle( + block: Block, + event: NewCollectionAdded, + storage: EntitiesStorage, + ): Promise { + const { codeId, metaLink, typeName, typeDescription } = event; + const existingCollectionType = await storage.getCollectionType(typeName); + if (existingCollectionType !== undefined) { + console.warn( + `[NewCollectionAddedHandler]: Collection type ${typeName} already exists`, + ); + return; + } + storage.setCollectionType( + new CollectionType({ + id: codeId, + description: typeDescription, + type: typeName, + metaUrl: metaLink, + metaStr: '', + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/nft-marketplace.handler.ts b/indexer/src/processing/marketplace/nft-marketplace.handler.ts new file mode 100644 index 0000000..761954e --- /dev/null +++ b/indexer/src/processing/marketplace/nft-marketplace.handler.ts @@ -0,0 +1,11 @@ +import { NftMarketplaceEvent } from '../../types/marketplace.events'; +import { EntitiesStorage } from '../entities.storage'; +import { Block } from '@subsquid/substrate-processor'; + +export interface INftMarketplaceEventHandler { + handle( + block: Block, + event: NftMarketplaceEvent, + storage: EntitiesStorage, + ): Promise; +} diff --git a/indexer/src/processing/marketplace/nft-sold.handler.ts b/indexer/src/processing/marketplace/nft-sold.handler.ts new file mode 100644 index 0000000..2e980c9 --- /dev/null +++ b/indexer/src/processing/marketplace/nft-sold.handler.ts @@ -0,0 +1,57 @@ +import { NftSold } from '../../types/marketplace.events'; +import { EntitiesStorage } from '../entities.storage'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Sale, Transfer } from '../../model'; +import { Block } from '@subsquid/substrate-processor'; + +export class NftSoldHandler implements INftMarketplaceEventHandler { + async handle( + block: Block, + event: NftSold, + storage: EntitiesStorage, + ): Promise { + const { collectionAddress, tokenId, price, currentOwner } = event; + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[NftSoldHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[AuctionCreatedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const sale = await storage.getSale(nft); + if (sale !== undefined) { + console.warn( + `[AuctionCreatedHandler] ${collectionAddress}-${tokenId}: sale is already exists`, + ); + return; + } + storage.setSale( + new Sale({ + nft, + price, + owner: currentOwner, + isSold: true, + blockNumber: block.header.hash, + }), + ); + storage.setTransfer( + new Transfer({ + nft, + from: nft.owner, + to: currentOwner, + blockNumber: block.header.hash, + }), + ); + storage.setNft({ + ...nft, + owner: currentOwner, + }); + } +} diff --git a/indexer/src/processing/nft/initialized.handler.ts b/indexer/src/processing/nft/initialized.handler.ts new file mode 100644 index 0000000..9377305 --- /dev/null +++ b/indexer/src/processing/nft/initialized.handler.ts @@ -0,0 +1,55 @@ +import { Block } from '@subsquid/substrate-processor'; +import { InitializedEvent } from '../../types/nft.events'; +import { EntitiesStorage } from '../entities.storage'; +import { INftEventHandler } from './nft.handler'; +import { Collection } from '../../model'; + +export class InitializedHandler implements INftEventHandler { + async handle( + block: Block, + collectionAddress: string, + event: InitializedEvent, + storage: EntitiesStorage, + ): Promise { + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[InitializedHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + let { + name, + description, + additionalLinks, + approvable, + attendable, + burnable, + collectionImg, + collectionLogo, + collectionTags, + paymentForMint, + royalty, + sellable, + transferable, + userMintLimit, + } = event.config; + storage.setCollection({ + ...collection, + name, + description, + additionalLinks, + approvable, + attendable, + burnable, + collectionImage: collectionImg, + collectionLogo, + tags: collectionTags, + paymentForMint, + royalty, + sellable, + transferable, + tokensLimit: userMintLimit, + } as Collection); + } +} diff --git a/indexer/src/processing/nft/nft-minted.handler.ts b/indexer/src/processing/nft/nft-minted.handler.ts new file mode 100644 index 0000000..7adfb48 --- /dev/null +++ b/indexer/src/processing/nft/nft-minted.handler.ts @@ -0,0 +1,35 @@ +import { Block } from '@subsquid/substrate-processor'; +import { MintedEvent } from '../../types/nft.events'; +import { EntitiesStorage } from '../entities.storage'; +import { INftEventHandler } from './nft.handler'; +import { Nft } from '../../model'; + +export class NftMintedHandler implements INftEventHandler { + async handle( + block: Block, + collectionAddress: string, + event: MintedEvent, + storage: EntitiesStorage, + ): Promise { + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[NftMintedHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + const { tokenId } = event; + let { description, mediaUrl, metadata, name, owner } = event.nftData; + storage.setNft( + new Nft({ + collection, + description, + idInCollection: tokenId, + mediaUrl, + name, + owner, + mintedAt: new Date(), + }), + ); + } +} diff --git a/indexer/src/processing/nft/nft.handler.ts b/indexer/src/processing/nft/nft.handler.ts new file mode 100644 index 0000000..d8fbfa9 --- /dev/null +++ b/indexer/src/processing/nft/nft.handler.ts @@ -0,0 +1,12 @@ +import { EntitiesStorage } from '../entities.storage'; +import { Block } from '@subsquid/substrate-processor'; +import { NftEvent } from '../../types/nft.events'; + +export interface INftEventHandler { + handle( + block: Block, + collectionAddress: string, + event: NftEvent, + storage: EntitiesStorage, + ): Promise; +} diff --git a/indexer/src/processor.ts b/indexer/src/processor.ts new file mode 100644 index 0000000..173e598 --- /dev/null +++ b/indexer/src/processor.ts @@ -0,0 +1,45 @@ +import { assertNotNull } from '@subsquid/util-internal'; +import { lookupArchive } from '@subsquid/archive-registry'; +import { + BlockHeader, + DataHandlerContext, + SubstrateBatchProcessor, + SubstrateBatchProcessorFields, + Event as _Event, + Call as _Call, + Extrinsic as _Extrinsic, +} from '@subsquid/substrate-processor'; + +export const processor = new SubstrateBatchProcessor() + .setDataSource({ + // archive: lookupArchive('vara-testnet', { release: 'ArrowSquid' }), + // Chain RPC endpoint is required on Substrate for metadata and real-time updates + chain: { + url: assertNotNull(process.env.RPC_ENDPOINT), + rateLimit: 100, + }, + }) + .addEvent({ + name: ['Gear.UserMessageSent'], + extrinsic: true, + }) + .setFields({ + event: { + args: true, + }, + extrinsic: { + hash: true, + fee: true, + }, + block: { + timestamp: true, + }, + }) + .setBlockRange({ from: 2608260 }); + +export type Fields = SubstrateBatchProcessorFields; +export type Block = BlockHeader; +export type Event = _Event; +export type Call = _Call; +export type Extrinsic = _Extrinsic; +export type ProcessorContext = DataHandlerContext; diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts new file mode 100644 index 0000000..f3e1e30 --- /dev/null +++ b/indexer/src/types/marketplace.events.ts @@ -0,0 +1,316 @@ +import { Enum, Option, Text, Vec, u64, u128 } from '@polkadot/types'; +import { Hash } from '@polkadot/types/interfaces'; +import { CodeId } from '@gear-js/api'; + +export enum NftMarketplaceEventType { + NewCollectionAdded = 'isNewCollectionAdded', + CollectionCreated = 'isCollectionCreated', + SaleNft = 'isSaleNft', + SaleNftCanceled = 'isSaleNftCanceled', + NftSold = 'isNftSold', + AuctionCreated = 'isAuctionCreated', + BidAdded = 'isBidAdded', + AuctionCanceled = 'isAuctionCanceled', + OfferCreated = 'isOfferCreated', + OfferCanceled = 'isOfferCanceled', + OfferAccepted = 'isOfferAccepted', + CollectionDeleted = 'isCollectionDeleted', + AdminsAdded = 'isAdminsAdded', + AdminDeleted = 'isAdminDeleted', + ConfigUpdated = 'isConfigUpdated', +} + +export type NewCollectionAdded = { + type: NftMarketplaceEventType.NewCollectionAdded; + codeId: string; + metaLink: string; + typeName: string; + typeDescription: string; +}; + +export type CollectionCreated = { + type: NftMarketplaceEventType.CollectionCreated; + typeName: string; + collectionAddress: string; +}; + +export type SaleNft = { + type: NftMarketplaceEventType.SaleNft; + collectionAddress: string; + tokenId: number; + price: bigint; + owner: string; +}; + +export type SaleNftCanceled = { + type: NftMarketplaceEventType.SaleNftCanceled; + collectionAddress: string; + tokenId: number; +}; + +export type NftSold = { + type: NftMarketplaceEventType.NftSold; + currentOwner: string; + tokenId: number; + price: bigint; + collectionAddress: string; +}; + +export type AuctionCreated = { + type: NftMarketplaceEventType.AuctionCreated; + collectionAddress: string; + tokenId: number; + price: bigint; + currentOwner: string; +}; + +export type BidAdded = { + type: NftMarketplaceEventType.BidAdded; + collectionAddress: string; + tokenId: number; +}; + +export type AuctionCanceled = { + type: NftMarketplaceEventType.AuctionCanceled; + collectionAddress: string; + tokenId: number; +}; + +export type OfferCreated = { + type: NftMarketplaceEventType.OfferCreated; + collectionAddress: string; + tokenId: number; + price: bigint; +}; + +export type OfferCanceled = { + type: NftMarketplaceEventType.OfferCanceled; + collectionAddress: string; + tokenId: number; +}; + +export type OfferAccepted = { + type: NftMarketplaceEventType.OfferAccepted; +}; + +export type CollectionDeleted = { + type: NftMarketplaceEventType.CollectionDeleted; + collectionAddress: string; +}; + +export type AdminsAdded = { + type: NftMarketplaceEventType.AdminsAdded; + users: string[]; +}; + +export type AdminDeleted = { + type: NftMarketplaceEventType.AdminDeleted; + user: string; +}; + +export type ConfigUpdated = { + type: NftMarketplaceEventType.ConfigUpdated; + gasForCreation: number | null; + timeBetweenCreateCollections: number | null; +}; + +export type NftMarketplaceEvent = + | NewCollectionAdded + | CollectionCreated + | SaleNft + | SaleNftCanceled + | NftSold + | AuctionCreated + | BidAdded + | AuctionCanceled + | OfferCreated + | OfferCanceled + | OfferAccepted + | CollectionDeleted + | AdminsAdded + | AdminDeleted + | ConfigUpdated; + +export interface NftMarketplaceEventPlain extends Enum { + newCollectionAdded: { + codeId: CodeId; + metaLink: Text; + typeName: Text; + typeDescription: Text; + }; + collectionCreated: { + typeName: Text; + collectionAddress: Hash; + }; + saleNft: { + collectionAddress: Hash; + tokenId: u64; + price: u128; + owner: Hash; + }; + saleNftCanceled: { + collectionAddress: Hash; + tokenId: u64; + }; + nftSold: { + currentOwner: Hash; + tokenId: u64; + price: u128; + collectionAddress: Hash; + }; + auctionCreated: { + collectionAddress: Hash; + tokenId: u64; + price: u128; + currentOwner: Hash; + }; + bidAdded: { + collectionAddress: Hash; + tokenId: u64; + }; + auctionCanceled: { + collectionAddress: Hash; + tokenId: u64; + }; + offerCreated: { + collectionAddress: Hash; + tokenId: u64; + price: u128; + }; + offerCanceled: { + collectionAddress: Hash; + tokenId: u64; + }; + offerAccepted: {}; + collectionDeleted: { + collectionAddress: Hash; + }; + adminsAdded: { + users: Vec; + }; + adminDeleted: { + user: Hash; + }; + configUpdated: { + gasForCreation: Option; + timeBetweenCreateCollections: Option; + }; +} + +export function getMarketplaceEvent( + event: NftMarketplaceEventPlain, +): NftMarketplaceEvent | undefined { + if (event.newCollectionAdded) { + return { + type: NftMarketplaceEventType.NewCollectionAdded, + codeId: event.newCollectionAdded.codeId.toString(), + metaLink: event.newCollectionAdded.metaLink.toString(), + typeName: event.newCollectionAdded.typeName.toString(), + typeDescription: event.newCollectionAdded.typeDescription.toString(), + }; + } + if (event.collectionCreated) { + return { + type: NftMarketplaceEventType.CollectionCreated, + typeName: event.collectionCreated.typeName.toString(), + collectionAddress: event.collectionCreated.collectionAddress.toString(), + }; + } + if (event.saleNft) { + return { + type: NftMarketplaceEventType.SaleNft, + collectionAddress: event.saleNft.collectionAddress.toString(), + tokenId: event.saleNft.tokenId.toNumber(), + price: event.saleNft.price.toBigInt(), + owner: event.saleNft.owner.toString(), + }; + } + if (event.saleNftCanceled) { + return { + type: NftMarketplaceEventType.SaleNftCanceled, + collectionAddress: event.saleNftCanceled.collectionAddress.toString(), + tokenId: event.saleNftCanceled.tokenId.toNumber(), + }; + } + if (event.nftSold) { + return { + type: NftMarketplaceEventType.NftSold, + currentOwner: event.nftSold.currentOwner.toString(), + tokenId: event.nftSold.tokenId.toNumber(), + price: event.nftSold.price.toBigInt(), + collectionAddress: event.nftSold.collectionAddress.toString(), + }; + } + if (event.auctionCreated) { + return { + type: NftMarketplaceEventType.AuctionCreated, + collectionAddress: event.auctionCreated.collectionAddress.toString(), + tokenId: event.auctionCreated.tokenId.toNumber(), + price: event.auctionCreated.price.toBigInt(), + currentOwner: event.auctionCreated.currentOwner.toString(), + }; + } + if (event.bidAdded) { + return { + type: NftMarketplaceEventType.BidAdded, + collectionAddress: event.bidAdded.collectionAddress.toString(), + tokenId: event.bidAdded.tokenId.toNumber(), + }; + } + if (event.auctionCanceled) { + return { + type: NftMarketplaceEventType.AuctionCanceled, + collectionAddress: event.auctionCanceled.collectionAddress.toString(), + tokenId: event.auctionCanceled.tokenId.toNumber(), + }; + } + if (event.offerCreated) { + return { + type: NftMarketplaceEventType.OfferCreated, + collectionAddress: event.offerCreated.collectionAddress.toString(), + tokenId: event.offerCreated.tokenId.toNumber(), + price: event.offerCreated.price.toBigInt(), + }; + } + if (event.offerCanceled) { + return { + type: NftMarketplaceEventType.OfferCanceled, + collectionAddress: event.offerCanceled.collectionAddress.toString(), + tokenId: event.offerCanceled.tokenId.toNumber(), + }; + } + if (event.offerAccepted) { + return { + type: NftMarketplaceEventType.OfferAccepted, + }; + } + if (event.collectionDeleted) { + return { + type: NftMarketplaceEventType.CollectionDeleted, + collectionAddress: event.collectionDeleted.collectionAddress.toString(), + }; + } + if (event.adminsAdded) { + return { + type: NftMarketplaceEventType.AdminsAdded, + users: event.adminsAdded.users.map((user) => user.toString()), + }; + } + if (event.adminDeleted) { + return { + type: NftMarketplaceEventType.AdminDeleted, + user: event.adminDeleted.user.toString(), + }; + } + if (event.configUpdated) { + return { + type: NftMarketplaceEventType.ConfigUpdated, + gasForCreation: + event.configUpdated.gasForCreation.unwrapOr(null)?.toNumber() ?? null, + timeBetweenCreateCollections: + event.configUpdated.timeBetweenCreateCollections + .unwrapOr(null) + ?.toNumber() ?? null, + }; + } +} diff --git a/indexer/src/types/nft.events.ts b/indexer/src/types/nft.events.ts new file mode 100644 index 0000000..fe4688d --- /dev/null +++ b/indexer/src/types/nft.events.ts @@ -0,0 +1,299 @@ +import { Enum, Option, Text, u128, u16, u32, u64, Vec } from '@polkadot/types'; +import { Hash } from '@polkadot/types/interfaces'; + +export enum NftEventType { + Transferred = 'Transferred', + TokenInfoReceived = 'TokenInfoReceived', + Initialized = 'Initialized', + Minted = 'Minted', + Approved = 'Approved', + ApprovalRevoked = 'ApprovalRevoked', + Expanded = 'Expanded', + ConfigChanged = 'ConfigChanged', + ImageChanged = 'ImageChanged', + MetadataAdded = 'MetadataAdded', +} + +export type TransferEvent = { + type: NftEventType.Transferred; + owner: string; + recipient: string; + tokenId: number; +}; + +export type TokenInfoReceivedEvent = { + type: NftEventType.TokenInfoReceived; + tokenOwner: string; + approval: string; + sellable: boolean; + collectionOwner: string; + royalty: number; +}; + +export type NftConfig = { + name: string; + description: string; + collectionTags: string[]; + collectionImg: string; + collectionLogo: string; + userMintLimit: number | null; + additionalLinks: number | null; + royalty: number; + paymentForMint: number; + transferable: boolean; + approvable: boolean; + burnable: boolean; + sellable: boolean; + attendable: boolean; +}; + +export type InitializedEvent = { + type: NftEventType.Initialized; + config: NftConfig; +}; + +export type Nft = { + owner: string; + name: string; + description: string; + metadata: string[]; + mediaUrl: string; +}; + +export type MintedEvent = { + type: NftEventType.Minted; + tokenId: number; + nftData: Nft; +}; + +export type ApprovedEvent = { + type: NftEventType.Approved; + to: string; + tokenId: number; +}; + +export type ApprovalRevokedEvent = { + type: NftEventType.ApprovalRevoked; + tokenId: number; +}; + +export type ExpandedEvent = { + type: NftEventType.Expanded; + additionalLinks: string[]; +}; + +export type ConfigChangedEvent = { + type: NftEventType.ConfigChanged; + config: NftConfig; +}; + +export type ImageChangedEvent = { + type: NftEventType.ImageChanged; + tokenId: number; + imgLink: string; +}; + +export type MetadataAddedEvent = { + type: NftEventType.MetadataAdded; + tokenId: number; + metadata: string; +}; + +export type NftEvent = + | TransferEvent + | TokenInfoReceivedEvent + | InitializedEvent + | MintedEvent + | ApprovedEvent + | ApprovalRevokedEvent + | ExpandedEvent + | ConfigChangedEvent + | ImageChangedEvent + | MetadataAddedEvent; + +export interface ConfigPlain { + name: Text; + description: Text; + collectionTags: Vec; + collectionImg: Text; + collectionLogo: Text; + userMintLimit: Option; + additionalLinks: Option; + royalty: u16; + paymentForMint: u128; + transferable: boolean; + approvable: boolean; + burnable: boolean; + sellable: boolean; + attendable: boolean; +} + +export interface NftEventPlain extends Enum { + transferred: { + owner: Hash; + recipient: Hash; + token_id: u64; + }; + tokenInfoReceived: { + token_owner: Hash; + approval: Option; + sellable: boolean; + collection_owner: Hash; + royalty: u16; + }; + initialized: ConfigPlain; + minted: { + token_id: u64; + nft_data: { + owner: Hash; + name: Text; + description: Text; + metadata: Vec; + mediaUrl: Text; + }; + }; + approved: { + to: Hash; + tokenId: u64; + }; + approvalRevoked: { + tokenId: u64; + }; + expanded: { + additional_links: Vec; + }; + configChanged: { + config: ConfigPlain; + }; + imageChanged: { + token_id: u64; + imgLink: Text; + }; + metadataAdded: { + token_id: u64; + metadata: Text; + }; +} + +export function getNftEvent(event: NftEventPlain): NftEvent | undefined { + if (event.transferred) { + return { + type: NftEventType.Transferred, + owner: event.transferred.owner.toString(), + recipient: event.transferred.recipient.toString(), + tokenId: event.transferred.token_id.toNumber(), + }; + } + if (event.tokenInfoReceived) { + return { + type: NftEventType.TokenInfoReceived, + tokenOwner: event.tokenInfoReceived.token_owner.toString(), + approval: event.tokenInfoReceived.approval?.toString() ?? null, + sellable: event.tokenInfoReceived.sellable, + collectionOwner: event.tokenInfoReceived.collection_owner.toString(), + royalty: event.tokenInfoReceived.royalty.toNumber(), + }; + } + if (event.initialized) { + return { + type: NftEventType.Initialized, + config: { + name: event.initialized.name.toString(), + description: event.initialized.description.toString(), + collectionTags: event.initialized.collectionTags.map((tag) => + tag.toString(), + ), + collectionImg: event.initialized.collectionImg.toString(), + collectionLogo: event.initialized.collectionLogo.toString(), + userMintLimit: + event.initialized.userMintLimit.unwrapOr(null)?.toNumber() ?? null, + additionalLinks: + event.initialized.additionalLinks.unwrapOr(null)?.toNumber() ?? null, + royalty: event.initialized.royalty.toNumber(), + paymentForMint: event.initialized.paymentForMint.toNumber(), + transferable: event.initialized.transferable, + approvable: event.initialized.approvable, + burnable: event.initialized.burnable, + sellable: event.initialized.sellable, + attendable: event.initialized.attendable, + }, + }; + } + if (event.minted) { + return { + type: NftEventType.Minted, + tokenId: event.minted.token_id.toNumber(), + nftData: { + owner: event.minted.nft_data.owner.toString(), + name: event.minted.nft_data.name.toString(), + description: event.minted.nft_data.description.toString(), + metadata: event.minted.nft_data.metadata.map((m) => m.toString()), + mediaUrl: event.minted.nft_data.mediaUrl.toString(), + }, + }; + } + if (event.approved) { + return { + type: NftEventType.Approved, + to: event.approved.to.toString(), + tokenId: event.approved.tokenId.toNumber(), + }; + } + if (event.approvalRevoked) { + return { + type: NftEventType.ApprovalRevoked, + tokenId: event.approvalRevoked.tokenId.toNumber(), + }; + } + if (event.expanded) { + return { + type: NftEventType.Expanded, + additionalLinks: event.expanded.additional_links.map((link) => + link.toString(), + ), + }; + } + if (event.configChanged) { + return { + type: NftEventType.ConfigChanged, + config: { + name: event.configChanged.config.name.toString(), + description: event.configChanged.config.description.toString(), + collectionTags: event.configChanged.config.collectionTags.map((tag) => + tag.toString(), + ), + collectionImg: event.configChanged.config.collectionImg.toString(), + collectionLogo: event.configChanged.config.collectionLogo.toString(), + userMintLimit: + event.configChanged.config.userMintLimit.unwrapOr(null)?.toNumber() ?? + null, + additionalLinks: + event.configChanged.config.additionalLinks + .unwrapOr(null) + ?.toNumber() ?? null, + royalty: event.configChanged.config.royalty.toNumber(), + paymentForMint: event.configChanged.config.paymentForMint.toNumber(), + transferable: event.configChanged.config.transferable, + approvable: event.configChanged.config.approvable, + burnable: event.configChanged.config.burnable, + sellable: event.configChanged.config.sellable, + attendable: event.configChanged.config.attendable, + }, + }; + } + if (event.imageChanged) { + return { + type: NftEventType.ImageChanged, + tokenId: event.imageChanged.token_id.toNumber(), + imgLink: event.imageChanged.imgLink.toString(), + }; + } + if (event.metadataAdded) { + return { + type: NftEventType.MetadataAdded, + tokenId: event.metadataAdded.token_id.toNumber(), + metadata: event.metadataAdded.metadata.toString(), + }; + } + return undefined; +} diff --git a/indexer/tsconfig.json b/indexer/tsconfig.json new file mode 100644 index 0000000..f1f63d5 --- /dev/null +++ b/indexer/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2020", + "outDir": "lib", + "rootDir": "src", + "strict": true, + "declaration": false, + "sourceMap": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "skipLibCheck": true + }, + "include": ["src"], + "exclude": [ + "node_modules" + ] +} diff --git a/indexer/typegen.json b/indexer/typegen.json new file mode 100644 index 0000000..aff16dd --- /dev/null +++ b/indexer/typegen.json @@ -0,0 +1,14 @@ +{ + "outDir": "src/types", + "specVersions": "https://v2.archive.subsquid.io/metadata/kusama", + "pallets": { + "Balances": { + "events": [ + "Transfer" + ], + "calls": [], + "storage": [], + "constants": [] + } + } +} From 0c4e23c59bf25e96b38f863dac5272ea72dfc4fa Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 29 Dec 2023 11:43:15 +0300 Subject: [PATCH 02/50] indexer draft --- indexer/src/main.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/indexer/src/main.ts b/indexer/src/main.ts index 45817ce..e74629b 100644 --- a/indexer/src/main.ts +++ b/indexer/src/main.ts @@ -3,6 +3,7 @@ import { TypeormDatabase } from '@subsquid/typeorm-store'; import { processor } from './processor'; import { config } from './config'; import { EventsProcessing } from './processing/events.processing'; +import {Collection} from "./model"; processor.run(new TypeormDatabase(), async (ctx) => { const processing = new EventsProcessing(ctx.store); @@ -21,7 +22,8 @@ processor.run(new TypeormDatabase(), async (ctx) => { if (details && details.code.__kind !== 'Success') { continue; } - if (config.nftProgram && config.nftProgram === source) { + const collection = await ctx.store.findOne(Collection, { where: { id: source } }); + if (collection) { await processing.handleNftEvent(block, payload, source); } if (config.marketplaceProgram && config.marketplaceProgram === source) { From 120cf525ced4ba00a4a6daba2a0b8d730b0e07ea Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 19 Jan 2024 14:38:36 +0300 Subject: [PATCH 03/50] indexer improvements --- indexer/.env | 5 +- indexer/.env.example | 5 +- indexer/Dockerfile-explorer | 39 ++ indexer/Dockerfile-indexer | 8 + indexer/assets/nft.meta.txt | 2 +- indexer/assets/nft_marketplace.meta.txt | 2 +- indexer/db/migrations/1703490897133-Data.js | 45 -- indexer/package-lock.json | 548 +++++++++--------- indexer/package.json | 6 +- indexer/schema.graphql | 101 +++- indexer/src/config.ts | 16 +- indexer/src/main.ts | 82 ++- indexer/src/model/generated/auction.model.ts | 61 ++ indexer/src/model/generated/bid.model.ts | 38 ++ .../src/model/generated/collection.model.ts | 55 +- indexer/src/model/generated/index.ts | 5 + .../src/model/generated/marketplace.model.ts | 15 + .../generated/marketplaceConfig.model.ts | 50 ++ .../model/generated/marketplaceEvent.model.ts | 37 ++ indexer/src/model/generated/nft.model.ts | 22 +- indexer/src/model/generated/offer.model.ts | 47 ++ indexer/src/model/generated/sale.model.ts | 14 +- indexer/src/model/generated/transfer.model.ts | 4 +- indexer/src/model/types.ts | 17 + indexer/src/processing/batch.service.ts | 103 ++++ indexer/src/processing/entities.service.ts | 123 ++++ indexer/src/processing/entities.storage.ts | 119 ---- indexer/src/processing/event-info.type.ts | 7 + indexer/src/processing/events.processing.ts | 160 +++-- .../marketplace/admin-added.handler.ts | 22 + .../marketplace/admins-deleted.handler.ts | 22 + .../marketplace/auction-canceled.handler.ts | 21 +- .../marketplace/auction-closed.handler.ts | 36 ++ .../marketplace/auction-created.handler.ts | 35 +- .../marketplace/bid-added.handler.ts | 47 ++ .../marketplace/collection-created.handler.ts | 11 +- .../marketplace/collection-deleted.handler.ts | 8 +- .../marketplace/config-updated.handler.ts | 36 ++ .../new-collection-added.handler.ts | 10 +- .../marketplace/nft-marketplace.handler.ts | 8 +- .../marketplace/nft-sold.handler.ts | 39 +- .../marketplace/offer-accepted.handler.ts | 40 ++ .../marketplace/offer-canceled.handler.ts | 34 ++ .../marketplace/offer-created.handler.ts | 44 ++ .../marketplace/sale-nft-canceled.handler.ts | 37 ++ .../marketplace/sale-nft.handler.ts | 50 ++ .../processing/nft/config-changed.handler.ts | 57 ++ .../processing/nft/image-changed.handler.ts | 29 + .../src/processing/nft/initialized.handler.ts | 48 +- .../processing/nft/metadata-added.handler.ts | 29 + .../nft/nft-approval-revoked.handler.ts | 29 + .../processing/nft/nft-approved.handler.ts | 29 + .../src/processing/nft/nft-minted.handler.ts | 14 +- indexer/src/processing/nft/nft.handler.ts | 9 +- .../src/processing/nft/transferred.handler.ts | 32 + .../src/processing/storage/local.storage.ts | 216 +++++++ .../processing/storage/storage.inteface.ts | 33 ++ indexer/src/processor.ts | 13 +- indexer/src/types/event.utils.ts | 47 ++ indexer/src/types/marketplace.events.ts | 142 ++++- indexer/src/types/nft.events.ts | 171 ++++-- 61 files changed, 2382 insertions(+), 752 deletions(-) create mode 100644 indexer/Dockerfile-explorer create mode 100644 indexer/Dockerfile-indexer delete mode 100644 indexer/db/migrations/1703490897133-Data.js create mode 100644 indexer/src/model/generated/auction.model.ts create mode 100644 indexer/src/model/generated/bid.model.ts create mode 100644 indexer/src/model/generated/marketplaceConfig.model.ts create mode 100644 indexer/src/model/generated/marketplaceEvent.model.ts create mode 100644 indexer/src/model/generated/offer.model.ts create mode 100644 indexer/src/model/types.ts create mode 100644 indexer/src/processing/batch.service.ts create mode 100644 indexer/src/processing/entities.service.ts delete mode 100644 indexer/src/processing/entities.storage.ts create mode 100644 indexer/src/processing/event-info.type.ts create mode 100644 indexer/src/processing/marketplace/admin-added.handler.ts create mode 100644 indexer/src/processing/marketplace/admins-deleted.handler.ts create mode 100644 indexer/src/processing/marketplace/auction-closed.handler.ts create mode 100644 indexer/src/processing/marketplace/bid-added.handler.ts create mode 100644 indexer/src/processing/marketplace/config-updated.handler.ts create mode 100644 indexer/src/processing/marketplace/offer-accepted.handler.ts create mode 100644 indexer/src/processing/marketplace/offer-canceled.handler.ts create mode 100644 indexer/src/processing/marketplace/offer-created.handler.ts create mode 100644 indexer/src/processing/marketplace/sale-nft-canceled.handler.ts create mode 100644 indexer/src/processing/marketplace/sale-nft.handler.ts create mode 100644 indexer/src/processing/nft/config-changed.handler.ts create mode 100644 indexer/src/processing/nft/image-changed.handler.ts create mode 100644 indexer/src/processing/nft/metadata-added.handler.ts create mode 100644 indexer/src/processing/nft/nft-approval-revoked.handler.ts create mode 100644 indexer/src/processing/nft/nft-approved.handler.ts create mode 100644 indexer/src/processing/nft/transferred.handler.ts create mode 100644 indexer/src/processing/storage/local.storage.ts create mode 100644 indexer/src/processing/storage/storage.inteface.ts create mode 100644 indexer/src/types/event.utils.ts diff --git a/indexer/.env b/indexer/.env index 119eb7f..6716a7d 100644 --- a/indexer/.env +++ b/indexer/.env @@ -8,8 +8,9 @@ GQL_PORT=4350 # Set urls via secrets if deploying to Cloud: https://docs.subsquid.io/deploy-squid/env-variables/ # OR use the RPC proxy service: https://docs.subsquid.io/deploy-squid/rpc-proxy RPC_ENDPOINT=wss://testnet-archive.vara.network -MARKETPLACE_PROGRAM=0x9d1f3a81c636d59decc2c4336bca2480aa4fea7cecd742e5792799c0637baad9 -# NFT_PROGRAM=0x9d1f3a81c636d59decc2c4336bca2480aa4fea7cecd742e5792799c0637baad9 +MARKETPLACE_PROGRAM=0x44842bc912e6ec8eba11cc565e373c6d805600386a9fe874765515cf303215d9 +MIN_BLOCK_NUM=3276150 +RATE_LIMIT=100 # Uncommenting this line enables the debug mode # More info at https://docs.subsquid.io/basics/logging/ diff --git a/indexer/.env.example b/indexer/.env.example index 119eb7f..6716a7d 100644 --- a/indexer/.env.example +++ b/indexer/.env.example @@ -8,8 +8,9 @@ GQL_PORT=4350 # Set urls via secrets if deploying to Cloud: https://docs.subsquid.io/deploy-squid/env-variables/ # OR use the RPC proxy service: https://docs.subsquid.io/deploy-squid/rpc-proxy RPC_ENDPOINT=wss://testnet-archive.vara.network -MARKETPLACE_PROGRAM=0x9d1f3a81c636d59decc2c4336bca2480aa4fea7cecd742e5792799c0637baad9 -# NFT_PROGRAM=0x9d1f3a81c636d59decc2c4336bca2480aa4fea7cecd742e5792799c0637baad9 +MARKETPLACE_PROGRAM=0x44842bc912e6ec8eba11cc565e373c6d805600386a9fe874765515cf303215d9 +MIN_BLOCK_NUM=3276150 +RATE_LIMIT=100 # Uncommenting this line enables the debug mode # More info at https://docs.subsquid.io/basics/logging/ diff --git a/indexer/Dockerfile-explorer b/indexer/Dockerfile-explorer new file mode 100644 index 0000000..b6d40dd --- /dev/null +++ b/indexer/Dockerfile-explorer @@ -0,0 +1,39 @@ +FROM node:16-alpine AS node +FROM node AS node-with-gyp +RUN apk add g++ make python3 +FROM node-with-gyp AS builder +WORKDIR /squid +ADD package.json . +ADD package-lock.json . +# remove if needed +ADD assets assets +# remove if needed +ADD db db +# remove if needed +ADD schema.graphql . +RUN npm ci +ADD tsconfig.json . +ADD src src +RUN npm run build +FROM node-with-gyp AS deps +WORKDIR /squid +ADD package.json . +ADD package-lock.json . +RUN npm ci --production +FROM node AS squid +WORKDIR /squid +COPY --from=deps /squid/package.json . +COPY --from=deps /squid/package-lock.json . +COPY --from=deps /squid/node_modules node_modules +COPY --from=builder /squid/lib lib +# remove if no assets folder +COPY --from=builder /squid/assets assets +# remove if no db folder +COPY --from=builder /squid/db db +# remove if no schema.graphql is in the root +COPY --from=builder /squid/schema.graphql schema.graphql +# remove if no commands.json is in the root +ADD commands.json . +RUN echo -e "loglevel=silent\\nupdate-notifier=false" > /squid/.npmrc +RUN npm i -g @subsquid/commands && mv $(which squid-commands) /usr/local/bin/sqd +ENV PROCESSOR_PROMETHEUS_PORT 3000 diff --git a/indexer/Dockerfile-indexer b/indexer/Dockerfile-indexer new file mode 100644 index 0000000..97e5e26 --- /dev/null +++ b/indexer/Dockerfile-indexer @@ -0,0 +1,8 @@ +FROM node:20-alpine + +WORKDIR /app +COPY . . +RUN npm install +RUN npm run build + +CMD ["npm", "start"] diff --git a/indexer/assets/nft.meta.txt b/indexer/assets/nft.meta.txt index 6445168..9b5200c 100644 --- a/indexer/assets/nft.meta.txt +++ b/indexer/assets/nft.meta.txt @@ -1 +1 @@ -0002000100000000000117000000011800000000000000011e000000011f000000f52ca00008186e66745f696f1c4e6674496e697400000c0140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000118636f6e666967100118436f6e666967000124696d675f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e00000410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004000801205b75383b2033325d000008000003200000000c000c00000503001008186e66745f696f18436f6e66696700002c01106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e6700013c636f6c6c656374696f6e5f7461677318012c5665633c537472696e673e000144636f6c6c656374696f6e5f62616e6e6572140118537472696e6700013c636f6c6c656374696f6e5f6c6f676f140118537472696e6700013c757365725f6d696e745f6c696d69741c012c4f7074696f6e3c7533323e0001406164646974696f6e616c5f6c696e6b7324015c4f7074696f6e3c4164646974696f6e616c4c696e6b733e00011c726f79616c747930010c7531360001407061796d656e745f666f725f6d696e74340110753132380001307472616e7366657261626c6538012c4f7074696f6e3c7536343e00012073656c6c61626c6538012c4f7074696f6e3c7536343e00001400000502001800000214001c04184f7074696f6e04045401200108104e6f6e6500000010536f6d6504002000000100002000000505002404184f7074696f6e04045401280108104e6f6e6500000010536f6d6504002800000100002808186e66745f696f3c4164646974696f6e616c4c696e6b73000014013065787465726e616c5f75726c2c01384f7074696f6e3c537472696e673e00012074656c656772616d2c01384f7074696f6e3c537472696e673e00011078636f6d2c01384f7074696f6e3c537472696e673e0001186d656469756d2c01384f7074696f6e3c537472696e673e00011c646973636f72642c01384f7074696f6e3c537472696e673e00002c04184f7074696f6e04045401140108104e6f6e6500000010536f6d6504001400000100003000000504003400000507003804184f7074696f6e040454013c0108104e6f6e6500000010536f6d6504003c00000100003c000005060040000002440044000004081448004808186e66745f696f24496d6167654461746100000801306c696d69745f636f7069657320010c75333200014c6175746f5f6368616e67696e675f72756c65734c01784f7074696f6e3c5665633c2854696d655365632c20416374696f6e293e3e00004c04184f7074696f6e04045401500108104e6f6e6500000010536f6d65040050000001000050000002540054000004082058005808186e66745f696f18416374696f6e000108244368616e6765496d670400140118537472696e670000001c4164644d6574610400140118537472696e67000100005c08186e66745f696f244e6674416374696f6e00012c205472616e73666572080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000000305472616e7366657246726f6d0c011066726f6d04011c4163746f724964000108746f04011c4163746f724964000120746f6b656e5f69643c01144e6674496400010030476574546f6b656e496e666f040120746f6b656e5f69643c01144e667449640002002443616e44656c657465000300104d696e740004001c417070726f7665080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000500385265766f6b65417070726f76616c040120746f6b656e5f69643c01144e6674496400060018457870616e640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000700304368616e6765436f6e666967040118636f6e666967100118436f6e666967000800244368616e6765496d67080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e670009002c4164644d65746164617461080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a0000600418526573756c740804540164044501740108084f6b040064000000000c45727204007400000100006408186e66745f696f204e66744576656e7400012c2c5472616e736665727265640c01146f776e657204011c4163746f724964000124726563697069656e7404011c4163746f724964000120746f6b656e5f69643c01144e6674496400000044546f6b656e496e666f526563656976656414012c746f6b656e5f6f776e657204011c4163746f724964000120617070726f76616c68013c4f7074696f6e3c4163746f7249643e00012073656c6c61626c656c0110626f6f6c000140636f6c6c656374696f6e5f6f776e657204011c4163746f72496400011c726f79616c747930010c7531360001002443616e44656c65746504006c0110626f6f6c0002002c496e697469616c697a6564040118636f6e666967100118436f6e666967000300184d696e746564080120746f6b656e5f69643c01144e667449640001206e66745f6461746170010c4e667400040020417070726f766564080108746f04011c4163746f724964000120746f6b656e5f69643c01144e667449640005003c417070726f76616c5265766f6b6564040120746f6b656e5f69643c01144e6674496400060020457870616e6465640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e00070034436f6e6669674368616e676564040118636f6e666967100118436f6e66696700080030496d6167654368616e676564080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e67000900344d657461646174614164646564080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a00006804184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100006c00000500007008186e66745f696f0c4e667400001801146f776e657204011c4163746f7249640001106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e670001206d6574616461746118012c5665633c537472696e673e0001246d656469615f75726c140118537472696e670001246d696e745f74696d653c010c75363400007408186e66745f696f204e66744572726f7200000400140118537472696e6700007808186e66745f696f2853746174655175657279000110104e616d650000002c4465736372697074696f6e00010018436f6e6669670002000c416c6c000300007c08186e66745f696f2853746174655265706c79000110104e616d650400140118537472696e670000002c4465736372697074696f6e0400140118537472696e6700010018436f6e6669670400100118436f6e6669670002000c416c6c04008001204e66745374617465000300008008186e66745f696f204e6674537461746500001c0118746f6b656e738401445665633c284e667449642c204e6674293e0001186f776e6572738c01685665633c284163746f7249642c205665633c4e667449643e293e00013c746f6b656e5f617070726f76616c739801545665633c284e667449642c204163746f724964293e000118636f6e666967100118436f6e6669670001146e6f6e63653c01144e66744964000124696d675f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000084000002880088000004083c70008c00000290009000000408049400940000023c00980000029c009c000004083c0400 \ No newline at end of file +0002000100000000000117000000011800000000000000011e000000011f000000f92da00008186e66745f696f1c4e6674496e697400000c0140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000118636f6e666967100118436f6e666967000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e00000410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004000801205b75383b2033325d000008000003200000000c000c00000503001008186e66745f696f18436f6e66696700002c01106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e6700013c636f6c6c656374696f6e5f7461677318012c5665633c537472696e673e000144636f6c6c656374696f6e5f62616e6e6572140118537472696e6700013c636f6c6c656374696f6e5f6c6f676f140118537472696e6700013c757365725f6d696e745f6c696d69741c012c4f7074696f6e3c7533323e0001406164646974696f6e616c5f6c696e6b7324015c4f7074696f6e3c4164646974696f6e616c4c696e6b733e00011c726f79616c747930010c7531360001407061796d656e745f666f725f6d696e74340110753132380001307472616e7366657261626c6538012c4f7074696f6e3c7536343e00012073656c6c61626c6538012c4f7074696f6e3c7536343e00001400000502001800000214001c04184f7074696f6e04045401200108104e6f6e6500000010536f6d6504002000000100002000000505002404184f7074696f6e04045401280108104e6f6e6500000010536f6d6504002800000100002808186e66745f696f3c4164646974696f6e616c4c696e6b73000014013065787465726e616c5f75726c2c01384f7074696f6e3c537472696e673e00012074656c656772616d2c01384f7074696f6e3c537472696e673e00011078636f6d2c01384f7074696f6e3c537472696e673e0001186d656469756d2c01384f7074696f6e3c537472696e673e00011c646973636f72642c01384f7074696f6e3c537472696e673e00002c04184f7074696f6e04045401140108104e6f6e6500000010536f6d6504001400000100003000000504003400000507003804184f7074696f6e040454013c0108104e6f6e6500000010536f6d6504003c00000100003c000005060040000002440044000004081448004808186e66745f696f24496d6167654461746100000801306c696d69745f636f706965731c012c4f7074696f6e3c7533323e00014c6175746f5f6368616e67696e675f72756c65734c01784f7074696f6e3c5665633c2854696d655365632c20416374696f6e293e3e00004c04184f7074696f6e04045401500108104e6f6e6500000010536f6d65040050000001000050000002540054000004082058005808186e66745f696f18416374696f6e000108244368616e6765496d670400140118537472696e670000001c4164644d6574610400140118537472696e67000100005c08186e66745f696f244e6674416374696f6e00012c205472616e73666572080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000000305472616e7366657246726f6d0c011066726f6d04011c4163746f724964000108746f04011c4163746f724964000120746f6b656e5f69643c01144e6674496400010030476574546f6b656e496e666f040120746f6b656e5f69643c01144e667449640002002443616e44656c657465000300104d696e740004001c417070726f7665080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000500385265766f6b65417070726f76616c040120746f6b656e5f69643c01144e6674496400060018457870616e640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000700304368616e6765436f6e666967040118636f6e666967100118436f6e666967000800244368616e6765496d67080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e670009002c4164644d65746164617461080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a0000600418526573756c740804540164044501740108084f6b040064000000000c45727204007400000100006408186e66745f696f204e66744576656e7400012c2c5472616e736665727265640c01146f776e657204011c4163746f724964000124726563697069656e7404011c4163746f724964000120746f6b656e5f69643c01144e6674496400000044546f6b656e496e666f526563656976656414012c746f6b656e5f6f776e657204011c4163746f724964000120617070726f76616c68013c4f7074696f6e3c4163746f7249643e00012073656c6c61626c656c0110626f6f6c000140636f6c6c656374696f6e5f6f776e657204011c4163746f72496400011c726f79616c747930010c7531360001002443616e44656c65746504006c0110626f6f6c0002002c496e697469616c697a6564040118636f6e666967100118436f6e666967000300184d696e746564080120746f6b656e5f69643c01144e667449640001206e66745f6461746170010c4e667400040020417070726f766564080108746f04011c4163746f724964000120746f6b656e5f69643c01144e667449640005003c417070726f76616c5265766f6b6564040120746f6b656e5f69643c01144e6674496400060020457870616e6465640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e00070034436f6e6669674368616e676564040118636f6e666967100118436f6e66696700080030496d6167654368616e676564080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e67000900344d657461646174614164646564080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a00006804184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100006c00000500007008186e66745f696f0c4e667400001801146f776e657204011c4163746f7249640001106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e670001206d6574616461746118012c5665633c537472696e673e0001246d656469615f75726c140118537472696e670001246d696e745f74696d653c010c75363400007408186e66745f696f204e66744572726f7200000400140118537472696e6700007808186e66745f696f2853746174655175657279000110104e616d650000002c4465736372697074696f6e00010018436f6e6669670002000c416c6c000300007c08186e66745f696f2853746174655265706c79000110104e616d650400140118537472696e670000002c4465736372697074696f6e0400140118537472696e6700010018436f6e6669670400100118436f6e6669670002000c416c6c04008001204e66745374617465000300008008186e66745f696f204e667453746174650000200118746f6b656e738401445665633c284e667449642c204e6674293e0001186f776e6572738c01685665633c284163746f7249642c205665633c4e667449643e293e00013c746f6b656e5f617070726f76616c739801545665633c284e667449642c204163746f724964293e000118636f6e666967100118436f6e6669670001146e6f6e63653c01144e66744964000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e000140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e000084000002880088000004083c70008c00000290009000000408049400940000023c00980000029c009c000004083c0400 \ No newline at end of file diff --git a/indexer/assets/nft_marketplace.meta.txt b/indexer/assets/nft_marketplace.meta.txt index a143e5c..c421bcc 100644 --- a/indexer/assets/nft_marketplace.meta.txt +++ b/indexer/assets/nft_marketplace.meta.txt @@ -1 +1 @@ -0002000100000000000103000000010e0000000000000001110000000112000000793f940008486e66745f6d61726b6574706c6163655f696f484e66744d61726b6574706c616365496e697400000c01406761735f666f725f6372656174696f6e04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001586d696e696d756d5f7472616e736665725f76616c75650801107531323800000400000506000800000507000c08486e66745f6d61726b6574706c6163655f696f504e66744d61726b6574706c616365416374696f6e000140404164644e6577436f6c6c656374696f6e10011c636f64655f6964100118436f646549640001246d6574615f6c696e6b1c0118537472696e67000124747970655f6e616d651c0118537472696e67000140747970655f6465736372697074696f6e1c0118537472696e6700000040437265617465436f6c6c656374696f6e080124747970655f6e616d651c0118537472696e6700011c7061796c6f616420011c5665633c75383e0001001c53616c654e66740c0148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380002003443616e63656c53616c654e6674080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000300184275794e6674080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340004003443726561746541756374696f6e100148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d7328010c75333200050018416464426964080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c75363400060030436c6f736541756374696f6e080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340007003443616e63656c41756374696f6e080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340008002c4372656174654f66666572080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340009002c43616e63656c4f66666572080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000a002c4163636570744f666665720401146f666665722c01144f66666572000b004044656c657465436f6c6c656374696f6e040148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000c002441646441646d696e7304011475736572733001305665633c4163746f7249643e000d002c44656c65746541646d696e0401107573657224011c4163746f724964000e0030557064617465436f6e6669670801406761735f666f725f6372656174696f6e34012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7334012c4f7074696f6e3c7536343e000f00001010106773746418636f6d6d6f6e287072696d69746976657318436f64654964000004001401205b75383b2033325d0000140000032000000018001800000503001c00000502002000000218002410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004001401205b75383b2033325d00002800000505002c08486e66745f6d61726b6574706c6163655f696f144f6666657200000c0148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c75363400011c63726561746f7224011c4163746f72496400003000000224003404184f7074696f6e04045401040108104e6f6e6500000010536f6d650400040000010000380418526573756c74080454013c044501400108084f6b04003c000000000c45727204004000000100003c08486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654576656e74000140484e6577436f6c6c656374696f6e416464656410011c636f64655f6964100118436f646549640001246d6574615f6c696e6b1c0118537472696e67000124747970655f6e616d651c0118537472696e67000140747970655f6465736372697074696f6e1c0118537472696e6700000044436f6c6c656374696f6e43726561746564080124747970655f6e616d651c0118537472696e67000148636f6c6c656374696f6e5f6164647265737324011c4163746f7249640001001c53616c654e6674100148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380001146f776e657224011c4163746f7249640002003c53616c654e667443616e63656c6564080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340003001c4e6674536f6c640c013463757272656e745f6f776e657224011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380004003841756374696f6e43726561746564100148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d7328010c7533320005003441756374696f6e436c6f736564100148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c75363400011470726963650801107531323800013463757272656e745f6f776e657224011c4163746f724964000600204269644164646564080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c7536340007003c41756374696f6e43616e63656c6564080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000800304f66666572437265617465640c0148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000114707269636508011075313238000900344f6666657243616e63656c6564080148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000120746f6b656e5f696404010c753634000a00344f6666657241636365707465640401146f666665722c01144f66666572000b0044436f6c6c656374696f6e44656c65746564040148636f6c6c656374696f6e5f6164647265737324011c4163746f724964000c002c41646d696e73416464656404011475736572733001305665633c4163746f7249643e000d003041646d696e44656c657465640401107573657224011c4163746f724964000e0034436f6e666967557064617465640801406761735f666f725f6372656174696f6e34012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7334012c4f7074696f6e3c7536343e000f00004008486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654572726f72000004001c0118537472696e6700004408486e66745f6d61726b6574706c6163655f696f28537461746551756572790001140c416c6c0000001841646d696e730001003c436f6c6c656374696f6e73496e666f00020018436f6e66696700030038416c6c436f6c6c656374696f6e73000400004808486e66745f6d61726b6574706c6163655f696f2853746174655265706c790001140c416c6c04004c011453746174650000001841646d696e7304003001305665633c4163746f7249643e0001003c436f6c6c656374696f6e73496e666f04006001745665633c28537472696e672c20436f6c6c656374696f6e496e666f293e00020018436f6e6669670400900118436f6e66696700030038416c6c436f6c6c656374696f6e73040050015c5665633c284163746f7249642c204163746f724964293e000400004c08486e66745f6d61726b6574706c6163655f696f145374617465000020011861646d696e733001305665633c4163746f7249643e00014c636f6c6c656374696f6e5f746f5f6f776e657250015c5665633c284163746f7249642c204163746f724964293e00013474696d655f6372656174696f6e58014c5665633c284163746f7249642c20753634293e000140747970655f636f6c6c656374696f6e736001745665633c28537472696e672c20436f6c6c656374696f6e496e666f293e00011473616c65736c01945665633c28284163746f7249642c20753634292c204e6674496e666f466f7253616c65293e00012061756374696f6e737c01785665633c28284163746f7249642c20753634292c2041756374696f6e293e0001186f66666572738801485665633c284f666665722c2075313238293e000118636f6e666967900118436f6e66696700005000000254005400000408242400580000025c005c0000040824040060000002640064000004081c68006808486e66745f6d61726b6574706c6163655f696f38436f6c6c656374696f6e496e666f00000c011c636f64655f6964100118436f646549640001246d6574615f6c696e6b1c0118537472696e67000140747970655f6465736372697074696f6e1c0118537472696e6700006c000002700070000004085c74007408486e66745f6d61726b6574706c6163655f696f384e6674496e666f466f7253616c65000010011470726963650801107531323800012c746f6b656e5f6f776e657224011c4163746f724964000140636f6c6c656374696f6e5f6f776e657224011c4163746f72496400011c726f79616c747978010c75313600007800000504007c000002800080000004085c84008408486e66745f6d61726b6574706c6163655f696f1c41756374696f6e00001c01146f776e657224011c4163746f724964000128737461727465645f617404010c753634000120656e6465645f617404010c75363400013463757272656e745f70726963650801107531323800013863757272656e745f77696e6e657224011c4163746f724964000140636f6c6c656374696f6e5f6f776e657224011c4163746f72496400011c726f79616c747978010c7531360000880000028c008c000004082c08009008486e66745f6d61726b6574706c6163655f696f18436f6e66696700000c01406761735f666f725f6372656174696f6e04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001586d696e696d756d5f7472616e736665725f76616c7565080110753132380000 +0002000100000000000104000000011000000000000000011300000001140000001551a80008486e66745f6d61726b6574706c6163655f696f484e66744d61726b6574706c616365496e697400002001406761735f666f725f6372656174696f6e04010c7536340001586761735f666f725f7472616e736665725f746f6b656e04010c7536340001546761735f666f725f636c6f73655f61756374696f6e04010c7536340001646761735f666f725f64656c6574655f636f6c6c656374696f6e04010c7536340001586761735f666f725f6765745f746f6b656e5f696e666f04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001586d696e696d756d5f7472616e736665725f76616c75650801107531323800012c6d735f696e5f626c6f636b0c010c75333200000400000506000800000507000c00000505001008486e66745f6d61726b6574706c6163655f696f504e66744d61726b6574706c616365416374696f6e000140404164644e6577436f6c6c656374696f6e10011c636f64655f6964140118436f646549640001246d6574615f6c696e6b200118537472696e67000124747970655f6e616d65200118537472696e67000140747970655f6465736372697074696f6e200118537472696e6700000040437265617465436f6c6c656374696f6e080124747970655f6e616d65200118537472696e6700011c7061796c6f616424011c5665633c75383e0001001c53616c654e66740c0148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380002003443616e63656c53616c654e6674080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000300184275794e6674080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340004003443726561746541756374696f6e100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d730c010c75333200050018416464426964080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400060030436c6f736541756374696f6e080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340007003443616e63656c41756374696f6e080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340008002c4372656174654f66666572080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340009002c43616e63656c4f66666572080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000a002c4163636570744f666665720401146f666665722c01144f66666572000b004044656c657465436f6c6c656374696f6e040148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000c002441646441646d696e7304011475736572733001305665633c4163746f7249643e000d002c44656c65746541646d696e0401107573657228011c4163746f724964000e0030557064617465436f6e6669672001406761735f666f725f6372656174696f6e34012c4f7074696f6e3c7536343e0001586761735f666f725f7472616e736665725f746f6b656e34012c4f7074696f6e3c7536343e0001546761735f666f725f636c6f73655f61756374696f6e34012c4f7074696f6e3c7536343e0001646761735f666f725f64656c6574655f636f6c6c656374696f6e34012c4f7074696f6e3c7536343e0001586761735f666f725f6765745f746f6b656e5f696e666f34012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7334012c4f7074696f6e3c7536343e0001586d696e696d756d5f7472616e736665725f76616c75653801304f7074696f6e3c753132383e00012c6d735f696e5f626c6f636b3c012c4f7074696f6e3c7533323e000f00001410106773746418636f6d6d6f6e287072696d69746976657318436f64654964000004001801205b75383b2033325d000018000003200000001c001c0000050300200000050200240000021c002810106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004001801205b75383b2033325d00002c08486e66745f6d61726b6574706c6163655f696f144f6666657200000c0148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400011c63726561746f7228011c4163746f72496400003000000228003404184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100003804184f7074696f6e04045401080108104e6f6e6500000010536f6d6504000800000100003c04184f7074696f6e040454010c0108104e6f6e6500000010536f6d6504000c0000010000400418526573756c740804540144044501480108084f6b040044000000000c45727204004800000100004408486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654576656e74000140484e6577436f6c6c656374696f6e416464656410011c636f64655f6964140118436f646549640001246d6574615f6c696e6b200118537472696e67000124747970655f6e616d65200118537472696e67000140747970655f6465736372697074696f6e200118537472696e6700000044436f6c6c656374696f6e43726561746564080124747970655f6e616d65200118537472696e67000148636f6c6c656374696f6e5f6164647265737328011c4163746f7249640001001c53616c654e6674100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380001146f776e657228011c4163746f7249640002003c53616c654e667443616e63656c6564080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340003001c4e6674536f6c64100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400011470726963650801107531323800013463757272656e745f6f776e657228011c4163746f7249640004003841756374696f6e43726561746564100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d730c010c7533320005003441756374696f6e436c6f736564100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400011470726963650801107531323800013463757272656e745f6f776e657228011c4163746f7249640006002042696441646465640c0148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400013463757272656e745f7072696365080110753132380007003c41756374696f6e43616e63656c6564080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000800304f66666572437265617465640c0148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000114707269636508011075313238000900344f6666657243616e63656c6564080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000a00344f6666657241636365707465640401146f666665722c01144f66666572000b0044436f6c6c656374696f6e44656c65746564040148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000c002c41646d696e73416464656404011475736572733001305665633c4163746f7249643e000d003041646d696e44656c657465640401107573657228011c4163746f724964000e0034436f6e666967557064617465642001406761735f666f725f6372656174696f6e34012c4f7074696f6e3c7536343e0001586761735f666f725f7472616e736665725f746f6b656e34012c4f7074696f6e3c7536343e0001546761735f666f725f636c6f73655f61756374696f6e34012c4f7074696f6e3c7536343e0001646761735f666f725f64656c6574655f636f6c6c656374696f6e34012c4f7074696f6e3c7536343e0001586761735f666f725f6765745f746f6b656e5f696e666f34012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7334012c4f7074696f6e3c7536343e0001586d696e696d756d5f7472616e736665725f76616c75653801304f7074696f6e3c753132383e00012c6d735f696e5f626c6f636b3c012c4f7074696f6e3c7533323e000f00004808486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654572726f7200000400200118537472696e6700004c08486e66745f6d61726b6574706c6163655f696f28537461746551756572790001180c416c6c0000001841646d696e730001003c436f6c6c656374696f6e73496e666f00020018436f6e66696700030038416c6c436f6c6c656374696f6e7300040044476574436f6c6c656374696f6e496e666f040028011c4163746f724964000500005008486e66745f6d61726b6574706c6163655f696f2853746174655265706c790001180c416c6c040054011453746174650000001841646d696e7304003001305665633c4163746f7249643e0001003c436f6c6c656374696f6e73496e666f04006c01845665633c28537472696e672c2054797065436f6c6c656374696f6e496e666f293e00020018436f6e66696704009c0118436f6e66696700030038416c6c436f6c6c656374696f6e7304005801845665633c284163746f7249642c2028537472696e672c204163746f72496429293e00040038436f6c6c656374696f6e496e666f0400a001584f7074696f6e3c436f6c6c656374696f6e496e666f3e000500005408486e66745f6d61726b6574706c6163655f696f145374617465000020011861646d696e733001305665633c4163746f7249643e00014c636f6c6c656374696f6e5f746f5f6f776e65725801845665633c284163746f7249642c2028537472696e672c204163746f72496429293e00013474696d655f6372656174696f6e64014c5665633c284163746f7249642c20753634293e000140747970655f636f6c6c656374696f6e736c01845665633c28537472696e672c2054797065436f6c6c656374696f6e496e666f293e00011473616c65737801945665633c28284163746f7249642c20753634292c204e6674496e666f466f7253616c65293e00012061756374696f6e738801785665633c28284163746f7249642c20753634292c2041756374696f6e293e0001186f66666572739401485665633c284f666665722c2075313238293e000118636f6e6669679c0118436f6e6669670000580000025c005c00000408286000600000040820280064000002680068000004082804006c000002700070000004082074007408486e66745f6d61726b6574706c6163655f696f4854797065436f6c6c656374696f6e496e666f00000c011c636f64655f6964140118436f646549640001246d6574615f6c696e6b200118537472696e67000140747970655f6465736372697074696f6e200118537472696e670000780000027c007c000004086880008008486e66745f6d61726b6574706c6163655f696f384e6674496e666f466f7253616c65000010011470726963650801107531323800012c746f6b656e5f6f776e657228011c4163746f724964000140636f6c6c656374696f6e5f6f776e657228011c4163746f72496400011c726f79616c747984010c7531360000840000050400880000028c008c000004086890009008486e66745f6d61726b6574706c6163655f696f1c41756374696f6e00001c01146f776e657228011c4163746f724964000128737461727465645f617404010c753634000120656e6465645f617404010c75363400013463757272656e745f70726963650801107531323800013863757272656e745f77696e6e657228011c4163746f724964000140636f6c6c656374696f6e5f6f776e657228011c4163746f72496400011c726f79616c747984010c753136000094000002980098000004082c08009c08486e66745f6d61726b6574706c6163655f696f18436f6e66696700002001406761735f666f725f6372656174696f6e04010c7536340001586761735f666f725f7472616e736665725f746f6b656e04010c7536340001546761735f666f725f636c6f73655f61756374696f6e04010c7536340001646761735f666f725f64656c6574655f636f6c6c656374696f6e04010c7536340001586761735f666f725f6765745f746f6b656e5f696e666f04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001586d696e696d756d5f7472616e736665725f76616c75650801107531323800012c6d735f696e5f626c6f636b0c010c7533320000a004184f7074696f6e04045401a40108104e6f6e6500000010536f6d650400a40000010000a408486e66745f6d61726b6574706c6163655f696f38436f6c6c656374696f6e496e666f00000c01146f776e657228011c4163746f724964000124747970655f6e616d65200118537472696e670001246d6574615f6c696e6b200118537472696e670000 \ No newline at end of file diff --git a/indexer/db/migrations/1703490897133-Data.js b/indexer/db/migrations/1703490897133-Data.js deleted file mode 100644 index 6f4ec57..0000000 --- a/indexer/db/migrations/1703490897133-Data.js +++ /dev/null @@ -1,45 +0,0 @@ -module.exports = class Data1703490897133 { - name = 'Data1703490897133' - - async up(db) { - await db.query(`CREATE TABLE "collection_type" ("id" character varying NOT NULL, "description" text NOT NULL, "type" text NOT NULL, "meta_url" text NOT NULL, "meta_str" text NOT NULL, "marketplace_id" character varying, CONSTRAINT "PK_75c673f46e25c52205fae22130c" PRIMARY KEY ("id"))`) - await db.query(`CREATE INDEX "IDX_be423ee528eb245b57165bd597" ON "collection_type" ("marketplace_id") `) - await db.query(`CREATE TABLE "transfer" ("id" character varying NOT NULL, "from" text NOT NULL, "to" text NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" text NOT NULL, "tx_hash" text NOT NULL, "nft_id" character varying, CONSTRAINT "PK_fd9ddbdd49a17afcbe014401295" PRIMARY KEY ("id"))`) - await db.query(`CREATE INDEX "IDX_52fc453ba5ff660f331db4b359" ON "transfer" ("nft_id") `) - await db.query(`CREATE TABLE "sale" ("id" character varying NOT NULL, "owner" text NOT NULL, "price" numeric NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" text NOT NULL, "is_sold" boolean NOT NULL, "nft_id" character varying, CONSTRAINT "PK_d03891c457cbcd22974732b5de2" PRIMARY KEY ("id"))`) - await db.query(`CREATE INDEX "IDX_8524438f82167bcb795bcb8663" ON "sale" ("nft_id") `) - await db.query(`CREATE TABLE "nft" ("id" character varying NOT NULL, "owner" text NOT NULL, "id_in_collection" text NOT NULL, "media_url" text NOT NULL, "minted_at" TIMESTAMP WITH TIME ZONE NOT NULL, "approved_account" text, "on_sale" boolean NOT NULL, "collection_id" character varying, CONSTRAINT "PK_8f46897c58e23b0e7bf6c8e56b0" PRIMARY KEY ("id"))`) - await db.query(`CREATE INDEX "IDX_ffe58aa05707db77c2f20ecdbc" ON "nft" ("collection_id") `) - await db.query(`CREATE TABLE "collection" ("id" character varying NOT NULL, "admin" text NOT NULL, "name" text NOT NULL, "description" text NOT NULL, "user_mint_limit" numeric, "tokens_limit" numeric, "collection_image" text NOT NULL, "transferable" boolean NOT NULL, "approvable" boolean NOT NULL, "burnable" boolean NOT NULL, "sellable" boolean NOT NULL, "attandable" boolean NOT NULL, "tags" text array NOT NULL, "marketplace_id" character varying, "type_id" character varying, CONSTRAINT "PK_ad3f485bbc99d875491f44d7c85" PRIMARY KEY ("id"))`) - await db.query(`CREATE INDEX "IDX_4698f01445e4833a95f214f862" ON "collection" ("marketplace_id") `) - await db.query(`CREATE INDEX "IDX_75c673f46e25c52205fae22130" ON "collection" ("type_id") `) - await db.query(`CREATE TABLE "marketplace" ("id" character varying NOT NULL, CONSTRAINT "PK_d9c9a956a1a45b27b56db53bfc8" PRIMARY KEY ("id"))`) - await db.query(`ALTER TABLE "collection_type" ADD CONSTRAINT "FK_be423ee528eb245b57165bd597b" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) - await db.query(`ALTER TABLE "transfer" ADD CONSTRAINT "FK_52fc453ba5ff660f331db4b3591" FOREIGN KEY ("nft_id") REFERENCES "nft"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) - await db.query(`ALTER TABLE "sale" ADD CONSTRAINT "FK_8524438f82167bcb795bcb86637" FOREIGN KEY ("nft_id") REFERENCES "nft"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) - await db.query(`ALTER TABLE "nft" ADD CONSTRAINT "FK_ffe58aa05707db77c2f20ecdbc3" FOREIGN KEY ("collection_id") REFERENCES "collection"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) - await db.query(`ALTER TABLE "collection" ADD CONSTRAINT "FK_4698f01445e4833a95f214f862b" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) - await db.query(`ALTER TABLE "collection" ADD CONSTRAINT "FK_75c673f46e25c52205fae22130c" FOREIGN KEY ("type_id") REFERENCES "collection_type"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) - } - - async down(db) { - await db.query(`DROP TABLE "collection_type"`) - await db.query(`DROP INDEX "public"."IDX_be423ee528eb245b57165bd597"`) - await db.query(`DROP TABLE "transfer"`) - await db.query(`DROP INDEX "public"."IDX_52fc453ba5ff660f331db4b359"`) - await db.query(`DROP TABLE "sale"`) - await db.query(`DROP INDEX "public"."IDX_8524438f82167bcb795bcb8663"`) - await db.query(`DROP TABLE "nft"`) - await db.query(`DROP INDEX "public"."IDX_ffe58aa05707db77c2f20ecdbc"`) - await db.query(`DROP TABLE "collection"`) - await db.query(`DROP INDEX "public"."IDX_4698f01445e4833a95f214f862"`) - await db.query(`DROP INDEX "public"."IDX_75c673f46e25c52205fae22130"`) - await db.query(`DROP TABLE "marketplace"`) - await db.query(`ALTER TABLE "collection_type" DROP CONSTRAINT "FK_be423ee528eb245b57165bd597b"`) - await db.query(`ALTER TABLE "transfer" DROP CONSTRAINT "FK_52fc453ba5ff660f331db4b3591"`) - await db.query(`ALTER TABLE "sale" DROP CONSTRAINT "FK_8524438f82167bcb795bcb86637"`) - await db.query(`ALTER TABLE "nft" DROP CONSTRAINT "FK_ffe58aa05707db77c2f20ecdbc3"`) - await db.query(`ALTER TABLE "collection" DROP CONSTRAINT "FK_4698f01445e4833a95f214f862b"`) - await db.query(`ALTER TABLE "collection" DROP CONSTRAINT "FK_75c673f46e25c52205fae22130c"`) - } -} diff --git a/indexer/package-lock.json b/indexer/package-lock.json index d68e3c9..a3e8113 100644 --- a/indexer/package-lock.json +++ b/indexer/package-lock.json @@ -7,7 +7,7 @@ "name": "nft-marketplace-indexer", "dependencies": { "@gear-js/api": "^0.35.2", - "@polkadot/types": "^10.11.2", + "@polkadot/types": "10.10.1", "@subsquid/archive-registry": "^3.3.0", "@subsquid/graphql-server": "^4.3.1", "@subsquid/ss58": "^2.0.1", @@ -16,13 +16,15 @@ "@subsquid/typeorm-store": "^1.2.4", "dotenv": "^16.3.1", "pg": "8.11.3", - "typeorm": "^0.3.17" + "typeorm": "^0.3.19", + "uuid": "^9.0.1" }, "devDependencies": { "@subsquid/substrate-metadata-explorer": "^3.1.1", "@subsquid/substrate-typegen": "^8.0.1", "@subsquid/typeorm-codegen": "^1.3.2", "@types/node": "^20.8.4", + "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", "eslint": "^8.0.1", @@ -826,17 +828,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", @@ -1232,6 +1223,95 @@ "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1752,6 +1832,15 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@polkadot/api": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.10.1.tgz", @@ -1798,25 +1887,6 @@ "node": ">=16" } }, - "node_modules/@polkadot/api-augment/node_modules/@polkadot/types": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", - "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, - "dependencies": { - "@polkadot/keyring": "^12.5.1", - "@polkadot/types-augment": "10.10.1", - "@polkadot/types-codec": "10.10.1", - "@polkadot/types-create": "10.10.1", - "@polkadot/util": "^12.5.1", - "@polkadot/util-crypto": "^12.5.1", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@polkadot/api-base": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.10.1.tgz", @@ -1833,25 +1903,6 @@ "node": ">=16" } }, - "node_modules/@polkadot/api-base/node_modules/@polkadot/types": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", - "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, - "dependencies": { - "@polkadot/keyring": "^12.5.1", - "@polkadot/types-augment": "10.10.1", - "@polkadot/types-codec": "10.10.1", - "@polkadot/types-create": "10.10.1", - "@polkadot/util": "^12.5.1", - "@polkadot/util-crypto": "^12.5.1", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@polkadot/api-derive": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.10.1.tgz", @@ -1873,44 +1924,6 @@ "node": ">=16" } }, - "node_modules/@polkadot/api-derive/node_modules/@polkadot/types": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", - "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, - "dependencies": { - "@polkadot/keyring": "^12.5.1", - "@polkadot/types-augment": "10.10.1", - "@polkadot/types-codec": "10.10.1", - "@polkadot/types-create": "10.10.1", - "@polkadot/util": "^12.5.1", - "@polkadot/util-crypto": "^12.5.1", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api/node_modules/@polkadot/types": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", - "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, - "dependencies": { - "@polkadot/keyring": "^12.5.1", - "@polkadot/types-augment": "10.10.1", - "@polkadot/types-codec": "10.10.1", - "@polkadot/types-create": "10.10.1", - "@polkadot/util": "^12.5.1", - "@polkadot/util-crypto": "^12.5.1", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@polkadot/keyring": { "version": "12.6.2", "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.6.2.tgz", @@ -1957,25 +1970,6 @@ "node": ">=16" } }, - "node_modules/@polkadot/rpc-augment/node_modules/@polkadot/types": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", - "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, - "dependencies": { - "@polkadot/keyring": "^12.5.1", - "@polkadot/types-augment": "10.10.1", - "@polkadot/types-codec": "10.10.1", - "@polkadot/types-create": "10.10.1", - "@polkadot/util": "^12.5.1", - "@polkadot/util-crypto": "^12.5.1", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@polkadot/rpc-core": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.10.1.tgz", @@ -1993,25 +1987,6 @@ "node": ">=16" } }, - "node_modules/@polkadot/rpc-core/node_modules/@polkadot/types": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", - "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, - "dependencies": { - "@polkadot/keyring": "^12.5.1", - "@polkadot/types-augment": "10.10.1", - "@polkadot/types-codec": "10.10.1", - "@polkadot/types-create": "10.10.1", - "@polkadot/util": "^12.5.1", - "@polkadot/util-crypto": "^12.5.1", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@polkadot/rpc-provider": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.10.1.tgz", @@ -2038,11 +2013,10 @@ "@substrate/connect": "0.7.33" } }, - "node_modules/@polkadot/rpc-provider/node_modules/@polkadot/types": { + "node_modules/@polkadot/types": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, "dependencies": { "@polkadot/keyring": "^12.5.1", "@polkadot/types-augment": "10.10.1", @@ -2057,29 +2031,10 @@ "node": ">=16" } }, - "node_modules/@polkadot/types": { - "version": "10.11.2", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.11.2.tgz", - "integrity": "sha512-d52j3xXni+C8GdYZVTSfu8ROAnzXFMlyRvXtor0PudUc8UQHOaC4+mYAkTBGA2gKdmL8MHSfRSbhcxHhsikY6Q==", - "dependencies": { - "@polkadot/keyring": "^12.6.2", - "@polkadot/types-augment": "10.11.2", - "@polkadot/types-codec": "10.11.2", - "@polkadot/types-create": "10.11.2", - "@polkadot/util": "^12.6.2", - "@polkadot/util-crypto": "^12.6.2", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@polkadot/types-augment": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.10.1.tgz", "integrity": "sha512-XRHE75IocXfFE6EADYov3pqXCyBk5SWbiHoZ0+4WYWP9SwMuzsBaAy84NlhLBlkG3+ehIqi0HpAd/qrljJGZbg==", - "peer": true, "dependencies": { "@polkadot/types": "10.10.1", "@polkadot/types-codec": "10.10.1", @@ -2090,30 +2045,10 @@ "node": ">=16" } }, - "node_modules/@polkadot/types-augment/node_modules/@polkadot/types": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", - "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, - "dependencies": { - "@polkadot/keyring": "^12.5.1", - "@polkadot/types-augment": "10.10.1", - "@polkadot/types-codec": "10.10.1", - "@polkadot/types-create": "10.10.1", - "@polkadot/util": "^12.5.1", - "@polkadot/util-crypto": "^12.5.1", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@polkadot/types-codec": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.10.1.tgz", "integrity": "sha512-ETPG0wzWzt/bDKRQmYbO7CLe/0lUt8VrG6/bECdv+Kye+8Qedba2LZyTWm/9f2ngms8TZ82yI8mPv/mozdtfnw==", - "peer": true, "dependencies": { "@polkadot/util": "^12.5.1", "@polkadot/x-bigint": "^12.5.1", @@ -2127,7 +2062,6 @@ "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.10.1.tgz", "integrity": "sha512-7OiLzd+Ter5zrpjP7fDwA1m89kd38VvMVixfOSv8x7ld2pDT+yyyKl14TCwRSWrKWCMtIb6M3iasPhq5cUa7cw==", - "peer": true, "dependencies": { "@polkadot/types-codec": "10.10.1", "@polkadot/util": "^12.5.1", @@ -2154,25 +2088,6 @@ "node": ">=16" } }, - "node_modules/@polkadot/types-known/node_modules/@polkadot/types": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.10.1.tgz", - "integrity": "sha512-Ben62P1tjYEhKag34GBGcLX6NqcFR1VD5nNbWaxgr+t36Jl/tlHs6P9DlbFqQP7Tt9FmGrAYY0m3oTkhjG1NzA==", - "peer": true, - "dependencies": { - "@polkadot/keyring": "^12.5.1", - "@polkadot/types-augment": "10.10.1", - "@polkadot/types-codec": "10.10.1", - "@polkadot/types-create": "10.10.1", - "@polkadot/util": "^12.5.1", - "@polkadot/util-crypto": "^12.5.1", - "rxjs": "^7.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@polkadot/types-support": { "version": "10.10.1", "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.10.1.tgz", @@ -2186,46 +2101,6 @@ "node": ">=16" } }, - "node_modules/@polkadot/types/node_modules/@polkadot/types-augment": { - "version": "10.11.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.11.2.tgz", - "integrity": "sha512-8eB8ew04wZiE5GnmFvEFW1euJWmF62SGxb1O+8wL3zoUtB9Xgo1vB6w6xbTrd+HLV6jNSeXXnbbF1BEUvi9cNg==", - "dependencies": { - "@polkadot/types": "10.11.2", - "@polkadot/types-codec": "10.11.2", - "@polkadot/util": "^12.6.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/types/node_modules/@polkadot/types-codec": { - "version": "10.11.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.11.2.tgz", - "integrity": "sha512-3xjOQL+LOOMzYqlgP9ROL0FQnzU8lGflgYewzau7AsDlFziSEtb49a9BpYo6zil4koC+QB8zQ9OHGFumG08T8w==", - "dependencies": { - "@polkadot/util": "^12.6.2", - "@polkadot/x-bigint": "^12.6.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/types/node_modules/@polkadot/types-create": { - "version": "10.11.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.11.2.tgz", - "integrity": "sha512-SJt23NxYvefRxVZZm6mT9ed1pR6FDoIGQ3xUpbjhTLfU2wuhpKjekMVorYQ6z/gK2JLMu2kV92Ardsz+6GX5XQ==", - "dependencies": { - "@polkadot/types-codec": "10.11.2", - "@polkadot/util": "^12.6.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@polkadot/util": { "version": "12.6.2", "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.6.2.tgz", @@ -3590,6 +3465,12 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, "node_modules/@types/yargs": { "version": "16.0.9", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", @@ -5016,7 +4897,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5137,20 +5017,10 @@ "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" }, "node_modules/debug": { "version": "2.6.9", @@ -5373,6 +5243,11 @@ "node": ">=4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/easy-table": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", @@ -6137,6 +6012,32 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", @@ -6181,7 +6082,8 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -6266,18 +6168,21 @@ } }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -6711,6 +6616,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -7088,8 +6994,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -7201,6 +7106,23 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -8325,14 +8247,25 @@ } }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" } }, "node_modules/mkdirp": { @@ -8600,6 +8533,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -8758,7 +8692,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -8769,6 +8702,29 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -9206,11 +9162,6 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, - "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", @@ -9556,7 +9507,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -9568,7 +9518,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -9730,6 +9679,20 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -9741,6 +9704,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -10109,19 +10084,19 @@ } }, "node_modules/typeorm": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.17.tgz", - "integrity": "sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.19.tgz", + "integrity": "sha512-OGelrY5qEoAU80mR1iyvmUHiKCPUydL6xp6bebXzS7jyv/X70Gp/jBWRAfF4qGOfy2A7orMiGRfwsBUNbEL65g==", "dependencies": { "@sqltools/formatter": "^1.2.5", "app-root-path": "^3.1.0", "buffer": "^6.0.3", "chalk": "^4.1.2", "cli-highlight": "^2.1.11", - "date-fns": "^2.29.3", + "dayjs": "^1.11.9", "debug": "^4.3.4", "dotenv": "^16.0.3", - "glob": "^8.1.0", + "glob": "^10.3.10", "mkdirp": "^2.1.3", "reflect-metadata": "^0.1.13", "sha.js": "^2.4.11", @@ -10143,13 +10118,13 @@ "peerDependencies": { "@google-cloud/spanner": "^5.18.0", "@sap/hana-client": "^2.12.25", - "better-sqlite3": "^7.1.2 || ^8.0.0", + "better-sqlite3": "^7.1.2 || ^8.0.0 || ^9.0.0", "hdb-pool": "^0.1.6", "ioredis": "^5.0.4", - "mongodb": "^5.2.0", - "mssql": "^9.1.1", + "mongodb": "^5.8.0", + "mssql": "^9.1.1 || ^10.0.1", "mysql2": "^2.2.5 || ^3.0.1", - "oracledb": "^5.1.0", + "oracledb": "^6.3.0", "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", @@ -10488,7 +10463,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -10562,10 +10536,28 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "3.0.3", diff --git a/indexer/package.json b/indexer/package.json index 87cba11..d04dec5 100644 --- a/indexer/package.json +++ b/indexer/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@gear-js/api": "^0.35.2", - "@polkadot/types": "^10.11.2", + "@polkadot/types": "10.10.1", "@subsquid/archive-registry": "^3.3.0", "@subsquid/graphql-server": "^4.3.1", "@subsquid/ss58": "^2.0.1", @@ -22,13 +22,15 @@ "@subsquid/typeorm-store": "^1.2.4", "dotenv": "^16.3.1", "pg": "8.11.3", - "typeorm": "^0.3.17" + "typeorm": "^0.3.19", + "uuid": "^9.0.1" }, "devDependencies": { "@subsquid/substrate-metadata-explorer": "^3.1.1", "@subsquid/substrate-typegen": "^8.0.1", "@subsquid/typeorm-codegen": "^1.3.2", "@types/node": "^20.8.4", + "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", "eslint": "^8.0.1", diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 29ca1c2..e3cd20f 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -1,7 +1,32 @@ type Marketplace @entity { id: ID! + admins: [String!]! + config: MarketplaceConfig! collections: [Collection!]! @derivedFrom(field: "marketplace") collectionTypes: [CollectionType!]! @derivedFrom(field: "marketplace") + events: [MarketplaceEvent!]! @derivedFrom(field: "marketplace") +} + +type MarketplaceConfig @entity { + gasForCreation: Int + gasForTransferToken: Int + gasForCloseAuction: Int + gasForDeleteCollection: Int + gasForGetTokenInfo: Int + timeBetweenCreateCollections: Int + minimumTransferValue: BigInt + msInBlock: Int + marketplace: Marketplace! +} + +type MarketplaceEvent @entity { + id: ID! + type: String! + raw: String! + marketplace: Marketplace! + blockNumber: Int! + txHash: String! + timestamp: DateTime! } type CollectionType @entity { @@ -17,19 +42,23 @@ type Collection @entity { id: ID! marketplace: Marketplace! type: CollectionType! - admin: String! - name: String! - description: String! + admin: String + name: String + description: String userMintLimit: BigInt tokensLimit: BigInt - collectionImage: String! - transferable: Boolean! - approvable: Boolean! - burnable: Boolean! - sellable: Boolean! - attandable: Boolean! - nfts: [Nft!]! @derivedFrom(field: "collection") - tags: [String!]! + paymentForMint: BigInt + royalty: Int + collectionLogo: String + collectionBanner: String + transferable: Boolean + approvable: Boolean + burnable: Boolean + sellable: Boolean + attendable: Boolean + createdAt: DateTime + nfts: [Nft!] @derivedFrom(field: "collection") + tags: [String!] } type Nft @entity { @@ -40,11 +69,15 @@ type Nft @entity { idInCollection: Int! collection: Collection! mediaUrl: String! - mintedAt: DateTime! approvedAccount: String + metadata: String onSale: Boolean! + createdAt: DateTime! + updatedAt: DateTime! transfers: [Transfer!]! @derivedFrom(field: "nft") sales: [Sale!]! @derivedFrom(field: "nft") + auctions: [Auction!]! @derivedFrom(field: "nft") + offers: [Offer!]! @derivedFrom(field: "nft") } type Transfer @entity { @@ -53,16 +86,54 @@ type Transfer @entity { from: String! to: String! timestamp: DateTime! - blockNumber: String! + blockNumber: Int! txHash: String! } type Sale @entity { + id: ID! + nft: Nft! + owner: String! + newOwner: String + price: BigInt! + timestamp: DateTime! + updatedAt: DateTime! + blockNumber: Int! + status: String! +} + +type Auction @entity { + id: ID! + nft: Nft! + owner: String! + minPrice: BigInt! + newOwner: String + lastPrice: BigInt + status: String! + durationMs: Int! + timestamp: DateTime! + updatedAt: DateTime! + blockNumber: Int! + bids: [Bid!]! @derivedFrom(field: "auction") +} + +type Bid @entity { + id: ID! + auction: Auction! + bidder: String! + price: BigInt! + timestamp: DateTime! + blockNumber: Int! +} + +type Offer @entity { id: ID! nft: Nft! owner: String! price: BigInt! + status: String! + creator: String! timestamp: DateTime! - blockNumber: String! - isSold: Boolean! + updatedAt: DateTime! + blockNumber: Int! } diff --git a/indexer/src/config.ts b/indexer/src/config.ts index ec95b28..51834e0 100644 --- a/indexer/src/config.ts +++ b/indexer/src/config.ts @@ -1,4 +1,16 @@ +import { strict as assert } from 'assert'; + +export const checkEnv = (envName: string, defaultValue?: string) => { + const env = process.env[envName] ?? defaultValue; + if (env) { + return env; + } + assert.notStrictEqual(env, undefined, `${envName} is not specified`); + return env as string; +}; + export const config = { - marketplaceProgram: process.env.MARKETPLACE_PROGRAM, - nftProgram: process.env.NFT_PROGRAM, + marketplaceProgram: checkEnv('MARKETPLACE_PROGRAM'), + minBlockNum: Number.parseInt(checkEnv('MIN_BLOCK_NUM')), + rateLimit: Number.parseInt(checkEnv('RATE_LIMIT', '100')), }; diff --git a/indexer/src/main.ts b/indexer/src/main.ts index e74629b..a497425 100644 --- a/indexer/src/main.ts +++ b/indexer/src/main.ts @@ -3,18 +3,43 @@ import { TypeormDatabase } from '@subsquid/typeorm-store'; import { processor } from './processor'; import { config } from './config'; import { EventsProcessing } from './processing/events.processing'; -import {Collection} from "./model"; +import { EventInfo } from './processing/event-info.type'; +import { Block } from '@subsquid/substrate-processor'; +import { NftMarketplaceEventType } from './types/marketplace.events'; +import { EntitiesService } from './processing/entities.service'; +import { getLocalStorage } from './processing/storage/local.storage'; +import { BatchService } from './processing/batch.service'; + +const NFT_INITIALIZED_CLEAR_TIME = 5 * 60 * 1000; // 5 minutes + +function getBlockDate( + block: Block<{ block: { timestamp: boolean }; event: { args: boolean } }>, +) { + return new Date(block.header.timestamp ?? new Date().getTime()); +} + +let possibleNftInitializedEvents: { + payload: string; + eventInfo: EventInfo; +}[] = []; processor.run(new TypeormDatabase(), async (ctx) => { - const processing = new EventsProcessing(ctx.store); + const localStorage = await getLocalStorage(ctx.store); + const entitiesService = new EntitiesService( + localStorage, + new BatchService(ctx.store), + ctx.store, + ); + const processing = new EventsProcessing(entitiesService); + const firstBlockDate = getBlockDate(ctx.blocks[0]); + console.log( + `[main] start processing ${ctx.blocks.length} blocks at ${firstBlockDate}.`, + ); for (const block of ctx.blocks) { - const events = [ - ...block.events, - ...block.extrinsics.flatMap((e) => e.events), - ].filter((e) => e.args && e.args.message); + const events = block.events.filter((e) => e.args && e.args.message); for (const item of events) { const { - message: { source, payload, details }, + message: { source, payload, details, destination, id }, } = item.args; if (payload === '0x') { continue; @@ -22,14 +47,45 @@ processor.run(new TypeormDatabase(), async (ctx) => { if (details && details.code.__kind !== 'Success') { continue; } - const collection = await ctx.store.findOne(Collection, { where: { id: source } }); - if (collection) { - await processing.handleNftEvent(block, payload, source); - } - if (config.marketplaceProgram && config.marketplaceProgram === source) { - await processing.handleMarketplaceEvent(block, payload, source); + const eventInfo: EventInfo = { + blockNumber: block.header.height, + destination, + source, + timestamp: getBlockDate(block), + txHash: id, + }; + if (config.marketplaceProgram === source) { + const marketplaceEvent = await processing.handleMarketplaceEvent( + payload, + eventInfo, + ); + if ( + marketplaceEvent && + marketplaceEvent.type === NftMarketplaceEventType.CollectionCreated + ) { + const nftInitialize = possibleNftInitializedEvents.find( + (e) => e.eventInfo.source === marketplaceEvent.collectionAddress, + ); + if (nftInitialize) { + await processing.handleNftEvent( + nftInitialize.payload, + nftInitialize.eventInfo, + ); + } + } + } else { + let collection = await localStorage.getCollection(source); + if (collection) { + await processing.handleNftEvent(payload, eventInfo); + } + possibleNftInitializedEvents.push({ payload, eventInfo }); } } } + possibleNftInitializedEvents = possibleNftInitializedEvents.filter( + (s) => + s.eventInfo.timestamp > + new Date(firstBlockDate.getTime() - NFT_INITIALIZED_CLEAR_TIME), + ); await processing.saveAll(); }); diff --git a/indexer/src/model/generated/auction.model.ts b/indexer/src/model/generated/auction.model.ts new file mode 100644 index 0000000..ef51d57 --- /dev/null +++ b/indexer/src/model/generated/auction.model.ts @@ -0,0 +1,61 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, + OneToMany as OneToMany_, +} from 'typeorm'; +import * as marshal from './marshal'; +import { Nft } from './nft.model'; +import { Bid } from './bid.model'; + +@Entity_() +export class Auction { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Index_() + @ManyToOne_(() => Nft, { nullable: true }) + nft!: Nft; + + @Column_('text', { nullable: false }) + owner!: string; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + minPrice!: bigint; + + @Column_('text', { nullable: true }) + newOwner!: string | undefined | null; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: true, + }) + lastPrice!: bigint | undefined | null; + + @Column_('text', { nullable: false }) + status!: string; + + @Column_('int4', { nullable: false }) + durationMs!: number; + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date; + + @Column_('timestamp with time zone', { nullable: false }) + updatedAt!: Date; + + @Column_('int4', { nullable: false }) + blockNumber!: number; + + @OneToMany_(() => Bid, (e) => e.auction) + bids!: Bid[]; +} diff --git a/indexer/src/model/generated/bid.model.ts b/indexer/src/model/generated/bid.model.ts new file mode 100644 index 0000000..b3ed36a --- /dev/null +++ b/indexer/src/model/generated/bid.model.ts @@ -0,0 +1,38 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm'; +import * as marshal from './marshal'; +import { Auction } from './auction.model'; + +@Entity_() +export class Bid { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Index_() + @ManyToOne_(() => Auction, { nullable: true }) + auction!: Auction; + + @Column_('text', { nullable: false }) + bidder!: string; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + price!: bigint; + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date; + + @Column_('int4', { nullable: false }) + blockNumber!: number; +} diff --git a/indexer/src/model/generated/collection.model.ts b/indexer/src/model/generated/collection.model.ts index bd98a06..14856dc 100644 --- a/indexer/src/model/generated/collection.model.ts +++ b/indexer/src/model/generated/collection.model.ts @@ -28,14 +28,14 @@ export class Collection { @ManyToOne_(() => CollectionType, { nullable: true }) type!: CollectionType; - @Column_('text', { nullable: false }) - admin!: string; + @Column_('text', { nullable: true }) + admin!: string | undefined | null; - @Column_('text', { nullable: false }) - name!: string; + @Column_('text', { nullable: true }) + name!: string | undefined | null; - @Column_('text', { nullable: false }) - description!: string; + @Column_('text', { nullable: true }) + description!: string | undefined | null; @Column_('numeric', { transformer: marshal.bigintTransformer, @@ -49,27 +49,42 @@ export class Collection { }) tokensLimit!: bigint | undefined | null; - @Column_('text', { nullable: false }) - collectionImage!: string; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: true, + }) + paymentForMint!: bigint | undefined | null; + + @Column_('int4', { nullable: true }) + royalty!: number | undefined | null; + + @Column_('text', { nullable: true }) + collectionLogo!: string | undefined | null; + + @Column_('text', { nullable: true }) + collectionBanner!: string | undefined | null; + + @Column_('bool', { nullable: true }) + transferable!: boolean | undefined | null; - @Column_('bool', { nullable: false }) - transferable!: boolean; + @Column_('bool', { nullable: true }) + approvable!: boolean | undefined | null; - @Column_('bool', { nullable: false }) - approvable!: boolean; + @Column_('bool', { nullable: true }) + burnable!: boolean | undefined | null; - @Column_('bool', { nullable: false }) - burnable!: boolean; + @Column_('bool', { nullable: true }) + sellable!: boolean | undefined | null; - @Column_('bool', { nullable: false }) - sellable!: boolean; + @Column_('bool', { nullable: true }) + attendable!: boolean | undefined | null; - @Column_('bool', { nullable: false }) - attandable!: boolean; + @Column_('timestamp with time zone', { nullable: true }) + createdAt!: Date | undefined | null; @OneToMany_(() => Nft, (e) => e.collection) nfts!: Nft[]; - @Column_('text', { array: true, nullable: false }) - tags!: string[]; + @Column_('text', { array: true, nullable: true }) + tags!: string[] | undefined | null; } diff --git a/indexer/src/model/generated/index.ts b/indexer/src/model/generated/index.ts index 935528e..4a647ae 100644 --- a/indexer/src/model/generated/index.ts +++ b/indexer/src/model/generated/index.ts @@ -1,6 +1,11 @@ export * from './marketplace.model'; +export * from './marketplaceConfig.model'; +export * from './marketplaceEvent.model'; export * from './collectionType.model'; export * from './collection.model'; export * from './nft.model'; export * from './transfer.model'; export * from './sale.model'; +export * from './auction.model'; +export * from './bid.model'; +export * from './offer.model'; diff --git a/indexer/src/model/generated/marketplace.model.ts b/indexer/src/model/generated/marketplace.model.ts index a25bdf8..56154bf 100644 --- a/indexer/src/model/generated/marketplace.model.ts +++ b/indexer/src/model/generated/marketplace.model.ts @@ -1,10 +1,15 @@ import { Entity as Entity_, + Column as Column_, PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, OneToMany as OneToMany_, } from 'typeorm'; +import { MarketplaceConfig } from './marketplaceConfig.model'; import { Collection } from './collection.model'; import { CollectionType } from './collectionType.model'; +import { MarketplaceEvent } from './marketplaceEvent.model'; @Entity_() export class Marketplace { @@ -15,9 +20,19 @@ export class Marketplace { @PrimaryColumn_() id!: string; + @Column_('text', { array: true, nullable: false }) + admins!: string[]; + + @Index_() + @ManyToOne_(() => MarketplaceConfig, { nullable: true }) + config!: MarketplaceConfig; + @OneToMany_(() => Collection, (e) => e.marketplace) collections!: Collection[]; @OneToMany_(() => CollectionType, (e) => e.marketplace) collectionTypes!: CollectionType[]; + + @OneToMany_(() => MarketplaceEvent, (e) => e.marketplace) + events!: MarketplaceEvent[]; } diff --git a/indexer/src/model/generated/marketplaceConfig.model.ts b/indexer/src/model/generated/marketplaceConfig.model.ts new file mode 100644 index 0000000..ba153f9 --- /dev/null +++ b/indexer/src/model/generated/marketplaceConfig.model.ts @@ -0,0 +1,50 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm'; +import * as marshal from './marshal'; +import { Marketplace } from './marketplace.model'; + +@Entity_() +export class MarketplaceConfig { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Column_('int4', { nullable: true }) + gasForCreation!: number | undefined | null; + + @Column_('int4', { nullable: true }) + gasForTransferToken!: number | undefined | null; + + @Column_('int4', { nullable: true }) + gasForCloseAuction!: number | undefined | null; + + @Column_('int4', { nullable: true }) + gasForDeleteCollection!: number | undefined | null; + + @Column_('int4', { nullable: true }) + gasForGetTokenInfo!: number | undefined | null; + + @Column_('int4', { nullable: true }) + timeBetweenCreateCollections!: number | undefined | null; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: true, + }) + minimumTransferValue!: bigint | undefined | null; + + @Column_('int4', { nullable: true }) + msInBlock!: number | undefined | null; + + @Index_() + @ManyToOne_(() => Marketplace, { nullable: true }) + marketplace!: Marketplace; +} diff --git a/indexer/src/model/generated/marketplaceEvent.model.ts b/indexer/src/model/generated/marketplaceEvent.model.ts new file mode 100644 index 0000000..88db268 --- /dev/null +++ b/indexer/src/model/generated/marketplaceEvent.model.ts @@ -0,0 +1,37 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm'; +import { Marketplace } from './marketplace.model'; + +@Entity_() +export class MarketplaceEvent { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Column_('text', { nullable: false }) + type!: string; + + @Column_('text', { nullable: false }) + raw!: string; + + @Index_() + @ManyToOne_(() => Marketplace, { nullable: true }) + marketplace!: Marketplace; + + @Column_('int4', { nullable: false }) + blockNumber!: number; + + @Column_('text', { nullable: false }) + txHash!: string; + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date; +} diff --git a/indexer/src/model/generated/nft.model.ts b/indexer/src/model/generated/nft.model.ts index bc0ac3f..5bd5943 100644 --- a/indexer/src/model/generated/nft.model.ts +++ b/indexer/src/model/generated/nft.model.ts @@ -9,6 +9,8 @@ import { import { Collection } from './collection.model'; import { Transfer } from './transfer.model'; import { Sale } from './sale.model'; +import { Auction } from './auction.model'; +import { Offer } from './offer.model'; @Entity_() export class Nft { @@ -28,7 +30,7 @@ export class Nft { @Column_('text', { nullable: false }) description!: string; - @Column_('int', { nullable: false }) + @Column_('int4', { nullable: false }) idInCollection!: number; @Index_() @@ -38,18 +40,30 @@ export class Nft { @Column_('text', { nullable: false }) mediaUrl!: string; - @Column_('timestamp with time zone', { nullable: false }) - mintedAt!: Date; - @Column_('text', { nullable: true }) approvedAccount!: string | undefined | null; + @Column_('text', { nullable: true }) + metadata!: string | undefined | null; + @Column_('bool', { nullable: false }) onSale!: boolean; + @Column_('timestamp with time zone', { nullable: false }) + createdAt!: Date; + + @Column_('timestamp with time zone', { nullable: false }) + updatedAt!: Date; + @OneToMany_(() => Transfer, (e) => e.nft) transfers!: Transfer[]; @OneToMany_(() => Sale, (e) => e.nft) sales!: Sale[]; + + @OneToMany_(() => Auction, (e) => e.nft) + auctions!: Auction[]; + + @OneToMany_(() => Offer, (e) => e.nft) + offers!: Offer[]; } diff --git a/indexer/src/model/generated/offer.model.ts b/indexer/src/model/generated/offer.model.ts new file mode 100644 index 0000000..31be115 --- /dev/null +++ b/indexer/src/model/generated/offer.model.ts @@ -0,0 +1,47 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm'; +import * as marshal from './marshal'; +import { Nft } from './nft.model'; + +@Entity_() +export class Offer { + constructor(props?: Partial) { + Object.assign(this, props); + } + + @PrimaryColumn_() + id!: string; + + @Index_() + @ManyToOne_(() => Nft, { nullable: true }) + nft!: Nft; + + @Column_('text', { nullable: false }) + owner!: string; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + price!: bigint; + + @Column_('text', { nullable: false }) + status!: string; + + @Column_('text', { nullable: false }) + creator!: string; + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date; + + @Column_('timestamp with time zone', { nullable: false }) + updatedAt!: Date; + + @Column_('int4', { nullable: false }) + blockNumber!: number; +} diff --git a/indexer/src/model/generated/sale.model.ts b/indexer/src/model/generated/sale.model.ts index 725a94c..bfdab02 100644 --- a/indexer/src/model/generated/sale.model.ts +++ b/indexer/src/model/generated/sale.model.ts @@ -24,6 +24,9 @@ export class Sale { @Column_('text', { nullable: false }) owner!: string; + @Column_('text', { nullable: true }) + newOwner!: string | undefined | null; + @Column_('numeric', { transformer: marshal.bigintTransformer, nullable: false, @@ -33,9 +36,12 @@ export class Sale { @Column_('timestamp with time zone', { nullable: false }) timestamp!: Date; - @Column_('text', { nullable: false }) - blockNumber!: string; + @Column_('timestamp with time zone', { nullable: false }) + updatedAt!: Date; - @Column_('bool', { nullable: false }) - isSold!: boolean; + @Column_('int4', { nullable: false }) + blockNumber!: number; + + @Column_('text', { nullable: false }) + status!: string; } diff --git a/indexer/src/model/generated/transfer.model.ts b/indexer/src/model/generated/transfer.model.ts index 0f40ed6..de354df 100644 --- a/indexer/src/model/generated/transfer.model.ts +++ b/indexer/src/model/generated/transfer.model.ts @@ -29,8 +29,8 @@ export class Transfer { @Column_('timestamp with time zone', { nullable: false }) timestamp!: Date; - @Column_('text', { nullable: false }) - blockNumber!: string; + @Column_('int4', { nullable: false }) + blockNumber!: number; @Column_('text', { nullable: false }) txHash!: string; diff --git a/indexer/src/model/types.ts b/indexer/src/model/types.ts new file mode 100644 index 0000000..93250dc --- /dev/null +++ b/indexer/src/model/types.ts @@ -0,0 +1,17 @@ +export enum SaleStatus { + Open = 'open', + Sold = 'sold', + Canceled = 'canceled', +} + +export enum AuctionStatus { + Open = 'open', + Closed = 'closed', + Canceled = 'canceled', +} + +export enum OfferStatus { + Open = 'open', + Accepted = 'accepted', + Canceled = 'canceled', +} diff --git a/indexer/src/processing/batch.service.ts b/indexer/src/processing/batch.service.ts new file mode 100644 index 0000000..1ace1e1 --- /dev/null +++ b/indexer/src/processing/batch.service.ts @@ -0,0 +1,103 @@ +import { Store } from '@subsquid/typeorm-store'; +import { + Auction, + Bid, + Collection, + CollectionType, + Marketplace, + MarketplaceEvent, + Nft, + Offer, + Sale, + Transfer, +} from '../model'; + +export class BatchService { + private collectionTypes: CollectionType[] = []; + private marketplace: Marketplace | undefined; + private collections: Collection[] = []; + private nfts: Nft[] = []; + private transfers: Transfer[] = []; + private bids: Bid[] = []; + private sales: Sale[] = []; + private auctions: Auction[] = []; + private offers: Offer[] = []; + private events: MarketplaceEvent[] = []; + + constructor(private readonly store: Store) {} + + async saveAll() { + await Promise.all([ + this.marketplace ? this.store.save(this.marketplace) : Promise.resolve(), + this.store.save(this.collectionTypes), + this.store.save(this.collections), + this.store.save(this.nfts), + this.store.save(this.offers), + this.store.save(this.auctions), + this.store.save(this.transfers), + this.store.save(this.sales), + this.store.save(this.events), + this.store.save(this.bids), + ]).catch((err) => { + console.error('Error saving batch', err); + }); + } + + clearAll() { + this.collectionTypes = []; + this.marketplace = undefined; + this.collections = []; + this.nfts = []; + this.transfers = []; + this.bids = []; + this.sales = []; + this.auctions = []; + this.offers = []; + this.events = []; + } + + setMarketplace(marketplace: Marketplace) { + this.marketplace = marketplace; + } + + addEvent(entity: MarketplaceEvent) { + this.events.push(entity); + } + + addCollectionUpdate(collection: Collection) { + this.safelyPush('collections', collection); + } + + addAuctionUpdate(auction: Auction) { + this.safelyPush('auctions', auction); + } + + addBidUpdate(bid: Bid) { + this.bids.push(bid); + } + + addOfferUpdate(offer: Offer) { + this.safelyPush('offers', offer); + } + + addSaleUpdate(sale: Sale) { + this.safelyPush('sales', sale); + } + + addCollectionTypeUpdate(collectionType: CollectionType) { + this.safelyPush('collectionTypes', collectionType); + } + + addNftUpdate(nft: Nft) { + this.safelyPush('nfts', nft); + } + + addTransfer(transfer: Transfer) { + this.transfers.push(transfer); + } + + private safelyPush(entity: string, value: any) { + // @ts-ignore + this[entity] = [...this[entity].filter((e) => e.id !== value.id), value]; + } +} diff --git a/indexer/src/processing/entities.service.ts b/indexer/src/processing/entities.service.ts new file mode 100644 index 0000000..56d748b --- /dev/null +++ b/indexer/src/processing/entities.service.ts @@ -0,0 +1,123 @@ +import { + Collection, + CollectionType, + MarketplaceEvent, + Marketplace, + Nft, + Sale, + Transfer, + Auction, + Bid, + MarketplaceConfig, + Offer, +} from '../model'; +import { v4 as uuidv4 } from 'uuid'; +import { IStorage } from './storage/storage.inteface'; +import { BatchService } from './batch.service'; +import { Store } from '@subsquid/typeorm-store'; + +export class EntitiesService { + constructor( + private readonly storage: IStorage, + private readonly batchService: BatchService, + private readonly store: Store, + ) {} + + async getMarketplace(): Promise { + return this.storage.getMarketplace(); + } + + async setMarketplace(marketplace: Marketplace) { + await this.storage.updateMarketplace(marketplace); + this.batchService.setMarketplace(marketplace); + } + + async addEvent(event: Omit) { + const entity = new MarketplaceEvent({ + ...event, + id: uuidv4(), + marketplace: await this.storage.getMarketplace(), + } as MarketplaceEvent); + this.batchService.addEvent(entity); + } + + async saveAll() { + await this.batchService.saveAll(); + } + + async getCollection(collectionAddress: string) { + return this.storage.getCollection(collectionAddress); + } + + async getNft(collectionAddress: string, tokenId: number) { + return this.storage.getNft(collectionAddress, tokenId); + } + + async setCollection(collection: Collection) { + await this.storage.updateCollection(collection); + this.batchService.addCollectionUpdate(collection); + } + + getSale(nft: Nft) { + return this.storage.getSale(nft); + } + + async setAuction(auction: Auction) { + await this.storage.updateAuction(auction); + this.batchService.addAuctionUpdate(auction); + } + + addBid(bid: Bid) { + this.batchService.addBidUpdate(bid); + } + + getAuction(nft: Nft) { + return this.storage.getAuction(nft); + } + + async setOffer(offer: Offer) { + await this.storage.updateOffer(offer); + this.batchService.addOfferUpdate(offer); + } + + getOffer(nft: Nft, creator: string) { + return this.storage.getOffer(nft, creator); + } + + async setSale(sale: Sale) { + await this.storage.updateSale(sale); + this.batchService.addSaleUpdate(sale); + } + + async deleteCollection(collection: Collection) { + await this.storage.deleteCollection(collection); + await this.store.remove(collection); + } + + async getCollectionType( + typeName: string, + ): Promise { + return this.storage.getCollectionType(typeName); + } + + async setCollectionType(collectionType: CollectionType) { + await this.storage.updateCollectionType(collectionType); + this.batchService.addCollectionTypeUpdate(collectionType); + } + + async setNft(nft: Nft) { + await this.storage.updateNft(nft); + this.batchService.addNftUpdate(nft); + } + + addTransfer(transfer: Transfer) { + this.batchService.addTransfer(transfer); + } + + async setMarketplaceConfig(marketplaceConfig: MarketplaceConfig) { + const marketplace = await this.storage.getMarketplace(); + marketplace.config = marketplaceConfig; + await this.storage.updateMarketplace(marketplace); + this.batchService.setMarketplace(marketplace); + } +} diff --git a/indexer/src/processing/entities.storage.ts b/indexer/src/processing/entities.storage.ts deleted file mode 100644 index bf73ee3..0000000 --- a/indexer/src/processing/entities.storage.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { - Collection, - CollectionType, - Marketplace, - Nft, - Sale, - Transfer, -} from '../model'; -import { Store } from '@subsquid/typeorm-store'; - -export class EntitiesStorage { - // typeName -> CollectionType - private collectionTypes: Record = {}; - // collectionAddress -> Collection - private collections: Record = {}; - // // collectionAddress-tokenId -> Nft - private nfts: Record = {}; - private transfers: Transfer[] = []; - private sale: Record = {}; - private marketplace: Marketplace = new Marketplace(); - - constructor(private readonly store: Store) {} - - async saveAll() { - await Promise.all([ - this.store.save(Object.values(this.collectionTypes)), - this.store.save(Object.values(this.collections)), - this.store.save(Object.values(this.nfts)), - this.store.save(this.transfers), - this.store.save(Object.values(this.sale)), - ]); - } - - async getCollection(collectionAddress: string) { - if (this.collections[collectionAddress] !== undefined) { - return this.collections[collectionAddress]; - } - return this.store.findOne(Collection, { where: { id: collectionAddress } }); - } - - async getNft(collectionAddress: string, tokenId: number) { - const key = this.getNftKey(collectionAddress, tokenId); - if (this.nfts[key] !== undefined) { - return this.nfts[key]; - } - return this.store.findOne(Nft, { - where: { - collection: { - id: 'collectionAddress', - }, - idInCollection: tokenId, - }, - }); - } - - setCollection(collection: Collection) { - this.collections[collection.id] = collection; - } - - getSale(nft: Nft) { - const key = this.getNftKey(nft.collection.id, nft.idInCollection); - if (this.sale[key] !== undefined) { - return this.sale[key]; - } - return this.store.findOne(Sale, { - where: { - nft: { - collection: { - id: nft.collection.id, - }, - idInCollection: nft.idInCollection, - }, - isSold: false, - }, - }); - } - - setSale(sale: Sale) { - this.sale[this.getNftKey(sale.nft.collection.id, sale.nft.idInCollection)] = - sale; - } - - async deleteSale(sale: Sale) { - delete this.sale[ - this.getNftKey(sale.nft.collection.id, sale.nft.idInCollection) - ]; - await this.store.remove(sale); - } - - async deleteCollection(collection: Collection) { - delete this.collections[collection.id]; - await this.store.remove(collection); - } - - async getCollectionType( - typeName: string, - ): Promise { - if (this.collectionTypes[typeName] !== undefined) { - return this.collectionTypes[typeName]; - } - return this.store.findOne(CollectionType, { where: { type: typeName } }); - } - - setCollectionType(collectionType: CollectionType) { - this.collectionTypes[collectionType.type] = collectionType; - } - - setNft(nft: Nft) { - this.nfts[this.getNftKey(nft.collection.id, nft.idInCollection)] = nft; - } - - setTransfer(transfer: Transfer) { - this.transfers.push(transfer); - } - - private getNftKey(collectionAddress: string, idInCollection: number) { - return `${collectionAddress}-${idInCollection}`; - } -} diff --git a/indexer/src/processing/event-info.type.ts b/indexer/src/processing/event-info.type.ts new file mode 100644 index 0000000..63711f8 --- /dev/null +++ b/indexer/src/processing/event-info.type.ts @@ -0,0 +1,7 @@ +export type EventInfo = { + blockNumber: number; + source: string; + destination: string; + txHash: string; + timestamp: Date; +}; diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index d54a317..27b519c 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -2,15 +2,18 @@ import { readFileSync } from 'fs'; import { ProgramMetadata } from '@gear-js/api'; import { getMarketplaceEvent, + NftMarketplaceEvent, NftMarketplaceEventPlain, NftMarketplaceEventType, } from '../types/marketplace.events'; -import { getNftEvent, NftEventPlain, NftEventType } from '../types/nft.events'; -import { EntitiesStorage } from './entities.storage'; +import { + getNftEvent, + NftEvent, + NftEventPlain, + NftEventType, +} from '../types/nft.events'; import { INftMarketplaceEventHandler } from './marketplace/nft-marketplace.handler'; import { NewCollectionAddedHandler } from './marketplace/new-collection-added.handler'; -import { Store } from '@subsquid/typeorm-store'; -import { Block } from '@subsquid/substrate-processor'; import { AuctionCreatedHandler } from './marketplace/auction-created.handler'; import { AuctionCanceledHandler } from './marketplace/auction-canceled.handler'; import { CollectionDeletedHandler } from './marketplace/collection-deleted.handler'; @@ -18,6 +21,26 @@ import { NftSoldHandler } from './marketplace/nft-sold.handler'; import { InitializedHandler } from './nft/initialized.handler'; import { INftEventHandler } from './nft/nft.handler'; import { NftMintedHandler } from './nft/nft-minted.handler'; +import { CollectionCreatedHandler } from './marketplace/collection-created.handler'; +import { AdminDeletedHandler } from './marketplace/admins-deleted.handler'; +import { AdminAddedHandler } from './marketplace/admin-added.handler'; +import { AuctionClosedHandler } from './marketplace/auction-closed.handler'; +import { SaleNftHandler } from './marketplace/sale-nft.handler'; +import { SaleNftCanceledHandler } from './marketplace/sale-nft-canceled.handler'; +import { BidAddedHandler } from './marketplace/bid-added.handler'; +import { ConfigUpdatedHandler } from './marketplace/config-updated.handler'; +import { OfferCreatedHandler } from './marketplace/offer-created.handler'; +import { OfferCanceledHandler } from './marketplace/offer-canceled.handler'; +import { OfferAcceptedHandler } from './marketplace/offer-accepted.handler'; +import { NftApprovedHandler } from './nft/nft-approved.handler'; +import { NftApprovalRevokedHandler } from './nft/nft-approval-revoked.handler'; +import { ConfigChangedHandler } from './nft/config-changed.handler'; +import { ImageChangedHandler } from './nft/image-changed.handler'; +import { TransferredHandler } from './nft/transferred.handler'; +import { MetadataAddedHandler } from './nft/metadata-added.handler'; +import { EventInfo } from './event-info.type'; +import { MarketplaceEvent } from '../model'; +import { EntitiesService } from './entities.service'; const marketplaceMeta = ProgramMetadata.from( readFileSync('./assets/nft_marketplace.meta.txt', 'utf8'), @@ -31,105 +54,144 @@ const marketplaceEventsToHandler: Record< INftMarketplaceEventHandler | undefined > = { [NftMarketplaceEventType.NewCollectionAdded]: new NewCollectionAddedHandler(), - [NftMarketplaceEventType.CollectionCreated]: new NewCollectionAddedHandler(), - [NftMarketplaceEventType.AuctionCreated]: new AuctionCreatedHandler(), - [NftMarketplaceEventType.AuctionCanceled]: new AuctionCanceledHandler(), + [NftMarketplaceEventType.CollectionCreated]: new CollectionCreatedHandler(), [NftMarketplaceEventType.CollectionDeleted]: new CollectionDeletedHandler(), + + [NftMarketplaceEventType.SaleNft]: new SaleNftHandler(), + [NftMarketplaceEventType.SaleNftCanceled]: new SaleNftCanceledHandler(), [NftMarketplaceEventType.NftSold]: new NftSoldHandler(), - // TODO: handle marketplace and admin events - [NftMarketplaceEventType.AdminDeleted]: undefined, - [NftMarketplaceEventType.AdminsAdded]: undefined, - [NftMarketplaceEventType.ConfigUpdated]: undefined, - [NftMarketplaceEventType.OfferCreated]: undefined, - [NftMarketplaceEventType.OfferCanceled]: undefined, - [NftMarketplaceEventType.OfferAccepted]: undefined, - [NftMarketplaceEventType.BidAdded]: undefined, - [NftMarketplaceEventType.SaleNft]: undefined, - [NftMarketplaceEventType.SaleNftCanceled]: undefined, + + [NftMarketplaceEventType.AdminDeleted]: new AdminDeletedHandler(), + [NftMarketplaceEventType.AdminsAdded]: new AdminAddedHandler(), + + [NftMarketplaceEventType.AuctionCreated]: new AuctionCreatedHandler(), + [NftMarketplaceEventType.BidAdded]: new BidAddedHandler(), + [NftMarketplaceEventType.AuctionClosed]: new AuctionClosedHandler(), + [NftMarketplaceEventType.AuctionCanceled]: new AuctionCanceledHandler(), + + [NftMarketplaceEventType.OfferCreated]: new OfferCreatedHandler(), + [NftMarketplaceEventType.OfferCanceled]: new OfferCanceledHandler(), + [NftMarketplaceEventType.OfferAccepted]: new OfferAcceptedHandler(), + + [NftMarketplaceEventType.ConfigUpdated]: new ConfigUpdatedHandler(), }; const nftEventsToHandler: Record = { [NftEventType.Initialized]: new InitializedHandler(), [NftEventType.Minted]: new NftMintedHandler(), - [NftEventType.Approved]: undefined, - [NftEventType.ApprovalRevoked]: undefined, + [NftEventType.Approved]: new NftApprovedHandler(), + [NftEventType.ApprovalRevoked]: new NftApprovalRevokedHandler(), [NftEventType.Expanded]: undefined, - [NftEventType.ConfigChanged]: undefined, - [NftEventType.ImageChanged]: undefined, - [NftEventType.MetadataAdded]: undefined, + [NftEventType.ConfigChanged]: new ConfigChangedHandler(), + [NftEventType.ImageChanged]: new ImageChangedHandler(), + [NftEventType.MetadataAdded]: new MetadataAddedHandler(), [NftEventType.TokenInfoReceived]: undefined, - [NftEventType.Transferred]: undefined, + [NftEventType.Transferred]: new TransferredHandler(), }; export class EventsProcessing { - private readonly entitiesStorage: EntitiesStorage; - - constructor(private readonly store: Store) { - this.entitiesStorage = new EntitiesStorage(store); - } + constructor(private readonly entitiesService: EntitiesService) {} saveAll() { - return this.entitiesStorage.saveAll(); + return this.entitiesService.saveAll(); } - async handleMarketplaceEvent(block: Block, payload: string, source: string) { + async handleMarketplaceEvent( + payload: string, + eventInfo: EventInfo, + ): Promise { + const { blockNumber, txHash } = eventInfo; try { - console.log(`${block.header.hash}: handling marketplace event`); + console.log(`${blockNumber}-${txHash}: handling marketplace event`); const data = marketplaceMeta.createType( marketplaceMeta.types.handle.output!, payload, ); const parsed = data.toJSON() as { ok: NftMarketplaceEventPlain } | null; if (!parsed || !parsed.ok) { - return; + return null; } const event = getMarketplaceEvent(parsed.ok); if (!event) { - console.warn(`${block.header.hash}: unknown event type`, parsed); - return; + console.warn(`${blockNumber}-${txHash}: unknown event type`, parsed); + return null; } + console.log(`${blockNumber}-${txHash}: detected event: ${event.type}`); + this.entitiesService + .addEvent({ + blockNumber: eventInfo.blockNumber, + timestamp: eventInfo.timestamp, + type: event.type, + raw: JSON.stringify(event), + txHash: eventInfo.txHash, + }) + .catch((err) => + console.error(`${blockNumber}-${txHash}: error adding event`, err), + ); const eventHandler = marketplaceEventsToHandler[event.type]; if (!eventHandler) { console.warn( - `${block.header.hash}: no event handlers found for ${event.type}`, + `${blockNumber}-${txHash}: no event handlers found for ${event.type}`, ); - return; + return null; } - await eventHandler.handle(block, event, this.entitiesStorage); + await eventHandler.handle(event, eventInfo, this.entitiesService); + return event; } catch (e) { console.error( - `${block.header.hash}: error handling marketplace event`, + `${blockNumber}-${txHash}: error handling marketplace event`, e, ); + return null; } } - async handleNftEvent(block: Block, payload: string, source: string) { + async handleNftEvent( + payload: string, + eventInfo: EventInfo, + ): Promise { + const { blockNumber, txHash } = eventInfo; try { - console.log(`${block.header.hash}: handling nft event`); - const data = marketplaceMeta.createType( + console.log(`${blockNumber}-${txHash}: handling nft event`); + const data = nftMeta.createType( + // @ts-ignore nftMeta.types.handle.output!, payload, ); const parsed = data.toJSON() as { ok: NftEventPlain } | null; if (!parsed || !parsed.ok) { - return; + console.warn( + `${blockNumber}-${txHash}: failed to parse event`, + parsed, + payload, + ); + return null; } - const event = getNftEvent(data); + const event = getNftEvent(parsed.ok); if (!event) { - console.warn(`${block.header.hash}: unknown event type`, parsed); - return; + console.warn( + `${blockNumber}-${txHash}: unknown nft event type`, + parsed, + ); + return null; } + console.log(`${blockNumber}-${txHash}: detected event: ${event.type}`); const eventHandler = nftEventsToHandler[event.type]; if (!eventHandler) { console.warn( - `${block.header.hash}: no nft event handlers found for ${event.type}`, + `${blockNumber}-${txHash}: no nft event handlers found for ${event.type}`, ); - return; + return null; } - await eventHandler.handle(block, source, event, this.entitiesStorage); + await eventHandler.handle(event, eventInfo, this.entitiesService); + return event; } catch (e) { - console.error(`${block.header.hash}: error handling nft event`, e); + console.error( + `${blockNumber}-${txHash}: error handling nft event`, + e, + payload, + ); + return null; } } } diff --git a/indexer/src/processing/marketplace/admin-added.handler.ts b/indexer/src/processing/marketplace/admin-added.handler.ts new file mode 100644 index 0000000..0670162 --- /dev/null +++ b/indexer/src/processing/marketplace/admin-added.handler.ts @@ -0,0 +1,22 @@ +import { AdminsAdded } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Marketplace } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class AdminAddedHandler implements INftMarketplaceEventHandler { + async handle( + event: AdminsAdded, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { users } = event; + const marketplace = await storage.getMarketplace(); + await storage.setMarketplace( + new Marketplace({ + ...marketplace, + admins: [...marketplace.admins, ...users], + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/admins-deleted.handler.ts b/indexer/src/processing/marketplace/admins-deleted.handler.ts new file mode 100644 index 0000000..03339ca --- /dev/null +++ b/indexer/src/processing/marketplace/admins-deleted.handler.ts @@ -0,0 +1,22 @@ +import { AdminDeleted } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Marketplace } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class AdminDeletedHandler implements INftMarketplaceEventHandler { + async handle( + event: AdminDeleted, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { user } = event; + const marketplace = await storage.getMarketplace(); + await storage.setMarketplace( + new Marketplace({ + ...marketplace, + admins: marketplace.admins.filter((admin) => admin !== user), + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/auction-canceled.handler.ts b/indexer/src/processing/marketplace/auction-canceled.handler.ts index 0fb7742..d1082b6 100644 --- a/indexer/src/processing/marketplace/auction-canceled.handler.ts +++ b/indexer/src/processing/marketplace/auction-canceled.handler.ts @@ -1,13 +1,14 @@ import { AuctionCanceled } from '../../types/marketplace.events'; -import { EntitiesStorage } from '../entities.storage'; +import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { Block } from '@subsquid/substrate-processor'; +import { AuctionStatus } from '../../model/types'; +import { EventInfo } from '../event-info.type'; export class AuctionCanceledHandler implements INftMarketplaceEventHandler { async handle( - block: Block, event: AuctionCanceled, - storage: EntitiesStorage, + eventInfo: EventInfo, + storage: EntitiesService, ): Promise { const { collectionAddress, tokenId } = event; const nft = await storage.getNft(collectionAddress, tokenId); @@ -17,13 +18,17 @@ export class AuctionCanceledHandler implements INftMarketplaceEventHandler { ); return; } - const sale = await storage.getSale(nft); - if (sale === undefined) { + const auction = await storage.getAuction(nft); + if (auction === undefined) { console.warn( - `[AuctionCanceledHandler] ${collectionAddress}-${tokenId}: sale is not found`, + `[AuctionCanceledHandler] ${collectionAddress}-${tokenId}: auction is not found`, ); return; } - await storage.deleteSale(sale); + await storage.setAuction({ + ...auction, + status: AuctionStatus.Canceled, + updatedAt: eventInfo.timestamp, + }); } } diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts new file mode 100644 index 0000000..a63213c --- /dev/null +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -0,0 +1,36 @@ +import { AuctionClosed } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { AuctionStatus } from '../../model/types'; +import { EventInfo } from '../event-info.type'; + +export class AuctionClosedHandler implements INftMarketplaceEventHandler { + async handle( + event: AuctionClosed, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { collectionAddress, tokenId, currentOwner, price } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[AuctionClosedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const auction = await storage.getAuction(nft); + if (auction?.status !== AuctionStatus.Open) { + console.warn( + `[AuctionClosedHandler] ${collectionAddress}-${tokenId}: auction is not found or not open`, + ); + return; + } + await storage.setAuction({ + ...auction, + status: AuctionStatus.Closed, + newOwner: currentOwner, + lastPrice: price, + updatedAt: eventInfo.timestamp, + }); + } +} diff --git a/indexer/src/processing/marketplace/auction-created.handler.ts b/indexer/src/processing/marketplace/auction-created.handler.ts index 7d37e04..01f36e8 100644 --- a/indexer/src/processing/marketplace/auction-created.handler.ts +++ b/indexer/src/processing/marketplace/auction-created.handler.ts @@ -1,16 +1,18 @@ import { AuctionCreated } from '../../types/marketplace.events'; -import { EntitiesStorage } from '../entities.storage'; +import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { Sale } from '../../model'; -import { Block } from '@subsquid/substrate-processor'; +import { Auction } from '../../model'; +import { AuctionStatus, SaleStatus } from '../../model/types'; +import { EventInfo } from '../event-info.type'; +import { v4 as uuidv4 } from 'uuid'; export class AuctionCreatedHandler implements INftMarketplaceEventHandler { async handle( - block: Block, event: AuctionCreated, - storage: EntitiesStorage, + eventInfo: EventInfo, + storage: EntitiesService, ): Promise { - const { collectionAddress, tokenId, price, currentOwner } = event; + const { collectionAddress, tokenId, minPrice, durationMs } = event; const collection = await storage.getCollection(collectionAddress); if (collection === undefined) { console.warn( @@ -25,20 +27,23 @@ export class AuctionCreatedHandler implements INftMarketplaceEventHandler { ); return; } - const sale = await storage.getSale(nft); - if (sale !== undefined) { + const auction = await storage.getAuction(nft); + if (auction?.status === AuctionStatus.Open) { console.warn( - `[AuctionCreatedHandler] ${collectionAddress}-${tokenId}: sale is already exists`, + `[AuctionCreatedHandler] ${collectionAddress}-${tokenId}: auction is already exists`, ); return; } - storage.setSale( - new Sale({ + await storage.setAuction( + new Auction({ + id: uuidv4(), nft, - price, - owner: currentOwner, - isSold: false, - blockNumber: block.header.hash, + owner: nft.owner, + minPrice, + durationMs, + status: SaleStatus.Open, + blockNumber: eventInfo.blockNumber, + timestamp: eventInfo.timestamp, }), ); } diff --git a/indexer/src/processing/marketplace/bid-added.handler.ts b/indexer/src/processing/marketplace/bid-added.handler.ts new file mode 100644 index 0000000..d951a63 --- /dev/null +++ b/indexer/src/processing/marketplace/bid-added.handler.ts @@ -0,0 +1,47 @@ +import { BidAdded } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Bid } from '../../model'; +import { EventInfo } from '../event-info.type'; +import { v4 as uuidv4 } from 'uuid'; + +export class BidAddedHandler implements INftMarketplaceEventHandler { + async handle( + event: BidAdded, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { collectionAddress, tokenId, price } = event; + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[BidAddedHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[BidAddedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const auction = await storage.getAuction(nft); + if (auction === undefined) { + console.warn( + `[BidAddedHandler] ${collectionAddress}-${tokenId}: auction is not exists `, + ); + return; + } + storage.addBid( + new Bid({ + id: uuidv4(), + auction, + price, + bidder: eventInfo.destination, + timestamp: eventInfo.timestamp, + blockNumber: eventInfo.blockNumber, + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/collection-created.handler.ts b/indexer/src/processing/marketplace/collection-created.handler.ts index e235382..b5c5392 100644 --- a/indexer/src/processing/marketplace/collection-created.handler.ts +++ b/indexer/src/processing/marketplace/collection-created.handler.ts @@ -1,14 +1,14 @@ import { CollectionCreated } from '../../types/marketplace.events'; -import { EntitiesStorage } from '../entities.storage'; +import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { Collection } from '../../model'; -import { Block } from '@subsquid/substrate-processor'; +import { EventInfo } from '../event-info.type'; export class CollectionCreatedHandler implements INftMarketplaceEventHandler { async handle( - block: Block, event: CollectionCreated, - storage: EntitiesStorage, + eventInfo: EventInfo, + storage: EntitiesService, ): Promise { const { typeName, collectionAddress } = event; const existingCollection = await storage.getCollection(collectionAddress); @@ -25,10 +25,11 @@ export class CollectionCreatedHandler implements INftMarketplaceEventHandler { ); return; } - storage.setCollection( + await storage.setCollection( new Collection({ id: collectionAddress, type: collectionType, + createdAt: eventInfo.timestamp, }), ); } diff --git a/indexer/src/processing/marketplace/collection-deleted.handler.ts b/indexer/src/processing/marketplace/collection-deleted.handler.ts index 4a0bbce..98a9ac9 100644 --- a/indexer/src/processing/marketplace/collection-deleted.handler.ts +++ b/indexer/src/processing/marketplace/collection-deleted.handler.ts @@ -1,13 +1,13 @@ import { CollectionDeleted } from '../../types/marketplace.events'; -import { EntitiesStorage } from '../entities.storage'; +import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { Block } from '@subsquid/substrate-processor'; +import { EventInfo } from '../event-info.type'; export class CollectionDeletedHandler implements INftMarketplaceEventHandler { async handle( - block: Block, event: CollectionDeleted, - storage: EntitiesStorage, + eventInfo: EventInfo, + storage: EntitiesService, ): Promise { const { collectionAddress } = event; const existingCollection = await storage.getCollection(collectionAddress); diff --git a/indexer/src/processing/marketplace/config-updated.handler.ts b/indexer/src/processing/marketplace/config-updated.handler.ts new file mode 100644 index 0000000..5c71003 --- /dev/null +++ b/indexer/src/processing/marketplace/config-updated.handler.ts @@ -0,0 +1,36 @@ +import { ConfigUpdated } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { MarketplaceConfig } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class ConfigUpdatedHandler implements INftMarketplaceEventHandler { + async handle( + event: ConfigUpdated, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + let { + gasForCloseAuction, + gasForCreation, + gasForDeleteCollection, + gasForGetTokenInfo, + gasForTransferToken, + minimumTransferValue, + msInBlock, + timeBetweenCreateCollections, + } = event; + await storage.setMarketplaceConfig( + new MarketplaceConfig({ + gasForCloseAuction, + gasForCreation, + gasForDeleteCollection, + gasForGetTokenInfo, + gasForTransferToken, + minimumTransferValue, + msInBlock, + timeBetweenCreateCollections, + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/new-collection-added.handler.ts b/indexer/src/processing/marketplace/new-collection-added.handler.ts index a6eb8ca..ef29f16 100644 --- a/indexer/src/processing/marketplace/new-collection-added.handler.ts +++ b/indexer/src/processing/marketplace/new-collection-added.handler.ts @@ -1,14 +1,14 @@ import { NewCollectionAdded } from '../../types/marketplace.events'; -import { EntitiesStorage } from '../entities.storage'; +import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { CollectionType } from '../../model'; -import { Block } from '@subsquid/substrate-processor'; +import { EventInfo } from '../event-info.type'; export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { async handle( - block: Block, event: NewCollectionAdded, - storage: EntitiesStorage, + eventInfo: EventInfo, + storage: EntitiesService, ): Promise { const { codeId, metaLink, typeName, typeDescription } = event; const existingCollectionType = await storage.getCollectionType(typeName); @@ -18,7 +18,7 @@ export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { ); return; } - storage.setCollectionType( + await storage.setCollectionType( new CollectionType({ id: codeId, description: typeDescription, diff --git a/indexer/src/processing/marketplace/nft-marketplace.handler.ts b/indexer/src/processing/marketplace/nft-marketplace.handler.ts index 761954e..d65e50b 100644 --- a/indexer/src/processing/marketplace/nft-marketplace.handler.ts +++ b/indexer/src/processing/marketplace/nft-marketplace.handler.ts @@ -1,11 +1,11 @@ import { NftMarketplaceEvent } from '../../types/marketplace.events'; -import { EntitiesStorage } from '../entities.storage'; -import { Block } from '@subsquid/substrate-processor'; +import { EntitiesService } from '../entities.service'; +import { EventInfo } from '../event-info.type'; export interface INftMarketplaceEventHandler { handle( - block: Block, event: NftMarketplaceEvent, - storage: EntitiesStorage, + eventInfo: EventInfo, + storage: EntitiesService, ): Promise; } diff --git a/indexer/src/processing/marketplace/nft-sold.handler.ts b/indexer/src/processing/marketplace/nft-sold.handler.ts index 2e980c9..70a4db0 100644 --- a/indexer/src/processing/marketplace/nft-sold.handler.ts +++ b/indexer/src/processing/marketplace/nft-sold.handler.ts @@ -1,14 +1,15 @@ import { NftSold } from '../../types/marketplace.events'; -import { EntitiesStorage } from '../entities.storage'; +import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { Sale, Transfer } from '../../model'; -import { Block } from '@subsquid/substrate-processor'; +import { Sale } from '../../model'; +import { SaleStatus } from '../../model/types'; +import { EventInfo } from '../event-info.type'; export class NftSoldHandler implements INftMarketplaceEventHandler { async handle( - block: Block, event: NftSold, - storage: EntitiesStorage, + eventInfo: EventInfo, + storage: EntitiesService, ): Promise { const { collectionAddress, tokenId, price, currentOwner } = event; const collection = await storage.getCollection(collectionAddress); @@ -21,37 +22,27 @@ export class NftSoldHandler implements INftMarketplaceEventHandler { const nft = await storage.getNft(collectionAddress, tokenId); if (nft === undefined) { console.warn( - `[AuctionCreatedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + `[NftSoldHandler] ${collectionAddress}-${tokenId}: nft is not found`, ); return; } const sale = await storage.getSale(nft); - if (sale !== undefined) { + if (sale === undefined) { console.warn( - `[AuctionCreatedHandler] ${collectionAddress}-${tokenId}: sale is already exists`, + `[NftSoldHandler] ${collectionAddress}-${tokenId}: sale not found`, ); return; } - storage.setSale( + await storage.setSale( new Sale({ + ...sale, nft, price, - owner: currentOwner, - isSold: true, - blockNumber: block.header.hash, + newOwner: currentOwner, + status: SaleStatus.Sold, + blockNumber: eventInfo.blockNumber, + updatedAt: eventInfo.timestamp, }), ); - storage.setTransfer( - new Transfer({ - nft, - from: nft.owner, - to: currentOwner, - blockNumber: block.header.hash, - }), - ); - storage.setNft({ - ...nft, - owner: currentOwner, - }); } } diff --git a/indexer/src/processing/marketplace/offer-accepted.handler.ts b/indexer/src/processing/marketplace/offer-accepted.handler.ts new file mode 100644 index 0000000..056b30c --- /dev/null +++ b/indexer/src/processing/marketplace/offer-accepted.handler.ts @@ -0,0 +1,40 @@ +import { OfferAccepted } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { OfferStatus } from '../../model/types'; +import { Offer } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class OfferAcceptedHandler implements INftMarketplaceEventHandler { + async handle( + event: OfferAccepted, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { + offer: { collectionAddress, tokenId, creator }, + } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[OfferAcceptedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const offer = await storage.getOffer(nft, creator); + if (offer?.status !== OfferStatus.Open) { + console.warn( + `[OfferAcceptedHandler] ${collectionAddress}-${tokenId}: offer is not found or not active`, + ); + return; + } + await storage.setOffer( + new Offer({ + ...offer, + status: OfferStatus.Accepted, + updatedAt: eventInfo.timestamp, + blockNumber: eventInfo.blockNumber, + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/offer-canceled.handler.ts b/indexer/src/processing/marketplace/offer-canceled.handler.ts new file mode 100644 index 0000000..cae612e --- /dev/null +++ b/indexer/src/processing/marketplace/offer-canceled.handler.ts @@ -0,0 +1,34 @@ +import { OfferCanceled } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { OfferStatus } from '../../model/types'; +import { EventInfo } from '../event-info.type'; + +export class OfferCanceledHandler implements INftMarketplaceEventHandler { + async handle( + event: OfferCanceled, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { collectionAddress, tokenId } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[OfferCanceledHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const offer = await storage.getOffer(nft, eventInfo.destination); + if (offer?.status !== OfferStatus.Open) { + console.warn( + `[OfferCanceledHandler] ${collectionAddress}-${tokenId}: offer is not found or not active`, + ); + return; + } + await storage.setOffer({ + ...offer, + status: OfferStatus.Canceled, + updatedAt: eventInfo.timestamp, + }); + } +} diff --git a/indexer/src/processing/marketplace/offer-created.handler.ts b/indexer/src/processing/marketplace/offer-created.handler.ts new file mode 100644 index 0000000..1139d64 --- /dev/null +++ b/indexer/src/processing/marketplace/offer-created.handler.ts @@ -0,0 +1,44 @@ +import { v4 as uuidv4 } from 'uuid'; +import { OfferCreated } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { OfferStatus } from '../../model/types'; +import { Offer } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class OfferCreatedHandler implements INftMarketplaceEventHandler { + async handle( + event: OfferCreated, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { collectionAddress, tokenId, price } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[OfferCreatedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const offer = await storage.getOffer(nft, eventInfo.destination); + if (offer?.status !== OfferStatus.Open) { + console.warn( + `[OfferCreatedHandler] ${collectionAddress}-${tokenId}: offer is not found or not active`, + ); + return; + } + await storage.setOffer( + new Offer({ + id: uuidv4(), + price, + nft, + owner: nft.owner, + status: OfferStatus.Open, + creator: eventInfo.destination, + timestamp: eventInfo.timestamp, + updatedAt: eventInfo.timestamp, + blockNumber: eventInfo.blockNumber, + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts b/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts new file mode 100644 index 0000000..63b56b5 --- /dev/null +++ b/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts @@ -0,0 +1,37 @@ +import { AuctionCanceled } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { AuctionStatus, SaleStatus } from '../../model/types'; +import { Sale } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class SaleNftCanceledHandler implements INftMarketplaceEventHandler { + async handle( + event: AuctionCanceled, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { collectionAddress, tokenId } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[SaleCanceledHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const sale = await storage.getSale(nft); + if (sale?.status !== AuctionStatus.Open) { + console.warn( + `[SaleCanceledHandler] ${collectionAddress}-${tokenId}: auction is not found or not open`, + ); + return; + } + await storage.setSale( + new Sale({ + ...sale, + status: SaleStatus.Canceled, + updatedAt: eventInfo.timestamp, + }), + ); + } +} diff --git a/indexer/src/processing/marketplace/sale-nft.handler.ts b/indexer/src/processing/marketplace/sale-nft.handler.ts new file mode 100644 index 0000000..74de971 --- /dev/null +++ b/indexer/src/processing/marketplace/sale-nft.handler.ts @@ -0,0 +1,50 @@ +import { SaleNft } from '../../types/marketplace.events'; +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { Sale } from '../../model'; +import { SaleStatus } from '../../model/types'; +import { EventInfo } from '../event-info.type'; +import { v4 as uuidv4 } from 'uuid'; + +export class SaleNftHandler implements INftMarketplaceEventHandler { + async handle( + event: SaleNft, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const { collectionAddress, tokenId, price } = event; + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[SaleNftHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[SaleNftHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + const sale = await storage.getSale(nft); + if (sale?.status === SaleStatus.Open) { + console.warn( + `[SaleNftHandler] ${collectionAddress}-${tokenId}: open sale already exists`, + ); + return; + } + await storage.setSale( + new Sale({ + id: uuidv4(), + nft, + price, + owner: nft.owner, + status: SaleStatus.Open, + blockNumber: eventInfo.blockNumber, + timestamp: eventInfo.timestamp, + updatedAt: eventInfo.timestamp, + }), + ); + } +} diff --git a/indexer/src/processing/nft/config-changed.handler.ts b/indexer/src/processing/nft/config-changed.handler.ts new file mode 100644 index 0000000..085e8c9 --- /dev/null +++ b/indexer/src/processing/nft/config-changed.handler.ts @@ -0,0 +1,57 @@ +import { ConfigChangedEvent } from '../../types/nft.events'; +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Collection } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class ConfigChangedHandler implements INftEventHandler { + async handle( + event: ConfigChangedEvent, + { source: collectionAddress, destination }: EventInfo, + storage: EntitiesService, + ): Promise { + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[ConfigChangedHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + console.log(`[ConfigChangedHandler] ${event}`); + let { + name, + description, + additionalLinks, + approvable, + attendable, + burnable, + collectionBanner, + collectionLogo, + collectionTags, + paymentForMint, + royalty, + sellable, + transferable, + userMintLimit, + } = event.config; + await storage.setCollection( + new Collection({ + ...collection, + name, + admin: destination, + description, + approvable, + attendable, + burnable, + collectionBanner: collectionBanner, + collectionLogo, + tags: collectionTags, + paymentForMint, + royalty, + sellable, + transferable, + userMintLimit: userMintLimit, + }), + ); + } +} diff --git a/indexer/src/processing/nft/image-changed.handler.ts b/indexer/src/processing/nft/image-changed.handler.ts new file mode 100644 index 0000000..eb32316 --- /dev/null +++ b/indexer/src/processing/nft/image-changed.handler.ts @@ -0,0 +1,29 @@ +import { ImageChangedEvent } from '../../types/nft.events'; +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Nft } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class ImageChangedHandler implements INftEventHandler { + async handle( + event: ImageChangedEvent, + { source: collectionAddress, timestamp }: EventInfo, + storage: EntitiesService, + ): Promise { + const { tokenId, imgLink } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[ImageChangedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + await storage.setNft( + new Nft({ + ...nft, + mediaUrl: imgLink, + updatedAt: timestamp, + }), + ); + } +} diff --git a/indexer/src/processing/nft/initialized.handler.ts b/indexer/src/processing/nft/initialized.handler.ts index 9377305..4ad8fb7 100644 --- a/indexer/src/processing/nft/initialized.handler.ts +++ b/indexer/src/processing/nft/initialized.handler.ts @@ -1,15 +1,14 @@ -import { Block } from '@subsquid/substrate-processor'; import { InitializedEvent } from '../../types/nft.events'; -import { EntitiesStorage } from '../entities.storage'; +import { EntitiesService } from '../entities.service'; import { INftEventHandler } from './nft.handler'; import { Collection } from '../../model'; +import { EventInfo } from '../event-info.type'; export class InitializedHandler implements INftEventHandler { async handle( - block: Block, - collectionAddress: string, event: InitializedEvent, - storage: EntitiesStorage, + { source: collectionAddress, destination, timestamp }: EventInfo, + storage: EntitiesService, ): Promise { const collection = await storage.getCollection(collectionAddress); if (collection === undefined) { @@ -25,7 +24,7 @@ export class InitializedHandler implements INftEventHandler { approvable, attendable, burnable, - collectionImg, + collectionBanner, collectionLogo, collectionTags, paymentForMint, @@ -34,22 +33,25 @@ export class InitializedHandler implements INftEventHandler { transferable, userMintLimit, } = event.config; - storage.setCollection({ - ...collection, - name, - description, - additionalLinks, - approvable, - attendable, - burnable, - collectionImage: collectionImg, - collectionLogo, - tags: collectionTags, - paymentForMint, - royalty, - sellable, - transferable, - tokensLimit: userMintLimit, - } as Collection); + await storage.setCollection( + new Collection({ + ...collection, + name, + admin: destination, + description, + approvable, + attendable, + burnable, + collectionBanner: collectionBanner, + collectionLogo, + tags: collectionTags, + paymentForMint, + royalty, + sellable, + transferable, + userMintLimit: userMintLimit, + createdAt: timestamp, + }), + ); } } diff --git a/indexer/src/processing/nft/metadata-added.handler.ts b/indexer/src/processing/nft/metadata-added.handler.ts new file mode 100644 index 0000000..adc997c --- /dev/null +++ b/indexer/src/processing/nft/metadata-added.handler.ts @@ -0,0 +1,29 @@ +import { MetadataAddedEvent } from '../../types/nft.events'; +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Nft } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class MetadataAddedHandler implements INftEventHandler { + async handle( + event: MetadataAddedEvent, + { source: collectionAddress, timestamp }: EventInfo, + storage: EntitiesService, + ): Promise { + const { tokenId, metadata } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[MetadataAddedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + await storage.setNft( + new Nft({ + ...nft, + metadata, + updatedAt: timestamp, + }), + ); + } +} diff --git a/indexer/src/processing/nft/nft-approval-revoked.handler.ts b/indexer/src/processing/nft/nft-approval-revoked.handler.ts new file mode 100644 index 0000000..f38e296 --- /dev/null +++ b/indexer/src/processing/nft/nft-approval-revoked.handler.ts @@ -0,0 +1,29 @@ +import { ApprovalRevokedEvent } from '../../types/nft.events'; +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Nft } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class NftApprovalRevokedHandler implements INftEventHandler { + async handle( + event: ApprovalRevokedEvent, + { source: collectionAddress, timestamp }: EventInfo, + storage: EntitiesService, + ): Promise { + const { tokenId } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[NftApprovalRevokedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + await storage.setNft( + new Nft({ + ...nft, + approvedAccount: null, + updatedAt: timestamp, + }), + ); + } +} diff --git a/indexer/src/processing/nft/nft-approved.handler.ts b/indexer/src/processing/nft/nft-approved.handler.ts new file mode 100644 index 0000000..ad16e38 --- /dev/null +++ b/indexer/src/processing/nft/nft-approved.handler.ts @@ -0,0 +1,29 @@ +import { ApprovedEvent } from '../../types/nft.events'; +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Nft } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class NftApprovedHandler implements INftEventHandler { + async handle( + event: ApprovedEvent, + { source: collectionAddress, timestamp }: EventInfo, + storage: EntitiesService, + ): Promise { + const { tokenId, to } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[NftApprovedHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + await storage.setNft( + new Nft({ + ...nft, + approvedAccount: to, + updatedAt: timestamp, + }), + ); + } +} diff --git a/indexer/src/processing/nft/nft-minted.handler.ts b/indexer/src/processing/nft/nft-minted.handler.ts index 7adfb48..78f2588 100644 --- a/indexer/src/processing/nft/nft-minted.handler.ts +++ b/indexer/src/processing/nft/nft-minted.handler.ts @@ -1,15 +1,14 @@ -import { Block } from '@subsquid/substrate-processor'; import { MintedEvent } from '../../types/nft.events'; -import { EntitiesStorage } from '../entities.storage'; +import { EntitiesService } from '../entities.service'; import { INftEventHandler } from './nft.handler'; import { Nft } from '../../model'; +import { EventInfo } from '../event-info.type'; export class NftMintedHandler implements INftEventHandler { async handle( - block: Block, - collectionAddress: string, event: MintedEvent, - storage: EntitiesStorage, + { source: collectionAddress, timestamp }: EventInfo, + storage: EntitiesService, ): Promise { const collection = await storage.getCollection(collectionAddress); if (collection === undefined) { @@ -20,15 +19,16 @@ export class NftMintedHandler implements INftEventHandler { } const { tokenId } = event; let { description, mediaUrl, metadata, name, owner } = event.nftData; - storage.setNft( + await storage.setNft( new Nft({ + id: `${collection.id}-${tokenId}`, collection, description, idInCollection: tokenId, mediaUrl, name, owner, - mintedAt: new Date(), + createdAt: timestamp, }), ); } diff --git a/indexer/src/processing/nft/nft.handler.ts b/indexer/src/processing/nft/nft.handler.ts index d8fbfa9..ca39a6a 100644 --- a/indexer/src/processing/nft/nft.handler.ts +++ b/indexer/src/processing/nft/nft.handler.ts @@ -1,12 +1,11 @@ -import { EntitiesStorage } from '../entities.storage'; -import { Block } from '@subsquid/substrate-processor'; +import { EntitiesService } from '../entities.service'; import { NftEvent } from '../../types/nft.events'; +import { EventInfo } from '../event-info.type'; export interface INftEventHandler { handle( - block: Block, - collectionAddress: string, event: NftEvent, - storage: EntitiesStorage, + eventInfo: EventInfo, + storage: EntitiesService, ): Promise; } diff --git a/indexer/src/processing/nft/transferred.handler.ts b/indexer/src/processing/nft/transferred.handler.ts new file mode 100644 index 0000000..74c01b2 --- /dev/null +++ b/indexer/src/processing/nft/transferred.handler.ts @@ -0,0 +1,32 @@ +import { TransferEvent } from '../../types/nft.events'; +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Transfer } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class TransferredHandler implements INftEventHandler { + async handle( + event: TransferEvent, + { source: collectionAddress, timestamp, blockNumber, txHash }: EventInfo, + storage: EntitiesService, + ): Promise { + const { owner, recipient, tokenId } = event; + const nft = await storage.getNft(collectionAddress, tokenId); + if (nft === undefined) { + console.warn( + `[TransferredHandler] ${collectionAddress}-${tokenId}: nft is not found`, + ); + return; + } + storage.addTransfer( + new Transfer({ + nft, + from: owner, + to: recipient, + blockNumber, + timestamp, + txHash, + }), + ); + } +} diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts new file mode 100644 index 0000000..e0e37ad --- /dev/null +++ b/indexer/src/processing/storage/local.storage.ts @@ -0,0 +1,216 @@ +import { + Auction, + Collection, + CollectionType, + Marketplace, + Nft, + Offer, + Sale, +} from '../../model'; +import { Store } from '@subsquid/typeorm-store'; +import { IStorage } from './storage.inteface'; + +let storage: LocalStorage | undefined; + +export async function getLocalStorage(store: Store): Promise { + if (storage === undefined) { + storage = new LocalStorage(store); + await storage.waitInit(); + } + storage.setStore(store); + return storage; +} + +export class LocalStorage implements IStorage { + async updateNft(nft: Nft): Promise { + this.nfts[this.getNftKey(nft.collection.id, nft.idInCollection)] = nft; + } + async updateCollectionType(collectionType: CollectionType): Promise { + this.collectionTypes[collectionType.type] = collectionType; + } + private initialized = false; + // typeName -> CollectionType + private collectionTypes: Record = {}; + // collectionAddress -> Collection + private collections: Record = {}; + // // collectionAddress-tokenId -> Nft + private nfts: Record = {}; + private sale: Record = {}; + private auctions: Record = {}; + private offers: Record = {}; + private marketplace: Marketplace | undefined; + + constructor(private store: Store) {} + + async waitInit() { + if (this.initialized) { + return; + } + await this.loadEntities(); + this.initialized = true; + } + + setStore(store: Store) { + this.store = store; + } + + async getMarketplace(): Promise { + return this.marketplace!; + } + + async updateMarketplace(marketplace: Marketplace): Promise { + this.marketplace = marketplace; + } + + async getCollection( + collectionAddress: string, + ): Promise { + if (this.collections[collectionAddress] !== undefined) { + return this.collections[collectionAddress]; + } + return this.store.findOne(Collection, { where: { id: collectionAddress } }); + } + + async updateCollection(collection: Collection): Promise { + this.collections[collection.id] = collection; + } + + async updateAuction(auction: Auction): Promise { + this.auctions[ + this.getNftKey(auction.nft.collection.id, auction.nft.idInCollection) + ] = auction; + } + + async getNft( + collectionAddress: string, + tokenId: number, + ): Promise { + const key = this.getNftKey(collectionAddress, tokenId); + if (this.nfts[key] !== undefined) { + return this.nfts[key]; + } + return this.store.findOne(Nft, { + where: { + collection: { + id: collectionAddress, + }, + idInCollection: tokenId, + }, + }); + } + + async getSale(nft: Nft): Promise { + const key = this.getNftKey(nft.collection.id, nft.idInCollection); + if (this.sale[key] !== undefined) { + return this.sale[key]; + } + return this.store.findOne(Sale, { + where: { + nft: { + collection: { + id: nft.collection.id, + }, + idInCollection: nft.idInCollection, + }, + }, + order: { timestamp: 'DESC' }, + }); + } + + async updateSale(sale: Sale): Promise { + this.sale[this.getNftKey(sale.nft.collection.id, sale.nft.idInCollection)] = + sale; + } + + async getAuction(nft: Nft): Promise { + const key = this.getNftKey(nft.collection.id, nft.idInCollection); + if (this.auctions[key] !== undefined) { + return this.auctions[key]; + } + return this.store.findOne(Auction, { + where: { + nft: { + collection: { + id: nft.collection.id, + }, + idInCollection: nft.idInCollection, + }, + }, + order: { timestamp: 'DESC' }, + }); + } + + async getOffer(nft: Nft, creator: string): Promise { + const key = this.getOfferKey( + nft.collection.id, + nft.idInCollection, + creator, + ); + if (this.offers[key] !== undefined) { + return this.offers[key]; + } + return this.store.findOne(Offer, { + where: { + nft: { + collection: { + id: nft.collection.id, + }, + idInCollection: nft.idInCollection, + }, + creator, + }, + order: { timestamp: 'DESC' }, + }); + } + + async getCollectionType( + typeName: string, + ): Promise { + if (this.collectionTypes[typeName] !== undefined) { + return this.collectionTypes[typeName]; + } + return this.store.findOne(CollectionType, { where: { type: typeName } }); + } + + async deleteCollection(collection: Collection): Promise { + delete this.collections[collection.id]; + } + + async updateOffer(offer: Offer): Promise { + this.offers[ + this.getOfferKey( + offer.nft.collection.id, + offer.nft.idInCollection, + offer.creator, + ) + '-' + ] = offer; + } + + private async loadEntities() { + await Promise.all([this.loadMarketplace(), this.loadCollections()]); + } + + private async loadMarketplace() { + this.marketplace = await this.store.findOne(Marketplace, { where: {} }); + } + + private async loadCollections() { + const collections = await this.store.find(Collection, { where: {} }); + console.log(collections); + for (const entity of collections) { + this.collections[entity.id] = entity; + } + } + + private getNftKey(collectionAddress: string, idInCollection: number) { + return `${collectionAddress}-${idInCollection}`; + } + + private getOfferKey( + collectionAddress: string, + idInCollection: number, + creator: string, + ) { + return `${collectionAddress}-${idInCollection}-${creator}`; + } +} diff --git a/indexer/src/processing/storage/storage.inteface.ts b/indexer/src/processing/storage/storage.inteface.ts new file mode 100644 index 0000000..6e5a37d --- /dev/null +++ b/indexer/src/processing/storage/storage.inteface.ts @@ -0,0 +1,33 @@ +import { + Auction, + Collection, + CollectionType, + Marketplace, + Nft, + Offer, + Sale, +} from '../../model'; + +export interface IStorage { + getMarketplace(): Promise; + updateMarketplace(marketplace: Marketplace): Promise; + + getCollection(collectionAddress: string): Promise; + deleteCollection(collection: Collection): Promise; + updateCollection(collection: Collection): Promise; + + getNft(collectionAddress: string, tokenId: number): Promise; + updateNft(nft: Nft): Promise; + + getSale(nft: Nft): Promise; + updateSale(sale: Sale): Promise; + + updateAuction(auction: Auction): Promise; + getAuction(nft: Nft): Promise; + + getOffer(nft: Nft, creator: string): Promise; + updateOffer(offer: Offer): Promise; + + getCollectionType(typeName: string): Promise; + updateCollectionType(collectionType: CollectionType): Promise; +} diff --git a/indexer/src/processor.ts b/indexer/src/processor.ts index 173e598..a0d2606 100644 --- a/indexer/src/processor.ts +++ b/indexer/src/processor.ts @@ -1,5 +1,4 @@ import { assertNotNull } from '@subsquid/util-internal'; -import { lookupArchive } from '@subsquid/archive-registry'; import { BlockHeader, DataHandlerContext, @@ -9,33 +8,27 @@ import { Call as _Call, Extrinsic as _Extrinsic, } from '@subsquid/substrate-processor'; +import { config } from './config'; export const processor = new SubstrateBatchProcessor() .setDataSource({ - // archive: lookupArchive('vara-testnet', { release: 'ArrowSquid' }), - // Chain RPC endpoint is required on Substrate for metadata and real-time updates chain: { url: assertNotNull(process.env.RPC_ENDPOINT), - rateLimit: 100, + rateLimit: config.rateLimit, }, }) .addEvent({ name: ['Gear.UserMessageSent'], - extrinsic: true, }) .setFields({ event: { args: true, }, - extrinsic: { - hash: true, - fee: true, - }, block: { timestamp: true, }, }) - .setBlockRange({ from: 2608260 }); + .setBlockRange({ from: config.minBlockNum }); export type Fields = SubstrateBatchProcessorFields; export type Block = BlockHeader; diff --git a/indexer/src/types/event.utils.ts b/indexer/src/types/event.utils.ts new file mode 100644 index 0000000..bce7138 --- /dev/null +++ b/indexer/src/types/event.utils.ts @@ -0,0 +1,47 @@ +import { Option, u128, u16, u32, u64 } from '@polkadot/types'; +import { Codec } from '@polkadot/types-codec/types/codec'; + +export function safeUnwrapToNumber( + value: number | u16 | u32 | u64 | u128 | null, +): number | null { + if (typeof value === 'number') { + return value; + } + if (value === null) { + return null; + } + return value.toNumber(); +} + +export function safeUnwrapOptional( + value: Option | T | null, +): T | null { + if (value === null) { + return null; + } + if (isOption(value)) { + return value.unwrapOr(null) as T | null; + } + return value; +} + +function isOption( + value: Option | T | null, +): value is Option { + return (value as Option).unwrapOr !== undefined; +} + +export function safeUnwrapToBigInt( + value: number | bigint | u16 | u32 | u64 | u128 | null, +): bigint | null { + if (typeof value === 'number') { + return BigInt(value); + } + if (typeof value === 'bigint') { + return value; + } + if (value === null) { + return null; + } + return value.toBigInt(); +} diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index f3e1e30..fcc1d14 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -1,6 +1,11 @@ -import { Enum, Option, Text, Vec, u64, u128 } from '@polkadot/types'; +import { Enum, Option, Text, Vec, u64, u128, u32 } from '@polkadot/types'; import { Hash } from '@polkadot/types/interfaces'; import { CodeId } from '@gear-js/api'; +import { + safeUnwrapOptional, + safeUnwrapToBigInt, + safeUnwrapToNumber, +} from './event.utils'; export enum NftMarketplaceEventType { NewCollectionAdded = 'isNewCollectionAdded', @@ -11,6 +16,7 @@ export enum NftMarketplaceEventType { AuctionCreated = 'isAuctionCreated', BidAdded = 'isBidAdded', AuctionCanceled = 'isAuctionCanceled', + AuctionClosed = 'isAuctionClosed', OfferCreated = 'isOfferCreated', OfferCanceled = 'isOfferCanceled', OfferAccepted = 'isOfferAccepted', @@ -60,14 +66,15 @@ export type AuctionCreated = { type: NftMarketplaceEventType.AuctionCreated; collectionAddress: string; tokenId: number; - price: bigint; - currentOwner: string; + minPrice: bigint; + durationMs: number; }; export type BidAdded = { type: NftMarketplaceEventType.BidAdded; collectionAddress: string; tokenId: number; + price: bigint; }; export type AuctionCanceled = { @@ -76,6 +83,14 @@ export type AuctionCanceled = { tokenId: number; }; +export type AuctionClosed = { + type: NftMarketplaceEventType.AuctionClosed; + collectionAddress: string; + tokenId: number; + price: bigint; + currentOwner: string; +}; + export type OfferCreated = { type: NftMarketplaceEventType.OfferCreated; collectionAddress: string; @@ -91,6 +106,13 @@ export type OfferCanceled = { export type OfferAccepted = { type: NftMarketplaceEventType.OfferAccepted; + offer: Offer; +}; + +export type Offer = { + collectionAddress: string; + tokenId: number; + creator: string; }; export type CollectionDeleted = { @@ -111,7 +133,13 @@ export type AdminDeleted = { export type ConfigUpdated = { type: NftMarketplaceEventType.ConfigUpdated; gasForCreation: number | null; + gasForTransferToken: number | null; + gasForCloseAuction: number | null; + gasForDeleteCollection: number | null; + gasForGetTokenInfo: number | null; timeBetweenCreateCollections: number | null; + minimumTransferValue: bigint | null; + msInBlock: number | null; }; export type NftMarketplaceEvent = @@ -123,6 +151,7 @@ export type NftMarketplaceEvent = | AuctionCreated | BidAdded | AuctionCanceled + | AuctionClosed | OfferCreated | OfferCanceled | OfferAccepted @@ -161,17 +190,24 @@ export interface NftMarketplaceEventPlain extends Enum { auctionCreated: { collectionAddress: Hash; tokenId: u64; - price: u128; - currentOwner: Hash; + minPrice: u128; + durationMs: u32; }; bidAdded: { collectionAddress: Hash; tokenId: u64; + price: u128; }; auctionCanceled: { collectionAddress: Hash; tokenId: u64; }; + auctionClosed: { + collectionAddress: Hash; + tokenId: u64; + price: u128; + currentOwner: Hash; + }; offerCreated: { collectionAddress: Hash; tokenId: u64; @@ -181,19 +217,33 @@ export interface NftMarketplaceEventPlain extends Enum { collectionAddress: Hash; tokenId: u64; }; - offerAccepted: {}; + offerAccepted: { + offer: { + collectionAddress: Hash; + tokenId: u64; + creator: Hash; + }; + }; collectionDeleted: { collectionAddress: Hash; }; adminsAdded: { users: Vec; + collectionAddress: Hash; }; adminDeleted: { user: Hash; + collectionAddress: Hash; }; configUpdated: { gasForCreation: Option; + gasForTransferToken: Option; + gasForCloseAuction: Option; + gasForDeleteCollection: Option; + gasForGetTokenInfo: Option; timeBetweenCreateCollections: Option; + minimumTransferValue: Option; + msInBlock: Option; }; } @@ -220,8 +270,8 @@ export function getMarketplaceEvent( return { type: NftMarketplaceEventType.SaleNft, collectionAddress: event.saleNft.collectionAddress.toString(), - tokenId: event.saleNft.tokenId.toNumber(), - price: event.saleNft.price.toBigInt(), + tokenId: safeUnwrapToNumber(event.saleNft.tokenId)!, + price: safeUnwrapToBigInt(event.saleNft.price)!, owner: event.saleNft.owner.toString(), }; } @@ -229,15 +279,15 @@ export function getMarketplaceEvent( return { type: NftMarketplaceEventType.SaleNftCanceled, collectionAddress: event.saleNftCanceled.collectionAddress.toString(), - tokenId: event.saleNftCanceled.tokenId.toNumber(), + tokenId: safeUnwrapToNumber(event.saleNftCanceled.tokenId)!, }; } if (event.nftSold) { return { type: NftMarketplaceEventType.NftSold, currentOwner: event.nftSold.currentOwner.toString(), - tokenId: event.nftSold.tokenId.toNumber(), - price: event.nftSold.price.toBigInt(), + tokenId: safeUnwrapToNumber(event.nftSold.tokenId)!, + price: safeUnwrapToBigInt(event.nftSold.price)!, collectionAddress: event.nftSold.collectionAddress.toString(), }; } @@ -245,43 +295,59 @@ export function getMarketplaceEvent( return { type: NftMarketplaceEventType.AuctionCreated, collectionAddress: event.auctionCreated.collectionAddress.toString(), - tokenId: event.auctionCreated.tokenId.toNumber(), - price: event.auctionCreated.price.toBigInt(), - currentOwner: event.auctionCreated.currentOwner.toString(), + tokenId: safeUnwrapToNumber(event.auctionCreated.tokenId)!, + minPrice: safeUnwrapToBigInt(event.auctionCreated.minPrice)!, + durationMs: safeUnwrapToNumber(event.auctionCreated.durationMs)!, }; } if (event.bidAdded) { return { type: NftMarketplaceEventType.BidAdded, collectionAddress: event.bidAdded.collectionAddress.toString(), - tokenId: event.bidAdded.tokenId.toNumber(), + tokenId: safeUnwrapToNumber(event.bidAdded.tokenId)!, + price: safeUnwrapToBigInt(event.bidAdded.price)!, }; } if (event.auctionCanceled) { return { type: NftMarketplaceEventType.AuctionCanceled, collectionAddress: event.auctionCanceled.collectionAddress.toString(), - tokenId: event.auctionCanceled.tokenId.toNumber(), + tokenId: safeUnwrapToNumber(event.auctionCanceled.tokenId)!, + }; + } + if (event.auctionClosed) { + return { + type: NftMarketplaceEventType.AuctionClosed, + collectionAddress: event.auctionClosed.collectionAddress.toString(), + tokenId: safeUnwrapToNumber(event.auctionClosed.tokenId)!, + price: safeUnwrapToBigInt(event.auctionClosed.price)!, + currentOwner: event.auctionClosed.currentOwner.toString(), }; } if (event.offerCreated) { return { type: NftMarketplaceEventType.OfferCreated, collectionAddress: event.offerCreated.collectionAddress.toString(), - tokenId: event.offerCreated.tokenId.toNumber(), - price: event.offerCreated.price.toBigInt(), + tokenId: safeUnwrapToNumber(event.offerCreated.tokenId)!, + price: safeUnwrapToBigInt(event.offerCreated.price)!, }; } if (event.offerCanceled) { return { type: NftMarketplaceEventType.OfferCanceled, collectionAddress: event.offerCanceled.collectionAddress.toString(), - tokenId: event.offerCanceled.tokenId.toNumber(), + tokenId: safeUnwrapToNumber(event.offerCanceled.tokenId)!, }; } if (event.offerAccepted) { return { type: NftMarketplaceEventType.OfferAccepted, + offer: { + collectionAddress: + event.offerAccepted.offer.collectionAddress.toString(), + tokenId: safeUnwrapToNumber(event.offerAccepted.offer.tokenId)!, + creator: event.offerAccepted.offer.creator.toString(), + }, }; } if (event.collectionDeleted) { @@ -305,12 +371,38 @@ export function getMarketplaceEvent( if (event.configUpdated) { return { type: NftMarketplaceEventType.ConfigUpdated, - gasForCreation: - event.configUpdated.gasForCreation.unwrapOr(null)?.toNumber() ?? null, - timeBetweenCreateCollections: - event.configUpdated.timeBetweenCreateCollections - .unwrapOr(null) - ?.toNumber() ?? null, + gasForCreation: safeUnwrapToNumber( + safeUnwrapOptional(event.configUpdated.gasForCreation), + ), + gasForTransferToken: safeUnwrapToNumber( + safeUnwrapOptional( + event.configUpdated.gasForTransferToken, + ), + ), + gasForCloseAuction: safeUnwrapToNumber( + safeUnwrapOptional(event.configUpdated.gasForCloseAuction), + ), + gasForDeleteCollection: safeUnwrapToNumber( + safeUnwrapOptional( + event.configUpdated.gasForDeleteCollection, + ), + ), + gasForGetTokenInfo: safeUnwrapToNumber( + safeUnwrapOptional(event.configUpdated.gasForGetTokenInfo), + ), + timeBetweenCreateCollections: safeUnwrapToNumber( + safeUnwrapOptional( + event.configUpdated.timeBetweenCreateCollections, + ), + ), + minimumTransferValue: safeUnwrapToBigInt( + safeUnwrapOptional( + event.configUpdated.minimumTransferValue, + ), + ), + msInBlock: safeUnwrapToNumber( + safeUnwrapOptional(event.configUpdated.msInBlock), + ), }; } } diff --git a/indexer/src/types/nft.events.ts b/indexer/src/types/nft.events.ts index fe4688d..ff5b708 100644 --- a/indexer/src/types/nft.events.ts +++ b/indexer/src/types/nft.events.ts @@ -1,5 +1,10 @@ import { Enum, Option, Text, u128, u16, u32, u64, Vec } from '@polkadot/types'; import { Hash } from '@polkadot/types/interfaces'; +import { + safeUnwrapOptional, + safeUnwrapToBigInt, + safeUnwrapToNumber, +} from './event.utils'; export enum NftEventType { Transferred = 'Transferred', @@ -34,12 +39,12 @@ export type NftConfig = { name: string; description: string; collectionTags: string[]; - collectionImg: string; + collectionBanner: string; collectionLogo: string; - userMintLimit: number | null; - additionalLinks: number | null; + userMintLimit: bigint | null; + additionalLinks: AdditionalLink | null; royalty: number; - paymentForMint: number; + paymentForMint: bigint; transferable: boolean; approvable: boolean; burnable: boolean; @@ -79,7 +84,7 @@ export type ApprovalRevokedEvent = { export type ExpandedEvent = { type: NftEventType.Expanded; - additionalLinks: string[]; + additionalLinks: AdditionalLink | null; }; export type ConfigChangedEvent = { @@ -99,6 +104,14 @@ export type MetadataAddedEvent = { metadata: string; }; +export type AdditionalLink = { + externalUrl: string | null; + telegram: string | null; + xcom: string | null; + medium: string | null; + discord: string | null; +}; + export type NftEvent = | TransferEvent | TokenInfoReceivedEvent @@ -111,14 +124,22 @@ export type NftEvent = | ImageChangedEvent | MetadataAddedEvent; +export interface AdditionalLinkPlain { + externalUrl: Option; + telegram: Option; + xcom: Option; + medium: Option; + discord: Option; +} + export interface ConfigPlain { name: Text; description: Text; collectionTags: Vec; - collectionImg: Text; + collectionBanner: Text; collectionLogo: Text; - userMintLimit: Option; - additionalLinks: Option; + userMintLimit: Option | number; + additionalLinks: AdditionalLinkPlain; royalty: u16; paymentForMint: u128; transferable: boolean; @@ -132,19 +153,21 @@ export interface NftEventPlain extends Enum { transferred: { owner: Hash; recipient: Hash; - token_id: u64; + tokenId: u64; }; tokenInfoReceived: { token_owner: Hash; approval: Option; sellable: boolean; - collection_owner: Hash; + collectionOwner: Hash; royalty: u16; }; - initialized: ConfigPlain; + initialized: { + config: ConfigPlain; + }; minted: { - token_id: u64; - nft_data: { + tokenId: u64; + nftData: { owner: Hash; name: Text; description: Text; @@ -160,17 +183,17 @@ export interface NftEventPlain extends Enum { tokenId: u64; }; expanded: { - additional_links: Vec; + additionalLinks: AdditionalLinkPlain; }; configChanged: { config: ConfigPlain; }; imageChanged: { - token_id: u64; + tokenId: u64; imgLink: Text; }; metadataAdded: { - token_id: u64; + tokenId: u64; metadata: Text; }; } @@ -181,7 +204,7 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { type: NftEventType.Transferred, owner: event.transferred.owner.toString(), recipient: event.transferred.recipient.toString(), - tokenId: event.transferred.token_id.toNumber(), + tokenId: safeUnwrapToNumber(event.transferred.tokenId)!, }; } if (event.tokenInfoReceived) { @@ -190,45 +213,59 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { tokenOwner: event.tokenInfoReceived.token_owner.toString(), approval: event.tokenInfoReceived.approval?.toString() ?? null, sellable: event.tokenInfoReceived.sellable, - collectionOwner: event.tokenInfoReceived.collection_owner.toString(), - royalty: event.tokenInfoReceived.royalty.toNumber(), + collectionOwner: event.tokenInfoReceived.collectionOwner.toString(), + royalty: safeUnwrapToNumber(event.tokenInfoReceived.royalty)!, }; } if (event.initialized) { return { type: NftEventType.Initialized, config: { - name: event.initialized.name.toString(), - description: event.initialized.description.toString(), - collectionTags: event.initialized.collectionTags.map((tag) => + name: event.initialized.config.name.toString(), + description: event.initialized.config.description.toString(), + collectionTags: event.initialized.config.collectionTags.map((tag) => tag.toString(), ), - collectionImg: event.initialized.collectionImg.toString(), - collectionLogo: event.initialized.collectionLogo.toString(), - userMintLimit: - event.initialized.userMintLimit.unwrapOr(null)?.toNumber() ?? null, - additionalLinks: - event.initialized.additionalLinks.unwrapOr(null)?.toNumber() ?? null, - royalty: event.initialized.royalty.toNumber(), - paymentForMint: event.initialized.paymentForMint.toNumber(), - transferable: event.initialized.transferable, - approvable: event.initialized.approvable, - burnable: event.initialized.burnable, - sellable: event.initialized.sellable, - attendable: event.initialized.attendable, + collectionBanner: event.initialized.config.collectionBanner.toString(), + collectionLogo: event.initialized.config.collectionLogo.toString(), + userMintLimit: safeUnwrapToBigInt( + safeUnwrapOptional(event.initialized.config.userMintLimit), + ), + additionalLinks: event.initialized.config.additionalLinks + ? { + externalUrl: + event.initialized.config.additionalLinks.externalUrl.toString(), + telegram: + event.initialized.config.additionalLinks.telegram.toString(), + xcom: event.initialized.config.additionalLinks.xcom.toString(), + medium: + event.initialized.config.additionalLinks.medium.toString(), + discord: + event.initialized.config.additionalLinks.discord.toString(), + } + : null, + royalty: safeUnwrapToNumber(event.initialized.config.royalty)!, + paymentForMint: safeUnwrapToBigInt( + event.initialized.config.paymentForMint, + )!, + transferable: event.initialized.config.transferable, + approvable: event.initialized.config.approvable, + burnable: event.initialized.config.burnable, + sellable: event.initialized.config.sellable, + attendable: event.initialized.config.attendable, }, }; } if (event.minted) { return { type: NftEventType.Minted, - tokenId: event.minted.token_id.toNumber(), + tokenId: safeUnwrapToNumber(event.minted.tokenId)!, nftData: { - owner: event.minted.nft_data.owner.toString(), - name: event.minted.nft_data.name.toString(), - description: event.minted.nft_data.description.toString(), - metadata: event.minted.nft_data.metadata.map((m) => m.toString()), - mediaUrl: event.minted.nft_data.mediaUrl.toString(), + owner: event.minted.nftData.owner.toString(), + name: event.minted.nftData.name.toString(), + description: event.minted.nftData.description.toString(), + metadata: event.minted.nftData.metadata.map((m) => m.toString()), + mediaUrl: event.minted.nftData.mediaUrl.toString(), }, }; } @@ -236,21 +273,27 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { return { type: NftEventType.Approved, to: event.approved.to.toString(), - tokenId: event.approved.tokenId.toNumber(), + tokenId: safeUnwrapToNumber(event.approved.tokenId)!, }; } if (event.approvalRevoked) { return { type: NftEventType.ApprovalRevoked, - tokenId: event.approvalRevoked.tokenId.toNumber(), + tokenId: safeUnwrapToNumber(event.approvalRevoked.tokenId)!, }; } if (event.expanded) { return { type: NftEventType.Expanded, - additionalLinks: event.expanded.additional_links.map((link) => - link.toString(), - ), + additionalLinks: event.expanded.additionalLinks + ? { + externalUrl: event.expanded.additionalLinks.externalUrl.toString(), + telegram: event.expanded.additionalLinks.telegram.toString(), + xcom: event.expanded.additionalLinks.xcom.toString(), + medium: event.expanded.additionalLinks.medium.toString(), + discord: event.expanded.additionalLinks.discord.toString(), + } + : null, }; } if (event.configChanged) { @@ -262,17 +305,29 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { collectionTags: event.configChanged.config.collectionTags.map((tag) => tag.toString(), ), - collectionImg: event.configChanged.config.collectionImg.toString(), + collectionBanner: + event.configChanged.config.collectionBanner.toString(), collectionLogo: event.configChanged.config.collectionLogo.toString(), - userMintLimit: - event.configChanged.config.userMintLimit.unwrapOr(null)?.toNumber() ?? - null, - additionalLinks: - event.configChanged.config.additionalLinks - .unwrapOr(null) - ?.toNumber() ?? null, - royalty: event.configChanged.config.royalty.toNumber(), - paymentForMint: event.configChanged.config.paymentForMint.toNumber(), + userMintLimit: safeUnwrapToBigInt( + safeUnwrapOptional(event.configChanged.config.userMintLimit), + ), + additionalLinks: event.configChanged.config.additionalLinks + ? { + externalUrl: + event.configChanged.config.additionalLinks.externalUrl.toString(), + telegram: + event.configChanged.config.additionalLinks.telegram.toString(), + xcom: event.configChanged.config.additionalLinks.xcom.toString(), + medium: + event.configChanged.config.additionalLinks.medium.toString(), + discord: + event.configChanged.config.additionalLinks.discord.toString(), + } + : null, + royalty: safeUnwrapToNumber(event.configChanged.config.royalty)!, + paymentForMint: safeUnwrapToBigInt( + event.configChanged.config.paymentForMint, + )!, transferable: event.configChanged.config.transferable, approvable: event.configChanged.config.approvable, burnable: event.configChanged.config.burnable, @@ -284,14 +339,14 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { if (event.imageChanged) { return { type: NftEventType.ImageChanged, - tokenId: event.imageChanged.token_id.toNumber(), + tokenId: safeUnwrapToNumber(event.imageChanged.tokenId)!, imgLink: event.imageChanged.imgLink.toString(), }; } if (event.metadataAdded) { return { type: NftEventType.MetadataAdded, - tokenId: event.metadataAdded.token_id.toNumber(), + tokenId: safeUnwrapToNumber(event.metadataAdded.tokenId)!, metadata: event.metadataAdded.metadata.toString(), }; } From 5d9e48203c0c16b5b27cdb66a0ea4838f52a6ad9 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 19 Jan 2024 14:38:49 +0300 Subject: [PATCH 04/50] indexer improvements --- indexer/db/migrations/1705664292143-Data.js | 79 +++++++++++++++++++++ indexer/src/processing/events.processing.ts | 1 - 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 indexer/db/migrations/1705664292143-Data.js diff --git a/indexer/db/migrations/1705664292143-Data.js b/indexer/db/migrations/1705664292143-Data.js new file mode 100644 index 0000000..cd8300a --- /dev/null +++ b/indexer/db/migrations/1705664292143-Data.js @@ -0,0 +1,79 @@ +module.exports = class Data1705664292143 { + name = 'Data1705664292143' + + async up(db) { + await db.query(`CREATE TABLE "marketplace_config" ("id" character varying NOT NULL, "gas_for_creation" integer, "gas_for_transfer_token" integer, "gas_for_close_auction" integer, "gas_for_delete_collection" integer, "gas_for_get_token_info" integer, "time_between_create_collections" integer, "minimum_transfer_value" numeric, "ms_in_block" integer, "marketplace_id" character varying, CONSTRAINT "PK_73c68d1a502db50c13ff91f8ec3" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_49bd93aa35746a6971bb299ce3" ON "marketplace_config" ("marketplace_id") `) + await db.query(`CREATE TABLE "collection_type" ("id" character varying NOT NULL, "description" text NOT NULL, "type" text NOT NULL, "meta_url" text NOT NULL, "meta_str" text NOT NULL, "marketplace_id" character varying, CONSTRAINT "PK_75c673f46e25c52205fae22130c" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_be423ee528eb245b57165bd597" ON "collection_type" ("marketplace_id") `) + await db.query(`CREATE TABLE "transfer" ("id" character varying NOT NULL, "from" text NOT NULL, "to" text NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "tx_hash" text NOT NULL, "nft_id" character varying, CONSTRAINT "PK_fd9ddbdd49a17afcbe014401295" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_52fc453ba5ff660f331db4b359" ON "transfer" ("nft_id") `) + await db.query(`CREATE TABLE "sale" ("id" character varying NOT NULL, "owner" text NOT NULL, "new_owner" text, "price" numeric NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "status" text NOT NULL, "nft_id" character varying, CONSTRAINT "PK_d03891c457cbcd22974732b5de2" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_8524438f82167bcb795bcb8663" ON "sale" ("nft_id") `) + await db.query(`CREATE TABLE "bid" ("id" character varying NOT NULL, "bidder" text NOT NULL, "price" numeric NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "auction_id" character varying, CONSTRAINT "PK_ed405dda320051aca2dcb1a50bb" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_9e594e5a61c0f3cb25679f6ba8" ON "bid" ("auction_id") `) + await db.query(`CREATE TABLE "auction" ("id" character varying NOT NULL, "owner" text NOT NULL, "min_price" numeric NOT NULL, "new_owner" text, "last_price" numeric, "status" text NOT NULL, "duration_ms" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "nft_id" character varying, CONSTRAINT "PK_9dc876c629273e71646cf6dfa67" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_cfb47e97e60c9d1462576f85a8" ON "auction" ("nft_id") `) + await db.query(`CREATE TABLE "offer" ("id" character varying NOT NULL, "owner" text NOT NULL, "price" numeric NOT NULL, "status" text NOT NULL, "creator" text NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "nft_id" character varying, CONSTRAINT "PK_57c6ae1abe49201919ef68de900" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_71609884f4478ed41be6672a66" ON "offer" ("nft_id") `) + await db.query(`CREATE TABLE "nft" ("id" character varying NOT NULL, "owner" text NOT NULL, "name" text NOT NULL, "description" text NOT NULL, "id_in_collection" integer NOT NULL, "media_url" text NOT NULL, "approved_account" text, "metadata" text, "on_sale" boolean NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "collection_id" character varying, CONSTRAINT "PK_8f46897c58e23b0e7bf6c8e56b0" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_ffe58aa05707db77c2f20ecdbc" ON "nft" ("collection_id") `) + await db.query(`CREATE TABLE "collection" ("id" character varying NOT NULL, "admin" text, "name" text, "description" text, "user_mint_limit" numeric, "tokens_limit" numeric, "payment_for_mint" numeric, "royalty" integer, "collection_logo" text, "collection_banner" text, "transferable" boolean, "approvable" boolean, "burnable" boolean, "sellable" boolean, "attendable" boolean, "created_at" TIMESTAMP WITH TIME ZONE, "tags" text array, "marketplace_id" character varying, "type_id" character varying, CONSTRAINT "PK_ad3f485bbc99d875491f44d7c85" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_4698f01445e4833a95f214f862" ON "collection" ("marketplace_id") `) + await db.query(`CREATE INDEX "IDX_75c673f46e25c52205fae22130" ON "collection" ("type_id") `) + await db.query(`CREATE TABLE "marketplace_event" ("id" character varying NOT NULL, "type" text NOT NULL, "raw" text NOT NULL, "block_number" integer NOT NULL, "tx_hash" text NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "marketplace_id" character varying, CONSTRAINT "PK_805265912d311b94048601bd286" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_7fb5589ddd0a773530e3b05af0" ON "marketplace_event" ("marketplace_id") `) + await db.query(`CREATE TABLE "marketplace" ("id" character varying NOT NULL, "admins" text array NOT NULL, "config_id" character varying, CONSTRAINT "PK_d9c9a956a1a45b27b56db53bfc8" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_73c68d1a502db50c13ff91f8ec" ON "marketplace" ("config_id") `) + await db.query(`ALTER TABLE "marketplace_config" ADD CONSTRAINT "FK_49bd93aa35746a6971bb299ce37" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "collection_type" ADD CONSTRAINT "FK_be423ee528eb245b57165bd597b" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "transfer" ADD CONSTRAINT "FK_52fc453ba5ff660f331db4b3591" FOREIGN KEY ("nft_id") REFERENCES "nft"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "sale" ADD CONSTRAINT "FK_8524438f82167bcb795bcb86637" FOREIGN KEY ("nft_id") REFERENCES "nft"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "bid" ADD CONSTRAINT "FK_9e594e5a61c0f3cb25679f6ba8d" FOREIGN KEY ("auction_id") REFERENCES "auction"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "auction" ADD CONSTRAINT "FK_cfb47e97e60c9d1462576f85a88" FOREIGN KEY ("nft_id") REFERENCES "nft"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "offer" ADD CONSTRAINT "FK_71609884f4478ed41be6672a668" FOREIGN KEY ("nft_id") REFERENCES "nft"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "nft" ADD CONSTRAINT "FK_ffe58aa05707db77c2f20ecdbc3" FOREIGN KEY ("collection_id") REFERENCES "collection"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "collection" ADD CONSTRAINT "FK_4698f01445e4833a95f214f862b" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "collection" ADD CONSTRAINT "FK_75c673f46e25c52205fae22130c" FOREIGN KEY ("type_id") REFERENCES "collection_type"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "marketplace_event" ADD CONSTRAINT "FK_7fb5589ddd0a773530e3b05af08" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "marketplace" ADD CONSTRAINT "FK_73c68d1a502db50c13ff91f8ec3" FOREIGN KEY ("config_id") REFERENCES "marketplace_config"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + } + + async down(db) { + await db.query(`DROP TABLE "marketplace_config"`) + await db.query(`DROP INDEX "public"."IDX_49bd93aa35746a6971bb299ce3"`) + await db.query(`DROP TABLE "collection_type"`) + await db.query(`DROP INDEX "public"."IDX_be423ee528eb245b57165bd597"`) + await db.query(`DROP TABLE "transfer"`) + await db.query(`DROP INDEX "public"."IDX_52fc453ba5ff660f331db4b359"`) + await db.query(`DROP TABLE "sale"`) + await db.query(`DROP INDEX "public"."IDX_8524438f82167bcb795bcb8663"`) + await db.query(`DROP TABLE "bid"`) + await db.query(`DROP INDEX "public"."IDX_9e594e5a61c0f3cb25679f6ba8"`) + await db.query(`DROP TABLE "auction"`) + await db.query(`DROP INDEX "public"."IDX_cfb47e97e60c9d1462576f85a8"`) + await db.query(`DROP TABLE "offer"`) + await db.query(`DROP INDEX "public"."IDX_71609884f4478ed41be6672a66"`) + await db.query(`DROP TABLE "nft"`) + await db.query(`DROP INDEX "public"."IDX_ffe58aa05707db77c2f20ecdbc"`) + await db.query(`DROP TABLE "collection"`) + await db.query(`DROP INDEX "public"."IDX_4698f01445e4833a95f214f862"`) + await db.query(`DROP INDEX "public"."IDX_75c673f46e25c52205fae22130"`) + await db.query(`DROP TABLE "marketplace_event"`) + await db.query(`DROP INDEX "public"."IDX_7fb5589ddd0a773530e3b05af0"`) + await db.query(`DROP TABLE "marketplace"`) + await db.query(`DROP INDEX "public"."IDX_73c68d1a502db50c13ff91f8ec"`) + await db.query(`ALTER TABLE "marketplace_config" DROP CONSTRAINT "FK_49bd93aa35746a6971bb299ce37"`) + await db.query(`ALTER TABLE "collection_type" DROP CONSTRAINT "FK_be423ee528eb245b57165bd597b"`) + await db.query(`ALTER TABLE "transfer" DROP CONSTRAINT "FK_52fc453ba5ff660f331db4b3591"`) + await db.query(`ALTER TABLE "sale" DROP CONSTRAINT "FK_8524438f82167bcb795bcb86637"`) + await db.query(`ALTER TABLE "bid" DROP CONSTRAINT "FK_9e594e5a61c0f3cb25679f6ba8d"`) + await db.query(`ALTER TABLE "auction" DROP CONSTRAINT "FK_cfb47e97e60c9d1462576f85a88"`) + await db.query(`ALTER TABLE "offer" DROP CONSTRAINT "FK_71609884f4478ed41be6672a668"`) + await db.query(`ALTER TABLE "nft" DROP CONSTRAINT "FK_ffe58aa05707db77c2f20ecdbc3"`) + await db.query(`ALTER TABLE "collection" DROP CONSTRAINT "FK_4698f01445e4833a95f214f862b"`) + await db.query(`ALTER TABLE "collection" DROP CONSTRAINT "FK_75c673f46e25c52205fae22130c"`) + await db.query(`ALTER TABLE "marketplace_event" DROP CONSTRAINT "FK_7fb5589ddd0a773530e3b05af08"`) + await db.query(`ALTER TABLE "marketplace" DROP CONSTRAINT "FK_73c68d1a502db50c13ff91f8ec3"`) + } +} diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index 27b519c..89d09bf 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -39,7 +39,6 @@ import { ImageChangedHandler } from './nft/image-changed.handler'; import { TransferredHandler } from './nft/transferred.handler'; import { MetadataAddedHandler } from './nft/metadata-added.handler'; import { EventInfo } from './event-info.type'; -import { MarketplaceEvent } from '../model'; import { EntitiesService } from './entities.service'; const marketplaceMeta = ProgramMetadata.from( From fefb5bc8d1cf557c3adc54ab9786d4ef80248166 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 19 Jan 2024 14:57:08 +0300 Subject: [PATCH 05/50] remove .env --- indexer/.env | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 indexer/.env diff --git a/indexer/.env b/indexer/.env deleted file mode 100644 index 6716a7d..0000000 --- a/indexer/.env +++ /dev/null @@ -1,17 +0,0 @@ -DB_NAME=squid -DB_HOST=localhost -DB_PORT=5432 -GQL_PORT=4350 - -# JSON-RPC node endpoints (wss or https) -# Use private endpoints in production! -# Set urls via secrets if deploying to Cloud: https://docs.subsquid.io/deploy-squid/env-variables/ -# OR use the RPC proxy service: https://docs.subsquid.io/deploy-squid/rpc-proxy -RPC_ENDPOINT=wss://testnet-archive.vara.network -MARKETPLACE_PROGRAM=0x44842bc912e6ec8eba11cc565e373c6d805600386a9fe874765515cf303215d9 -MIN_BLOCK_NUM=3276150 -RATE_LIMIT=100 - -# Uncommenting this line enables the debug mode -# More info at https://docs.subsquid.io/basics/logging/ -# SQD_DEBUG=* From 26ebde41938e69dd20bafb3d0f6efdf71f65f859 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 19 Jan 2024 15:00:59 +0300 Subject: [PATCH 06/50] remove console logs --- indexer/src/processing/nft/config-changed.handler.ts | 1 - indexer/src/processing/storage/local.storage.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/indexer/src/processing/nft/config-changed.handler.ts b/indexer/src/processing/nft/config-changed.handler.ts index 085e8c9..244ecb1 100644 --- a/indexer/src/processing/nft/config-changed.handler.ts +++ b/indexer/src/processing/nft/config-changed.handler.ts @@ -17,7 +17,6 @@ export class ConfigChangedHandler implements INftEventHandler { ); return; } - console.log(`[ConfigChangedHandler] ${event}`); let { name, description, diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index e0e37ad..77687d8 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -196,7 +196,6 @@ export class LocalStorage implements IStorage { private async loadCollections() { const collections = await this.store.find(Collection, { where: {} }); - console.log(collections); for (const entity of collections) { this.collections[entity.id] = entity; } From 963158986127e595aa47c9a5e419ff5178cec240 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 22 Jan 2024 10:58:02 +0300 Subject: [PATCH 07/50] fix graphql server --- indexer/Dockerfile-explorer | 3 +- indexer/package-lock.json | 283 ++++++++++++++++++++---------------- indexer/package.json | 6 +- 3 files changed, 166 insertions(+), 126 deletions(-) diff --git a/indexer/Dockerfile-explorer b/indexer/Dockerfile-explorer index b6d40dd..d0c17ab 100644 --- a/indexer/Dockerfile-explorer +++ b/indexer/Dockerfile-explorer @@ -6,7 +6,7 @@ WORKDIR /squid ADD package.json . ADD package-lock.json . # remove if needed -ADD assets assets +ADD assets assets # remove if needed ADD db db # remove if needed @@ -37,3 +37,4 @@ ADD commands.json . RUN echo -e "loglevel=silent\\nupdate-notifier=false" > /squid/.npmrc RUN npm i -g @subsquid/commands && mv $(which squid-commands) /usr/local/bin/sqd ENV PROCESSOR_PROMETHEUS_PORT 3000 +CMD ["npm", "run", "serve"] diff --git a/indexer/package-lock.json b/indexer/package-lock.json index a3e8113..e1a55c4 100644 --- a/indexer/package-lock.json +++ b/indexer/package-lock.json @@ -9,7 +9,7 @@ "@gear-js/api": "^0.35.2", "@polkadot/types": "10.10.1", "@subsquid/archive-registry": "^3.3.0", - "@subsquid/graphql-server": "^4.3.1", + "@subsquid/graphql-server": "^4.5.0", "@subsquid/ss58": "^2.0.1", "@subsquid/substrate-processor": "^7.2.1", "@subsquid/typeorm-migration": "^1.2.2", @@ -1033,11 +1033,11 @@ } }, "node_modules/@graphql-tools/merge": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", - "integrity": "sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.1.tgz", + "integrity": "sha512-hIEExWO9fjA6vzsVjJ3s0cCQ+Q/BEeMVJZtMXd7nbaVefVy0YDyYlEkeoYYNV3NVVvu1G9lr6DM1Qd0DGo9Caw==", "dependencies": { - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.0.10", "tslib": "^2.4.0" }, "engines": { @@ -1100,12 +1100,12 @@ } }, "node_modules/@graphql-tools/schema": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.0.tgz", - "integrity": "sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.2.tgz", + "integrity": "sha512-TbPsIZnWyDCLhgPGnDjt4hosiNU2mF/rNtSk5BVaXWnZqvKJ6gzJV4fcHcvhRIwtscDMW2/YTnK6dLVnk8pc4w==", "dependencies": { - "@graphql-tools/merge": "^9.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/merge": "^9.0.1", + "@graphql-tools/utils": "^10.0.10", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" }, @@ -1117,11 +1117,12 @@ } }, "node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "version": "10.0.12", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.12.tgz", + "integrity": "sha512-+yS1qlFwXlwU3Gv8ek/h2aJ95quog4yF22haC11M0zReMSTddbGJZ5yXKkE3sXoY2BcL1utilSFjylJ9uXpSNQ==", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", + "cross-inspect": "1.0.0", "dset": "^3.1.2", "tslib": "^2.4.0" }, @@ -2584,31 +2585,32 @@ "integrity": "sha512-C89mus6IXnNi0xMQrZqUFBZwLj8tbuq9lye8Gq/lHmmERAUpi6UsWEyLdJLx2mneZzF3JtY8eNiiZ16jmjtvfw==" }, "node_modules/@subsquid/graphql-server": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@subsquid/graphql-server/-/graphql-server-4.3.1.tgz", - "integrity": "sha512-EEZXaZf3TSK0JD+kcBgr+ENf2WOAjb7EREQP28+9NRWQhtn1s1w3XQNMjjurfyeb5Us/pRODAmfl8jOcXj3CAQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@subsquid/graphql-server/-/graphql-server-4.5.0.tgz", + "integrity": "sha512-SKCq6qF8FGrsrzFpjLzyDf3Cbcp4e8Z2M+t6Er3en7WLY3jZtdEGf3HbfCH6ukhQoJ72lUSNsESdwEoazOslRA==", "dependencies": { "@apollo/utils.keyvadapter": "~1.1.2", "@apollo/utils.keyvaluecache": "~1.0.2", - "@graphql-tools/merge": "^9.0.0", - "@graphql-tools/schema": "^10.0.0", - "@graphql-tools/utils": "^10.0.6", + "@graphql-tools/merge": "^9.0.1", + "@graphql-tools/schema": "^10.0.2", + "@graphql-tools/utils": "^10.0.11", "@keyv/redis": "~2.5.8", - "@subsquid/logger": "^1.3.1", - "@subsquid/openreader": "^4.4.1", - "@subsquid/typeorm-config": "^3.3.1", - "@subsquid/util-internal": "^2.5.2", - "@subsquid/util-internal-commander": "^1.3.1", - "@subsquid/util-internal-http-server": "^1.2.1", - "apollo-server-core": "^3.12.1", - "apollo-server-express": "^3.12.1", + "@subsquid/logger": "^1.3.2", + "@subsquid/openreader": "^4.5.0", + "@subsquid/typeorm-config": "^4.1.0", + "@subsquid/util-internal": "^3.0.0", + "@subsquid/util-internal-commander": "^1.3.2", + "@subsquid/util-internal-http-server": "^1.2.2", + "@subsquid/util-internal-ts-node": "^0.0.0", + "apollo-server-core": "^3.13.0", + "apollo-server-express": "^3.13.0", "apollo-server-plugin-response-cache": "~3.7.1", - "commander": "^11.0.0", + "commander": "^11.1.0", "dotenv": "^16.3.1", "express": "^4.18.2", "graphql": "^15.8.0", - "graphql-ws": "^5.14.1", - "keyv": "~4.5.3", + "graphql-ws": "^5.14.2", + "keyv": "~4.5.4", "pg": "^8.11.3", "ws": "^8.14.2" }, @@ -2636,17 +2638,35 @@ } } }, + "node_modules/@subsquid/graphql-server/node_modules/@subsquid/typeorm-config": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@subsquid/typeorm-config/-/typeorm-config-4.1.0.tgz", + "integrity": "sha512-onZsHQIypCTRguOeec1Gmm+6EPlTg63QNE7Y74nrbBb4sabZtrK3K+EQJId4KIdk/kxA2Wi/g5H/VDNZNFSe9A==", + "dependencies": { + "@subsquid/logger": "^1.3.2", + "@subsquid/util-internal-ts-node": "^0.0.0", + "@subsquid/util-naming": "^1.2.2" + }, + "peerDependencies": { + "typeorm": "^0.3.17" + }, + "peerDependenciesMeta": { + "typeorm": { + "optional": true + } + } + }, "node_modules/@subsquid/graphql-server/node_modules/@subsquid/util-internal": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", - "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-3.0.0.tgz", + "integrity": "sha512-aGPTiLF21N9f67DgHS4PBR8d6mdvXHTOIhr2mFQPX7GQCgZhNlCZDM/1Sqn+teJawCy3w6Y9f6KOtVbN4T5SFQ==" }, "node_modules/@subsquid/graphql-server/node_modules/@subsquid/util-internal-commander": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@subsquid/util-internal-commander/-/util-internal-commander-1.3.1.tgz", - "integrity": "sha512-KeGsOghBU20tM1BzqryOf3MKvrDFSfPuhnl9LhhEC00ysp8rRPyejlw6jIJhO2NRJ+oaUi5jHRdf64/o21N7Lw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-commander/-/util-internal-commander-1.3.2.tgz", + "integrity": "sha512-9/1vI1dmGQMp5wjN6hb94VCnSosT+caob33tAesFaIdqLzqQlDtlTSRq1TFFossAgtsEJFi7GiQ8i31L/gaxSQ==", "peerDependencies": { - "commander": "^11.0.0" + "commander": "^11.1.0" } }, "node_modules/@subsquid/graphql-server/node_modules/commander": { @@ -2673,36 +2693,36 @@ "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" }, "node_modules/@subsquid/logger": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@subsquid/logger/-/logger-1.3.1.tgz", - "integrity": "sha512-OBhelb0HbhqSygq/IxEm9PPX8thQSDiCPV45UlCqWOoQ9UpiROiQLL+2nwt+HAHQq+LlHTzQmGXV43eabrTfwQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@subsquid/logger/-/logger-1.3.2.tgz", + "integrity": "sha512-5YPdeRu0WD9iBak+r3S8blBeg2uyliPUlmCjj/ZE6dpXmXsSN9T+ZYrNeDr9eAbRV7OXVI49lSfCuAGenFcYjQ==", "dependencies": { - "@subsquid/util-internal-hex": "^1.2.1", - "@subsquid/util-internal-json": "^1.2.1", + "@subsquid/util-internal-hex": "^1.2.2", + "@subsquid/util-internal-json": "^1.2.2", "supports-color": "^8.1.1" } }, "node_modules/@subsquid/openreader": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@subsquid/openreader/-/openreader-4.4.1.tgz", - "integrity": "sha512-Z2M+scuoJx1H3U+KttIEjrSvZ+5K3ioNdWatUS42k9xgOIEMJzDCJM8ZxhqgP/fMTrR9RPjeFqjy6NBS0kgwtg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@subsquid/openreader/-/openreader-4.5.0.tgz", + "integrity": "sha512-A07K1TM0YY2iZjJcY2qD0jXco1S7D00OfqAnN4tqxVtj4ddLJVZ3bLIAHn7r3P3JB4iT+3daBNTTa17vH1k2XA==", "dependencies": { - "@graphql-tools/merge": "^9.0.0", + "@graphql-tools/merge": "^9.0.1", "@subsquid/graphiql-console": "^0.3.0", - "@subsquid/logger": "^1.3.1", - "@subsquid/util-internal": "^2.5.2", - "@subsquid/util-internal-commander": "^1.3.1", - "@subsquid/util-internal-hex": "^1.2.1", - "@subsquid/util-internal-http-server": "^1.2.1", - "@subsquid/util-naming": "^1.2.1", - "apollo-server-core": "^3.12.1", - "apollo-server-express": "^3.12.1", - "commander": "^11.0.0", - "deep-equal": "^2.2.2", + "@subsquid/logger": "^1.3.2", + "@subsquid/util-internal": "^3.0.0", + "@subsquid/util-internal-commander": "^1.3.2", + "@subsquid/util-internal-hex": "^1.2.2", + "@subsquid/util-internal-http-server": "^1.2.2", + "@subsquid/util-naming": "^1.2.2", + "apollo-server-core": "^3.13.0", + "apollo-server-express": "^3.13.0", + "commander": "^11.1.0", + "deep-equal": "^2.2.3", "express": "^4.18.2", "graphql": "^15.8.0", - "graphql-parse-resolve-info": "^4.13.0", - "graphql-ws": "^5.14.1", + "graphql-parse-resolve-info": "^4.14.0", + "graphql-ws": "^5.14.2", "pg": "^8.11.3", "ws": "^8.14.2" }, @@ -2719,16 +2739,16 @@ } }, "node_modules/@subsquid/openreader/node_modules/@subsquid/util-internal": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-2.5.2.tgz", - "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal/-/util-internal-3.0.0.tgz", + "integrity": "sha512-aGPTiLF21N9f67DgHS4PBR8d6mdvXHTOIhr2mFQPX7GQCgZhNlCZDM/1Sqn+teJawCy3w6Y9f6KOtVbN4T5SFQ==" }, "node_modules/@subsquid/openreader/node_modules/@subsquid/util-internal-commander": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@subsquid/util-internal-commander/-/util-internal-commander-1.3.1.tgz", - "integrity": "sha512-KeGsOghBU20tM1BzqryOf3MKvrDFSfPuhnl9LhhEC00ysp8rRPyejlw6jIJhO2NRJ+oaUi5jHRdf64/o21N7Lw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-commander/-/util-internal-commander-1.3.2.tgz", + "integrity": "sha512-9/1vI1dmGQMp5wjN6hb94VCnSosT+caob33tAesFaIdqLzqQlDtlTSRq1TFFossAgtsEJFi7GiQ8i31L/gaxSQ==", "peerDependencies": { - "commander": "^11.0.0" + "commander": "^11.1.0" } }, "node_modules/@subsquid/openreader/node_modules/commander": { @@ -3125,14 +3145,14 @@ "integrity": "sha512-bc22t8lEvoCBn31F+B763E81+ZDaL7ufpwr0VLXZzcA5wZ6NEqqRfs4bJtPeBNGEjyeLLrItXWxfjSkR7sGKAg==" }, "node_modules/@subsquid/util-internal-hex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@subsquid/util-internal-hex/-/util-internal-hex-1.2.1.tgz", - "integrity": "sha512-R7TYDsftjguapzWia97WGvcF4s65VKArzSga5i1i4aZSq9Z330kPYpgAUkqDGsJqD/Ki3PTE4cXhuKLRyMHPvg==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-hex/-/util-internal-hex-1.2.2.tgz", + "integrity": "sha512-E43HVqf23jP5hvtWF9GsiN8luANjnJ1daR2SVTwaIUAYU/uNjv1Bi6tHz2uexlflBhyxAgBDmHgunXZ45wQTIw==" }, "node_modules/@subsquid/util-internal-http-server": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@subsquid/util-internal-http-server/-/util-internal-http-server-1.2.1.tgz", - "integrity": "sha512-aQIodM3xWDu8wxllOONU5Fy6hmYYAZzS2PglC2FfdUi6HUxaZ8aCUkjFisG56tglhsoAh/TQSQX1YhCX00MCcg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-http-server/-/util-internal-http-server-1.2.2.tgz", + "integrity": "sha512-B2SOSz8frUkXarbsELljew25iXFFyATEtS8NV31xKUXmhYfPklqrcF4YNJ/aLlfCtVOiR042YKVZDx2T8RbN6w==", "dependencies": { "stoppable": "^1.1.0" } @@ -3153,11 +3173,11 @@ "integrity": "sha512-N7lfZdWEkM35jG5wdGYx25TJKGGLMOx9VInSeRhW9T/3BEmHAuSWI2mIIYnZ8w5L041V8HGo61ijWF6qsXvZjg==" }, "node_modules/@subsquid/util-internal-json": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@subsquid/util-internal-json/-/util-internal-json-1.2.1.tgz", - "integrity": "sha512-Jtbhur/QaRk727fiZ/w8so0M0o4BIkfvnT6zBnC3s1mQ9fKve0Q6aj22gbimpX7Whj6tAGF0Bz8LFhbAethbkA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-json/-/util-internal-json-1.2.2.tgz", + "integrity": "sha512-+axQnlkIzscdy0T/vR1Dez/2NVCryWgB3OocMGJcx2GjhHVkmuJSLFqOdk9o90OocfQFC57NTZx22oa2yd+4Yw==", "dependencies": { - "@subsquid/util-internal-hex": "^1.2.1" + "@subsquid/util-internal-hex": "^1.2.2" } }, "node_modules/@subsquid/util-internal-processor-tools": { @@ -3209,10 +3229,15 @@ "integrity": "sha512-Fh7lGlIwFr88pJ39UdkDeQ2z8JEDk13OuoHJHTmgLtThI4kvmDSpVgMdIUUh9nrzFrP/rzlDsvjACTw4D/mTHw==", "dev": true }, + "node_modules/@subsquid/util-internal-ts-node": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@subsquid/util-internal-ts-node/-/util-internal-ts-node-0.0.0.tgz", + "integrity": "sha512-VBnrKrkNcqbT3hMLrjpEPuwMAihFhW9oUmK53bccBCCXrUiATNUblQD2S4IWd9/UBO5Q33ohpbE9sAodDq2DXw==" + }, "node_modules/@subsquid/util-naming": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@subsquid/util-naming/-/util-naming-1.2.1.tgz", - "integrity": "sha512-l5rvAXG7TxMPeB5kFTTZWisgN0DNe1mVBHT2V2/nxUx4sOfYfneWIN/+02YqJI/GHX9FoOTB6ru7WLfQEMhvhg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@subsquid/util-naming/-/util-naming-1.2.2.tgz", + "integrity": "sha512-NveXOiAbWiWkWd3Iv2jEwSAKvQHOG/HfIsPmmNab8TPX/XgJ6J5Ngx6lHEiqs746m4sOhZ2yipxKAEDgrERaxA==", "dependencies": { "camelcase": "^6.3.0", "inflected": "^2.1.0" @@ -3266,9 +3291,9 @@ } }, "node_modules/@types/accepts": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.6.tgz", - "integrity": "sha512-6+qlUg57yfE9OO63wnsJXLeq9cG3gSHBBIxNMOjNrbDRlDnm/NaR7RctfYcVCPq+j7d+MwOxqVEludH5+FKrlg==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==", "dependencies": { "@types/node": "*" } @@ -3332,9 +3357,9 @@ } }, "node_modules/@types/connect": { - "version": "3.4.37", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", - "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dependencies": { "@types/node": "*" } @@ -3375,9 +3400,9 @@ } }, "node_modules/@types/http-errors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", - "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", @@ -3415,9 +3440,9 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/mime": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.3.tgz", - "integrity": "sha512-i8MBln35l856k5iOhKk2XJ4SeAWg75mLIpZB4v6imOagKL6twsukBZGDMNhdOVk7yRFTMPpfILocMos59Q1otQ==" + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.4.tgz", + "integrity": "sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==" }, "node_modules/@types/node": { "version": "20.8.9", @@ -3434,14 +3459,14 @@ "dev": true }, "node_modules/@types/qs": { - "version": "6.9.9", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", - "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==" + "version": "6.9.11", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==" }, "node_modules/@types/range-parser": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", - "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "node_modules/@types/semver": { "version": "7.5.6", @@ -3450,9 +3475,9 @@ "dev": true }, "node_modules/@types/serve-static": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", - "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -4014,10 +4039,9 @@ "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" }, "node_modules/apollo-server-core": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-3.12.1.tgz", - "integrity": "sha512-9SF5WAkkV0FZQ2HVUWI9Jada1U0jg7e8NCN9EklbtvaCeUlOLyXyM+KCWuZ7+dqHxjshbtcwylPHutt3uzoNkw==", - "deprecated": "The `apollo-server-core` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-3.13.0.tgz", + "integrity": "sha512-v/g6DR6KuHn9DYSdtQijz8dLOkP78I5JSVJzPkARhDbhpH74QNwrQ2PP2URAPPEDJ2EeZNQDX8PvbYkAKqg+kg==", "dependencies": { "@apollo/utils.keyvaluecache": "^1.0.1", "@apollo/utils.logger": "^1.0.0", @@ -4150,10 +4174,9 @@ } }, "node_modules/apollo-server-express": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-3.12.1.tgz", - "integrity": "sha512-5A9efrhEXqDx08BnORWf0zPYCABENqur47VZZW8osQpSSnMINqzJiV5RMrzz8wIznecRRhEcz+BqLdiexqZdgg==", - "deprecated": "The `apollo-server-express` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-3.13.0.tgz", + "integrity": "sha512-iSxICNbDUyebOuM8EKb3xOrpIwOQgKxGbR2diSr4HP3IW8T3njKFOoMce50vr+moOCe1ev8BnLcw9SNbuUtf7g==", "dependencies": { "@types/accepts": "^1.3.5", "@types/body-parser": "1.19.2", @@ -4161,7 +4184,7 @@ "@types/express": "4.17.14", "@types/express-serve-static-core": "4.17.31", "accepts": "^1.3.5", - "apollo-server-core": "^3.12.1", + "apollo-server-core": "^3.13.0", "apollo-server-types": "^3.8.0", "body-parser": "^1.19.0", "cors": "^2.8.5", @@ -4893,6 +4916,17 @@ "node": ">= 0.10" } }, + "node_modules/cross-inspect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.0.tgz", + "integrity": "sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==", + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -5043,14 +5077,14 @@ "dev": true }, "node_modules/deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", "dependencies": { "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", @@ -5060,11 +5094,14 @@ "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", + "regexp.prototype.flags": "^1.5.1", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6267,9 +6304,9 @@ } }, "node_modules/graphql-parse-resolve-info": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/graphql-parse-resolve-info/-/graphql-parse-resolve-info-4.13.0.tgz", - "integrity": "sha512-VVJ1DdHYcR7hwOGQKNH+QTzuNgsLA8l/y436HtP9YHoX6nmwXRWq3xWthU3autMysXdm0fQUbhTZCx0W9ICozw==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/graphql-parse-resolve-info/-/graphql-parse-resolve-info-4.14.0.tgz", + "integrity": "sha512-5Fbquh3IZMciLYgtiWeFxAeZOwpPyonhbaN05fzL/Gll0HS0hMqJh1Q88NQLHiASD6//cJ3LTXLncuajRqsUcA==", "dependencies": { "debug": "^4.1.1", "tslib": "^2.0.1" @@ -8502,12 +8539,12 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, diff --git a/indexer/package.json b/indexer/package.json index d04dec5..6831e8a 100644 --- a/indexer/package.json +++ b/indexer/package.json @@ -9,13 +9,15 @@ "run": "sqd process", "migrations:generate": "sqd migration:generate", "migrations:apply": "sqd migration:apply", - "format": "prettier --write \"src/**/*.ts\"" + "serve": "squid-graphql-server serve", + "format": "prettier --write \"src/**/*.ts\"", + "start": "npm run migration:apply && node lib/main.js" }, "dependencies": { "@gear-js/api": "^0.35.2", "@polkadot/types": "10.10.1", "@subsquid/archive-registry": "^3.3.0", - "@subsquid/graphql-server": "^4.3.1", + "@subsquid/graphql-server": "^4.5.0", "@subsquid/ss58": "^2.0.1", "@subsquid/substrate-processor": "^7.2.1", "@subsquid/typeorm-migration": "^1.2.2", From f90af3065fc5e4bd0160acd18545ee9b815cd287 Mon Sep 17 00:00:00 2001 From: magorsky Date: Mon, 22 Jan 2024 17:18:08 +0300 Subject: [PATCH 08/50] add wf dirs --- .github/workflows/build-explorer-to-k8s.yml | 110 +++++++++++++++++++ .github/workflows/build-inxder-to-k8s.yml | 110 +++++++++++++++++++ .github/workflows/deploy-to-k8s.yml | 115 ++++++++++++++++++++ 3 files changed, 335 insertions(+) create mode 100644 .github/workflows/build-explorer-to-k8s.yml create mode 100644 .github/workflows/build-inxder-to-k8s.yml create mode 100644 .github/workflows/deploy-to-k8s.yml diff --git a/.github/workflows/build-explorer-to-k8s.yml b/.github/workflows/build-explorer-to-k8s.yml new file mode 100644 index 0000000..1d30d96 --- /dev/null +++ b/.github/workflows/build-explorer-to-k8s.yml @@ -0,0 +1,110 @@ +name: Explorer - Build and Deploy + +on: + workflow_dispatch: + push: + branches: ['master', 'main', 'staging'] + paths: + - indexer/** + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + ENVIRONMENT: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }} + KUBECTL_VERSION: 'v1.22.17' + KUBE_NAMESPACE: gear-dapps + KUBE_DEPLOYMENT_PREFIX: nft-marketplace-explorer + REGISTRY: ghcr.io/${{ github.repository }} + +jobs: + prepair: + runs-on: ubuntu-latest + outputs: + image_name: ${{ steps.image.outputs.image_name }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get branch + id: branch + run: | + branch_name=${GITHUB_REF#refs/heads/} + echo "branch_name=$branch_name" >> $GITHUB_ENV + + - name: Get short SHA + id: sha + run: | + sha_short=$(git rev-parse --short HEAD) + echo "sha_short=$sha_short" >> $GITHUB_ENV + + - name: Set IMAGE_NAME + id: image + run: | + image_name=${{ env.REGISTRY }}-${{ env.KUBE_DEPLOYMENT_PREFIX }}:${{ env.branch_name }}-${{ env.sha_short }} + echo "image_name=$image_name" >> $GITHUB_OUTPUT + + build-and-push-image: + needs: [prepair] + runs-on: ubuntu-latest + environment: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the github container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push image + uses: docker/build-push-action@v5 + with: + file: frontend/Dockerfile + push: true + tags: ${{ needs.prepair.outputs.image_name }} + + deploy-to-k8s: + needs: [prepair, build-and-push-image] + runs-on: ubuntu-latest + environment: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Update deployment image + uses: kodermax/kubectl-aws-eks@main + with: + args: | + set image deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + ${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }}=${{ needs.prepair.outputs.image_name }} \ + -n ${{ env.KUBE_NAMESPACE }} + + - name: Restart deployment + uses: kodermax/kubectl-aws-eks@main + with: + args: | + rollout restart deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + -n ${{ env.KUBE_NAMESPACE }} + + - name: Check deployment + uses: kodermax/kubectl-aws-eks@main + with: + args: | + rollout status deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + --timeout=240s \ + -n ${{ env.KUBE_NAMESPACE }} diff --git a/.github/workflows/build-inxder-to-k8s.yml b/.github/workflows/build-inxder-to-k8s.yml new file mode 100644 index 0000000..f2b50c9 --- /dev/null +++ b/.github/workflows/build-inxder-to-k8s.yml @@ -0,0 +1,110 @@ +name: Indexer - Build and Deploy + +on: + workflow_dispatch: + push: + branches: ['master', 'main', 'staging'] + paths: + - indexer/** + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + ENVIRONMENT: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }} + KUBECTL_VERSION: 'v1.22.17' + KUBE_NAMESPACE: gear-dapps + KUBE_DEPLOYMENT_PREFIX: nft-marketplace-indexer + REGISTRY: ghcr.io/${{ github.repository }} + +jobs: + prepair: + runs-on: ubuntu-latest + outputs: + image_name: ${{ steps.image.outputs.image_name }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get branch + id: branch + run: | + branch_name=${GITHUB_REF#refs/heads/} + echo "branch_name=$branch_name" >> $GITHUB_ENV + + - name: Get short SHA + id: sha + run: | + sha_short=$(git rev-parse --short HEAD) + echo "sha_short=$sha_short" >> $GITHUB_ENV + + - name: Set IMAGE_NAME + id: image + run: | + image_name=${{ env.REGISTRY }}-${{ env.KUBE_DEPLOYMENT_PREFIX }}:${{ env.branch_name }}-${{ env.sha_short }} + echo "image_name=$image_name" >> $GITHUB_OUTPUT + + build-and-push-image: + needs: [prepair] + runs-on: ubuntu-latest + environment: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the github container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push image + uses: docker/build-push-action@v5 + with: + file: frontend/Dockerfile + push: true + tags: ${{ needs.prepair.outputs.image_name }} + + deploy-to-k8s: + needs: [prepair, build-and-push-image] + runs-on: ubuntu-latest + environment: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Update deployment image + uses: kodermax/kubectl-aws-eks@main + with: + args: | + set image deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + ${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }}=${{ needs.prepair.outputs.image_name }} \ + -n ${{ env.KUBE_NAMESPACE }} + + - name: Restart deployment + uses: kodermax/kubectl-aws-eks@main + with: + args: | + rollout restart deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + -n ${{ env.KUBE_NAMESPACE }} + + - name: Check deployment + uses: kodermax/kubectl-aws-eks@main + with: + args: | + rollout status deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + --timeout=240s \ + -n ${{ env.KUBE_NAMESPACE }} diff --git a/.github/workflows/deploy-to-k8s.yml b/.github/workflows/deploy-to-k8s.yml new file mode 100644 index 0000000..40d38d8 --- /dev/null +++ b/.github/workflows/deploy-to-k8s.yml @@ -0,0 +1,115 @@ +name: Build and Deploy NFT Marketplace + +on: + workflow_dispatch: + push: + branches: ['master', 'main', 'staging'] + paths: + - frontend/** + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + ENVIRONMENT: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }} + KUBECTL_VERSION: 'v1.22.17' + KUBE_NAMESPACE: gear-dapps + KUBE_DEPLOYMENT_PREFIX: nft-marketplace-new + REGISTRY: ghcr.io/${{ github.repository }} + +jobs: + prepair: + runs-on: ubuntu-latest + outputs: + image_name: ${{ steps.image.outputs.image_name }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get branch + id: branch + run: | + branch_name=${GITHUB_REF#refs/heads/} + echo "branch_name=$branch_name" >> $GITHUB_ENV + + - name: Get short SHA + id: sha + run: | + sha_short=$(git rev-parse --short HEAD) + echo "sha_short=$sha_short" >> $GITHUB_ENV + + - name: Set IMAGE_NAME + id: image + run: | + image_name=${{ env.REGISTRY }}-${{ env.KUBE_DEPLOYMENT_PREFIX }}:${{ env.branch_name }}-${{ env.sha_short }} + echo "image_name=$image_name" >> $GITHUB_OUTPUT + + build-and-push-image: + needs: [prepair] + runs-on: ubuntu-latest + environment: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the github container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push image + uses: docker/build-push-action@v5 + with: + file: frontend/Dockerfile + push: true + tags: ${{ needs.prepair.outputs.image_name }} + build-args: | + VITE_NODE_ADDRESS=${{ secrets.VITE_NODE_ADDRESS }} + VITE_IPFS_ADDRESS=${{ secrets.VITE_IPFS_ADDRESS }} + VITE_IPFS_GATEWAY_ADDRESS=${{ secrets.VITE_IPFS_GATEWAY_ADDRESS }} + VITE_CONTRACT_ADDRESS=${{ secrets.VITE_CONTRACT_ADDRESS }} + + deploy-to-k8s: + needs: [prepair, build-and-push-image] + runs-on: ubuntu-latest + environment: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && 'prod' || 'stg' }} + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Update deployment image + uses: kodermax/kubectl-aws-eks@main + with: + args: | + set image deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + ${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }}=${{ needs.prepair.outputs.image_name }} \ + -n ${{ env.KUBE_NAMESPACE }} + + - name: Restart deployment + uses: kodermax/kubectl-aws-eks@main + with: + args: | + rollout restart deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + -n ${{ env.KUBE_NAMESPACE }} + + - name: Check deployment + uses: kodermax/kubectl-aws-eks@main + with: + args: | + rollout status deployment/${{ env.KUBE_DEPLOYMENT_PREFIX }}-${{ env.ENVIRONMENT }} \ + --timeout=240s \ + -n ${{ env.KUBE_NAMESPACE }} From 4d8b8546c8ed9ac391f82cefdf9ba2f273a331dc Mon Sep 17 00:00:00 2001 From: magorsky Date: Mon, 22 Jan 2024 17:21:42 +0300 Subject: [PATCH 09/50] fix wf --- .github/workflows/build-explorer-to-k8s.yml | 2 +- .../{build-inxder-to-k8s.yml => build-indexer-to-k8s.yml} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{build-inxder-to-k8s.yml => build-indexer-to-k8s.yml} (98%) diff --git a/.github/workflows/build-explorer-to-k8s.yml b/.github/workflows/build-explorer-to-k8s.yml index 1d30d96..30bf024 100644 --- a/.github/workflows/build-explorer-to-k8s.yml +++ b/.github/workflows/build-explorer-to-k8s.yml @@ -70,7 +70,7 @@ jobs: - name: Build and push image uses: docker/build-push-action@v5 with: - file: frontend/Dockerfile + file: indexer/Dockerfile-explorer push: true tags: ${{ needs.prepair.outputs.image_name }} diff --git a/.github/workflows/build-inxder-to-k8s.yml b/.github/workflows/build-indexer-to-k8s.yml similarity index 98% rename from .github/workflows/build-inxder-to-k8s.yml rename to .github/workflows/build-indexer-to-k8s.yml index f2b50c9..000fd4c 100644 --- a/.github/workflows/build-inxder-to-k8s.yml +++ b/.github/workflows/build-indexer-to-k8s.yml @@ -70,7 +70,7 @@ jobs: - name: Build and push image uses: docker/build-push-action@v5 with: - file: frontend/Dockerfile + file: indexer/Dockerfile-indexer push: true tags: ${{ needs.prepair.outputs.image_name }} From e129ae594d09e25781fb1691f85255b2fb818b5d Mon Sep 17 00:00:00 2001 From: magorsky Date: Mon, 22 Jan 2024 17:30:42 +0300 Subject: [PATCH 10/50] fix --- .github/workflows/build-explorer-to-k8s.yml | 1 + .github/workflows/build-indexer-to-k8s.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/build-explorer-to-k8s.yml b/.github/workflows/build-explorer-to-k8s.yml index 30bf024..abf8ca8 100644 --- a/.github/workflows/build-explorer-to-k8s.yml +++ b/.github/workflows/build-explorer-to-k8s.yml @@ -70,6 +70,7 @@ jobs: - name: Build and push image uses: docker/build-push-action@v5 with: + context: indexer file: indexer/Dockerfile-explorer push: true tags: ${{ needs.prepair.outputs.image_name }} diff --git a/.github/workflows/build-indexer-to-k8s.yml b/.github/workflows/build-indexer-to-k8s.yml index 000fd4c..ebbf389 100644 --- a/.github/workflows/build-indexer-to-k8s.yml +++ b/.github/workflows/build-indexer-to-k8s.yml @@ -70,6 +70,7 @@ jobs: - name: Build and push image uses: docker/build-push-action@v5 with: + context: indexer file: indexer/Dockerfile-indexer push: true tags: ${{ needs.prepair.outputs.image_name }} From 0af25c94f7393696e9e2fbd3424673b5710fbd6c Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 22 Jan 2024 20:27:12 +0300 Subject: [PATCH 11/50] fix dockerfile --- indexer/Dockerfile-explorer | 5 +++-- indexer/Dockerfile-indexer | 45 ++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/indexer/Dockerfile-explorer b/indexer/Dockerfile-explorer index d0c17ab..1f10fee 100644 --- a/indexer/Dockerfile-explorer +++ b/indexer/Dockerfile-explorer @@ -20,7 +20,10 @@ WORKDIR /squid ADD package.json . ADD package-lock.json . RUN npm ci --production + FROM node AS squid +RUN npm i -g @subsquid/cli@latest +RUN echo -e "loglevel=silent\\nupdate-notifier=false" > /squid/.npmrc WORKDIR /squid COPY --from=deps /squid/package.json . COPY --from=deps /squid/package-lock.json . @@ -34,7 +37,5 @@ COPY --from=builder /squid/db db COPY --from=builder /squid/schema.graphql schema.graphql # remove if no commands.json is in the root ADD commands.json . -RUN echo -e "loglevel=silent\\nupdate-notifier=false" > /squid/.npmrc -RUN npm i -g @subsquid/commands && mv $(which squid-commands) /usr/local/bin/sqd ENV PROCESSOR_PROMETHEUS_PORT 3000 CMD ["npm", "run", "serve"] diff --git a/indexer/Dockerfile-indexer b/indexer/Dockerfile-indexer index 97e5e26..4fff97e 100644 --- a/indexer/Dockerfile-indexer +++ b/indexer/Dockerfile-indexer @@ -1,8 +1,41 @@ -FROM node:20-alpine - -WORKDIR /app -COPY . . -RUN npm install +FROM node:16-alpine AS node +FROM node AS node-with-gyp +RUN apk add g++ make python3 +FROM node-with-gyp AS builder +WORKDIR /squid +ADD package.json . +ADD package-lock.json . +# remove if needed +ADD assets assets +# remove if needed +ADD db db +# remove if needed +ADD schema.graphql . +RUN npm ci +ADD tsconfig.json . +ADD src src RUN npm run build +FROM node-with-gyp AS deps +WORKDIR /squid +ADD package.json . +ADD package-lock.json . +RUN npm ci --production -CMD ["npm", "start"] +FROM node AS squid +WORKDIR /squid +RUN npm i -g @subsquid/cli@latest +RUN echo -e "loglevel=silent\\nupdate-notifier=false" > /squid/.npmrc +COPY --from=deps /squid/package.json . +COPY --from=deps /squid/package-lock.json . +COPY --from=deps /squid/node_modules node_modules +COPY --from=builder /squid/lib lib +# remove if no assets folder +COPY --from=builder /squid/assets assets +# remove if no db folder +COPY --from=builder /squid/db db +# remove if no schema.graphql is in the root +COPY --from=builder /squid/schema.graphql schema.graphql +# remove if no commands.json is in the root +ADD commands.json . +ENV PROCESSOR_PROMETHEUS_PORT 3000 +CMD ["sqd", "process"] From 4ff2978bf0692b6ce4510b8fc14bf3c5601d8651 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 22 Jan 2024 23:01:45 +0300 Subject: [PATCH 12/50] fix dockerfile --- indexer/Dockerfile-explorer | 1 + indexer/Dockerfile-indexer | 26 +++----------------------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/indexer/Dockerfile-explorer b/indexer/Dockerfile-explorer index 1f10fee..229f492 100644 --- a/indexer/Dockerfile-explorer +++ b/indexer/Dockerfile-explorer @@ -15,6 +15,7 @@ RUN npm ci ADD tsconfig.json . ADD src src RUN npm run build + FROM node-with-gyp AS deps WORKDIR /squid ADD package.json . diff --git a/indexer/Dockerfile-indexer b/indexer/Dockerfile-indexer index 4fff97e..442e947 100644 --- a/indexer/Dockerfile-indexer +++ b/indexer/Dockerfile-indexer @@ -1,41 +1,21 @@ FROM node:16-alpine AS node -FROM node AS node-with-gyp RUN apk add g++ make python3 -FROM node-with-gyp AS builder +RUN npm i -g @subsquid/cli@latest +RUN npm i -g typescript@5.2.2 WORKDIR /squid ADD package.json . ADD package-lock.json . +RUN npm i @types/node # remove if needed ADD assets assets # remove if needed ADD db db # remove if needed ADD schema.graphql . -RUN npm ci ADD tsconfig.json . ADD src src RUN npm run build -FROM node-with-gyp AS deps -WORKDIR /squid -ADD package.json . -ADD package-lock.json . -RUN npm ci --production -FROM node AS squid -WORKDIR /squid -RUN npm i -g @subsquid/cli@latest -RUN echo -e "loglevel=silent\\nupdate-notifier=false" > /squid/.npmrc -COPY --from=deps /squid/package.json . -COPY --from=deps /squid/package-lock.json . -COPY --from=deps /squid/node_modules node_modules -COPY --from=builder /squid/lib lib -# remove if no assets folder -COPY --from=builder /squid/assets assets -# remove if no db folder -COPY --from=builder /squid/db db -# remove if no schema.graphql is in the root -COPY --from=builder /squid/schema.graphql schema.graphql -# remove if no commands.json is in the root ADD commands.json . ENV PROCESSOR_PROMETHEUS_PORT 3000 CMD ["sqd", "process"] From 78a49dcc733219d40a22e52e9e1b319b3b79e2c8 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 2 Feb 2024 10:52:54 +0300 Subject: [PATCH 13/50] fix review comments --- indexer/.github/ISSUE_TEMPLATE/bug_report.md | 45 -------------------- indexer/src/main.ts | 6 ++- indexer/src/processing/event-info.type.ts | 1 + indexer/src/processing/events.processing.ts | 28 ++++++------ 4 files changed, 19 insertions(+), 61 deletions(-) delete mode 100644 indexer/.github/ISSUE_TEMPLATE/bug_report.md diff --git a/indexer/.github/ISSUE_TEMPLATE/bug_report.md b/indexer/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index bf3db9c..0000000 --- a/indexer/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Environment (please complete the following information):** - - specify the version of the core packages (@subsquid/cli, @subsquid/substrate-processor, ...) - - node.js version - - npm version - - OS version - - Reproducible example or a repo link - -**Applicable to decoding issues:** - - chain name - - typesBundle (if it's not built-in) -optional: - - block - - extrinsic - - call - - event - - spec version - - endpoint - -**Additional context** -Add any other context about the problem here. diff --git a/indexer/src/main.ts b/indexer/src/main.ts index a497425..1e29587 100644 --- a/indexer/src/main.ts +++ b/indexer/src/main.ts @@ -36,7 +36,8 @@ processor.run(new TypeormDatabase(), async (ctx) => { `[main] start processing ${ctx.blocks.length} blocks at ${firstBlockDate}.`, ); for (const block of ctx.blocks) { - const events = block.events.filter((e) => e.args && e.args.message); + const { events } = block; + const timestamp = getBlockDate(block); for (const item of events) { const { message: { source, payload, details, destination, id }, @@ -51,7 +52,8 @@ processor.run(new TypeormDatabase(), async (ctx) => { blockNumber: block.header.height, destination, source, - timestamp: getBlockDate(block), + timestamp, + messageId: id, txHash: id, }; if (config.marketplaceProgram === source) { diff --git a/indexer/src/processing/event-info.type.ts b/indexer/src/processing/event-info.type.ts index 63711f8..a15ff6c 100644 --- a/indexer/src/processing/event-info.type.ts +++ b/indexer/src/processing/event-info.type.ts @@ -2,6 +2,7 @@ export type EventInfo = { blockNumber: number; source: string; destination: string; + messageId: string; txHash: string; timestamp: Date; }; diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index 89d09bf..7506c34 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -99,9 +99,9 @@ export class EventsProcessing { payload: string, eventInfo: EventInfo, ): Promise { - const { blockNumber, txHash } = eventInfo; + const { blockNumber, messageId } = eventInfo; try { - console.log(`${blockNumber}-${txHash}: handling marketplace event`); + console.log(`${blockNumber}-${messageId}: handling marketplace event`); const data = marketplaceMeta.createType( marketplaceMeta.types.handle.output!, payload, @@ -112,10 +112,10 @@ export class EventsProcessing { } const event = getMarketplaceEvent(parsed.ok); if (!event) { - console.warn(`${blockNumber}-${txHash}: unknown event type`, parsed); + console.warn(`${blockNumber}-${messageId}: unknown event type`, parsed); return null; } - console.log(`${blockNumber}-${txHash}: detected event: ${event.type}`); + console.log(`${blockNumber}-${messageId}: detected event: ${event.type}`); this.entitiesService .addEvent({ blockNumber: eventInfo.blockNumber, @@ -125,12 +125,12 @@ export class EventsProcessing { txHash: eventInfo.txHash, }) .catch((err) => - console.error(`${blockNumber}-${txHash}: error adding event`, err), + console.error(`${blockNumber}-${messageId}: error adding event`, err), ); const eventHandler = marketplaceEventsToHandler[event.type]; if (!eventHandler) { console.warn( - `${blockNumber}-${txHash}: no event handlers found for ${event.type}`, + `${blockNumber}-${messageId}: no event handlers found for ${event.type}`, ); return null; } @@ -138,7 +138,7 @@ export class EventsProcessing { return event; } catch (e) { console.error( - `${blockNumber}-${txHash}: error handling marketplace event`, + `${blockNumber}-${messageId}: error handling marketplace event`, e, ); return null; @@ -149,9 +149,9 @@ export class EventsProcessing { payload: string, eventInfo: EventInfo, ): Promise { - const { blockNumber, txHash } = eventInfo; + const { blockNumber, messageId } = eventInfo; try { - console.log(`${blockNumber}-${txHash}: handling nft event`); + console.log(`${blockNumber}-${messageId}: handling nft event`); const data = nftMeta.createType( // @ts-ignore nftMeta.types.handle.output!, @@ -160,7 +160,7 @@ export class EventsProcessing { const parsed = data.toJSON() as { ok: NftEventPlain } | null; if (!parsed || !parsed.ok) { console.warn( - `${blockNumber}-${txHash}: failed to parse event`, + `${blockNumber}-${messageId}: failed to parse event`, parsed, payload, ); @@ -169,16 +169,16 @@ export class EventsProcessing { const event = getNftEvent(parsed.ok); if (!event) { console.warn( - `${blockNumber}-${txHash}: unknown nft event type`, + `${blockNumber}-${messageId}: unknown nft event type`, parsed, ); return null; } - console.log(`${blockNumber}-${txHash}: detected event: ${event.type}`); + console.log(`${blockNumber}-${messageId}: detected event: ${event.type}`); const eventHandler = nftEventsToHandler[event.type]; if (!eventHandler) { console.warn( - `${blockNumber}-${txHash}: no nft event handlers found for ${event.type}`, + `${blockNumber}-${messageId}: no nft event handlers found for ${event.type}`, ); return null; } @@ -186,7 +186,7 @@ export class EventsProcessing { return event; } catch (e) { console.error( - `${blockNumber}-${txHash}: error handling nft event`, + `${blockNumber}-${messageId}: error handling nft event`, e, payload, ); From 6ded52bd086ab49bb3b29196d25a6db1c40d2718 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 5 Feb 2024 10:14:15 +0300 Subject: [PATCH 14/50] fix save nft --- indexer/src/processing/nft/nft-minted.handler.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/indexer/src/processing/nft/nft-minted.handler.ts b/indexer/src/processing/nft/nft-minted.handler.ts index 78f2588..c2b55d9 100644 --- a/indexer/src/processing/nft/nft-minted.handler.ts +++ b/indexer/src/processing/nft/nft-minted.handler.ts @@ -1,7 +1,7 @@ import { MintedEvent } from '../../types/nft.events'; import { EntitiesService } from '../entities.service'; import { INftEventHandler } from './nft.handler'; -import { Nft } from '../../model'; +import { Nft, Offer } from '../../model'; import { EventInfo } from '../event-info.type'; export class NftMintedHandler implements INftEventHandler { @@ -28,7 +28,13 @@ export class NftMintedHandler implements INftEventHandler { mediaUrl, name, owner, + metadata: JSON.stringify(metadata), + onSale: false, createdAt: timestamp, + sales: [], + offers: [], + transfers: [], + auctions: [], }), ); } From 420de4690e80fd7d6a50447f674013e2ac3b0178 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 5 Feb 2024 10:50:59 +0300 Subject: [PATCH 15/50] fix save nft --- indexer/src/processing/nft/nft-minted.handler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/indexer/src/processing/nft/nft-minted.handler.ts b/indexer/src/processing/nft/nft-minted.handler.ts index c2b55d9..6d796a2 100644 --- a/indexer/src/processing/nft/nft-minted.handler.ts +++ b/indexer/src/processing/nft/nft-minted.handler.ts @@ -31,6 +31,7 @@ export class NftMintedHandler implements INftEventHandler { metadata: JSON.stringify(metadata), onSale: false, createdAt: timestamp, + updatedAt: timestamp, sales: [], offers: [], transfers: [], From fb89a5b4b175d4ad562268f6c4f82d1b1f01e955 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Wed, 7 Feb 2024 15:50:53 +0300 Subject: [PATCH 16/50] fix auction and saled --- indexer/assets/nft.meta.txt | 2 +- indexer/src/processing/batch.service.ts | 1 + indexer/src/processing/events.processing.ts | 6 +++++- .../src/processing/marketplace/auction-created.handler.ts | 1 + indexer/src/processing/marketplace/nft-sold.handler.ts | 6 +++++- .../src/processing/marketplace/sale-nft-canceled.handler.ts | 6 +++++- indexer/src/processing/marketplace/sale-nft.handler.ts | 6 +++++- indexer/src/processing/storage/local.storage.ts | 1 + 8 files changed, 24 insertions(+), 5 deletions(-) diff --git a/indexer/assets/nft.meta.txt b/indexer/assets/nft.meta.txt index 9b5200c..6507aba 100644 --- a/indexer/assets/nft.meta.txt +++ b/indexer/assets/nft.meta.txt @@ -1 +1 @@ -0002000100000000000117000000011800000000000000011e000000011f000000f92da00008186e66745f696f1c4e6674496e697400000c0140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000118636f6e666967100118436f6e666967000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e00000410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004000801205b75383b2033325d000008000003200000000c000c00000503001008186e66745f696f18436f6e66696700002c01106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e6700013c636f6c6c656374696f6e5f7461677318012c5665633c537472696e673e000144636f6c6c656374696f6e5f62616e6e6572140118537472696e6700013c636f6c6c656374696f6e5f6c6f676f140118537472696e6700013c757365725f6d696e745f6c696d69741c012c4f7074696f6e3c7533323e0001406164646974696f6e616c5f6c696e6b7324015c4f7074696f6e3c4164646974696f6e616c4c696e6b733e00011c726f79616c747930010c7531360001407061796d656e745f666f725f6d696e74340110753132380001307472616e7366657261626c6538012c4f7074696f6e3c7536343e00012073656c6c61626c6538012c4f7074696f6e3c7536343e00001400000502001800000214001c04184f7074696f6e04045401200108104e6f6e6500000010536f6d6504002000000100002000000505002404184f7074696f6e04045401280108104e6f6e6500000010536f6d6504002800000100002808186e66745f696f3c4164646974696f6e616c4c696e6b73000014013065787465726e616c5f75726c2c01384f7074696f6e3c537472696e673e00012074656c656772616d2c01384f7074696f6e3c537472696e673e00011078636f6d2c01384f7074696f6e3c537472696e673e0001186d656469756d2c01384f7074696f6e3c537472696e673e00011c646973636f72642c01384f7074696f6e3c537472696e673e00002c04184f7074696f6e04045401140108104e6f6e6500000010536f6d6504001400000100003000000504003400000507003804184f7074696f6e040454013c0108104e6f6e6500000010536f6d6504003c00000100003c000005060040000002440044000004081448004808186e66745f696f24496d6167654461746100000801306c696d69745f636f706965731c012c4f7074696f6e3c7533323e00014c6175746f5f6368616e67696e675f72756c65734c01784f7074696f6e3c5665633c2854696d655365632c20416374696f6e293e3e00004c04184f7074696f6e04045401500108104e6f6e6500000010536f6d65040050000001000050000002540054000004082058005808186e66745f696f18416374696f6e000108244368616e6765496d670400140118537472696e670000001c4164644d6574610400140118537472696e67000100005c08186e66745f696f244e6674416374696f6e00012c205472616e73666572080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000000305472616e7366657246726f6d0c011066726f6d04011c4163746f724964000108746f04011c4163746f724964000120746f6b656e5f69643c01144e6674496400010030476574546f6b656e496e666f040120746f6b656e5f69643c01144e667449640002002443616e44656c657465000300104d696e740004001c417070726f7665080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000500385265766f6b65417070726f76616c040120746f6b656e5f69643c01144e6674496400060018457870616e640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000700304368616e6765436f6e666967040118636f6e666967100118436f6e666967000800244368616e6765496d67080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e670009002c4164644d65746164617461080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a0000600418526573756c740804540164044501740108084f6b040064000000000c45727204007400000100006408186e66745f696f204e66744576656e7400012c2c5472616e736665727265640c01146f776e657204011c4163746f724964000124726563697069656e7404011c4163746f724964000120746f6b656e5f69643c01144e6674496400000044546f6b656e496e666f526563656976656414012c746f6b656e5f6f776e657204011c4163746f724964000120617070726f76616c68013c4f7074696f6e3c4163746f7249643e00012073656c6c61626c656c0110626f6f6c000140636f6c6c656374696f6e5f6f776e657204011c4163746f72496400011c726f79616c747930010c7531360001002443616e44656c65746504006c0110626f6f6c0002002c496e697469616c697a6564040118636f6e666967100118436f6e666967000300184d696e746564080120746f6b656e5f69643c01144e667449640001206e66745f6461746170010c4e667400040020417070726f766564080108746f04011c4163746f724964000120746f6b656e5f69643c01144e667449640005003c417070726f76616c5265766f6b6564040120746f6b656e5f69643c01144e6674496400060020457870616e6465640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e00070034436f6e6669674368616e676564040118636f6e666967100118436f6e66696700080030496d6167654368616e676564080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e67000900344d657461646174614164646564080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a00006804184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100006c00000500007008186e66745f696f0c4e667400001801146f776e657204011c4163746f7249640001106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e670001206d6574616461746118012c5665633c537472696e673e0001246d656469615f75726c140118537472696e670001246d696e745f74696d653c010c75363400007408186e66745f696f204e66744572726f7200000400140118537472696e6700007808186e66745f696f2853746174655175657279000110104e616d650000002c4465736372697074696f6e00010018436f6e6669670002000c416c6c000300007c08186e66745f696f2853746174655265706c79000110104e616d650400140118537472696e670000002c4465736372697074696f6e0400140118537472696e6700010018436f6e6669670400100118436f6e6669670002000c416c6c04008001204e66745374617465000300008008186e66745f696f204e667453746174650000200118746f6b656e738401445665633c284e667449642c204e6674293e0001186f776e6572738c01685665633c284163746f7249642c205665633c4e667449643e293e00013c746f6b656e5f617070726f76616c739801545665633c284e667449642c204163746f724964293e000118636f6e666967100118436f6e6669670001146e6f6e63653c01144e66744964000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e000140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e000084000002880088000004083c70008c00000290009000000408049400940000023c00980000029c009c000004083c0400 \ No newline at end of file +0002000100000000000117000000011800000000000000011e000000011f000000312fa00008186e66745f696f1c4e6674496e697400000c0140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000118636f6e666967100118436f6e666967000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e00000410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004000801205b75383b2033325d000008000003200000000c000c00000503001008186e66745f696f18436f6e66696700002c01106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e6700013c636f6c6c656374696f6e5f7461677318012c5665633c537472696e673e000144636f6c6c656374696f6e5f62616e6e6572140118537472696e6700013c636f6c6c656374696f6e5f6c6f676f140118537472696e6700013c757365725f6d696e745f6c696d69741c012c4f7074696f6e3c7533323e0001406164646974696f6e616c5f6c696e6b7324015c4f7074696f6e3c4164646974696f6e616c4c696e6b733e00011c726f79616c747930010c7531360001407061796d656e745f666f725f6d696e74340110753132380001307472616e7366657261626c6538012c4f7074696f6e3c7536343e00012073656c6c61626c6538012c4f7074696f6e3c7536343e00001400000502001800000214001c04184f7074696f6e04045401200108104e6f6e6500000010536f6d6504002000000100002000000505002404184f7074696f6e04045401280108104e6f6e6500000010536f6d6504002800000100002808186e66745f696f3c4164646974696f6e616c4c696e6b73000014013065787465726e616c5f75726c2c01384f7074696f6e3c537472696e673e00012074656c656772616d2c01384f7074696f6e3c537472696e673e00011078636f6d2c01384f7074696f6e3c537472696e673e0001186d656469756d2c01384f7074696f6e3c537472696e673e00011c646973636f72642c01384f7074696f6e3c537472696e673e00002c04184f7074696f6e04045401140108104e6f6e6500000010536f6d6504001400000100003000000504003400000507003804184f7074696f6e040454013c0108104e6f6e6500000010536f6d6504003c00000100003c000005060040000002440044000004081448004808186e66745f696f24496d6167654461746100000801306c696d69745f636f706965731c012c4f7074696f6e3c7533323e00014c6175746f5f6368616e67696e675f72756c65734c01784f7074696f6e3c5665633c2854696d655365632c20416374696f6e293e3e00004c04184f7074696f6e04045401500108104e6f6e6500000010536f6d65040050000001000050000002540054000004082058005808186e66745f696f18416374696f6e000108244368616e6765496d670400140118537472696e670000001c4164644d6574610400140118537472696e67000100005c08186e66745f696f244e6674416374696f6e00012c205472616e73666572080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000000305472616e7366657246726f6d0c011066726f6d04011c4163746f724964000108746f04011c4163746f724964000120746f6b656e5f69643c01144e6674496400010030476574546f6b656e496e666f040120746f6b656e5f69643c01144e667449640002002443616e44656c657465000300104d696e740004001c417070726f7665080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000500385265766f6b65417070726f76616c040120746f6b656e5f69643c01144e6674496400060018457870616e640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000700304368616e6765436f6e666967040118636f6e666967100118436f6e666967000800244368616e6765496d67080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e670009002c4164644d65746164617461080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a0000600418526573756c740804540164044501740108084f6b040064000000000c45727204007400000100006408186e66745f696f204e66744576656e7400012c2c5472616e736665727265640c01146f776e657204011c4163746f724964000124726563697069656e7404011c4163746f724964000120746f6b656e5f69643c01144e6674496400000044546f6b656e496e666f526563656976656414012c746f6b656e5f6f776e657204011c4163746f724964000120617070726f76616c68013c4f7074696f6e3c4163746f7249643e00012073656c6c61626c656c0110626f6f6c000140636f6c6c656374696f6e5f6f776e657204011c4163746f72496400011c726f79616c747930010c7531360001002443616e44656c65746504006c0110626f6f6c0002002c496e697469616c697a6564080118636f6e666967100118436f6e666967000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e000300184d696e746564080120746f6b656e5f69643c01144e667449640001206e66745f6461746170010c4e667400040020417070726f766564080108746f04011c4163746f724964000120746f6b656e5f69643c01144e667449640005003c417070726f76616c5265766f6b6564040120746f6b656e5f69643c01144e6674496400060020457870616e6465640801406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e00070034436f6e6669674368616e676564040118636f6e666967100118436f6e66696700080030496d6167654368616e676564080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e67000900344d657461646174614164646564080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a00006804184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100006c00000500007008186e66745f696f0c4e667400001801146f776e657204011c4163746f7249640001106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e670001206d6574616461746118012c5665633c537472696e673e0001246d656469615f75726c140118537472696e670001246d696e745f74696d653c010c75363400007408186e66745f696f204e66744572726f7200000400140118537472696e6700007808186e66745f696f2853746174655175657279000110104e616d650000002c4465736372697074696f6e00010018436f6e6669670002000c416c6c000300007c08186e66745f696f2853746174655265706c79000110104e616d650400140118537472696e670000002c4465736372697074696f6e0400140118537472696e6700010018436f6e6669670400100118436f6e6669670002000c416c6c04008001204e66745374617465000300008008186e66745f696f204e667453746174650000200118746f6b656e738401445665633c284e667449642c204e6674293e0001186f776e6572738c01685665633c284163746f7249642c205665633c4e667449643e293e00013c746f6b656e5f617070726f76616c739801545665633c284e667449642c204163746f724964293e000118636f6e666967100118436f6e6669670001146e6f6e63653c01144e66744964000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e000140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e000084000002880088000004083c70008c00000290009000000408049400940000023c00980000029c009c000004083c0400 diff --git a/indexer/src/processing/batch.service.ts b/indexer/src/processing/batch.service.ts index 1ace1e1..b8c8b69 100644 --- a/indexer/src/processing/batch.service.ts +++ b/indexer/src/processing/batch.service.ts @@ -41,6 +41,7 @@ export class BatchService { ]).catch((err) => { console.error('Error saving batch', err); }); + this.clearAll(); } clearAll() { diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index 7506c34..734f834 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -121,7 +121,11 @@ export class EventsProcessing { blockNumber: eventInfo.blockNumber, timestamp: eventInfo.timestamp, type: event.type, - raw: JSON.stringify(event), + raw: JSON.stringify(event, (key, value) => + typeof value === 'bigint' + ? value.toString() + : value // return everything else unchanged + ), txHash: eventInfo.txHash, }) .catch((err) => diff --git a/indexer/src/processing/marketplace/auction-created.handler.ts b/indexer/src/processing/marketplace/auction-created.handler.ts index 01f36e8..1873052 100644 --- a/indexer/src/processing/marketplace/auction-created.handler.ts +++ b/indexer/src/processing/marketplace/auction-created.handler.ts @@ -44,6 +44,7 @@ export class AuctionCreatedHandler implements INftMarketplaceEventHandler { status: SaleStatus.Open, blockNumber: eventInfo.blockNumber, timestamp: eventInfo.timestamp, + updatedAt: eventInfo.timestamp, }), ); } diff --git a/indexer/src/processing/marketplace/nft-sold.handler.ts b/indexer/src/processing/marketplace/nft-sold.handler.ts index 70a4db0..22b43ed 100644 --- a/indexer/src/processing/marketplace/nft-sold.handler.ts +++ b/indexer/src/processing/marketplace/nft-sold.handler.ts @@ -1,7 +1,7 @@ import { NftSold } from '../../types/marketplace.events'; import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { Sale } from '../../model'; +import { Nft, Sale } from '../../model'; import { SaleStatus } from '../../model/types'; import { EventInfo } from '../event-info.type'; @@ -44,5 +44,9 @@ export class NftSoldHandler implements INftMarketplaceEventHandler { updatedAt: eventInfo.timestamp, }), ); + await storage.setNft(new Nft({ + ...nft, + onSale: false, + })); } } diff --git a/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts b/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts index 63b56b5..376e7ee 100644 --- a/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts +++ b/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts @@ -2,7 +2,7 @@ import { AuctionCanceled } from '../../types/marketplace.events'; import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { AuctionStatus, SaleStatus } from '../../model/types'; -import { Sale } from '../../model'; +import { Nft, Sale } from '../../model'; import { EventInfo } from '../event-info.type'; export class SaleNftCanceledHandler implements INftMarketplaceEventHandler { @@ -33,5 +33,9 @@ export class SaleNftCanceledHandler implements INftMarketplaceEventHandler { updatedAt: eventInfo.timestamp, }), ); + await storage.setNft(new Nft({ + ...nft, + onSale: false, + })); } } diff --git a/indexer/src/processing/marketplace/sale-nft.handler.ts b/indexer/src/processing/marketplace/sale-nft.handler.ts index 74de971..d1f92c5 100644 --- a/indexer/src/processing/marketplace/sale-nft.handler.ts +++ b/indexer/src/processing/marketplace/sale-nft.handler.ts @@ -1,7 +1,7 @@ import { SaleNft } from '../../types/marketplace.events'; import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { Sale } from '../../model'; +import { Nft, Sale } from '../../model'; import { SaleStatus } from '../../model/types'; import { EventInfo } from '../event-info.type'; import { v4 as uuidv4 } from 'uuid'; @@ -46,5 +46,9 @@ export class SaleNftHandler implements INftMarketplaceEventHandler { updatedAt: eventInfo.timestamp, }), ); + await storage.setNft(new Nft({ + ...nft, + onSale: true, + })); } } diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index 77687d8..a9d719d 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -96,6 +96,7 @@ export class LocalStorage implements IStorage { }, idInCollection: tokenId, }, + relations: { collection: true }, }); } From 675103a391344ed88eb86ba06c9576c5e650d76f Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Wed, 7 Feb 2024 16:20:54 +0300 Subject: [PATCH 17/50] fix auction and saled --- indexer/db/migrations/1707311416201-Data.js | 15 +++++++ indexer/schema.graphql | 3 ++ indexer/src/main.ts | 5 +-- .../src/model/generated/marketplace.model.ts | 9 +++++ indexer/src/processing/entities.service.ts | 4 +- indexer/src/processing/events.processing.ts | 40 ++++++++++--------- .../marketplace/nft-sold.handler.ts | 10 +++-- .../marketplace/sale-nft-canceled.handler.ts | 10 +++-- .../marketplace/sale-nft.handler.ts | 10 +++-- .../src/processing/nft/initialized.handler.ts | 2 + .../src/processing/storage/local.storage.ts | 34 ++++++++++++---- .../processing/storage/storage.inteface.ts | 2 +- indexer/src/types/nft.events.ts | 9 +++++ 13 files changed, 109 insertions(+), 44 deletions(-) create mode 100644 indexer/db/migrations/1707311416201-Data.js diff --git a/indexer/db/migrations/1707311416201-Data.js b/indexer/db/migrations/1707311416201-Data.js new file mode 100644 index 0000000..4c463ee --- /dev/null +++ b/indexer/db/migrations/1707311416201-Data.js @@ -0,0 +1,15 @@ +module.exports = class Data1707311416201 { + name = 'Data1707311416201' + + async up(db) { + await db.query(`ALTER TABLE "marketplace" ADD "address" text NOT NULL default ''`) + await db.query(`ALTER TABLE "marketplace" ADD "metadata" text NOT NULL default ''`) + await db.query(`ALTER TABLE "marketplace" ADD "nft_metadata" text NOT NULL default ''`) + } + + async down(db) { + await db.query(`ALTER TABLE "marketplace" DROP COLUMN "address"`) + await db.query(`ALTER TABLE "marketplace" DROP COLUMN "metadata"`) + await db.query(`ALTER TABLE "marketplace" DROP COLUMN "nft_metadata"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index e3cd20f..9af8b90 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -5,6 +5,9 @@ type Marketplace @entity { collections: [Collection!]! @derivedFrom(field: "marketplace") collectionTypes: [CollectionType!]! @derivedFrom(field: "marketplace") events: [MarketplaceEvent!]! @derivedFrom(field: "marketplace") + address: String! + metadata: String! + nftMetadata: String! } type MarketplaceConfig @entity { diff --git a/indexer/src/main.ts b/indexer/src/main.ts index 1e29587..1c30006 100644 --- a/indexer/src/main.ts +++ b/indexer/src/main.ts @@ -1,7 +1,6 @@ import { TypeormDatabase } from '@subsquid/typeorm-store'; import { processor } from './processor'; -import { config } from './config'; import { EventsProcessing } from './processing/events.processing'; import { EventInfo } from './processing/event-info.type'; import { Block } from '@subsquid/substrate-processor'; @@ -30,7 +29,7 @@ processor.run(new TypeormDatabase(), async (ctx) => { new BatchService(ctx.store), ctx.store, ); - const processing = new EventsProcessing(entitiesService); + const processing = new EventsProcessing(entitiesService, localStorage); const firstBlockDate = getBlockDate(ctx.blocks[0]); console.log( `[main] start processing ${ctx.blocks.length} blocks at ${firstBlockDate}.`, @@ -56,7 +55,7 @@ processor.run(new TypeormDatabase(), async (ctx) => { messageId: id, txHash: id, }; - if (config.marketplaceProgram === source) { + if (localStorage.getMarketplace().address === source) { const marketplaceEvent = await processing.handleMarketplaceEvent( payload, eventInfo, diff --git a/indexer/src/model/generated/marketplace.model.ts b/indexer/src/model/generated/marketplace.model.ts index 56154bf..f8a5072 100644 --- a/indexer/src/model/generated/marketplace.model.ts +++ b/indexer/src/model/generated/marketplace.model.ts @@ -35,4 +35,13 @@ export class Marketplace { @OneToMany_(() => MarketplaceEvent, (e) => e.marketplace) events!: MarketplaceEvent[]; + + @Column_('text', { nullable: false }) + address!: string; + + @Column_('text', { nullable: false }) + metadata!: string; + + @Column_('text', { nullable: false }) + nftMetadata!: string; } diff --git a/indexer/src/processing/entities.service.ts b/indexer/src/processing/entities.service.ts index 56d748b..84683bb 100644 --- a/indexer/src/processing/entities.service.ts +++ b/indexer/src/processing/entities.service.ts @@ -36,7 +36,7 @@ export class EntitiesService { const entity = new MarketplaceEvent({ ...event, id: uuidv4(), - marketplace: await this.storage.getMarketplace(), + marketplace: this.storage.getMarketplace(), } as MarketplaceEvent); this.batchService.addEvent(entity); } @@ -115,7 +115,7 @@ export class EntitiesService { } async setMarketplaceConfig(marketplaceConfig: MarketplaceConfig) { - const marketplace = await this.storage.getMarketplace(); + const marketplace = this.storage.getMarketplace(); marketplace.config = marketplaceConfig; await this.storage.updateMarketplace(marketplace); this.batchService.setMarketplace(marketplace); diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index 734f834..ff16c37 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -1,5 +1,3 @@ -import { readFileSync } from 'fs'; -import { ProgramMetadata } from '@gear-js/api'; import { getMarketplaceEvent, NftMarketplaceEvent, @@ -40,13 +38,8 @@ import { TransferredHandler } from './nft/transferred.handler'; import { MetadataAddedHandler } from './nft/metadata-added.handler'; import { EventInfo } from './event-info.type'; import { EntitiesService } from './entities.service'; - -const marketplaceMeta = ProgramMetadata.from( - readFileSync('./assets/nft_marketplace.meta.txt', 'utf8'), -); -const nftMeta = ProgramMetadata.from( - readFileSync('./assets/nft.meta.txt', 'utf8'), -); +import { IStorage } from './storage/storage.inteface'; +import { ProgramMetadata } from '@gear-js/api'; const marketplaceEventsToHandler: Record< NftMarketplaceEventType, @@ -89,7 +82,17 @@ const nftEventsToHandler: Record = { }; export class EventsProcessing { - constructor(private readonly entitiesService: EntitiesService) {} + private readonly marketplaceMeta: ProgramMetadata; + private readonly nftMeta: ProgramMetadata; + + constructor( + private readonly entitiesService: EntitiesService, + private readonly storage: IStorage, + ) { + const marketplace = this.storage.getMarketplace(); + this.marketplaceMeta = ProgramMetadata.from(marketplace.metadata); + this.nftMeta = ProgramMetadata.from(marketplace.nftMetadata); + } saveAll() { return this.entitiesService.saveAll(); @@ -102,8 +105,8 @@ export class EventsProcessing { const { blockNumber, messageId } = eventInfo; try { console.log(`${blockNumber}-${messageId}: handling marketplace event`); - const data = marketplaceMeta.createType( - marketplaceMeta.types.handle.output!, + const data = this.marketplaceMeta.createType( + this.marketplaceMeta.types.handle.output!, payload, ); const parsed = data.toJSON() as { ok: NftMarketplaceEventPlain } | null; @@ -121,10 +124,10 @@ export class EventsProcessing { blockNumber: eventInfo.blockNumber, timestamp: eventInfo.timestamp, type: event.type, - raw: JSON.stringify(event, (key, value) => - typeof value === 'bigint' - ? value.toString() - : value // return everything else unchanged + raw: JSON.stringify( + event, + (key, value) => + typeof value === 'bigint' ? value.toString() : value, // return everything else unchanged ), txHash: eventInfo.txHash, }) @@ -156,9 +159,8 @@ export class EventsProcessing { const { blockNumber, messageId } = eventInfo; try { console.log(`${blockNumber}-${messageId}: handling nft event`); - const data = nftMeta.createType( - // @ts-ignore - nftMeta.types.handle.output!, + const data = this.nftMeta.createType( + this.nftMeta.types.handle.output!, payload, ); const parsed = data.toJSON() as { ok: NftEventPlain } | null; diff --git a/indexer/src/processing/marketplace/nft-sold.handler.ts b/indexer/src/processing/marketplace/nft-sold.handler.ts index 22b43ed..cc7edbe 100644 --- a/indexer/src/processing/marketplace/nft-sold.handler.ts +++ b/indexer/src/processing/marketplace/nft-sold.handler.ts @@ -44,9 +44,11 @@ export class NftSoldHandler implements INftMarketplaceEventHandler { updatedAt: eventInfo.timestamp, }), ); - await storage.setNft(new Nft({ - ...nft, - onSale: false, - })); + await storage.setNft( + new Nft({ + ...nft, + onSale: false, + }), + ); } } diff --git a/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts b/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts index 376e7ee..69d67a6 100644 --- a/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts +++ b/indexer/src/processing/marketplace/sale-nft-canceled.handler.ts @@ -33,9 +33,11 @@ export class SaleNftCanceledHandler implements INftMarketplaceEventHandler { updatedAt: eventInfo.timestamp, }), ); - await storage.setNft(new Nft({ - ...nft, - onSale: false, - })); + await storage.setNft( + new Nft({ + ...nft, + onSale: false, + }), + ); } } diff --git a/indexer/src/processing/marketplace/sale-nft.handler.ts b/indexer/src/processing/marketplace/sale-nft.handler.ts index d1f92c5..514c1e9 100644 --- a/indexer/src/processing/marketplace/sale-nft.handler.ts +++ b/indexer/src/processing/marketplace/sale-nft.handler.ts @@ -46,9 +46,11 @@ export class SaleNftHandler implements INftMarketplaceEventHandler { updatedAt: eventInfo.timestamp, }), ); - await storage.setNft(new Nft({ - ...nft, - onSale: true, - })); + await storage.setNft( + new Nft({ + ...nft, + onSale: true, + }), + ); } } diff --git a/indexer/src/processing/nft/initialized.handler.ts b/indexer/src/processing/nft/initialized.handler.ts index 4ad8fb7..a4a2b3b 100644 --- a/indexer/src/processing/nft/initialized.handler.ts +++ b/indexer/src/processing/nft/initialized.handler.ts @@ -32,6 +32,7 @@ export class InitializedHandler implements INftEventHandler { sellable, transferable, userMintLimit, + totalNumberOfTokens, } = event.config; await storage.setCollection( new Collection({ @@ -49,6 +50,7 @@ export class InitializedHandler implements INftEventHandler { royalty, sellable, transferable, + tokensLimit: totalNumberOfTokens, userMintLimit: userMintLimit, createdAt: timestamp, }), diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index a9d719d..5f74643 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -9,9 +9,17 @@ import { } from '../../model'; import { Store } from '@subsquid/typeorm-store'; import { IStorage } from './storage.inteface'; +import { config } from '../../config'; +import { readFileSync } from 'fs'; let storage: LocalStorage | undefined; +const marketplaceMeta = readFileSync( + './assets/nft_marketplace.meta.txt', + 'utf8', +); +const nftMeta = readFileSync('./assets/nft.meta.txt', 'utf8'); + export async function getLocalStorage(store: Store): Promise { if (storage === undefined) { storage = new LocalStorage(store); @@ -22,12 +30,6 @@ export async function getLocalStorage(store: Store): Promise { } export class LocalStorage implements IStorage { - async updateNft(nft: Nft): Promise { - this.nfts[this.getNftKey(nft.collection.id, nft.idInCollection)] = nft; - } - async updateCollectionType(collectionType: CollectionType): Promise { - this.collectionTypes[collectionType.type] = collectionType; - } private initialized = false; // typeName -> CollectionType private collectionTypes: Record = {}; @@ -48,13 +50,22 @@ export class LocalStorage implements IStorage { } await this.loadEntities(); this.initialized = true; + setInterval(() => this.loadMarketplace(), 10 * 1000); // 10 seconds } setStore(store: Store) { this.store = store; } - async getMarketplace(): Promise { + async updateNft(nft: Nft): Promise { + this.nfts[this.getNftKey(nft.collection.id, nft.idInCollection)] = nft; + } + + async updateCollectionType(collectionType: CollectionType): Promise { + this.collectionTypes[collectionType.type] = collectionType; + } + + getMarketplace(): Marketplace { return this.marketplace!; } @@ -193,6 +204,15 @@ export class LocalStorage implements IStorage { private async loadMarketplace() { this.marketplace = await this.store.findOne(Marketplace, { where: {} }); + if (!this.marketplace!.address) { + this.marketplace!.address = config.marketplaceProgram; + } + if (!this.marketplace!.metadata) { + this.marketplace!.metadata = marketplaceMeta; + } + if (!this.marketplace!.nftMetadata) { + this.marketplace!.nftMetadata = nftMeta; + } } private async loadCollections() { diff --git a/indexer/src/processing/storage/storage.inteface.ts b/indexer/src/processing/storage/storage.inteface.ts index 6e5a37d..0d885d5 100644 --- a/indexer/src/processing/storage/storage.inteface.ts +++ b/indexer/src/processing/storage/storage.inteface.ts @@ -9,7 +9,7 @@ import { } from '../../model'; export interface IStorage { - getMarketplace(): Promise; + getMarketplace(): Marketplace; updateMarketplace(marketplace: Marketplace): Promise; getCollection(collectionAddress: string): Promise; diff --git a/indexer/src/types/nft.events.ts b/indexer/src/types/nft.events.ts index ff5b708..2f68ddf 100644 --- a/indexer/src/types/nft.events.ts +++ b/indexer/src/types/nft.events.ts @@ -50,6 +50,7 @@ export type NftConfig = { burnable: boolean; sellable: boolean; attendable: boolean; + totalNumberOfTokens: bigint | null; }; export type InitializedEvent = { @@ -164,6 +165,7 @@ export interface NftEventPlain extends Enum { }; initialized: { config: ConfigPlain; + totalNumberOfTokens: u64; }; minted: { tokenId: u64; @@ -187,6 +189,7 @@ export interface NftEventPlain extends Enum { }; configChanged: { config: ConfigPlain; + totalNumberOfTokens: u64; }; imageChanged: { tokenId: u64; @@ -253,6 +256,9 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { burnable: event.initialized.config.burnable, sellable: event.initialized.config.sellable, attendable: event.initialized.config.attendable, + totalNumberOfTokens: safeUnwrapToBigInt( + event.initialized.totalNumberOfTokens, + ), }, }; } @@ -333,6 +339,9 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { burnable: event.configChanged.config.burnable, sellable: event.configChanged.config.sellable, attendable: event.configChanged.config.attendable, + totalNumberOfTokens: safeUnwrapToBigInt( + event.configChanged.totalNumberOfTokens, + ), }, }; } From 6e5b5f508b127bd426e4e28e3c1ca11865577d1b Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Wed, 7 Feb 2024 16:23:28 +0300 Subject: [PATCH 18/50] fix auction and saled --- indexer/Dockerfile-explorer | 1 - 1 file changed, 1 deletion(-) diff --git a/indexer/Dockerfile-explorer b/indexer/Dockerfile-explorer index 229f492..253494a 100644 --- a/indexer/Dockerfile-explorer +++ b/indexer/Dockerfile-explorer @@ -24,7 +24,6 @@ RUN npm ci --production FROM node AS squid RUN npm i -g @subsquid/cli@latest -RUN echo -e "loglevel=silent\\nupdate-notifier=false" > /squid/.npmrc WORKDIR /squid COPY --from=deps /squid/package.json . COPY --from=deps /squid/package-lock.json . From 66e68f54a6237b279b415956a9039477e5f51c65 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Wed, 7 Feb 2024 19:20:09 +0300 Subject: [PATCH 19/50] fix add new collection type --- indexer/src/processing/entities.service.ts | 2 +- indexer/src/processing/marketplace/admin-added.handler.ts | 2 +- indexer/src/processing/marketplace/admins-deleted.handler.ts | 2 +- .../src/processing/marketplace/new-collection-added.handler.ts | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/indexer/src/processing/entities.service.ts b/indexer/src/processing/entities.service.ts index 84683bb..c3a093f 100644 --- a/indexer/src/processing/entities.service.ts +++ b/indexer/src/processing/entities.service.ts @@ -23,7 +23,7 @@ export class EntitiesService { private readonly store: Store, ) {} - async getMarketplace(): Promise { + getMarketplace(): Marketplace { return this.storage.getMarketplace(); } diff --git a/indexer/src/processing/marketplace/admin-added.handler.ts b/indexer/src/processing/marketplace/admin-added.handler.ts index 0670162..2397e9d 100644 --- a/indexer/src/processing/marketplace/admin-added.handler.ts +++ b/indexer/src/processing/marketplace/admin-added.handler.ts @@ -11,7 +11,7 @@ export class AdminAddedHandler implements INftMarketplaceEventHandler { storage: EntitiesService, ): Promise { const { users } = event; - const marketplace = await storage.getMarketplace(); + const marketplace = storage.getMarketplace(); await storage.setMarketplace( new Marketplace({ ...marketplace, diff --git a/indexer/src/processing/marketplace/admins-deleted.handler.ts b/indexer/src/processing/marketplace/admins-deleted.handler.ts index 03339ca..e6abc86 100644 --- a/indexer/src/processing/marketplace/admins-deleted.handler.ts +++ b/indexer/src/processing/marketplace/admins-deleted.handler.ts @@ -11,7 +11,7 @@ export class AdminDeletedHandler implements INftMarketplaceEventHandler { storage: EntitiesService, ): Promise { const { user } = event; - const marketplace = await storage.getMarketplace(); + const marketplace = storage.getMarketplace(); await storage.setMarketplace( new Marketplace({ ...marketplace, diff --git a/indexer/src/processing/marketplace/new-collection-added.handler.ts b/indexer/src/processing/marketplace/new-collection-added.handler.ts index ef29f16..dedceec 100644 --- a/indexer/src/processing/marketplace/new-collection-added.handler.ts +++ b/indexer/src/processing/marketplace/new-collection-added.handler.ts @@ -25,6 +25,7 @@ export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { type: typeName, metaUrl: metaLink, metaStr: '', + marketplace: storage.getMarketplace() }), ); } From 44064f8e9a30d30e90a3372961f77a62022d7034 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 8 Feb 2024 14:21:53 +0300 Subject: [PATCH 20/50] indexer fixes --- indexer/db/migrations/1707389319792-Data.js | 11 +++++++++++ indexer/schema.graphql | 1 + indexer/src/model/generated/collection.model.ts | 3 +++ .../marketplace/auction-closed.handler.ts | 14 ++++++++++++++ .../marketplace/new-collection-added.handler.ts | 8 +++++++- .../processing/marketplace/nft-sold.handler.ts | 12 +++++++++++- .../marketplace/offer-accepted.handler.ts | 15 ++++++++++++++- indexer/src/processing/nft/initialized.handler.ts | 1 + indexer/src/processing/nft/transferred.handler.ts | 4 ++++ 9 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 indexer/db/migrations/1707389319792-Data.js diff --git a/indexer/db/migrations/1707389319792-Data.js b/indexer/db/migrations/1707389319792-Data.js new file mode 100644 index 0000000..72b9a0f --- /dev/null +++ b/indexer/db/migrations/1707389319792-Data.js @@ -0,0 +1,11 @@ +module.exports = class Data1707389319792 { + name = 'Data1707389319792' + + async up(db) { + await db.query(`ALTER TABLE "collection" ADD "additional_links" text`) + } + + async down(db) { + await db.query(`ALTER TABLE "collection" DROP COLUMN "additional_links"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 9af8b90..5e0f218 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -48,6 +48,7 @@ type Collection @entity { admin: String name: String description: String + additionalLinks: String userMintLimit: BigInt tokensLimit: BigInt paymentForMint: BigInt diff --git a/indexer/src/model/generated/collection.model.ts b/indexer/src/model/generated/collection.model.ts index 14856dc..e023499 100644 --- a/indexer/src/model/generated/collection.model.ts +++ b/indexer/src/model/generated/collection.model.ts @@ -37,6 +37,9 @@ export class Collection { @Column_('text', { nullable: true }) description!: string | undefined | null; + @Column_('text', { nullable: true }) + additionalLinks!: string | undefined | null; + @Column_('numeric', { transformer: marshal.bigintTransformer, nullable: true, diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts index a63213c..123109e 100644 --- a/indexer/src/processing/marketplace/auction-closed.handler.ts +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -3,6 +3,7 @@ import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { AuctionStatus } from '../../model/types'; import { EventInfo } from '../event-info.type'; +import { Transfer } from '../../model'; export class AuctionClosedHandler implements INftMarketplaceEventHandler { async handle( @@ -32,5 +33,18 @@ export class AuctionClosedHandler implements INftMarketplaceEventHandler { lastPrice: price, updatedAt: eventInfo.timestamp, }); + storage.addTransfer( + new Transfer({ + nft, + from: auction.owner, + to: currentOwner, + timestamp: eventInfo.timestamp, + txHash: eventInfo.txHash, + }), + ); + await storage.setNft({ + ...nft, + owner: currentOwner, + }) } } diff --git a/indexer/src/processing/marketplace/new-collection-added.handler.ts b/indexer/src/processing/marketplace/new-collection-added.handler.ts index dedceec..5fe3496 100644 --- a/indexer/src/processing/marketplace/new-collection-added.handler.ts +++ b/indexer/src/processing/marketplace/new-collection-added.handler.ts @@ -18,6 +18,12 @@ export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { ); return; } + if (!typeName) { + console.warn( + `[NewCollectionAddedHandler]: Collection type ${typeName} is not valid`, + ); + return; + } await storage.setCollectionType( new CollectionType({ id: codeId, @@ -25,7 +31,7 @@ export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { type: typeName, metaUrl: metaLink, metaStr: '', - marketplace: storage.getMarketplace() + marketplace: storage.getMarketplace(), }), ); } diff --git a/indexer/src/processing/marketplace/nft-sold.handler.ts b/indexer/src/processing/marketplace/nft-sold.handler.ts index cc7edbe..5ddbaee 100644 --- a/indexer/src/processing/marketplace/nft-sold.handler.ts +++ b/indexer/src/processing/marketplace/nft-sold.handler.ts @@ -1,7 +1,7 @@ import { NftSold } from '../../types/marketplace.events'; import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { Nft, Sale } from '../../model'; +import { Nft, Sale, Transfer } from '../../model'; import { SaleStatus } from '../../model/types'; import { EventInfo } from '../event-info.type'; @@ -44,9 +44,19 @@ export class NftSoldHandler implements INftMarketplaceEventHandler { updatedAt: eventInfo.timestamp, }), ); + storage.addTransfer( + new Transfer({ + nft, + from: sale.owner, + to: currentOwner, + timestamp: eventInfo.timestamp, + txHash: eventInfo.txHash, + }), + ); await storage.setNft( new Nft({ ...nft, + owner: currentOwner, onSale: false, }), ); diff --git a/indexer/src/processing/marketplace/offer-accepted.handler.ts b/indexer/src/processing/marketplace/offer-accepted.handler.ts index 056b30c..e9eb196 100644 --- a/indexer/src/processing/marketplace/offer-accepted.handler.ts +++ b/indexer/src/processing/marketplace/offer-accepted.handler.ts @@ -2,7 +2,7 @@ import { OfferAccepted } from '../../types/marketplace.events'; import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { OfferStatus } from '../../model/types'; -import { Offer } from '../../model'; +import { Offer, Transfer } from '../../model'; import { EventInfo } from '../event-info.type'; export class OfferAcceptedHandler implements INftMarketplaceEventHandler { @@ -36,5 +36,18 @@ export class OfferAcceptedHandler implements INftMarketplaceEventHandler { blockNumber: eventInfo.blockNumber, }), ); + storage.addTransfer( + new Transfer({ + nft, + from: nft.owner, + to: offer.creator, + timestamp: eventInfo.timestamp, + txHash: eventInfo.txHash, + }), + ); + await storage.setNft({ + ...nft, + owner: offer.creator, + }) } } diff --git a/indexer/src/processing/nft/initialized.handler.ts b/indexer/src/processing/nft/initialized.handler.ts index a4a2b3b..5685607 100644 --- a/indexer/src/processing/nft/initialized.handler.ts +++ b/indexer/src/processing/nft/initialized.handler.ts @@ -43,6 +43,7 @@ export class InitializedHandler implements INftEventHandler { approvable, attendable, burnable, + additionalLinks: JSON.stringify(additionalLinks), collectionBanner: collectionBanner, collectionLogo, tags: collectionTags, diff --git a/indexer/src/processing/nft/transferred.handler.ts b/indexer/src/processing/nft/transferred.handler.ts index 74c01b2..7f2aef6 100644 --- a/indexer/src/processing/nft/transferred.handler.ts +++ b/indexer/src/processing/nft/transferred.handler.ts @@ -28,5 +28,9 @@ export class TransferredHandler implements INftEventHandler { txHash, }), ); + await storage.setNft({ + ...nft, + owner: recipient, + }) } } From 08869ef024cda3ace9142af4eb60ec36c9229b72 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 8 Feb 2024 14:24:20 +0300 Subject: [PATCH 21/50] indexer fixes --- indexer/src/processing/events.processing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index ff16c37..d41f69f 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -119,7 +119,7 @@ export class EventsProcessing { return null; } console.log(`${blockNumber}-${messageId}: detected event: ${event.type}`); - this.entitiesService + await this.entitiesService .addEvent({ blockNumber: eventInfo.blockNumber, timestamp: eventInfo.timestamp, From 0b85c84d2aea7d3e38edfad722527e2002f4d38f Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 8 Feb 2024 14:50:05 +0300 Subject: [PATCH 22/50] indexer fixes --- indexer/db/migrations/1707392979676-Data.js | 29 +++++++++++++++ indexer/schema.graphql | 20 +++++------ .../src/model/generated/collection.model.ts | 36 +++++++++---------- indexer/src/processing/entities.service.ts | 4 ++- .../marketplace/auction-closed.handler.ts | 2 +- .../marketplace/offer-accepted.handler.ts | 2 +- .../src/processing/nft/transferred.handler.ts | 2 +- 7 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 indexer/db/migrations/1707392979676-Data.js diff --git a/indexer/db/migrations/1707392979676-Data.js b/indexer/db/migrations/1707392979676-Data.js new file mode 100644 index 0000000..2a08ba9 --- /dev/null +++ b/indexer/db/migrations/1707392979676-Data.js @@ -0,0 +1,29 @@ +module.exports = class Data1707392979676 { + name = 'Data1707392979676' + + async up(db) { + await db.query(`ALTER TABLE "collection" ADD "additional_links" text`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "admin" SET NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "name" SET NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "description" SET NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "payment_for_mint" SET NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "royalty" SET NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "collection_logo" SET NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "collection_banner" SET NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "created_at" SET NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "tags" SET NOT NULL`) + } + + async down(db) { + await db.query(`ALTER TABLE "collection" DROP COLUMN "additional_links"`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "admin" DROP NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "name" DROP NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "description" DROP NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "payment_for_mint" DROP NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "royalty" DROP NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "collection_logo" DROP NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "collection_banner" DROP NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "created_at" DROP NOT NULL`) + await db.query(`ALTER TABLE "collection" ALTER COLUMN "tags" DROP NOT NULL`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 5e0f218..6575bf8 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -45,24 +45,24 @@ type Collection @entity { id: ID! marketplace: Marketplace! type: CollectionType! - admin: String - name: String - description: String + admin: String! + name: String! + description: String! additionalLinks: String userMintLimit: BigInt tokensLimit: BigInt - paymentForMint: BigInt - royalty: Int - collectionLogo: String - collectionBanner: String + paymentForMint: BigInt! + royalty: Int! + collectionLogo: String! + collectionBanner: String! transferable: Boolean approvable: Boolean burnable: Boolean sellable: Boolean attendable: Boolean - createdAt: DateTime - nfts: [Nft!] @derivedFrom(field: "collection") - tags: [String!] + createdAt: DateTime! + nfts: [Nft!]! @derivedFrom(field: "collection") + tags: [String!]! } type Nft @entity { diff --git a/indexer/src/model/generated/collection.model.ts b/indexer/src/model/generated/collection.model.ts index e023499..77aa4b5 100644 --- a/indexer/src/model/generated/collection.model.ts +++ b/indexer/src/model/generated/collection.model.ts @@ -28,14 +28,14 @@ export class Collection { @ManyToOne_(() => CollectionType, { nullable: true }) type!: CollectionType; - @Column_('text', { nullable: true }) - admin!: string | undefined | null; + @Column_('text', { nullable: false }) + admin!: string; - @Column_('text', { nullable: true }) - name!: string | undefined | null; + @Column_('text', { nullable: false }) + name!: string; - @Column_('text', { nullable: true }) - description!: string | undefined | null; + @Column_('text', { nullable: false }) + description!: string; @Column_('text', { nullable: true }) additionalLinks!: string | undefined | null; @@ -54,18 +54,18 @@ export class Collection { @Column_('numeric', { transformer: marshal.bigintTransformer, - nullable: true, + nullable: false, }) - paymentForMint!: bigint | undefined | null; + paymentForMint!: bigint; - @Column_('int4', { nullable: true }) - royalty!: number | undefined | null; + @Column_('int4', { nullable: false }) + royalty!: number; - @Column_('text', { nullable: true }) - collectionLogo!: string | undefined | null; + @Column_('text', { nullable: false }) + collectionLogo!: string; - @Column_('text', { nullable: true }) - collectionBanner!: string | undefined | null; + @Column_('text', { nullable: false }) + collectionBanner!: string; @Column_('bool', { nullable: true }) transferable!: boolean | undefined | null; @@ -82,12 +82,12 @@ export class Collection { @Column_('bool', { nullable: true }) attendable!: boolean | undefined | null; - @Column_('timestamp with time zone', { nullable: true }) - createdAt!: Date | undefined | null; + @Column_('timestamp with time zone', { nullable: false }) + createdAt!: Date; @OneToMany_(() => Nft, (e) => e.collection) nfts!: Nft[]; - @Column_('text', { array: true, nullable: true }) - tags!: string[] | undefined | null; + @Column_('text', { array: true, nullable: false }) + tags!: string[]; } diff --git a/indexer/src/processing/entities.service.ts b/indexer/src/processing/entities.service.ts index c3a093f..9ac72fe 100644 --- a/indexer/src/processing/entities.service.ts +++ b/indexer/src/processing/entities.service.ts @@ -55,7 +55,9 @@ export class EntitiesService { async setCollection(collection: Collection) { await this.storage.updateCollection(collection); - this.batchService.addCollectionUpdate(collection); + if (collection.admin) { + this.batchService.addCollectionUpdate(collection); + } } getSale(nft: Nft) { diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts index 123109e..3f1bb83 100644 --- a/indexer/src/processing/marketplace/auction-closed.handler.ts +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -45,6 +45,6 @@ export class AuctionClosedHandler implements INftMarketplaceEventHandler { await storage.setNft({ ...nft, owner: currentOwner, - }) + }); } } diff --git a/indexer/src/processing/marketplace/offer-accepted.handler.ts b/indexer/src/processing/marketplace/offer-accepted.handler.ts index e9eb196..b979151 100644 --- a/indexer/src/processing/marketplace/offer-accepted.handler.ts +++ b/indexer/src/processing/marketplace/offer-accepted.handler.ts @@ -48,6 +48,6 @@ export class OfferAcceptedHandler implements INftMarketplaceEventHandler { await storage.setNft({ ...nft, owner: offer.creator, - }) + }); } } diff --git a/indexer/src/processing/nft/transferred.handler.ts b/indexer/src/processing/nft/transferred.handler.ts index 7f2aef6..9f6b737 100644 --- a/indexer/src/processing/nft/transferred.handler.ts +++ b/indexer/src/processing/nft/transferred.handler.ts @@ -31,6 +31,6 @@ export class TransferredHandler implements INftEventHandler { await storage.setNft({ ...nft, owner: recipient, - }) + }); } } From cfaddcb3cefd9dda910cb30865728ca13ad01216 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 8 Feb 2024 14:54:53 +0300 Subject: [PATCH 23/50] indexer fixes --- indexer/db/migrations/1707392979676-Data.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/indexer/db/migrations/1707392979676-Data.js b/indexer/db/migrations/1707392979676-Data.js index 2a08ba9..8c978d2 100644 --- a/indexer/db/migrations/1707392979676-Data.js +++ b/indexer/db/migrations/1707392979676-Data.js @@ -2,7 +2,6 @@ module.exports = class Data1707392979676 { name = 'Data1707392979676' async up(db) { - await db.query(`ALTER TABLE "collection" ADD "additional_links" text`) await db.query(`ALTER TABLE "collection" ALTER COLUMN "admin" SET NOT NULL`) await db.query(`ALTER TABLE "collection" ALTER COLUMN "name" SET NOT NULL`) await db.query(`ALTER TABLE "collection" ALTER COLUMN "description" SET NOT NULL`) @@ -15,7 +14,6 @@ module.exports = class Data1707392979676 { } async down(db) { - await db.query(`ALTER TABLE "collection" DROP COLUMN "additional_links"`) await db.query(`ALTER TABLE "collection" ALTER COLUMN "admin" DROP NOT NULL`) await db.query(`ALTER TABLE "collection" ALTER COLUMN "name" DROP NOT NULL`) await db.query(`ALTER TABLE "collection" ALTER COLUMN "description" DROP NOT NULL`) From 1ee0fb0ad84a4e7e1922d522ab4d6e6489e314f1 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 8 Feb 2024 15:02:48 +0300 Subject: [PATCH 24/50] indexer fixes --- .../src/processing/storage/local.storage.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index 5f74643..7afd696 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -203,15 +203,19 @@ export class LocalStorage implements IStorage { } private async loadMarketplace() { - this.marketplace = await this.store.findOne(Marketplace, { where: {} }); - if (!this.marketplace!.address) { - this.marketplace!.address = config.marketplaceProgram; - } - if (!this.marketplace!.metadata) { - this.marketplace!.metadata = marketplaceMeta; - } - if (!this.marketplace!.nftMetadata) { - this.marketplace!.nftMetadata = nftMeta; + try { + this.marketplace = await this.store.findOne(Marketplace, { where: {} }); + if (!this.marketplace!.address) { + this.marketplace!.address = config.marketplaceProgram; + } + if (!this.marketplace!.metadata) { + this.marketplace!.metadata = marketplaceMeta; + } + if (!this.marketplace!.nftMetadata) { + this.marketplace!.nftMetadata = nftMeta; + } + } catch (e) { + console.error(e); } } From 17eb91c1606192aacd12d111f37c76c150b3349a Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 8 Feb 2024 15:36:36 +0300 Subject: [PATCH 25/50] indexer fixes --- indexer/db/migrations/1707395758567-Data.js | 13 +++ indexer/schema.graphql | 9 ++- .../src/model/generated/_additionalLinks.ts | 81 +++++++++++++++++++ .../src/model/generated/collection.model.ts | 12 ++- indexer/src/model/generated/index.ts | 1 + .../src/processing/nft/initialized.handler.ts | 6 +- 6 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 indexer/db/migrations/1707395758567-Data.js create mode 100644 indexer/src/model/generated/_additionalLinks.ts diff --git a/indexer/db/migrations/1707395758567-Data.js b/indexer/db/migrations/1707395758567-Data.js new file mode 100644 index 0000000..eced619 --- /dev/null +++ b/indexer/db/migrations/1707395758567-Data.js @@ -0,0 +1,13 @@ +module.exports = class Data1707395758567 { + name = 'Data1707395758567' + + async up(db) { + await db.query(`ALTER TABLE "collection" DROP COLUMN "additional_links"`) + await db.query(`ALTER TABLE "collection" ADD "additional_links" jsonb`) + } + + async down(db) { + await db.query(`ALTER TABLE "collection" ADD "additional_links" text`) + await db.query(`ALTER TABLE "collection" DROP COLUMN "additional_links"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 6575bf8..4c09d3b 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -40,6 +40,13 @@ type CollectionType @entity { metaStr: String! marketplace: Marketplace! } +type AdditionalLinks { + externalUrl: String + telegram: String + xcom: String + medium: String + discord: String +} type Collection @entity { id: ID! @@ -48,7 +55,7 @@ type Collection @entity { admin: String! name: String! description: String! - additionalLinks: String + additionalLinks: AdditionalLinks userMintLimit: BigInt tokensLimit: BigInt paymentForMint: BigInt! diff --git a/indexer/src/model/generated/_additionalLinks.ts b/indexer/src/model/generated/_additionalLinks.ts new file mode 100644 index 0000000..11ad75d --- /dev/null +++ b/indexer/src/model/generated/_additionalLinks.ts @@ -0,0 +1,81 @@ +import * as marshal from './marshal'; + +export class AdditionalLinks { + private _externalUrl!: string | undefined | null; + private _telegram!: string | undefined | null; + private _xcom!: string | undefined | null; + private _medium!: string | undefined | null; + private _discord!: string | undefined | null; + + constructor(props?: Partial>, json?: any) { + Object.assign(this, props); + if (json != null) { + this._externalUrl = + json.externalUrl == null + ? undefined + : marshal.string.fromJSON(json.externalUrl); + this._telegram = + json.telegram == null + ? undefined + : marshal.string.fromJSON(json.telegram); + this._xcom = + json.xcom == null ? undefined : marshal.string.fromJSON(json.xcom); + this._medium = + json.medium == null ? undefined : marshal.string.fromJSON(json.medium); + this._discord = + json.discord == null + ? undefined + : marshal.string.fromJSON(json.discord); + } + } + + get externalUrl(): string | undefined | null { + return this._externalUrl; + } + + set externalUrl(value: string | undefined | null) { + this._externalUrl = value; + } + + get telegram(): string | undefined | null { + return this._telegram; + } + + set telegram(value: string | undefined | null) { + this._telegram = value; + } + + get xcom(): string | undefined | null { + return this._xcom; + } + + set xcom(value: string | undefined | null) { + this._xcom = value; + } + + get medium(): string | undefined | null { + return this._medium; + } + + set medium(value: string | undefined | null) { + this._medium = value; + } + + get discord(): string | undefined | null { + return this._discord; + } + + set discord(value: string | undefined | null) { + this._discord = value; + } + + toJSON(): object { + return { + externalUrl: this.externalUrl, + telegram: this.telegram, + xcom: this.xcom, + medium: this.medium, + discord: this.discord, + }; + } +} diff --git a/indexer/src/model/generated/collection.model.ts b/indexer/src/model/generated/collection.model.ts index 77aa4b5..cd95ce2 100644 --- a/indexer/src/model/generated/collection.model.ts +++ b/indexer/src/model/generated/collection.model.ts @@ -9,6 +9,7 @@ import { import * as marshal from './marshal'; import { Marketplace } from './marketplace.model'; import { CollectionType } from './collectionType.model'; +import { AdditionalLinks } from './_additionalLinks'; import { Nft } from './nft.model'; @Entity_() @@ -37,8 +38,15 @@ export class Collection { @Column_('text', { nullable: false }) description!: string; - @Column_('text', { nullable: true }) - additionalLinks!: string | undefined | null; + @Column_('jsonb', { + transformer: { + to: (obj) => (obj == null ? undefined : obj.toJSON()), + from: (obj) => + obj == null ? undefined : new AdditionalLinks(undefined, obj), + }, + nullable: true, + }) + additionalLinks!: AdditionalLinks | undefined | null; @Column_('numeric', { transformer: marshal.bigintTransformer, diff --git a/indexer/src/model/generated/index.ts b/indexer/src/model/generated/index.ts index 4a647ae..db68368 100644 --- a/indexer/src/model/generated/index.ts +++ b/indexer/src/model/generated/index.ts @@ -3,6 +3,7 @@ export * from './marketplaceConfig.model'; export * from './marketplaceEvent.model'; export * from './collectionType.model'; export * from './collection.model'; +export * from './_additionalLinks'; export * from './nft.model'; export * from './transfer.model'; export * from './sale.model'; diff --git a/indexer/src/processing/nft/initialized.handler.ts b/indexer/src/processing/nft/initialized.handler.ts index 5685607..e26ca16 100644 --- a/indexer/src/processing/nft/initialized.handler.ts +++ b/indexer/src/processing/nft/initialized.handler.ts @@ -1,7 +1,7 @@ import { InitializedEvent } from '../../types/nft.events'; import { EntitiesService } from '../entities.service'; import { INftEventHandler } from './nft.handler'; -import { Collection } from '../../model'; +import { AdditionalLinks, Collection } from '../../model'; import { EventInfo } from '../event-info.type'; export class InitializedHandler implements INftEventHandler { @@ -43,7 +43,9 @@ export class InitializedHandler implements INftEventHandler { approvable, attendable, burnable, - additionalLinks: JSON.stringify(additionalLinks), + additionalLinks: new AdditionalLinks({ + ...additionalLinks, + }), collectionBanner: collectionBanner, collectionLogo, tags: collectionTags, From a06a4b53e99e74ed60f745181d349a069553ab28 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 9 Feb 2024 12:07:47 +0300 Subject: [PATCH 26/50] indexer fixes --- indexer/db/migrations/1707469641353-Data.js | 17 +++++++++++++ indexer/schema.graphql | 4 ++-- .../src/model/generated/collection.model.ts | 14 +++++++---- .../marketplace/auction-closed.handler.ts | 2 ++ .../marketplace/nft-sold.handler.ts | 2 ++ .../marketplace/offer-accepted.handler.ts | 2 ++ .../src/processing/nft/transferred.handler.ts | 2 ++ indexer/src/types/nft.events.ts | 24 ++++++++++++------- 8 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 indexer/db/migrations/1707469641353-Data.js diff --git a/indexer/db/migrations/1707469641353-Data.js b/indexer/db/migrations/1707469641353-Data.js new file mode 100644 index 0000000..035d870 --- /dev/null +++ b/indexer/db/migrations/1707469641353-Data.js @@ -0,0 +1,17 @@ +module.exports = class Data1707469641353 { + name = 'Data1707469641353' + + async up(db) { + await db.query(`ALTER TABLE "collection" DROP COLUMN "transferable"`) + await db.query(`ALTER TABLE "collection" ADD "transferable" numeric`) + await db.query(`ALTER TABLE "collection" DROP COLUMN "sellable"`) + await db.query(`ALTER TABLE "collection" ADD "sellable" numeric`) + } + + async down(db) { + await db.query(`ALTER TABLE "collection" ADD "transferable" boolean`) + await db.query(`ALTER TABLE "collection" DROP COLUMN "transferable"`) + await db.query(`ALTER TABLE "collection" ADD "sellable" boolean`) + await db.query(`ALTER TABLE "collection" DROP COLUMN "sellable"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 4c09d3b..454b388 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -62,10 +62,10 @@ type Collection @entity { royalty: Int! collectionLogo: String! collectionBanner: String! - transferable: Boolean + transferable: BigInt approvable: Boolean burnable: Boolean - sellable: Boolean + sellable: BigInt attendable: Boolean createdAt: DateTime! nfts: [Nft!]! @derivedFrom(field: "collection") diff --git a/indexer/src/model/generated/collection.model.ts b/indexer/src/model/generated/collection.model.ts index cd95ce2..dcf4754 100644 --- a/indexer/src/model/generated/collection.model.ts +++ b/indexer/src/model/generated/collection.model.ts @@ -75,8 +75,11 @@ export class Collection { @Column_('text', { nullable: false }) collectionBanner!: string; - @Column_('bool', { nullable: true }) - transferable!: boolean | undefined | null; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: true, + }) + transferable!: bigint | undefined | null; @Column_('bool', { nullable: true }) approvable!: boolean | undefined | null; @@ -84,8 +87,11 @@ export class Collection { @Column_('bool', { nullable: true }) burnable!: boolean | undefined | null; - @Column_('bool', { nullable: true }) - sellable!: boolean | undefined | null; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: true, + }) + sellable!: bigint | undefined | null; @Column_('bool', { nullable: true }) attendable!: boolean | undefined | null; diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts index 3f1bb83..8eadb61 100644 --- a/indexer/src/processing/marketplace/auction-closed.handler.ts +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -4,6 +4,7 @@ import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { AuctionStatus } from '../../model/types'; import { EventInfo } from '../event-info.type'; import { Transfer } from '../../model'; +import { v4 as uuidv4 } from 'uuid'; export class AuctionClosedHandler implements INftMarketplaceEventHandler { async handle( @@ -35,6 +36,7 @@ export class AuctionClosedHandler implements INftMarketplaceEventHandler { }); storage.addTransfer( new Transfer({ + id: uuidv4(), nft, from: auction.owner, to: currentOwner, diff --git a/indexer/src/processing/marketplace/nft-sold.handler.ts b/indexer/src/processing/marketplace/nft-sold.handler.ts index 5ddbaee..5fd912b 100644 --- a/indexer/src/processing/marketplace/nft-sold.handler.ts +++ b/indexer/src/processing/marketplace/nft-sold.handler.ts @@ -4,6 +4,7 @@ import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { Nft, Sale, Transfer } from '../../model'; import { SaleStatus } from '../../model/types'; import { EventInfo } from '../event-info.type'; +import { v4 as uuidv4 } from 'uuid'; export class NftSoldHandler implements INftMarketplaceEventHandler { async handle( @@ -46,6 +47,7 @@ export class NftSoldHandler implements INftMarketplaceEventHandler { ); storage.addTransfer( new Transfer({ + id: uuidv4(), nft, from: sale.owner, to: currentOwner, diff --git a/indexer/src/processing/marketplace/offer-accepted.handler.ts b/indexer/src/processing/marketplace/offer-accepted.handler.ts index b979151..79a355b 100644 --- a/indexer/src/processing/marketplace/offer-accepted.handler.ts +++ b/indexer/src/processing/marketplace/offer-accepted.handler.ts @@ -4,6 +4,7 @@ import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { OfferStatus } from '../../model/types'; import { Offer, Transfer } from '../../model'; import { EventInfo } from '../event-info.type'; +import { v4 as uuidv4 } from 'uuid'; export class OfferAcceptedHandler implements INftMarketplaceEventHandler { async handle( @@ -38,6 +39,7 @@ export class OfferAcceptedHandler implements INftMarketplaceEventHandler { ); storage.addTransfer( new Transfer({ + id: uuidv4(), nft, from: nft.owner, to: offer.creator, diff --git a/indexer/src/processing/nft/transferred.handler.ts b/indexer/src/processing/nft/transferred.handler.ts index 9f6b737..e9ee0c1 100644 --- a/indexer/src/processing/nft/transferred.handler.ts +++ b/indexer/src/processing/nft/transferred.handler.ts @@ -3,6 +3,7 @@ import { EntitiesService } from '../entities.service'; import { INftEventHandler } from './nft.handler'; import { Transfer } from '../../model'; import { EventInfo } from '../event-info.type'; +import { v4 as uuidv4 } from 'uuid'; export class TransferredHandler implements INftEventHandler { async handle( @@ -20,6 +21,7 @@ export class TransferredHandler implements INftEventHandler { } storage.addTransfer( new Transfer({ + id: uuidv4(), nft, from: owner, to: recipient, diff --git a/indexer/src/types/nft.events.ts b/indexer/src/types/nft.events.ts index 2f68ddf..c5f6a4c 100644 --- a/indexer/src/types/nft.events.ts +++ b/indexer/src/types/nft.events.ts @@ -45,10 +45,10 @@ export type NftConfig = { additionalLinks: AdditionalLink | null; royalty: number; paymentForMint: bigint; - transferable: boolean; + transferable: bigint | null; approvable: boolean; burnable: boolean; - sellable: boolean; + sellable: bigint | null; attendable: boolean; totalNumberOfTokens: bigint | null; }; @@ -143,10 +143,10 @@ export interface ConfigPlain { additionalLinks: AdditionalLinkPlain; royalty: u16; paymentForMint: u128; - transferable: boolean; + transferable: Option | number; approvable: boolean; burnable: boolean; - sellable: boolean; + sellable: Option | number; attendable: boolean; } @@ -251,10 +251,14 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { paymentForMint: safeUnwrapToBigInt( event.initialized.config.paymentForMint, )!, - transferable: event.initialized.config.transferable, + transferable: safeUnwrapToBigInt( + safeUnwrapOptional(event.initialized.config.transferable), + ), approvable: event.initialized.config.approvable, burnable: event.initialized.config.burnable, - sellable: event.initialized.config.sellable, + sellable: safeUnwrapToBigInt( + safeUnwrapOptional(event.initialized.config.sellable), + ), attendable: event.initialized.config.attendable, totalNumberOfTokens: safeUnwrapToBigInt( event.initialized.totalNumberOfTokens, @@ -334,10 +338,14 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { paymentForMint: safeUnwrapToBigInt( event.configChanged.config.paymentForMint, )!, - transferable: event.configChanged.config.transferable, + transferable: safeUnwrapToBigInt( + safeUnwrapOptional(event.configChanged.config.transferable), + ), approvable: event.configChanged.config.approvable, burnable: event.configChanged.config.burnable, - sellable: event.configChanged.config.sellable, + sellable: safeUnwrapToBigInt( + safeUnwrapOptional(event.configChanged.config.sellable), + ), attendable: event.configChanged.config.attendable, totalNumberOfTokens: safeUnwrapToBigInt( event.configChanged.totalNumberOfTokens, From 6ed290f55197fe21cfcaaec8e822706801363928 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 9 Feb 2024 12:14:04 +0300 Subject: [PATCH 27/50] indexer fixes --- indexer/src/processing/marketplace/auction-closed.handler.ts | 1 + indexer/src/processing/marketplace/nft-sold.handler.ts | 1 + indexer/src/processing/marketplace/offer-accepted.handler.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts index 8eadb61..1783d1b 100644 --- a/indexer/src/processing/marketplace/auction-closed.handler.ts +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -41,6 +41,7 @@ export class AuctionClosedHandler implements INftMarketplaceEventHandler { from: auction.owner, to: currentOwner, timestamp: eventInfo.timestamp, + blockNumber: eventInfo.blockNumber, txHash: eventInfo.txHash, }), ); diff --git a/indexer/src/processing/marketplace/nft-sold.handler.ts b/indexer/src/processing/marketplace/nft-sold.handler.ts index 5fd912b..4e540c1 100644 --- a/indexer/src/processing/marketplace/nft-sold.handler.ts +++ b/indexer/src/processing/marketplace/nft-sold.handler.ts @@ -52,6 +52,7 @@ export class NftSoldHandler implements INftMarketplaceEventHandler { from: sale.owner, to: currentOwner, timestamp: eventInfo.timestamp, + blockNumber: eventInfo.blockNumber, txHash: eventInfo.txHash, }), ); diff --git a/indexer/src/processing/marketplace/offer-accepted.handler.ts b/indexer/src/processing/marketplace/offer-accepted.handler.ts index 79a355b..cae65f7 100644 --- a/indexer/src/processing/marketplace/offer-accepted.handler.ts +++ b/indexer/src/processing/marketplace/offer-accepted.handler.ts @@ -44,6 +44,7 @@ export class OfferAcceptedHandler implements INftMarketplaceEventHandler { from: nft.owner, to: offer.creator, timestamp: eventInfo.timestamp, + blockNumber: eventInfo.blockNumber, txHash: eventInfo.txHash, }), ); From f43098915d1f28c09bcf8e2940a70eaa0a0e4bbf Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 9 Feb 2024 14:49:59 +0300 Subject: [PATCH 28/50] indexer fixes --- indexer/db/migrations/1707479217496-Data.js | 11 +++++++++++ indexer/schema.graphql | 1 + indexer/src/model/generated/_additionalLinks.ts | 1 + indexer/src/model/generated/auction.model.ts | 3 +++ .../marketplace/auction-canceled.handler.ts | 1 + .../processing/marketplace/auction-closed.handler.ts | 1 + 6 files changed, 18 insertions(+) create mode 100644 indexer/db/migrations/1707479217496-Data.js diff --git a/indexer/db/migrations/1707479217496-Data.js b/indexer/db/migrations/1707479217496-Data.js new file mode 100644 index 0000000..1db0dfa --- /dev/null +++ b/indexer/db/migrations/1707479217496-Data.js @@ -0,0 +1,11 @@ +module.exports = class Data1707479217496 { + name = 'Data1707479217496' + + async up(db) { + await db.query(`ALTER TABLE "auction" ADD "end_timestamp" TIMESTAMP WITH TIME ZONE`) + } + + async down(db) { + await db.query(`ALTER TABLE "auction" DROP COLUMN "end_timestamp"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 454b388..5ac9573 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -124,6 +124,7 @@ type Auction @entity { durationMs: Int! timestamp: DateTime! updatedAt: DateTime! + endTimestamp: DateTime blockNumber: Int! bids: [Bid!]! @derivedFrom(field: "auction") } diff --git a/indexer/src/model/generated/_additionalLinks.ts b/indexer/src/model/generated/_additionalLinks.ts index 11ad75d..a75123e 100644 --- a/indexer/src/model/generated/_additionalLinks.ts +++ b/indexer/src/model/generated/_additionalLinks.ts @@ -1,3 +1,4 @@ +import assert from 'assert'; import * as marshal from './marshal'; export class AdditionalLinks { diff --git a/indexer/src/model/generated/auction.model.ts b/indexer/src/model/generated/auction.model.ts index ef51d57..312b1bf 100644 --- a/indexer/src/model/generated/auction.model.ts +++ b/indexer/src/model/generated/auction.model.ts @@ -53,6 +53,9 @@ export class Auction { @Column_('timestamp with time zone', { nullable: false }) updatedAt!: Date; + @Column_('timestamp with time zone', { nullable: true }) + endTimestamp!: Date | undefined | null; + @Column_('int4', { nullable: false }) blockNumber!: number; diff --git a/indexer/src/processing/marketplace/auction-canceled.handler.ts b/indexer/src/processing/marketplace/auction-canceled.handler.ts index d1082b6..b1774cf 100644 --- a/indexer/src/processing/marketplace/auction-canceled.handler.ts +++ b/indexer/src/processing/marketplace/auction-canceled.handler.ts @@ -29,6 +29,7 @@ export class AuctionCanceledHandler implements INftMarketplaceEventHandler { ...auction, status: AuctionStatus.Canceled, updatedAt: eventInfo.timestamp, + endTimestamp: eventInfo.timestamp, }); } } diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts index 1783d1b..06a8f6c 100644 --- a/indexer/src/processing/marketplace/auction-closed.handler.ts +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -33,6 +33,7 @@ export class AuctionClosedHandler implements INftMarketplaceEventHandler { newOwner: currentOwner, lastPrice: price, updatedAt: eventInfo.timestamp, + endTimestamp: eventInfo.timestamp, }); storage.addTransfer( new Transfer({ From 779d70f9649b80791171a1bf4bb6f338dd7aea9e Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 9 Feb 2024 16:04:57 +0300 Subject: [PATCH 29/50] add subscriptions --- indexer/commands.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indexer/commands.json b/indexer/commands.json index ac21a21..77be65a 100644 --- a/indexer/commands.json +++ b/indexer/commands.json @@ -57,11 +57,12 @@ }, "serve": { "description": "Start the GraphQL API server", - "cmd": ["squid-graphql-server"] + "cmd": ["squid-graphql-server", "--subscriptions"] }, "serve:prod": { "description": "Start the GraphQL API server with caching and limits", "cmd": ["squid-graphql-server", + "--subscriptions", "--dumb-cache", "in-memory", "--dumb-cache-ttl", "1000", "--dumb-cache-size", "100", From 241b7b12ab50780e0756c96875a629e26cc277f3 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Fri, 9 Feb 2024 16:18:37 +0300 Subject: [PATCH 30/50] add subscriptions --- indexer/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/package.json b/indexer/package.json index 6831e8a..b0c6d2a 100644 --- a/indexer/package.json +++ b/indexer/package.json @@ -9,7 +9,7 @@ "run": "sqd process", "migrations:generate": "sqd migration:generate", "migrations:apply": "sqd migration:apply", - "serve": "squid-graphql-server serve", + "serve": "squid-graphql-server --subscriptions serve", "format": "prettier --write \"src/**/*.ts\"", "start": "npm run migration:apply && node lib/main.js" }, From f615b3b52f24ae9c2e476822467f5c1e12097e28 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 12 Feb 2024 15:44:31 +0300 Subject: [PATCH 31/50] fix auction --- indexer/src/processing/marketplace/bid-added.handler.ts | 6 +++++- indexer/src/processing/storage/local.storage.ts | 4 +--- indexer/src/types/marketplace.events.ts | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/indexer/src/processing/marketplace/bid-added.handler.ts b/indexer/src/processing/marketplace/bid-added.handler.ts index d951a63..0f9519f 100644 --- a/indexer/src/processing/marketplace/bid-added.handler.ts +++ b/indexer/src/processing/marketplace/bid-added.handler.ts @@ -1,7 +1,7 @@ import { BidAdded } from '../../types/marketplace.events'; import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { Bid } from '../../model'; +import { Auction, Bid } from '../../model'; import { EventInfo } from '../event-info.type'; import { v4 as uuidv4 } from 'uuid'; @@ -33,6 +33,10 @@ export class BidAddedHandler implements INftMarketplaceEventHandler { ); return; } + await storage.setAuction(new Auction({ + ...auction, + lastPrice: price, + })) storage.addBid( new Bid({ id: uuidv4(), diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index 7afd696..53bb0ee 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -213,9 +213,7 @@ export class LocalStorage implements IStorage { } if (!this.marketplace!.nftMetadata) { this.marketplace!.nftMetadata = nftMeta; - } - } catch (e) { - console.error(e); + }} catch (e) { } } diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index fcc1d14..277d315 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -196,7 +196,7 @@ export interface NftMarketplaceEventPlain extends Enum { bidAdded: { collectionAddress: Hash; tokenId: u64; - price: u128; + currentPrice: u128; }; auctionCanceled: { collectionAddress: Hash; @@ -305,7 +305,7 @@ export function getMarketplaceEvent( type: NftMarketplaceEventType.BidAdded, collectionAddress: event.bidAdded.collectionAddress.toString(), tokenId: safeUnwrapToNumber(event.bidAdded.tokenId)!, - price: safeUnwrapToBigInt(event.bidAdded.price)!, + price: safeUnwrapToBigInt(event.bidAdded.currentPrice)!, }; } if (event.auctionCanceled) { From ff99d8b59660d6a81eff5acc23ce97f9bf99de5c Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 12 Feb 2024 16:18:24 +0300 Subject: [PATCH 32/50] fix auction --- indexer/src/processing/marketplace/auction-created.handler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/indexer/src/processing/marketplace/auction-created.handler.ts b/indexer/src/processing/marketplace/auction-created.handler.ts index 1873052..7315ea4 100644 --- a/indexer/src/processing/marketplace/auction-created.handler.ts +++ b/indexer/src/processing/marketplace/auction-created.handler.ts @@ -41,6 +41,7 @@ export class AuctionCreatedHandler implements INftMarketplaceEventHandler { owner: nft.owner, minPrice, durationMs, + endTimestamp: new Date(eventInfo.timestamp.getTime() + durationMs), status: SaleStatus.Open, blockNumber: eventInfo.blockNumber, timestamp: eventInfo.timestamp, From c51906e5b14b157aa2dbbbd05ba6dd7cd4e27196 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 12 Feb 2024 20:29:43 +0300 Subject: [PATCH 33/50] fix auction --- .../marketplace/auction-closed.handler.ts | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts index 06a8f6c..f794eee 100644 --- a/indexer/src/processing/marketplace/auction-closed.handler.ts +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -35,20 +35,22 @@ export class AuctionClosedHandler implements INftMarketplaceEventHandler { updatedAt: eventInfo.timestamp, endTimestamp: eventInfo.timestamp, }); - storage.addTransfer( - new Transfer({ - id: uuidv4(), - nft, - from: auction.owner, - to: currentOwner, - timestamp: eventInfo.timestamp, - blockNumber: eventInfo.blockNumber, - txHash: eventInfo.txHash, - }), - ); - await storage.setNft({ - ...nft, - owner: currentOwner, - }); + if (currentOwner !== null && currentOwner !== auction.owner) { + storage.addTransfer( + new Transfer({ + id: uuidv4(), + nft, + from: auction.owner, + to: currentOwner, + timestamp: eventInfo.timestamp, + blockNumber: eventInfo.blockNumber, + txHash: eventInfo.txHash, + }), + ); + await storage.setNft({ + ...nft, + owner: currentOwner, + }); + } } } From 13f9f42a45b7cedf678e906f62ff9255cb2f7ea1 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Wed, 14 Feb 2024 17:40:34 +0300 Subject: [PATCH 34/50] fix auction --- .../src/processing/marketplace/auction-closed.handler.ts | 6 +++--- .../src/processing/marketplace/offer-accepted.handler.ts | 6 +++--- indexer/src/types/nft.events.ts | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts index f794eee..1f6e710 100644 --- a/indexer/src/processing/marketplace/auction-closed.handler.ts +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -3,7 +3,7 @@ import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { AuctionStatus } from '../../model/types'; import { EventInfo } from '../event-info.type'; -import { Transfer } from '../../model'; +import { Nft, Transfer } from '../../model'; import { v4 as uuidv4 } from 'uuid'; export class AuctionClosedHandler implements INftMarketplaceEventHandler { @@ -47,10 +47,10 @@ export class AuctionClosedHandler implements INftMarketplaceEventHandler { txHash: eventInfo.txHash, }), ); - await storage.setNft({ + await storage.setNft(new Nft({ ...nft, owner: currentOwner, - }); + })); } } } diff --git a/indexer/src/processing/marketplace/offer-accepted.handler.ts b/indexer/src/processing/marketplace/offer-accepted.handler.ts index cae65f7..ecec8ec 100644 --- a/indexer/src/processing/marketplace/offer-accepted.handler.ts +++ b/indexer/src/processing/marketplace/offer-accepted.handler.ts @@ -2,7 +2,7 @@ import { OfferAccepted } from '../../types/marketplace.events'; import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; import { OfferStatus } from '../../model/types'; -import { Offer, Transfer } from '../../model'; +import { Nft, Offer, Transfer } from '../../model'; import { EventInfo } from '../event-info.type'; import { v4 as uuidv4 } from 'uuid'; @@ -48,9 +48,9 @@ export class OfferAcceptedHandler implements INftMarketplaceEventHandler { txHash: eventInfo.txHash, }), ); - await storage.setNft({ + await storage.setNft(new Nft({ ...nft, owner: offer.creator, - }); + })); } } diff --git a/indexer/src/types/nft.events.ts b/indexer/src/types/nft.events.ts index c5f6a4c..d2285dc 100644 --- a/indexer/src/types/nft.events.ts +++ b/indexer/src/types/nft.events.ts @@ -261,7 +261,7 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { ), attendable: event.initialized.config.attendable, totalNumberOfTokens: safeUnwrapToBigInt( - event.initialized.totalNumberOfTokens, + safeUnwrapOptional(event.initialized.totalNumberOfTokens), ), }, }; From 0f8274b90d07f60f01a5b8725875472b8d0e8824 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Wed, 14 Feb 2024 18:56:24 +0300 Subject: [PATCH 35/50] fix nft mint --- indexer/src/main.ts | 5 +++ indexer/src/processing/events.processing.ts | 6 ++-- .../src/processing/nft/transferred.handler.ts | 36 ++++++++++--------- indexer/src/types/event.utils.ts | 2 +- indexer/src/types/nft.events.ts | 2 +- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/indexer/src/main.ts b/indexer/src/main.ts index 1c30006..5ee3869 100644 --- a/indexer/src/main.ts +++ b/indexer/src/main.ts @@ -9,6 +9,11 @@ import { EntitiesService } from './processing/entities.service'; import { getLocalStorage } from './processing/storage/local.storage'; import { BatchService } from './processing/batch.service'; +// @ts-ignore +BigInt.prototype["toJSON"] = function () { + return this.toString(); +}; + const NFT_INITIALIZED_CLEAR_TIME = 5 * 60 * 1000; // 5 minutes function getBlockDate( diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index d41f69f..d6fc71d 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -113,12 +113,13 @@ export class EventsProcessing { if (!parsed || !parsed.ok) { return null; } + console.log(`${blockNumber}-${messageId}: extracting marketplace event ${JSON.stringify(parsed.ok)}`); const event = getMarketplaceEvent(parsed.ok); if (!event) { console.warn(`${blockNumber}-${messageId}: unknown event type`, parsed); return null; } - console.log(`${blockNumber}-${messageId}: detected event: ${event.type}`); + console.log(`${blockNumber}-${messageId}: detected event: ${event.type}\n${JSON.stringify(event)}`); await this.entitiesService .addEvent({ blockNumber: eventInfo.blockNumber, @@ -172,6 +173,7 @@ export class EventsProcessing { ); return null; } + console.log(`${blockNumber}-${messageId}: extracting nft event ${JSON.stringify(parsed.ok)}`); const event = getNftEvent(parsed.ok); if (!event) { console.warn( @@ -180,7 +182,7 @@ export class EventsProcessing { ); return null; } - console.log(`${blockNumber}-${messageId}: detected event: ${event.type}`); + console.log(`${blockNumber}-${messageId}: detected event: ${event.type}\n${JSON.stringify(event)}`); const eventHandler = nftEventsToHandler[event.type]; if (!eventHandler) { console.warn( diff --git a/indexer/src/processing/nft/transferred.handler.ts b/indexer/src/processing/nft/transferred.handler.ts index e9ee0c1..98087d2 100644 --- a/indexer/src/processing/nft/transferred.handler.ts +++ b/indexer/src/processing/nft/transferred.handler.ts @@ -1,10 +1,12 @@ import { TransferEvent } from '../../types/nft.events'; import { EntitiesService } from '../entities.service'; import { INftEventHandler } from './nft.handler'; -import { Transfer } from '../../model'; +import { Nft, Transfer } from '../../model'; import { EventInfo } from '../event-info.type'; import { v4 as uuidv4 } from 'uuid'; +const NullAddress = '0x0000000000000000000000000000000000000000000000000000000000000000' + export class TransferredHandler implements INftEventHandler { async handle( event: TransferEvent, @@ -19,20 +21,22 @@ export class TransferredHandler implements INftEventHandler { ); return; } - storage.addTransfer( - new Transfer({ - id: uuidv4(), - nft, - from: owner, - to: recipient, - blockNumber, - timestamp, - txHash, - }), - ); - await storage.setNft({ - ...nft, - owner: recipient, - }); + if (owner !== NullAddress && recipient !== NullAddress) { + storage.addTransfer( + new Transfer({ + id: uuidv4(), + nft, + from: owner, + to: recipient, + blockNumber, + timestamp, + txHash, + }), + ); + await storage.setNft(new Nft({ + ...nft, + owner: recipient, + })); + } } } diff --git a/indexer/src/types/event.utils.ts b/indexer/src/types/event.utils.ts index bce7138..ad19f90 100644 --- a/indexer/src/types/event.utils.ts +++ b/indexer/src/types/event.utils.ts @@ -16,7 +16,7 @@ export function safeUnwrapToNumber( export function safeUnwrapOptional( value: Option | T | null, ): T | null { - if (value === null) { + if (value === null || value === undefined) { return null; } if (isOption(value)) { diff --git a/indexer/src/types/nft.events.ts b/indexer/src/types/nft.events.ts index d2285dc..5d80b08 100644 --- a/indexer/src/types/nft.events.ts +++ b/indexer/src/types/nft.events.ts @@ -348,7 +348,7 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { ), attendable: event.configChanged.config.attendable, totalNumberOfTokens: safeUnwrapToBigInt( - event.configChanged.totalNumberOfTokens, + safeUnwrapOptional(event.configChanged.totalNumberOfTokens), ), }, }; From 0be128884ff24f08e563cc4089f18011d775c159 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Wed, 14 Feb 2024 19:00:40 +0300 Subject: [PATCH 36/50] add minted by --- indexer/db/migrations/1707926335271-Data.js | 11 +++++++++ indexer/schema.graphql | 1 + indexer/src/main.ts | 2 +- indexer/src/model/generated/nft.model.ts | 3 +++ indexer/src/processing/events.processing.ts | 24 +++++++++++++++---- .../marketplace/auction-closed.handler.ts | 10 ++++---- .../marketplace/bid-added.handler.ts | 10 ++++---- .../marketplace/offer-accepted.handler.ts | 10 ++++---- .../src/processing/nft/nft-minted.handler.ts | 1 + .../src/processing/nft/transferred.handler.ts | 13 ++++++---- .../src/processing/storage/local.storage.ts | 4 ++-- 11 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 indexer/db/migrations/1707926335271-Data.js diff --git a/indexer/db/migrations/1707926335271-Data.js b/indexer/db/migrations/1707926335271-Data.js new file mode 100644 index 0000000..656c25e --- /dev/null +++ b/indexer/db/migrations/1707926335271-Data.js @@ -0,0 +1,11 @@ +module.exports = class Data1707926335271 { + name = 'Data1707926335271' + + async up(db) { + await db.query(`ALTER TABLE "nft" ADD "minted_by" text NOT NULL`) + } + + async down(db) { + await db.query(`ALTER TABLE "nft" DROP COLUMN "minted_by"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 5ac9573..5ebd5ec 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -76,6 +76,7 @@ type Nft @entity { id: ID! owner: String! name: String! + mintedBy: String! description: String! idInCollection: Int! collection: Collection! diff --git a/indexer/src/main.ts b/indexer/src/main.ts index 5ee3869..f838bd4 100644 --- a/indexer/src/main.ts +++ b/indexer/src/main.ts @@ -10,7 +10,7 @@ import { getLocalStorage } from './processing/storage/local.storage'; import { BatchService } from './processing/batch.service'; // @ts-ignore -BigInt.prototype["toJSON"] = function () { +BigInt.prototype['toJSON'] = function () { return this.toString(); }; diff --git a/indexer/src/model/generated/nft.model.ts b/indexer/src/model/generated/nft.model.ts index 5bd5943..cec4f35 100644 --- a/indexer/src/model/generated/nft.model.ts +++ b/indexer/src/model/generated/nft.model.ts @@ -27,6 +27,9 @@ export class Nft { @Column_('text', { nullable: false }) name!: string; + @Column_('text', { nullable: false }) + mintedBy!: string; + @Column_('text', { nullable: false }) description!: string; diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index d6fc71d..02e731d 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -113,13 +113,21 @@ export class EventsProcessing { if (!parsed || !parsed.ok) { return null; } - console.log(`${blockNumber}-${messageId}: extracting marketplace event ${JSON.stringify(parsed.ok)}`); + console.log( + `${blockNumber}-${messageId}: extracting marketplace event ${JSON.stringify( + parsed.ok, + )}`, + ); const event = getMarketplaceEvent(parsed.ok); if (!event) { console.warn(`${blockNumber}-${messageId}: unknown event type`, parsed); return null; } - console.log(`${blockNumber}-${messageId}: detected event: ${event.type}\n${JSON.stringify(event)}`); + console.log( + `${blockNumber}-${messageId}: detected event: ${ + event.type + }\n${JSON.stringify(event)}`, + ); await this.entitiesService .addEvent({ blockNumber: eventInfo.blockNumber, @@ -173,7 +181,11 @@ export class EventsProcessing { ); return null; } - console.log(`${blockNumber}-${messageId}: extracting nft event ${JSON.stringify(parsed.ok)}`); + console.log( + `${blockNumber}-${messageId}: extracting nft event ${JSON.stringify( + parsed.ok, + )}`, + ); const event = getNftEvent(parsed.ok); if (!event) { console.warn( @@ -182,7 +194,11 @@ export class EventsProcessing { ); return null; } - console.log(`${blockNumber}-${messageId}: detected event: ${event.type}\n${JSON.stringify(event)}`); + console.log( + `${blockNumber}-${messageId}: detected event: ${ + event.type + }\n${JSON.stringify(event)}`, + ); const eventHandler = nftEventsToHandler[event.type]; if (!eventHandler) { console.warn( diff --git a/indexer/src/processing/marketplace/auction-closed.handler.ts b/indexer/src/processing/marketplace/auction-closed.handler.ts index 1f6e710..3805160 100644 --- a/indexer/src/processing/marketplace/auction-closed.handler.ts +++ b/indexer/src/processing/marketplace/auction-closed.handler.ts @@ -47,10 +47,12 @@ export class AuctionClosedHandler implements INftMarketplaceEventHandler { txHash: eventInfo.txHash, }), ); - await storage.setNft(new Nft({ - ...nft, - owner: currentOwner, - })); + await storage.setNft( + new Nft({ + ...nft, + owner: currentOwner, + }), + ); } } } diff --git a/indexer/src/processing/marketplace/bid-added.handler.ts b/indexer/src/processing/marketplace/bid-added.handler.ts index 0f9519f..1ba9db1 100644 --- a/indexer/src/processing/marketplace/bid-added.handler.ts +++ b/indexer/src/processing/marketplace/bid-added.handler.ts @@ -33,10 +33,12 @@ export class BidAddedHandler implements INftMarketplaceEventHandler { ); return; } - await storage.setAuction(new Auction({ - ...auction, - lastPrice: price, - })) + await storage.setAuction( + new Auction({ + ...auction, + lastPrice: price, + }), + ); storage.addBid( new Bid({ id: uuidv4(), diff --git a/indexer/src/processing/marketplace/offer-accepted.handler.ts b/indexer/src/processing/marketplace/offer-accepted.handler.ts index ecec8ec..8be7a77 100644 --- a/indexer/src/processing/marketplace/offer-accepted.handler.ts +++ b/indexer/src/processing/marketplace/offer-accepted.handler.ts @@ -48,9 +48,11 @@ export class OfferAcceptedHandler implements INftMarketplaceEventHandler { txHash: eventInfo.txHash, }), ); - await storage.setNft(new Nft({ - ...nft, - owner: offer.creator, - })); + await storage.setNft( + new Nft({ + ...nft, + owner: offer.creator, + }), + ); } } diff --git a/indexer/src/processing/nft/nft-minted.handler.ts b/indexer/src/processing/nft/nft-minted.handler.ts index 6d796a2..6570cfa 100644 --- a/indexer/src/processing/nft/nft-minted.handler.ts +++ b/indexer/src/processing/nft/nft-minted.handler.ts @@ -28,6 +28,7 @@ export class NftMintedHandler implements INftEventHandler { mediaUrl, name, owner, + mintedBy: owner, metadata: JSON.stringify(metadata), onSale: false, createdAt: timestamp, diff --git a/indexer/src/processing/nft/transferred.handler.ts b/indexer/src/processing/nft/transferred.handler.ts index 98087d2..f442a34 100644 --- a/indexer/src/processing/nft/transferred.handler.ts +++ b/indexer/src/processing/nft/transferred.handler.ts @@ -5,7 +5,8 @@ import { Nft, Transfer } from '../../model'; import { EventInfo } from '../event-info.type'; import { v4 as uuidv4 } from 'uuid'; -const NullAddress = '0x0000000000000000000000000000000000000000000000000000000000000000' +const NullAddress = + '0x0000000000000000000000000000000000000000000000000000000000000000'; export class TransferredHandler implements INftEventHandler { async handle( @@ -33,10 +34,12 @@ export class TransferredHandler implements INftEventHandler { txHash, }), ); - await storage.setNft(new Nft({ - ...nft, - owner: recipient, - })); + await storage.setNft( + new Nft({ + ...nft, + owner: recipient, + }), + ); } } } diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index 53bb0ee..e2b187d 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -213,8 +213,8 @@ export class LocalStorage implements IStorage { } if (!this.marketplace!.nftMetadata) { this.marketplace!.nftMetadata = nftMeta; - }} catch (e) { - } + } + } catch (e) {} } private async loadCollections() { From 4987a7766fa632c9a0e19a7384c34d8fe2672426 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Sat, 17 Feb 2024 16:19:43 +0300 Subject: [PATCH 37/50] add permission to mint --- indexer/assets/nft.meta.txt | 2 +- indexer/db/migrations/1708174915413-Data.js | 11 ++ indexer/schema.graphql | 1 + .../src/model/generated/collection.model.ts | 3 + indexer/src/processing/events.processing.ts | 6 + .../processing/nft/config-changed.handler.ts | 2 + .../src/processing/nft/initialized.handler.ts | 2 + .../nft/lift-restriction-mint.handler.ts | 27 +++++ .../nft/user-for-mint-deleted.handler.ts | 28 +++++ .../nft/users-for-mint-added.handler.ts | 28 +++++ indexer/src/types/nft.events.ts | 103 +++++++++++++----- 11 files changed, 185 insertions(+), 28 deletions(-) create mode 100644 indexer/db/migrations/1708174915413-Data.js create mode 100644 indexer/src/processing/nft/lift-restriction-mint.handler.ts create mode 100644 indexer/src/processing/nft/user-for-mint-deleted.handler.ts create mode 100644 indexer/src/processing/nft/users-for-mint-added.handler.ts diff --git a/indexer/assets/nft.meta.txt b/indexer/assets/nft.meta.txt index 6507aba..cfc894f 100644 --- a/indexer/assets/nft.meta.txt +++ b/indexer/assets/nft.meta.txt @@ -1 +1 @@ -0002000100000000000117000000011800000000000000011e000000011f000000312fa00008186e66745f696f1c4e6674496e697400000c0140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000118636f6e666967100118436f6e666967000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e00000410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004000801205b75383b2033325d000008000003200000000c000c00000503001008186e66745f696f18436f6e66696700002c01106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e6700013c636f6c6c656374696f6e5f7461677318012c5665633c537472696e673e000144636f6c6c656374696f6e5f62616e6e6572140118537472696e6700013c636f6c6c656374696f6e5f6c6f676f140118537472696e6700013c757365725f6d696e745f6c696d69741c012c4f7074696f6e3c7533323e0001406164646974696f6e616c5f6c696e6b7324015c4f7074696f6e3c4164646974696f6e616c4c696e6b733e00011c726f79616c747930010c7531360001407061796d656e745f666f725f6d696e74340110753132380001307472616e7366657261626c6538012c4f7074696f6e3c7536343e00012073656c6c61626c6538012c4f7074696f6e3c7536343e00001400000502001800000214001c04184f7074696f6e04045401200108104e6f6e6500000010536f6d6504002000000100002000000505002404184f7074696f6e04045401280108104e6f6e6500000010536f6d6504002800000100002808186e66745f696f3c4164646974696f6e616c4c696e6b73000014013065787465726e616c5f75726c2c01384f7074696f6e3c537472696e673e00012074656c656772616d2c01384f7074696f6e3c537472696e673e00011078636f6d2c01384f7074696f6e3c537472696e673e0001186d656469756d2c01384f7074696f6e3c537472696e673e00011c646973636f72642c01384f7074696f6e3c537472696e673e00002c04184f7074696f6e04045401140108104e6f6e6500000010536f6d6504001400000100003000000504003400000507003804184f7074696f6e040454013c0108104e6f6e6500000010536f6d6504003c00000100003c000005060040000002440044000004081448004808186e66745f696f24496d6167654461746100000801306c696d69745f636f706965731c012c4f7074696f6e3c7533323e00014c6175746f5f6368616e67696e675f72756c65734c01784f7074696f6e3c5665633c2854696d655365632c20416374696f6e293e3e00004c04184f7074696f6e04045401500108104e6f6e6500000010536f6d65040050000001000050000002540054000004082058005808186e66745f696f18416374696f6e000108244368616e6765496d670400140118537472696e670000001c4164644d6574610400140118537472696e67000100005c08186e66745f696f244e6674416374696f6e00012c205472616e73666572080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000000305472616e7366657246726f6d0c011066726f6d04011c4163746f724964000108746f04011c4163746f724964000120746f6b656e5f69643c01144e6674496400010030476574546f6b656e496e666f040120746f6b656e5f69643c01144e667449640002002443616e44656c657465000300104d696e740004001c417070726f7665080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000500385265766f6b65417070726f76616c040120746f6b656e5f69643c01144e6674496400060018457870616e640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000700304368616e6765436f6e666967040118636f6e666967100118436f6e666967000800244368616e6765496d67080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e670009002c4164644d65746164617461080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a0000600418526573756c740804540164044501740108084f6b040064000000000c45727204007400000100006408186e66745f696f204e66744576656e7400012c2c5472616e736665727265640c01146f776e657204011c4163746f724964000124726563697069656e7404011c4163746f724964000120746f6b656e5f69643c01144e6674496400000044546f6b656e496e666f526563656976656414012c746f6b656e5f6f776e657204011c4163746f724964000120617070726f76616c68013c4f7074696f6e3c4163746f7249643e00012073656c6c61626c656c0110626f6f6c000140636f6c6c656374696f6e5f6f776e657204011c4163746f72496400011c726f79616c747930010c7531360001002443616e44656c65746504006c0110626f6f6c0002002c496e697469616c697a6564080118636f6e666967100118436f6e666967000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e000300184d696e746564080120746f6b656e5f69643c01144e667449640001206e66745f6461746170010c4e667400040020417070726f766564080108746f04011c4163746f724964000120746f6b656e5f69643c01144e667449640005003c417070726f76616c5265766f6b6564040120746f6b656e5f69643c01144e6674496400060020457870616e6465640801406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e00070034436f6e6669674368616e676564040118636f6e666967100118436f6e66696700080030496d6167654368616e676564080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e67000900344d657461646174614164646564080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a00006804184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100006c00000500007008186e66745f696f0c4e667400001801146f776e657204011c4163746f7249640001106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e670001206d6574616461746118012c5665633c537472696e673e0001246d656469615f75726c140118537472696e670001246d696e745f74696d653c010c75363400007408186e66745f696f204e66744572726f7200000400140118537472696e6700007808186e66745f696f2853746174655175657279000110104e616d650000002c4465736372697074696f6e00010018436f6e6669670002000c416c6c000300007c08186e66745f696f2853746174655265706c79000110104e616d650400140118537472696e670000002c4465736372697074696f6e0400140118537472696e6700010018436f6e6669670400100118436f6e6669670002000c416c6c04008001204e66745374617465000300008008186e66745f696f204e667453746174650000200118746f6b656e738401445665633c284e667449642c204e6674293e0001186f776e6572738c01685665633c284163746f7249642c205665633c4e667449643e293e00013c746f6b656e5f617070726f76616c739801545665633c284e667449642c204163746f724964293e000118636f6e666967100118436f6e6669670001146e6f6e63653c01144e66744964000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e000140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e000084000002880088000004083c70008c00000290009000000408049400940000023c00980000029c009c000004083c0400 +0002000100000000000119000000011a00000000000000012000000001210000008134a80008186e66745f696f1c4e6674496e69740000100140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000118636f6e666967100118436f6e666967000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e0001487065726d697373696f6e5f746f5f6d696e745c01504f7074696f6e3c5665633c4163746f7249643e3e00000410106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004000801205b75383b2033325d000008000003200000000c000c00000503001008186e66745f696f18436f6e66696700002c01106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e6700013c636f6c6c656374696f6e5f7461677318012c5665633c537472696e673e000144636f6c6c656374696f6e5f62616e6e6572140118537472696e6700013c636f6c6c656374696f6e5f6c6f676f140118537472696e6700013c757365725f6d696e745f6c696d69741c012c4f7074696f6e3c7533323e0001406164646974696f6e616c5f6c696e6b7324015c4f7074696f6e3c4164646974696f6e616c4c696e6b733e00011c726f79616c747930010c7531360001407061796d656e745f666f725f6d696e74340110753132380001307472616e7366657261626c6538012c4f7074696f6e3c7536343e00012073656c6c61626c6538012c4f7074696f6e3c7536343e00001400000502001800000214001c04184f7074696f6e04045401200108104e6f6e6500000010536f6d6504002000000100002000000505002404184f7074696f6e04045401280108104e6f6e6500000010536f6d6504002800000100002808186e66745f696f3c4164646974696f6e616c4c696e6b73000014013065787465726e616c5f75726c2c01384f7074696f6e3c537472696e673e00012074656c656772616d2c01384f7074696f6e3c537472696e673e00011078636f6d2c01384f7074696f6e3c537472696e673e0001186d656469756d2c01384f7074696f6e3c537472696e673e00011c646973636f72642c01384f7074696f6e3c537472696e673e00002c04184f7074696f6e04045401140108104e6f6e6500000010536f6d6504001400000100003000000504003400000507003804184f7074696f6e040454013c0108104e6f6e6500000010536f6d6504003c00000100003c000005060040000002440044000004081448004808186e66745f696f24496d6167654461746100000801306c696d69745f636f706965731c012c4f7074696f6e3c7533323e00014c6175746f5f6368616e67696e675f72756c65734c01784f7074696f6e3c5665633c2854696d655365632c20416374696f6e293e3e00004c04184f7074696f6e04045401500108104e6f6e6500000010536f6d65040050000001000050000002540054000004082058005808186e66745f696f18416374696f6e000108244368616e6765496d670400140118537472696e670000001c4164644d6574610400140118537472696e67000100005c04184f7074696f6e04045401600108104e6f6e6500000010536f6d6504006000000100006000000204006408186e66745f696f244e6674416374696f6e000138205472616e73666572080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000000305472616e7366657246726f6d0c011066726f6d04011c4163746f724964000108746f04011c4163746f724964000120746f6b656e5f69643c01144e6674496400010030476574546f6b656e496e666f040120746f6b656e5f69643c01144e667449640002002443616e44656c657465000300104d696e740004001c417070726f7665080108746f04011c4163746f724964000120746f6b656e5f69643c01144e66744964000500385265766f6b65417070726f76616c040120746f6b656e5f69643c01144e6674496400060018457870616e640401406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000700304368616e6765436f6e666967040118636f6e666967100118436f6e666967000800244368616e6765496d67080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e670009002c4164644d65746164617461080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a003c4164645573657273466f724d696e7404011475736572736001305665633c4163746f7249643e000b004444656c65746555736572466f724d696e740401107573657204011c4163746f724964000c004c4c6966745265737472696374696f6e4d696e74000d0000680418526573756c74080454016c0445017c0108084f6b04006c000000000c45727204007c00000100006c08186e66745f696f204e66744576656e740001382c5472616e736665727265640c01146f776e657204011c4163746f724964000124726563697069656e7404011c4163746f724964000120746f6b656e5f69643c01144e6674496400000044546f6b656e496e666f526563656976656414012c746f6b656e5f6f776e657204011c4163746f724964000120617070726f76616c70013c4f7074696f6e3c4163746f7249643e00012073656c6c61626c65740110626f6f6c000140636f6c6c656374696f6e5f6f776e657204011c4163746f72496400011c726f79616c747930010c7531360001002443616e44656c6574650400740110626f6f6c0002002c496e697469616c697a6564080118636f6e666967100118436f6e666967000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e000300184d696e746564080120746f6b656e5f69643c01144e667449640001206e66745f6461746178010c4e667400040020417070726f766564080108746f04011c4163746f724964000120746f6b656e5f69643c01144e667449640005003c417070726f76616c5265766f6b6564040120746f6b656e5f69643c01144e6674496400060020457870616e6465640801406164646974696f6e616c5f6c696e6b734001605665633c28537472696e672c20496d61676544617461293e000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e00070034436f6e6669674368616e676564040118636f6e666967100118436f6e66696700080030496d6167654368616e676564080120746f6b656e5f69643c01144e66744964000120696d675f6c696e6b140118537472696e67000900344d657461646174614164646564080120746f6b656e5f69643c01144e667449640001206d65746164617461140118537472696e67000a00445573657273466f724d696e74416464656404011475736572736001305665633c4163746f7249643e000b004855736572466f724d696e7444656c657465640401107573657204011c4163746f724964000c004c4c6966745265737472696374696f6e4d696e74000d00007004184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100007400000500007808186e66745f696f0c4e667400001801146f776e657204011c4163746f7249640001106e616d65140118537472696e6700012c6465736372697074696f6e140118537472696e670001206d6574616461746118012c5665633c537472696e673e0001246d656469615f75726c140118537472696e670001246d696e745f74696d653c010c75363400007c08186e66745f696f204e66744572726f7200000400140118537472696e6700008008186e66745f696f2853746174655175657279000110104e616d650000002c4465736372697074696f6e00010018436f6e6669670002000c416c6c000300008408186e66745f696f2853746174655265706c79000110104e616d650400140118537472696e670000002c4465736372697074696f6e0400140118537472696e6700010018436f6e6669670400100118436f6e6669670002000c416c6c04008801204e66745374617465000300008808186e66745f696f204e667453746174650000240118746f6b656e738c01445665633c284e667449642c204e6674293e0001186f776e6572739401685665633c284163746f7249642c205665633c4e667449643e293e00013c746f6b656e5f617070726f76616c73a001545665633c284e667449642c204163746f724964293e000118636f6e666967100118436f6e6669670001146e6f6e63653c01144e66744964000148696d675f6c696e6b735f616e645f646174614001605665633c28537472696e672c20496d61676544617461293e000140636f6c6c656374696f6e5f6f776e657204011c4163746f724964000158746f74616c5f6e756d6265725f6f665f746f6b656e7338012c4f7074696f6e3c7536343e0001487065726d697373696f6e5f746f5f6d696e745c01504f7074696f6e3c5665633c4163746f7249643e3e00008c000002900090000004083c78009400000298009800000408049c009c0000023c00a0000002a400a4000004083c0400 \ No newline at end of file diff --git a/indexer/db/migrations/1708174915413-Data.js b/indexer/db/migrations/1708174915413-Data.js new file mode 100644 index 0000000..cd577ac --- /dev/null +++ b/indexer/db/migrations/1708174915413-Data.js @@ -0,0 +1,11 @@ +module.exports = class Data1708174915413 { + name = 'Data1708174915413' + + async up(db) { + await db.query(`ALTER TABLE "collection" ADD "permission_to_mint" text array`) + } + + async down(db) { + await db.query(`ALTER TABLE "collection" DROP COLUMN "permission_to_mint"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 5ebd5ec..7c3d23d 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -70,6 +70,7 @@ type Collection @entity { createdAt: DateTime! nfts: [Nft!]! @derivedFrom(field: "collection") tags: [String!]! + permissionToMint: [String!] } type Nft @entity { diff --git a/indexer/src/model/generated/collection.model.ts b/indexer/src/model/generated/collection.model.ts index dcf4754..f2ec639 100644 --- a/indexer/src/model/generated/collection.model.ts +++ b/indexer/src/model/generated/collection.model.ts @@ -104,4 +104,7 @@ export class Collection { @Column_('text', { array: true, nullable: false }) tags!: string[]; + + @Column_('text', { array: true, nullable: true }) + permissionToMint!: string[] | undefined | null; } diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index 02e731d..1e0eb44 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -40,6 +40,9 @@ import { EventInfo } from './event-info.type'; import { EntitiesService } from './entities.service'; import { IStorage } from './storage/storage.inteface'; import { ProgramMetadata } from '@gear-js/api'; +import { LiftRestrictionMintHandler } from './nft/lift-restriction-mint.handler'; +import { UserForMintDeletedHandler } from './nft/user-for-mint-deleted.handler'; +import { UsersForMintAddedHandler } from './nft/users-for-mint-added.handler'; const marketplaceEventsToHandler: Record< NftMarketplaceEventType, @@ -79,6 +82,9 @@ const nftEventsToHandler: Record = { [NftEventType.MetadataAdded]: new MetadataAddedHandler(), [NftEventType.TokenInfoReceived]: undefined, [NftEventType.Transferred]: new TransferredHandler(), + [NftEventType.UserForMintDeleted]: new UserForMintDeletedHandler(), + [NftEventType.UsersForMintAdded]: new UsersForMintAddedHandler(), + [NftEventType.LiftRestrictionMint]: new LiftRestrictionMintHandler(), }; export class EventsProcessing { diff --git a/indexer/src/processing/nft/config-changed.handler.ts b/indexer/src/processing/nft/config-changed.handler.ts index 244ecb1..42637a3 100644 --- a/indexer/src/processing/nft/config-changed.handler.ts +++ b/indexer/src/processing/nft/config-changed.handler.ts @@ -32,6 +32,7 @@ export class ConfigChangedHandler implements INftEventHandler { sellable, transferable, userMintLimit, + permissionToMint, } = event.config; await storage.setCollection( new Collection({ @@ -50,6 +51,7 @@ export class ConfigChangedHandler implements INftEventHandler { sellable, transferable, userMintLimit: userMintLimit, + permissionToMint, }), ); } diff --git a/indexer/src/processing/nft/initialized.handler.ts b/indexer/src/processing/nft/initialized.handler.ts index e26ca16..c6eecde 100644 --- a/indexer/src/processing/nft/initialized.handler.ts +++ b/indexer/src/processing/nft/initialized.handler.ts @@ -33,6 +33,7 @@ export class InitializedHandler implements INftEventHandler { transferable, userMintLimit, totalNumberOfTokens, + permissionToMint, } = event.config; await storage.setCollection( new Collection({ @@ -55,6 +56,7 @@ export class InitializedHandler implements INftEventHandler { transferable, tokensLimit: totalNumberOfTokens, userMintLimit: userMintLimit, + permissionToMint, createdAt: timestamp, }), ); diff --git a/indexer/src/processing/nft/lift-restriction-mint.handler.ts b/indexer/src/processing/nft/lift-restriction-mint.handler.ts new file mode 100644 index 0000000..1ab9286 --- /dev/null +++ b/indexer/src/processing/nft/lift-restriction-mint.handler.ts @@ -0,0 +1,27 @@ +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Collection } from '../../model'; +import { EventInfo } from '../event-info.type'; +import { LiftRestrictionMintEvent } from '../../types/nft.events'; + +export class LiftRestrictionMintHandler implements INftEventHandler { + async handle( + event: LiftRestrictionMintEvent, + { source: collectionAddress, timestamp }: EventInfo, + storage: EntitiesService, + ): Promise { + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[LiftRestrictionMintHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + await storage.setCollection( + new Collection({ + ...collection, + permissionToMint: null, + }), + ); + } +} diff --git a/indexer/src/processing/nft/user-for-mint-deleted.handler.ts b/indexer/src/processing/nft/user-for-mint-deleted.handler.ts new file mode 100644 index 0000000..cb98420 --- /dev/null +++ b/indexer/src/processing/nft/user-for-mint-deleted.handler.ts @@ -0,0 +1,28 @@ +import { UserForMintDeletedEvent } from '../../types/nft.events'; +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Collection } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class UserForMintDeletedHandler implements INftEventHandler { + async handle( + event: UserForMintDeletedEvent, + { source: collectionAddress, timestamp }: EventInfo, + storage: EntitiesService, + ): Promise { + const { user } = event; + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[UserForMintDeletedHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + await storage.setCollection( + new Collection({ + ...collection, + permissionToMint: (collection.permissionToMint || []).filter((u) => u !== user), + }), + ); + } +} diff --git a/indexer/src/processing/nft/users-for-mint-added.handler.ts b/indexer/src/processing/nft/users-for-mint-added.handler.ts new file mode 100644 index 0000000..cd64fee --- /dev/null +++ b/indexer/src/processing/nft/users-for-mint-added.handler.ts @@ -0,0 +1,28 @@ +import { UsersForMintAddedEvent } from '../../types/nft.events'; +import { EntitiesService } from '../entities.service'; +import { INftEventHandler } from './nft.handler'; +import { Collection } from '../../model'; +import { EventInfo } from '../event-info.type'; + +export class UsersForMintAddedHandler implements INftEventHandler { + async handle( + event: UsersForMintAddedEvent, + { source: collectionAddress, timestamp }: EventInfo, + storage: EntitiesService, + ): Promise { + const { users } = event; + const collection = await storage.getCollection(collectionAddress); + if (collection === undefined) { + console.warn( + `[UsersForMintAddedHandler] ${collectionAddress}: collection is not found`, + ); + return; + } + await storage.setCollection( + new Collection({ + ...collection, + permissionToMint: [...(collection.permissionToMint || []), ...users], + }), + ); + } +} diff --git a/indexer/src/types/nft.events.ts b/indexer/src/types/nft.events.ts index 5d80b08..a1f4eaa 100644 --- a/indexer/src/types/nft.events.ts +++ b/indexer/src/types/nft.events.ts @@ -17,6 +17,9 @@ export enum NftEventType { ConfigChanged = 'ConfigChanged', ImageChanged = 'ImageChanged', MetadataAdded = 'MetadataAdded', + UsersForMintAdded = 'UsersForMintAdded', + UserForMintDeleted = 'UserForMintDeleted', + LiftRestrictionMint = 'LiftRestrictionMint', } export type TransferEvent = { @@ -51,6 +54,7 @@ export type NftConfig = { sellable: bigint | null; attendable: boolean; totalNumberOfTokens: bigint | null; + permissionToMint: string[] | null; }; export type InitializedEvent = { @@ -113,6 +117,20 @@ export type AdditionalLink = { discord: string | null; }; +export type UsersForMintAddedEvent = { + type: NftEventType.UsersForMintAdded; + users: string[]; +}; + +export type UserForMintDeletedEvent = { + type: NftEventType.UserForMintDeleted; + user: string; +}; + +export type LiftRestrictionMintEvent = { + type: NftEventType.LiftRestrictionMint; +}; + export type NftEvent = | TransferEvent | TokenInfoReceivedEvent @@ -123,7 +141,10 @@ export type NftEvent = | ExpandedEvent | ConfigChangedEvent | ImageChangedEvent - | MetadataAddedEvent; + | MetadataAddedEvent + | UsersForMintAddedEvent + | UserForMintDeletedEvent + | LiftRestrictionMintEvent; export interface AdditionalLinkPlain { externalUrl: Option; @@ -166,6 +187,7 @@ export interface NftEventPlain extends Enum { initialized: { config: ConfigPlain; totalNumberOfTokens: u64; + permissionToMint: Option> }; minted: { tokenId: u64; @@ -190,6 +212,7 @@ export interface NftEventPlain extends Enum { configChanged: { config: ConfigPlain; totalNumberOfTokens: u64; + permissionToMint: Option> }; imageChanged: { tokenId: u64; @@ -199,6 +222,13 @@ export interface NftEventPlain extends Enum { tokenId: u64; metadata: Text; }; + usersForMintAdded: { + users: Vec + }; + userForMintDeleted: { + user: Hash + }; + liftRestrictionMint: {}; } export function getNftEvent(event: NftEventPlain): NftEvent | undefined { @@ -236,16 +266,16 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { ), additionalLinks: event.initialized.config.additionalLinks ? { - externalUrl: - event.initialized.config.additionalLinks.externalUrl.toString(), - telegram: - event.initialized.config.additionalLinks.telegram.toString(), - xcom: event.initialized.config.additionalLinks.xcom.toString(), - medium: - event.initialized.config.additionalLinks.medium.toString(), - discord: - event.initialized.config.additionalLinks.discord.toString(), - } + externalUrl: + event.initialized.config.additionalLinks.externalUrl.toString(), + telegram: + event.initialized.config.additionalLinks.telegram.toString(), + xcom: event.initialized.config.additionalLinks.xcom.toString(), + medium: + event.initialized.config.additionalLinks.medium.toString(), + discord: + event.initialized.config.additionalLinks.discord.toString(), + } : null, royalty: safeUnwrapToNumber(event.initialized.config.royalty)!, paymentForMint: safeUnwrapToBigInt( @@ -263,6 +293,7 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { totalNumberOfTokens: safeUnwrapToBigInt( safeUnwrapOptional(event.initialized.totalNumberOfTokens), ), + permissionToMint: safeUnwrapOptional, Vec>(event.initialized.permissionToMint)?.map((m: Text) => m.toString()) ?? null, }, }; } @@ -297,12 +328,12 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { type: NftEventType.Expanded, additionalLinks: event.expanded.additionalLinks ? { - externalUrl: event.expanded.additionalLinks.externalUrl.toString(), - telegram: event.expanded.additionalLinks.telegram.toString(), - xcom: event.expanded.additionalLinks.xcom.toString(), - medium: event.expanded.additionalLinks.medium.toString(), - discord: event.expanded.additionalLinks.discord.toString(), - } + externalUrl: event.expanded.additionalLinks.externalUrl.toString(), + telegram: event.expanded.additionalLinks.telegram.toString(), + xcom: event.expanded.additionalLinks.xcom.toString(), + medium: event.expanded.additionalLinks.medium.toString(), + discord: event.expanded.additionalLinks.discord.toString(), + } : null, }; } @@ -323,16 +354,16 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { ), additionalLinks: event.configChanged.config.additionalLinks ? { - externalUrl: - event.configChanged.config.additionalLinks.externalUrl.toString(), - telegram: - event.configChanged.config.additionalLinks.telegram.toString(), - xcom: event.configChanged.config.additionalLinks.xcom.toString(), - medium: - event.configChanged.config.additionalLinks.medium.toString(), - discord: - event.configChanged.config.additionalLinks.discord.toString(), - } + externalUrl: + event.configChanged.config.additionalLinks.externalUrl.toString(), + telegram: + event.configChanged.config.additionalLinks.telegram.toString(), + xcom: event.configChanged.config.additionalLinks.xcom.toString(), + medium: + event.configChanged.config.additionalLinks.medium.toString(), + discord: + event.configChanged.config.additionalLinks.discord.toString(), + } : null, royalty: safeUnwrapToNumber(event.configChanged.config.royalty)!, paymentForMint: safeUnwrapToBigInt( @@ -350,6 +381,7 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { totalNumberOfTokens: safeUnwrapToBigInt( safeUnwrapOptional(event.configChanged.totalNumberOfTokens), ), + permissionToMint: safeUnwrapOptional, Vec>(event.configChanged.permissionToMint)?.map((m: Text) => m.toString()) ?? null, }, }; } @@ -367,5 +399,22 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { metadata: event.metadataAdded.metadata.toString(), }; } + if (event.usersForMintAdded) { + return { + type: NftEventType.UsersForMintAdded, + users: event.usersForMintAdded.users.map((user) => user.toString()), + }; + } + if (event.userForMintDeleted) { + return { + type: NftEventType.UserForMintDeleted, + user: event.userForMintDeleted.user.toString(), + }; + } + if (event.liftRestrictionMint) { + return { + type: NftEventType.LiftRestrictionMint, + }; + } return undefined; } From 1c16873df66faab3f73b65cfcc71637d926b66e6 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 22 Feb 2024 18:28:11 +0300 Subject: [PATCH 38/50] add marketplace init --- indexer/assets/nft_marketplace.meta.txt | 2 +- indexer/db/migrations/1708614382580-Data.js | 15 ++++ indexer/schema.graphql | 3 + .../generated/marketplaceConfig.model.ts | 12 ++++ indexer/src/processing/batch.service.ts | 3 + indexer/src/processing/entities.service.ts | 3 + indexer/src/processing/events.processing.ts | 6 +- .../marketplace/config-updated.handler.ts | 24 ++----- .../marketplace/initialized.handler.ts | 24 +++++++ .../src/processing/nft/initialized.handler.ts | 4 +- .../nft/user-for-mint-deleted.handler.ts | 4 +- .../src/processing/storage/local.storage.ts | 2 + indexer/src/types/marketplace.events.ts | 56 ++++++++++++++- indexer/src/types/nft.events.ts | 70 ++++++++++--------- 14 files changed, 171 insertions(+), 57 deletions(-) create mode 100644 indexer/db/migrations/1708614382580-Data.js create mode 100644 indexer/src/processing/marketplace/initialized.handler.ts diff --git a/indexer/assets/nft_marketplace.meta.txt b/indexer/assets/nft_marketplace.meta.txt index c421bcc..2150a60 100644 --- a/indexer/assets/nft_marketplace.meta.txt +++ b/indexer/assets/nft_marketplace.meta.txt @@ -1 +1 @@ -0002000100000000000104000000011000000000000000011300000001140000001551a80008486e66745f6d61726b6574706c6163655f696f484e66744d61726b6574706c616365496e697400002001406761735f666f725f6372656174696f6e04010c7536340001586761735f666f725f7472616e736665725f746f6b656e04010c7536340001546761735f666f725f636c6f73655f61756374696f6e04010c7536340001646761735f666f725f64656c6574655f636f6c6c656374696f6e04010c7536340001586761735f666f725f6765745f746f6b656e5f696e666f04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001586d696e696d756d5f7472616e736665725f76616c75650801107531323800012c6d735f696e5f626c6f636b0c010c75333200000400000506000800000507000c00000505001008486e66745f6d61726b6574706c6163655f696f504e66744d61726b6574706c616365416374696f6e000140404164644e6577436f6c6c656374696f6e10011c636f64655f6964140118436f646549640001246d6574615f6c696e6b200118537472696e67000124747970655f6e616d65200118537472696e67000140747970655f6465736372697074696f6e200118537472696e6700000040437265617465436f6c6c656374696f6e080124747970655f6e616d65200118537472696e6700011c7061796c6f616424011c5665633c75383e0001001c53616c654e66740c0148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380002003443616e63656c53616c654e6674080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000300184275794e6674080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340004003443726561746541756374696f6e100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d730c010c75333200050018416464426964080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400060030436c6f736541756374696f6e080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340007003443616e63656c41756374696f6e080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340008002c4372656174654f66666572080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340009002c43616e63656c4f66666572080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000a002c4163636570744f666665720401146f666665722c01144f66666572000b004044656c657465436f6c6c656374696f6e040148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000c002441646441646d696e7304011475736572733001305665633c4163746f7249643e000d002c44656c65746541646d696e0401107573657228011c4163746f724964000e0030557064617465436f6e6669672001406761735f666f725f6372656174696f6e34012c4f7074696f6e3c7536343e0001586761735f666f725f7472616e736665725f746f6b656e34012c4f7074696f6e3c7536343e0001546761735f666f725f636c6f73655f61756374696f6e34012c4f7074696f6e3c7536343e0001646761735f666f725f64656c6574655f636f6c6c656374696f6e34012c4f7074696f6e3c7536343e0001586761735f666f725f6765745f746f6b656e5f696e666f34012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7334012c4f7074696f6e3c7536343e0001586d696e696d756d5f7472616e736665725f76616c75653801304f7074696f6e3c753132383e00012c6d735f696e5f626c6f636b3c012c4f7074696f6e3c7533323e000f00001410106773746418636f6d6d6f6e287072696d69746976657318436f64654964000004001801205b75383b2033325d000018000003200000001c001c0000050300200000050200240000021c002810106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004001801205b75383b2033325d00002c08486e66745f6d61726b6574706c6163655f696f144f6666657200000c0148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400011c63726561746f7228011c4163746f72496400003000000228003404184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100003804184f7074696f6e04045401080108104e6f6e6500000010536f6d6504000800000100003c04184f7074696f6e040454010c0108104e6f6e6500000010536f6d6504000c0000010000400418526573756c740804540144044501480108084f6b040044000000000c45727204004800000100004408486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654576656e74000140484e6577436f6c6c656374696f6e416464656410011c636f64655f6964140118436f646549640001246d6574615f6c696e6b200118537472696e67000124747970655f6e616d65200118537472696e67000140747970655f6465736372697074696f6e200118537472696e6700000044436f6c6c656374696f6e43726561746564080124747970655f6e616d65200118537472696e67000148636f6c6c656374696f6e5f6164647265737328011c4163746f7249640001001c53616c654e6674100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380001146f776e657228011c4163746f7249640002003c53616c654e667443616e63656c6564080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340003001c4e6674536f6c64100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400011470726963650801107531323800013463757272656e745f6f776e657228011c4163746f7249640004003841756374696f6e43726561746564100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d730c010c7533320005003441756374696f6e436c6f736564100148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400011470726963650801107531323800013463757272656e745f6f776e657228011c4163746f7249640006002042696441646465640c0148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c75363400013463757272656e745f7072696365080110753132380007003c41756374696f6e43616e63656c6564080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000800304f66666572437265617465640c0148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000114707269636508011075313238000900344f6666657243616e63656c6564080148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000120746f6b656e5f696404010c753634000a00344f6666657241636365707465640401146f666665722c01144f66666572000b0044436f6c6c656374696f6e44656c65746564040148636f6c6c656374696f6e5f6164647265737328011c4163746f724964000c002c41646d696e73416464656404011475736572733001305665633c4163746f7249643e000d003041646d696e44656c657465640401107573657228011c4163746f724964000e0034436f6e666967557064617465642001406761735f666f725f6372656174696f6e34012c4f7074696f6e3c7536343e0001586761735f666f725f7472616e736665725f746f6b656e34012c4f7074696f6e3c7536343e0001546761735f666f725f636c6f73655f61756374696f6e34012c4f7074696f6e3c7536343e0001646761735f666f725f64656c6574655f636f6c6c656374696f6e34012c4f7074696f6e3c7536343e0001586761735f666f725f6765745f746f6b656e5f696e666f34012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7334012c4f7074696f6e3c7536343e0001586d696e696d756d5f7472616e736665725f76616c75653801304f7074696f6e3c753132383e00012c6d735f696e5f626c6f636b3c012c4f7074696f6e3c7533323e000f00004808486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654572726f7200000400200118537472696e6700004c08486e66745f6d61726b6574706c6163655f696f28537461746551756572790001180c416c6c0000001841646d696e730001003c436f6c6c656374696f6e73496e666f00020018436f6e66696700030038416c6c436f6c6c656374696f6e7300040044476574436f6c6c656374696f6e496e666f040028011c4163746f724964000500005008486e66745f6d61726b6574706c6163655f696f2853746174655265706c790001180c416c6c040054011453746174650000001841646d696e7304003001305665633c4163746f7249643e0001003c436f6c6c656374696f6e73496e666f04006c01845665633c28537472696e672c2054797065436f6c6c656374696f6e496e666f293e00020018436f6e66696704009c0118436f6e66696700030038416c6c436f6c6c656374696f6e7304005801845665633c284163746f7249642c2028537472696e672c204163746f72496429293e00040038436f6c6c656374696f6e496e666f0400a001584f7074696f6e3c436f6c6c656374696f6e496e666f3e000500005408486e66745f6d61726b6574706c6163655f696f145374617465000020011861646d696e733001305665633c4163746f7249643e00014c636f6c6c656374696f6e5f746f5f6f776e65725801845665633c284163746f7249642c2028537472696e672c204163746f72496429293e00013474696d655f6372656174696f6e64014c5665633c284163746f7249642c20753634293e000140747970655f636f6c6c656374696f6e736c01845665633c28537472696e672c2054797065436f6c6c656374696f6e496e666f293e00011473616c65737801945665633c28284163746f7249642c20753634292c204e6674496e666f466f7253616c65293e00012061756374696f6e738801785665633c28284163746f7249642c20753634292c2041756374696f6e293e0001186f66666572739401485665633c284f666665722c2075313238293e000118636f6e6669679c0118436f6e6669670000580000025c005c00000408286000600000040820280064000002680068000004082804006c000002700070000004082074007408486e66745f6d61726b6574706c6163655f696f4854797065436f6c6c656374696f6e496e666f00000c011c636f64655f6964140118436f646549640001246d6574615f6c696e6b200118537472696e67000140747970655f6465736372697074696f6e200118537472696e670000780000027c007c000004086880008008486e66745f6d61726b6574706c6163655f696f384e6674496e666f466f7253616c65000010011470726963650801107531323800012c746f6b656e5f6f776e657228011c4163746f724964000140636f6c6c656374696f6e5f6f776e657228011c4163746f72496400011c726f79616c747984010c7531360000840000050400880000028c008c000004086890009008486e66745f6d61726b6574706c6163655f696f1c41756374696f6e00001c01146f776e657228011c4163746f724964000128737461727465645f617404010c753634000120656e6465645f617404010c75363400013463757272656e745f70726963650801107531323800013863757272656e745f77696e6e657228011c4163746f724964000140636f6c6c656374696f6e5f6f776e657228011c4163746f72496400011c726f79616c747984010c753136000094000002980098000004082c08009c08486e66745f6d61726b6574706c6163655f696f18436f6e66696700002001406761735f666f725f6372656174696f6e04010c7536340001586761735f666f725f7472616e736665725f746f6b656e04010c7536340001546761735f666f725f636c6f73655f61756374696f6e04010c7536340001646761735f666f725f64656c6574655f636f6c6c656374696f6e04010c7536340001586761735f666f725f6765745f746f6b656e5f696e666f04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001586d696e696d756d5f7472616e736665725f76616c75650801107531323800012c6d735f696e5f626c6f636b0c010c7533320000a004184f7074696f6e04045401a40108104e6f6e6500000010536f6d650400a40000010000a408486e66745f6d61726b6574706c6163655f696f38436f6c6c656374696f6e496e666f00000c01146f776e657228011c4163746f724964000124747970655f6e616d65200118537472696e670001246d6574615f6c696e6b200118537472696e670000 \ No newline at end of file +0002000100000000000105000000011200000000000000011500000001160000000166ac0008486e66745f6d61726b6574706c6163655f696f484e66744d61726b6574706c616365496e697400003001406761735f666f725f6372656174696f6e04010c7536340001586761735f666f725f7472616e736665725f746f6b656e04010c7536340001306761735f666f725f6d696e7404010c7536340001546761735f666f725f636c6f73655f61756374696f6e04010c7536340001646761735f666f725f64656c6574655f636f6c6c656374696f6e04010c7536340001406761735f666f725f6765745f696e666f04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001546665655f7065725f75706c6f616465645f66696c6508011075313238000180726f79616c74795f746f5f6d61726b6574706c6163655f666f725f74726164650c010c75313600017c726f79616c74795f746f5f6d61726b6574706c6163655f666f725f6d696e740c010c7531360001586d696e696d756d5f7472616e736665725f76616c75650801107531323800012c6d735f696e5f626c6f636b10010c75333200000400000506000800000507000c00000504001000000505001408486e66745f6d61726b6574706c6163655f696f504e66744d61726b6574706c616365416374696f6e000144404164644e6577436f6c6c656374696f6e10011c636f64655f6964180118436f646549640001246d6574615f6c696e6b240118537472696e67000124747970655f6e616d65240118537472696e67000140747970655f6465736372697074696f6e240118537472696e6700000040437265617465436f6c6c656374696f6e080124747970655f6e616d65240118537472696e6700011c7061796c6f616428011c5665633c75383e000100104d696e74040148636f6c6c656374696f6e5f616464726573732c011c4163746f7249640002001c53616c654e66740c0148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380003003443616e63656c53616c654e6674080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c753634000400184275794e6674080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c7536340005003443726561746541756374696f6e100148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d7310010c75333200060018416464426964080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c75363400070030436c6f736541756374696f6e080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c7536340008003443616e63656c41756374696f6e080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c7536340009002c4372656174654f66666572080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c753634000a002c43616e63656c4f66666572080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c753634000b002c4163636570744f666665720401146f666665723001144f66666572000c004044656c657465436f6c6c656374696f6e040148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000d002441646441646d696e7304011475736572733401305665633c4163746f7249643e000e002c44656c65746541646d696e040110757365722c011c4163746f724964000f0030557064617465436f6e6669673001406761735f666f725f6372656174696f6e38012c4f7074696f6e3c7536343e0001306761735f666f725f6d696e7438012c4f7074696f6e3c7536343e0001586761735f666f725f7472616e736665725f746f6b656e38012c4f7074696f6e3c7536343e0001546761735f666f725f636c6f73655f61756374696f6e38012c4f7074696f6e3c7536343e0001646761735f666f725f64656c6574655f636f6c6c656374696f6e38012c4f7074696f6e3c7536343e0001406761735f666f725f6765745f696e666f38012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7338012c4f7074696f6e3c7536343e0001546665655f7065725f75706c6f616465645f66696c653c01304f7074696f6e3c753132383e000180726f79616c74795f746f5f6d61726b6574706c6163655f666f725f747261646540012c4f7074696f6e3c7531363e00017c726f79616c74795f746f5f6d61726b6574706c6163655f666f725f6d696e7440012c4f7074696f6e3c7531363e0001586d696e696d756d5f7472616e736665725f76616c75653c01304f7074696f6e3c753132383e00012c6d735f696e5f626c6f636b44012c4f7074696f6e3c7533323e001000001810106773746418636f6d6d6f6e287072696d69746976657318436f64654964000004001c01205b75383b2033325d00001c0000032000000020002000000503002400000502002800000220002c10106773746418636f6d6d6f6e287072696d6974697665731c4163746f724964000004001c01205b75383b2033325d00003008486e66745f6d61726b6574706c6163655f696f144f6666657200000c0148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c75363400011c63726561746f722c011c4163746f7249640000340000022c003804184f7074696f6e04045401040108104e6f6e6500000010536f6d6504000400000100003c04184f7074696f6e04045401080108104e6f6e6500000010536f6d6504000800000100004004184f7074696f6e040454010c0108104e6f6e6500000010536f6d6504000c00000100004404184f7074696f6e04045401100108104e6f6e6500000010536f6d650400100000010000480418526573756c74080454014c044501500108084f6b04004c000000000c45727204005000000100004c08486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654576656e7400014c2c496e697469616c697a656410017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001546665655f7065725f75706c6f616465645f66696c6508011075313238000180726f79616c74795f746f5f6d61726b6574706c6163655f666f725f74726164650c010c75313600017c726f79616c74795f746f5f6d61726b6574706c6163655f666f725f6d696e740c010c753136000000484e6577436f6c6c656374696f6e416464656410011c636f64655f6964180118436f646549640001246d6574615f6c696e6b240118537472696e67000124747970655f6e616d65240118537472696e67000140747970655f6465736372697074696f6e240118537472696e6700010044436f6c6c656374696f6e43726561746564080124747970655f6e616d65240118537472696e67000148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000200184d696e746564080148636f6c6c656374696f6e5f616464726573732c011c4163746f7249640001186d696e7465722c011c4163746f7249640003001c53616c654e6674100148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c7536340001147072696365080110753132380001146f776e65722c011c4163746f7249640004003c53616c654e667443616e63656c6564080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c7536340005001c4e6674536f6c64100148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c75363400011470726963650801107531323800013463757272656e745f6f776e65722c011c4163746f7249640006003841756374696f6e43726561746564100148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c7536340001246d696e5f70726963650801107531323800012c6475726174696f6e5f6d7310010c7533320007003441756374696f6e436c6f736564100148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c75363400011470726963650801107531323800013463757272656e745f6f776e65722c011c4163746f7249640008002042696441646465640c0148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c75363400013463757272656e745f7072696365080110753132380009003c41756374696f6e43616e63656c6564080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c753634000a00304f66666572437265617465640c0148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c753634000114707269636508011075313238000b00344f6666657243616e63656c6564080148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000120746f6b656e5f696404010c753634000c00344f6666657241636365707465640401146f666665723001144f66666572000d0044436f6c6c656374696f6e44656c65746564040148636f6c6c656374696f6e5f616464726573732c011c4163746f724964000e002c41646d696e73416464656404011475736572733401305665633c4163746f7249643e000f003041646d696e44656c65746564040110757365722c011c4163746f72496400100034436f6e666967557064617465643001406761735f666f725f6372656174696f6e38012c4f7074696f6e3c7536343e0001306761735f666f725f6d696e7438012c4f7074696f6e3c7536343e0001586761735f666f725f7472616e736665725f746f6b656e38012c4f7074696f6e3c7536343e0001546761735f666f725f636c6f73655f61756374696f6e38012c4f7074696f6e3c7536343e0001646761735f666f725f64656c6574655f636f6c6c656374696f6e38012c4f7074696f6e3c7536343e0001406761735f666f725f6765745f696e666f38012c4f7074696f6e3c7536343e00017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7338012c4f7074696f6e3c7536343e0001546665655f7065725f75706c6f616465645f66696c653c01304f7074696f6e3c753132383e000180726f79616c74795f746f5f6d61726b6574706c6163655f666f725f747261646540012c4f7074696f6e3c7531363e00017c726f79616c74795f746f5f6d61726b6574706c6163655f666f725f6d696e7440012c4f7074696f6e3c7531363e0001586d696e696d756d5f7472616e736665725f76616c75653c01304f7074696f6e3c753132383e00012c6d735f696e5f626c6f636b44012c4f7074696f6e3c7533323e0011005c42616c616e63654861734265656e57697468647261776e04011476616c756508011075313238001200005008486e66745f6d61726b6574706c6163655f696f4c4e66744d61726b6574706c6163654572726f720001585857726f6e67436f6c6c656374696f6e4164647265737300000040416c72656164794f6e41756374696f6e0001003441756374696f6e436c6f73656400020034416c72656164794f6e53616c65000300684c6573735468616e4578697374656e7469616c4465706f7369740004002857726f6e675265706c790005004c57726f6e67436f6c6c656374696f6e4e616d650006003041636365737344656e69656400070034446561646c696e654572726f7200080050546865726549734e6f5375636841756374696f6e000900484c6573734f72457175616c5468616e426964000a002c4e6f7453656c6c61626c65000b00584e6f417070726f7665546f4d61726b6574706c616365000c004c4572726f7246726f6d436f6c6c656374696f6e000d003857726f6e67446174614f66666572000e00444f66666572446f65734e6f744578697374000f004053616c65446f65734e6f7445786973740010005056616c756549734c6573735468616e5072696365001100344372656174696f6e4572726f72001200304572726f72476574496e666f0013002857726f6e6756616c7565001400244d696e744572726f72001500005408486e66745f6d61726b6574706c6163655f696f28537461746551756572790001180c416c6c0000001841646d696e730001003c436f6c6c656374696f6e73496e666f00020018436f6e66696700030038416c6c436f6c6c656374696f6e7300040044476574436f6c6c656374696f6e496e666f04002c011c4163746f724964000500005808486e66745f6d61726b6574706c6163655f696f2853746174655265706c790001180c416c6c04005c011453746174650000001841646d696e7304003401305665633c4163746f7249643e0001003c436f6c6c656374696f6e73496e666f04007401845665633c28537472696e672c2054797065436f6c6c656374696f6e496e666f293e00020018436f6e6669670400a00118436f6e66696700030038416c6c436f6c6c656374696f6e7304006001845665633c284163746f7249642c2028537472696e672c204163746f72496429293e00040038436f6c6c656374696f6e496e666f0400a401584f7074696f6e3c436f6c6c656374696f6e496e666f3e000500005c08486e66745f6d61726b6574706c6163655f696f145374617465000020011861646d696e733401305665633c4163746f7249643e00014c636f6c6c656374696f6e5f746f5f6f776e65726001845665633c284163746f7249642c2028537472696e672c204163746f72496429293e00013474696d655f6372656174696f6e6c014c5665633c284163746f7249642c20753634293e000140747970655f636f6c6c656374696f6e737401845665633c28537472696e672c2054797065436f6c6c656374696f6e496e666f293e00011473616c65738001945665633c28284163746f7249642c20753634292c204e6674496e666f466f7253616c65293e00012061756374696f6e738c01785665633c28284163746f7249642c20753634292c2041756374696f6e293e0001186f66666572739801485665633c284f666665722c2075313238293e000118636f6e666967a00118436f6e666967000060000002640064000004082c68006800000408242c006c000002700070000004082c04007400000278007800000408247c007c08486e66745f6d61726b6574706c6163655f696f4854797065436f6c6c656374696f6e496e666f00000c011c636f64655f6964180118436f646549640001246d6574615f6c696e6b240118537472696e67000140747970655f6465736372697074696f6e240118537472696e67000080000002840084000004087088008808486e66745f6d61726b6574706c6163655f696f384e6674496e666f466f7253616c65000010011470726963650801107531323800012c746f6b656e5f6f776e65722c011c4163746f724964000140636f6c6c656374696f6e5f6f776e65722c011c4163746f72496400011c726f79616c74790c010c75313600008c000002900090000004087094009408486e66745f6d61726b6574706c6163655f696f1c41756374696f6e00001c01146f776e65722c011c4163746f724964000128737461727465645f617404010c753634000120656e6465645f617404010c75363400013463757272656e745f70726963650801107531323800013863757272656e745f77696e6e65722c011c4163746f724964000140636f6c6c656374696f6e5f6f776e65722c011c4163746f72496400011c726f79616c74790c010c7531360000980000029c009c00000408300800a008486e66745f6d61726b6574706c6163655f696f18436f6e66696700003001406761735f666f725f6372656174696f6e04010c7536340001306761735f666f725f6d696e7404010c7536340001586761735f666f725f7472616e736665725f746f6b656e04010c7536340001546761735f666f725f636c6f73655f61756374696f6e04010c7536340001646761735f666f725f64656c6574655f636f6c6c656374696f6e04010c7536340001406761735f666f725f6765745f696e666f04010c75363400017c74696d655f6265747765656e5f6372656174655f636f6c6c656374696f6e7304010c7536340001546665655f7065725f75706c6f616465645f66696c6508011075313238000180726f79616c74795f746f5f6d61726b6574706c6163655f666f725f74726164650c010c75313600017c726f79616c74795f746f5f6d61726b6574706c6163655f666f725f6d696e740c010c7531360001586d696e696d756d5f7472616e736665725f76616c75650801107531323800012c6d735f696e5f626c6f636b10010c7533320000a404184f7074696f6e04045401a80108104e6f6e6500000010536f6d650400a80000010000a808486e66745f6d61726b6574706c6163655f696f38436f6c6c656374696f6e496e666f00000c01146f776e65722c011c4163746f724964000124747970655f6e616d65240118537472696e670001246d6574615f6c696e6b240118537472696e670000 diff --git a/indexer/db/migrations/1708614382580-Data.js b/indexer/db/migrations/1708614382580-Data.js new file mode 100644 index 0000000..ce4e9c6 --- /dev/null +++ b/indexer/db/migrations/1708614382580-Data.js @@ -0,0 +1,15 @@ +module.exports = class Data1708614382580 { + name = 'Data1708614382580' + + async up(db) { + await db.query(`ALTER TABLE "marketplace_config" ADD "royalty_to_marketplace_for_mint" integer`) + await db.query(`ALTER TABLE "marketplace_config" ADD "royalty_to_marketplace_for_trade" integer`) + await db.query(`ALTER TABLE "marketplace_config" ADD "fee_per_uploaded_file" numeric`) + } + + async down(db) { + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "royalty_to_marketplace_for_mint"`) + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "royalty_to_marketplace_for_trade"`) + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "fee_per_uploaded_file"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 7c3d23d..4fcb7d4 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -17,6 +17,9 @@ type MarketplaceConfig @entity { gasForDeleteCollection: Int gasForGetTokenInfo: Int timeBetweenCreateCollections: Int + royaltyToMarketplaceForMint: Int + royaltyToMarketplaceForTrade: Int + feePerUploadedFile: BigInt minimumTransferValue: BigInt msInBlock: Int marketplace: Marketplace! diff --git a/indexer/src/model/generated/marketplaceConfig.model.ts b/indexer/src/model/generated/marketplaceConfig.model.ts index ba153f9..d634622 100644 --- a/indexer/src/model/generated/marketplaceConfig.model.ts +++ b/indexer/src/model/generated/marketplaceConfig.model.ts @@ -35,6 +35,18 @@ export class MarketplaceConfig { @Column_('int4', { nullable: true }) timeBetweenCreateCollections!: number | undefined | null; + @Column_('int4', { nullable: true }) + royaltyToMarketplaceForMint!: number | undefined | null; + + @Column_('int4', { nullable: true }) + royaltyToMarketplaceForTrade!: number | undefined | null; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: true, + }) + feePerUploadedFile!: bigint | undefined | null; + @Column_('numeric', { transformer: marshal.bigintTransformer, nullable: true, diff --git a/indexer/src/processing/batch.service.ts b/indexer/src/processing/batch.service.ts index b8c8b69..3bf8245 100644 --- a/indexer/src/processing/batch.service.ts +++ b/indexer/src/processing/batch.service.ts @@ -27,6 +27,9 @@ export class BatchService { constructor(private readonly store: Store) {} async saveAll() { + await (this.marketplace?.config + ? this.store.save(this.marketplace.config) + : Promise.resolve()); await Promise.all([ this.marketplace ? this.store.save(this.marketplace) : Promise.resolve(), this.store.save(this.collectionTypes), diff --git a/indexer/src/processing/entities.service.ts b/indexer/src/processing/entities.service.ts index 9ac72fe..047cd91 100644 --- a/indexer/src/processing/entities.service.ts +++ b/indexer/src/processing/entities.service.ts @@ -118,6 +118,9 @@ export class EntitiesService { async setMarketplaceConfig(marketplaceConfig: MarketplaceConfig) { const marketplace = this.storage.getMarketplace(); + if (marketplaceConfig.id === undefined) { + marketplaceConfig.id = uuidv4(); + } marketplace.config = marketplaceConfig; await this.storage.updateMarketplace(marketplace); this.batchService.setMarketplace(marketplace); diff --git a/indexer/src/processing/events.processing.ts b/indexer/src/processing/events.processing.ts index 1e0eb44..88a2f5f 100644 --- a/indexer/src/processing/events.processing.ts +++ b/indexer/src/processing/events.processing.ts @@ -16,7 +16,7 @@ import { AuctionCreatedHandler } from './marketplace/auction-created.handler'; import { AuctionCanceledHandler } from './marketplace/auction-canceled.handler'; import { CollectionDeletedHandler } from './marketplace/collection-deleted.handler'; import { NftSoldHandler } from './marketplace/nft-sold.handler'; -import { InitializedHandler } from './nft/initialized.handler'; +import { NftInitializedHandler } from './nft/initialized.handler'; import { INftEventHandler } from './nft/nft.handler'; import { NftMintedHandler } from './nft/nft-minted.handler'; import { CollectionCreatedHandler } from './marketplace/collection-created.handler'; @@ -43,11 +43,13 @@ import { ProgramMetadata } from '@gear-js/api'; import { LiftRestrictionMintHandler } from './nft/lift-restriction-mint.handler'; import { UserForMintDeletedHandler } from './nft/user-for-mint-deleted.handler'; import { UsersForMintAddedHandler } from './nft/users-for-mint-added.handler'; +import { MarketplaceInitializedHandler } from './marketplace/initialized.handler'; const marketplaceEventsToHandler: Record< NftMarketplaceEventType, INftMarketplaceEventHandler | undefined > = { + [NftMarketplaceEventType.Initialized]: new MarketplaceInitializedHandler(), [NftMarketplaceEventType.NewCollectionAdded]: new NewCollectionAddedHandler(), [NftMarketplaceEventType.CollectionCreated]: new CollectionCreatedHandler(), [NftMarketplaceEventType.CollectionDeleted]: new CollectionDeletedHandler(), @@ -72,7 +74,7 @@ const marketplaceEventsToHandler: Record< }; const nftEventsToHandler: Record = { - [NftEventType.Initialized]: new InitializedHandler(), + [NftEventType.Initialized]: new NftInitializedHandler(), [NftEventType.Minted]: new NftMintedHandler(), [NftEventType.Approved]: new NftApprovedHandler(), [NftEventType.ApprovalRevoked]: new NftApprovalRevokedHandler(), diff --git a/indexer/src/processing/marketplace/config-updated.handler.ts b/indexer/src/processing/marketplace/config-updated.handler.ts index 5c71003..86918cc 100644 --- a/indexer/src/processing/marketplace/config-updated.handler.ts +++ b/indexer/src/processing/marketplace/config-updated.handler.ts @@ -10,26 +10,14 @@ export class ConfigUpdatedHandler implements INftMarketplaceEventHandler { eventInfo: EventInfo, storage: EntitiesService, ): Promise { - let { - gasForCloseAuction, - gasForCreation, - gasForDeleteCollection, - gasForGetTokenInfo, - gasForTransferToken, - minimumTransferValue, - msInBlock, - timeBetweenCreateCollections, - } = event; + const marketplace = storage.getMarketplace(); await storage.setMarketplaceConfig( new MarketplaceConfig({ - gasForCloseAuction, - gasForCreation, - gasForDeleteCollection, - gasForGetTokenInfo, - gasForTransferToken, - minimumTransferValue, - msInBlock, - timeBetweenCreateCollections, + ...(marketplace.config || {}), + ...Object.fromEntries( + Object.entries(event).filter(([, value]) => value !== null), + ), + marketplace, }), ); } diff --git a/indexer/src/processing/marketplace/initialized.handler.ts b/indexer/src/processing/marketplace/initialized.handler.ts new file mode 100644 index 0000000..78df677 --- /dev/null +++ b/indexer/src/processing/marketplace/initialized.handler.ts @@ -0,0 +1,24 @@ +import { EntitiesService } from '../entities.service'; +import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; +import { MarketplaceConfig } from '../../model'; +import { EventInfo } from '../event-info.type'; +import { Initialized } from '../../types/marketplace.events'; + +export class MarketplaceInitializedHandler implements INftMarketplaceEventHandler { + async handle( + event: Initialized, + eventInfo: EventInfo, + storage: EntitiesService, + ): Promise { + const marketplace = storage.getMarketplace(); + await storage.setMarketplaceConfig( + new MarketplaceConfig({ + ...(marketplace.config || {}), + ...Object.fromEntries( + Object.entries(event).filter(([, value]) => value !== null), + ), + marketplace, + }), + ); + } +} diff --git a/indexer/src/processing/nft/initialized.handler.ts b/indexer/src/processing/nft/initialized.handler.ts index c6eecde..b21af23 100644 --- a/indexer/src/processing/nft/initialized.handler.ts +++ b/indexer/src/processing/nft/initialized.handler.ts @@ -4,7 +4,7 @@ import { INftEventHandler } from './nft.handler'; import { AdditionalLinks, Collection } from '../../model'; import { EventInfo } from '../event-info.type'; -export class InitializedHandler implements INftEventHandler { +export class NftInitializedHandler implements INftEventHandler { async handle( event: InitializedEvent, { source: collectionAddress, destination, timestamp }: EventInfo, @@ -17,7 +17,7 @@ export class InitializedHandler implements INftEventHandler { ); return; } - let { + const { name, description, additionalLinks, diff --git a/indexer/src/processing/nft/user-for-mint-deleted.handler.ts b/indexer/src/processing/nft/user-for-mint-deleted.handler.ts index cb98420..d30625a 100644 --- a/indexer/src/processing/nft/user-for-mint-deleted.handler.ts +++ b/indexer/src/processing/nft/user-for-mint-deleted.handler.ts @@ -21,7 +21,9 @@ export class UserForMintDeletedHandler implements INftEventHandler { await storage.setCollection( new Collection({ ...collection, - permissionToMint: (collection.permissionToMint || []).filter((u) => u !== user), + permissionToMint: (collection.permissionToMint || []).filter( + (u) => u !== user, + ), }), ); } diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index e2b187d..49ce571 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -3,6 +3,7 @@ import { Collection, CollectionType, Marketplace, + MarketplaceConfig, Nft, Offer, Sale, @@ -11,6 +12,7 @@ import { Store } from '@subsquid/typeorm-store'; import { IStorage } from './storage.inteface'; import { config } from '../../config'; import { readFileSync } from 'fs'; +import { v4 as uuidv4 } from 'uuid'; let storage: LocalStorage | undefined; diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index 277d315..8febd5a 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -1,4 +1,4 @@ -import { Enum, Option, Text, Vec, u64, u128, u32 } from '@polkadot/types'; +import { Enum, Option, Text, Vec, u64, u128, u32, u16 } from '@polkadot/types'; import { Hash } from '@polkadot/types/interfaces'; import { CodeId } from '@gear-js/api'; import { @@ -8,6 +8,7 @@ import { } from './event.utils'; export enum NftMarketplaceEventType { + Initialized = 'isInitialized', NewCollectionAdded = 'isNewCollectionAdded', CollectionCreated = 'isCollectionCreated', SaleNft = 'isSaleNft', @@ -26,6 +27,14 @@ export enum NftMarketplaceEventType { ConfigUpdated = 'isConfigUpdated', } +export type Initialized = { + type: NftMarketplaceEventType.Initialized; + timeBetweenCreateCollections: number | null; + feePerUploadedFile: bigint | null; + royaltyToMarketplaceForTrade: number | null; + royaltyToMarketplaceForMint: number | null; +}; + export type NewCollectionAdded = { type: NftMarketplaceEventType.NewCollectionAdded; codeId: string; @@ -138,11 +147,15 @@ export type ConfigUpdated = { gasForDeleteCollection: number | null; gasForGetTokenInfo: number | null; timeBetweenCreateCollections: number | null; + feePerUploadedFile: bigint | null; + royaltyToMarketplaceForTrade: number | null; + royaltyToMarketplaceForMint: number | null; minimumTransferValue: bigint | null; msInBlock: number | null; }; export type NftMarketplaceEvent = + | Initialized | NewCollectionAdded | CollectionCreated | SaleNft @@ -161,6 +174,12 @@ export type NftMarketplaceEvent = | ConfigUpdated; export interface NftMarketplaceEventPlain extends Enum { + initialized: { + timeBetweenCreateCollections: u64; + feePerUploadedFile: u128; + royaltyToMarketplaceForTrade: u16; + royaltyToMarketplaceForMint: u16; + }; newCollectionAdded: { codeId: CodeId; metaLink: Text; @@ -244,6 +263,9 @@ export interface NftMarketplaceEventPlain extends Enum { timeBetweenCreateCollections: Option; minimumTransferValue: Option; msInBlock: Option; + feePerUploadedFile: Option; + royaltyToMarketplaceForTrade: Option; + royaltyToMarketplaceForMint: Option; }; } @@ -403,6 +425,38 @@ export function getMarketplaceEvent( msInBlock: safeUnwrapToNumber( safeUnwrapOptional(event.configUpdated.msInBlock), ), + feePerUploadedFile: safeUnwrapToBigInt( + safeUnwrapOptional( + event.configUpdated.feePerUploadedFile, + ), + ), + royaltyToMarketplaceForTrade: safeUnwrapToNumber( + safeUnwrapOptional( + event.configUpdated.royaltyToMarketplaceForTrade, + ), + ), + royaltyToMarketplaceForMint: safeUnwrapToNumber( + safeUnwrapOptional( + event.configUpdated.royaltyToMarketplaceForMint, + ), + ), + }; + } + if (event.initialized) { + return { + type: NftMarketplaceEventType.Initialized, + timeBetweenCreateCollections: safeUnwrapToNumber( + event.initialized.timeBetweenCreateCollections, + ), + feePerUploadedFile: safeUnwrapToBigInt( + event.initialized.feePerUploadedFile, + ), + royaltyToMarketplaceForTrade: safeUnwrapToNumber( + event.initialized.royaltyToMarketplaceForTrade, + ), + royaltyToMarketplaceForMint: safeUnwrapToNumber( + event.initialized.royaltyToMarketplaceForMint, + ), }; } } diff --git a/indexer/src/types/nft.events.ts b/indexer/src/types/nft.events.ts index a1f4eaa..175835e 100644 --- a/indexer/src/types/nft.events.ts +++ b/indexer/src/types/nft.events.ts @@ -187,7 +187,7 @@ export interface NftEventPlain extends Enum { initialized: { config: ConfigPlain; totalNumberOfTokens: u64; - permissionToMint: Option> + permissionToMint: Option>; }; minted: { tokenId: u64; @@ -212,7 +212,7 @@ export interface NftEventPlain extends Enum { configChanged: { config: ConfigPlain; totalNumberOfTokens: u64; - permissionToMint: Option> + permissionToMint: Option>; }; imageChanged: { tokenId: u64; @@ -223,10 +223,10 @@ export interface NftEventPlain extends Enum { metadata: Text; }; usersForMintAdded: { - users: Vec + users: Vec; }; userForMintDeleted: { - user: Hash + user: Hash; }; liftRestrictionMint: {}; } @@ -266,16 +266,16 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { ), additionalLinks: event.initialized.config.additionalLinks ? { - externalUrl: - event.initialized.config.additionalLinks.externalUrl.toString(), - telegram: - event.initialized.config.additionalLinks.telegram.toString(), - xcom: event.initialized.config.additionalLinks.xcom.toString(), - medium: - event.initialized.config.additionalLinks.medium.toString(), - discord: - event.initialized.config.additionalLinks.discord.toString(), - } + externalUrl: + event.initialized.config.additionalLinks.externalUrl.toString(), + telegram: + event.initialized.config.additionalLinks.telegram.toString(), + xcom: event.initialized.config.additionalLinks.xcom.toString(), + medium: + event.initialized.config.additionalLinks.medium.toString(), + discord: + event.initialized.config.additionalLinks.discord.toString(), + } : null, royalty: safeUnwrapToNumber(event.initialized.config.royalty)!, paymentForMint: safeUnwrapToBigInt( @@ -293,7 +293,10 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { totalNumberOfTokens: safeUnwrapToBigInt( safeUnwrapOptional(event.initialized.totalNumberOfTokens), ), - permissionToMint: safeUnwrapOptional, Vec>(event.initialized.permissionToMint)?.map((m: Text) => m.toString()) ?? null, + permissionToMint: + safeUnwrapOptional, Vec>( + event.initialized.permissionToMint, + )?.map((m: Text) => m.toString()) ?? null, }, }; } @@ -328,12 +331,12 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { type: NftEventType.Expanded, additionalLinks: event.expanded.additionalLinks ? { - externalUrl: event.expanded.additionalLinks.externalUrl.toString(), - telegram: event.expanded.additionalLinks.telegram.toString(), - xcom: event.expanded.additionalLinks.xcom.toString(), - medium: event.expanded.additionalLinks.medium.toString(), - discord: event.expanded.additionalLinks.discord.toString(), - } + externalUrl: event.expanded.additionalLinks.externalUrl.toString(), + telegram: event.expanded.additionalLinks.telegram.toString(), + xcom: event.expanded.additionalLinks.xcom.toString(), + medium: event.expanded.additionalLinks.medium.toString(), + discord: event.expanded.additionalLinks.discord.toString(), + } : null, }; } @@ -354,16 +357,16 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { ), additionalLinks: event.configChanged.config.additionalLinks ? { - externalUrl: - event.configChanged.config.additionalLinks.externalUrl.toString(), - telegram: - event.configChanged.config.additionalLinks.telegram.toString(), - xcom: event.configChanged.config.additionalLinks.xcom.toString(), - medium: - event.configChanged.config.additionalLinks.medium.toString(), - discord: - event.configChanged.config.additionalLinks.discord.toString(), - } + externalUrl: + event.configChanged.config.additionalLinks.externalUrl.toString(), + telegram: + event.configChanged.config.additionalLinks.telegram.toString(), + xcom: event.configChanged.config.additionalLinks.xcom.toString(), + medium: + event.configChanged.config.additionalLinks.medium.toString(), + discord: + event.configChanged.config.additionalLinks.discord.toString(), + } : null, royalty: safeUnwrapToNumber(event.configChanged.config.royalty)!, paymentForMint: safeUnwrapToBigInt( @@ -381,7 +384,10 @@ export function getNftEvent(event: NftEventPlain): NftEvent | undefined { totalNumberOfTokens: safeUnwrapToBigInt( safeUnwrapOptional(event.configChanged.totalNumberOfTokens), ), - permissionToMint: safeUnwrapOptional, Vec>(event.configChanged.permissionToMint)?.map((m: Text) => m.toString()) ?? null, + permissionToMint: + safeUnwrapOptional, Vec>( + event.configChanged.permissionToMint, + )?.map((m: Text) => m.toString()) ?? null, }, }; } From 75cdc677ff72402e0ac9a3dddbbd05a3dd99e58b Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 22 Feb 2024 18:33:23 +0300 Subject: [PATCH 39/50] fix delete collection --- indexer/src/processing/entities.service.ts | 4 ++++ indexer/src/processing/storage/local.storage.ts | 13 +++++++++++-- indexer/src/processing/storage/storage.inteface.ts | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/indexer/src/processing/entities.service.ts b/indexer/src/processing/entities.service.ts index 047cd91..70c03e6 100644 --- a/indexer/src/processing/entities.service.ts +++ b/indexer/src/processing/entities.service.ts @@ -93,6 +93,10 @@ export class EntitiesService { async deleteCollection(collection: Collection) { await this.storage.deleteCollection(collection); + const nfts = await this.storage.getNfts(collection.id); + if (nfts.length) { + await this.store.remove(nfts); + } await this.store.remove(collection); } diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index 49ce571..f4d7032 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -3,7 +3,6 @@ import { Collection, CollectionType, Marketplace, - MarketplaceConfig, Nft, Offer, Sale, @@ -12,7 +11,6 @@ import { Store } from '@subsquid/typeorm-store'; import { IStorage } from './storage.inteface'; import { config } from '../../config'; import { readFileSync } from 'fs'; -import { v4 as uuidv4 } from 'uuid'; let storage: LocalStorage | undefined; @@ -113,6 +111,17 @@ export class LocalStorage implements IStorage { }); } + getNfts(collectionAddress: string): Promise { + return this.store.find(Nft, { + where: { + collection: { + id: collectionAddress, + }, + }, + relations: { collection: true }, + }); + } + async getSale(nft: Nft): Promise { const key = this.getNftKey(nft.collection.id, nft.idInCollection); if (this.sale[key] !== undefined) { diff --git a/indexer/src/processing/storage/storage.inteface.ts b/indexer/src/processing/storage/storage.inteface.ts index 0d885d5..d2ad8ce 100644 --- a/indexer/src/processing/storage/storage.inteface.ts +++ b/indexer/src/processing/storage/storage.inteface.ts @@ -17,6 +17,7 @@ export interface IStorage { updateCollection(collection: Collection): Promise; getNft(collectionAddress: string, tokenId: number): Promise; + getNfts(collectionAddress: string): Promise; updateNft(nft: Nft): Promise; getSale(nft: Nft): Promise; From 1debac7b4df8f725ac52e908d3e5321448082fc4 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 22 Feb 2024 19:57:36 +0300 Subject: [PATCH 40/50] add minimum transfer value --- indexer/src/types/marketplace.events.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index 8febd5a..9a1c166 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -33,6 +33,7 @@ export type Initialized = { feePerUploadedFile: bigint | null; royaltyToMarketplaceForTrade: number | null; royaltyToMarketplaceForMint: number | null; + minimumTransferValue: bigint | null; }; export type NewCollectionAdded = { @@ -177,6 +178,7 @@ export interface NftMarketplaceEventPlain extends Enum { initialized: { timeBetweenCreateCollections: u64; feePerUploadedFile: u128; + minimumTransferValue: u128; royaltyToMarketplaceForTrade: u16; royaltyToMarketplaceForMint: u16; }; @@ -451,6 +453,9 @@ export function getMarketplaceEvent( feePerUploadedFile: safeUnwrapToBigInt( event.initialized.feePerUploadedFile, ), + minimumTransferValue: safeUnwrapToBigInt( + event.initialized.minimumTransferValue, + ), royaltyToMarketplaceForTrade: safeUnwrapToNumber( event.initialized.royaltyToMarketplaceForTrade, ), From fe06159f46a52d3df80d7553eee15feff34f189a Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 26 Feb 2024 12:19:57 +0300 Subject: [PATCH 41/50] fix config --- indexer/db/migrations/1708938587449-Data.js | 31 +++++++++++++ indexer/schema.graphql | 22 +++++----- .../generated/marketplaceConfig.model.ts | 44 +++++++++---------- .../marketplace/initialized.handler.ts | 4 +- .../new-collection-added.handler.ts | 7 +-- 5 files changed, 68 insertions(+), 40 deletions(-) create mode 100644 indexer/db/migrations/1708938587449-Data.js diff --git a/indexer/db/migrations/1708938587449-Data.js b/indexer/db/migrations/1708938587449-Data.js new file mode 100644 index 0000000..83b4982 --- /dev/null +++ b/indexer/db/migrations/1708938587449-Data.js @@ -0,0 +1,31 @@ +module.exports = class Data1708938587449 { + name = 'Data1708938587449' + + async up(db) { + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_creation" TYPE int USING (COALESCE("gas_for_creation", 0)), ALTER COLUMN "gas_for_creation" SET DEFAULT 0, ALTER COLUMN "gas_for_creation" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_transfer_token" TYPE int USING (COALESCE("gas_for_transfer_token", 0)), ALTER COLUMN "gas_for_transfer_token" SET DEFAULT 0, ALTER COLUMN "gas_for_transfer_token" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_close_auction" TYPE int USING (COALESCE("gas_for_close_auction", 0)), ALTER COLUMN "gas_for_close_auction" SET DEFAULT 0, ALTER COLUMN "gas_for_close_auction" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_delete_collection" TYPE int USING (COALESCE("gas_for_delete_collection", 0)), ALTER COLUMN "gas_for_delete_collection" SET DEFAULT 0, ALTER COLUMN "gas_for_delete_collection" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_get_token_info" TYPE int USING (COALESCE("gas_for_get_token_info", 0)), ALTER COLUMN "gas_for_get_token_info" SET DEFAULT 0, ALTER COLUMN "gas_for_get_token_info" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "time_between_create_collections" TYPE int USING (COALESCE("time_between_create_collections", 0)), ALTER COLUMN "time_between_create_collections" SET DEFAULT 0, ALTER COLUMN "time_between_create_collections" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "royalty_to_marketplace_for_mint" TYPE int USING (COALESCE("royalty_to_marketplace_for_mint", 0)), ALTER COLUMN "royalty_to_marketplace_for_mint" SET DEFAULT 0, ALTER COLUMN "royalty_to_marketplace_for_mint" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "royalty_to_marketplace_for_trade" TYPE int USING (COALESCE("royalty_to_marketplace_for_trade", 0)), ALTER COLUMN "royalty_to_marketplace_for_trade" SET DEFAULT 0, ALTER COLUMN "royalty_to_marketplace_for_trade" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "fee_per_uploaded_file" TYPE numeric USING (COALESCE("fee_per_uploaded_file", 0)), ALTER COLUMN "fee_per_uploaded_file" SET DEFAULT 0, ALTER COLUMN "fee_per_uploaded_file" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "minimum_transfer_value" TYPE numeric USING (COALESCE("minimum_transfer_value", 0)), ALTER COLUMN "minimum_transfer_value" SET DEFAULT 0, ALTER COLUMN "minimum_transfer_value" SET NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "ms_in_block" TYPE int USING (COALESCE("ms_in_block", 0)), ALTER COLUMN "ms_in_block" SET DEFAULT 0, ALTER COLUMN "ms_in_block" SET NOT NULL`) + } + + async down(db) { + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_creation" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_transfer_token" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_close_auction" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_delete_collection" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_get_token_info" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "time_between_create_collections" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "royalty_to_marketplace_for_mint" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "royalty_to_marketplace_for_trade" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "fee_per_uploaded_file" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "minimum_transfer_value" DROP NOT NULL`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "ms_in_block" DROP NOT NULL`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 4fcb7d4..727433f 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -11,17 +11,17 @@ type Marketplace @entity { } type MarketplaceConfig @entity { - gasForCreation: Int - gasForTransferToken: Int - gasForCloseAuction: Int - gasForDeleteCollection: Int - gasForGetTokenInfo: Int - timeBetweenCreateCollections: Int - royaltyToMarketplaceForMint: Int - royaltyToMarketplaceForTrade: Int - feePerUploadedFile: BigInt - minimumTransferValue: BigInt - msInBlock: Int + gasForCreation: Int! + gasForTransferToken: Int! + gasForCloseAuction: Int! + gasForDeleteCollection: Int! + gasForGetTokenInfo: Int! + timeBetweenCreateCollections: Int! + royaltyToMarketplaceForMint: Int! + royaltyToMarketplaceForTrade: Int! + feePerUploadedFile: BigInt! + minimumTransferValue: BigInt! + msInBlock: Int! marketplace: Marketplace! } diff --git a/indexer/src/model/generated/marketplaceConfig.model.ts b/indexer/src/model/generated/marketplaceConfig.model.ts index d634622..bfd8fbb 100644 --- a/indexer/src/model/generated/marketplaceConfig.model.ts +++ b/indexer/src/model/generated/marketplaceConfig.model.ts @@ -17,44 +17,44 @@ export class MarketplaceConfig { @PrimaryColumn_() id!: string; - @Column_('int4', { nullable: true }) - gasForCreation!: number | undefined | null; + @Column_('int4', { nullable: false }) + gasForCreation!: number; - @Column_('int4', { nullable: true }) - gasForTransferToken!: number | undefined | null; + @Column_('int4', { nullable: false }) + gasForTransferToken!: number; - @Column_('int4', { nullable: true }) - gasForCloseAuction!: number | undefined | null; + @Column_('int4', { nullable: false }) + gasForCloseAuction!: number; - @Column_('int4', { nullable: true }) - gasForDeleteCollection!: number | undefined | null; + @Column_('int4', { nullable: false }) + gasForDeleteCollection!: number; - @Column_('int4', { nullable: true }) - gasForGetTokenInfo!: number | undefined | null; + @Column_('int4', { nullable: false }) + gasForGetTokenInfo!: number; - @Column_('int4', { nullable: true }) - timeBetweenCreateCollections!: number | undefined | null; + @Column_('int4', { nullable: false }) + timeBetweenCreateCollections!: number; - @Column_('int4', { nullable: true }) - royaltyToMarketplaceForMint!: number | undefined | null; + @Column_('int4', { nullable: false }) + royaltyToMarketplaceForMint!: number; - @Column_('int4', { nullable: true }) - royaltyToMarketplaceForTrade!: number | undefined | null; + @Column_('int4', { nullable: false }) + royaltyToMarketplaceForTrade!: number; @Column_('numeric', { transformer: marshal.bigintTransformer, - nullable: true, + nullable: false, }) - feePerUploadedFile!: bigint | undefined | null; + feePerUploadedFile!: bigint; @Column_('numeric', { transformer: marshal.bigintTransformer, - nullable: true, + nullable: false, }) - minimumTransferValue!: bigint | undefined | null; + minimumTransferValue!: bigint; - @Column_('int4', { nullable: true }) - msInBlock!: number | undefined | null; + @Column_('int4', { nullable: false }) + msInBlock!: number; @Index_() @ManyToOne_(() => Marketplace, { nullable: true }) diff --git a/indexer/src/processing/marketplace/initialized.handler.ts b/indexer/src/processing/marketplace/initialized.handler.ts index 78df677..dc6d5df 100644 --- a/indexer/src/processing/marketplace/initialized.handler.ts +++ b/indexer/src/processing/marketplace/initialized.handler.ts @@ -4,7 +4,9 @@ import { MarketplaceConfig } from '../../model'; import { EventInfo } from '../event-info.type'; import { Initialized } from '../../types/marketplace.events'; -export class MarketplaceInitializedHandler implements INftMarketplaceEventHandler { +export class MarketplaceInitializedHandler + implements INftMarketplaceEventHandler +{ async handle( event: Initialized, eventInfo: EventInfo, diff --git a/indexer/src/processing/marketplace/new-collection-added.handler.ts b/indexer/src/processing/marketplace/new-collection-added.handler.ts index 5fe3496..b7476e6 100644 --- a/indexer/src/processing/marketplace/new-collection-added.handler.ts +++ b/indexer/src/processing/marketplace/new-collection-added.handler.ts @@ -12,12 +12,6 @@ export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { ): Promise { const { codeId, metaLink, typeName, typeDescription } = event; const existingCollectionType = await storage.getCollectionType(typeName); - if (existingCollectionType !== undefined) { - console.warn( - `[NewCollectionAddedHandler]: Collection type ${typeName} already exists`, - ); - return; - } if (!typeName) { console.warn( `[NewCollectionAddedHandler]: Collection type ${typeName} is not valid`, @@ -26,6 +20,7 @@ export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { } await storage.setCollectionType( new CollectionType({ + ...(existingCollectionType ?? {}), id: codeId, description: typeDescription, type: typeName, From 2da215b030cd7084cc81a2d1c3e17c796e73605b Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 26 Feb 2024 12:24:27 +0300 Subject: [PATCH 42/50] fix config --- indexer/src/types/marketplace.events.ts | 38 +++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index 9a1c166..3b29f4c 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -29,11 +29,17 @@ export enum NftMarketplaceEventType { export type Initialized = { type: NftMarketplaceEventType.Initialized; + gasForCreation: number | null; + gasForTransferToken: number | null; + gasForCloseAuction: number | null; + gasForDeleteCollection: number | null; + gasForGetTokenInfo: number | null; timeBetweenCreateCollections: number | null; feePerUploadedFile: bigint | null; royaltyToMarketplaceForTrade: number | null; royaltyToMarketplaceForMint: number | null; minimumTransferValue: bigint | null; + msInBlock: number | null; }; export type NewCollectionAdded = { @@ -181,6 +187,12 @@ export interface NftMarketplaceEventPlain extends Enum { minimumTransferValue: u128; royaltyToMarketplaceForTrade: u16; royaltyToMarketplaceForMint: u16; + gasForCreation: Option; + gasForTransferToken: Option; + gasForCloseAuction: Option; + gasForDeleteCollection: Option; + gasForGetTokenInfo: Option; + msInBlock: Option; }; newCollectionAdded: { codeId: CodeId; @@ -447,15 +459,35 @@ export function getMarketplaceEvent( if (event.initialized) { return { type: NftMarketplaceEventType.Initialized, + gasForCreation: safeUnwrapToNumber( + safeUnwrapOptional(event.initialized.gasForCreation), + ), + gasForTransferToken: safeUnwrapToNumber( + safeUnwrapOptional(event.initialized.gasForTransferToken), + ), + gasForCloseAuction: safeUnwrapToNumber( + safeUnwrapOptional(event.initialized.gasForCloseAuction), + ), + gasForDeleteCollection: safeUnwrapToNumber( + safeUnwrapOptional( + event.initialized.gasForDeleteCollection, + ), + ), + gasForGetTokenInfo: safeUnwrapToNumber( + safeUnwrapOptional(event.initialized.gasForGetTokenInfo), + ), timeBetweenCreateCollections: safeUnwrapToNumber( event.initialized.timeBetweenCreateCollections, ), - feePerUploadedFile: safeUnwrapToBigInt( - event.initialized.feePerUploadedFile, - ), minimumTransferValue: safeUnwrapToBigInt( event.initialized.minimumTransferValue, ), + msInBlock: safeUnwrapToNumber( + safeUnwrapOptional(event.initialized.msInBlock), + ), + feePerUploadedFile: safeUnwrapToBigInt( + event.initialized.feePerUploadedFile, + ), royaltyToMarketplaceForTrade: safeUnwrapToNumber( event.initialized.royaltyToMarketplaceForTrade, ), From b52af49ffc23cbc4eb28b63853e0c4c9715f1db8 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 26 Feb 2024 12:34:46 +0300 Subject: [PATCH 43/50] fix config --- indexer/db/migrations/1708939752324-Data.js | 25 ++++++++++ indexer/schema.graphql | 12 ++--- .../generated/marketplaceConfig.model.ts | 42 +++++++++++----- indexer/src/types/marketplace.events.ts | 48 +++++++++---------- 4 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 indexer/db/migrations/1708939752324-Data.js diff --git a/indexer/db/migrations/1708939752324-Data.js b/indexer/db/migrations/1708939752324-Data.js new file mode 100644 index 0000000..42c2d1e --- /dev/null +++ b/indexer/db/migrations/1708939752324-Data.js @@ -0,0 +1,25 @@ +module.exports = class Data1708939752324 { + name = 'Data1708939752324' + + async up(db) { + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_creation" TYPE numeric`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_transfer_token" TYPE numeric`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_close_auction" TYPE numeric`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_delete_collection" TYPE numeric`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_get_token_info" TYPE numeric`) + await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "time_between_create_collections" TYPE numeric`) + } + + async down(db) { + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_creation"`) + await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_creation" integer NOT NULL DEFAULT '0'`) + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_transfer_token"`) + await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_transfer_token" integer NOT NULL DEFAULT '0'`) + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_close_auction"`) + await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_close_auction" integer NOT NULL DEFAULT '0'`) + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_delete_collection"`) + await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_delete_collection" integer NOT NULL DEFAULT '0'`) + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_get_token_info"`) + await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_get_token_info" integer NOT NULL DEFAULT '0'`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index 727433f..d75aa09 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -11,12 +11,12 @@ type Marketplace @entity { } type MarketplaceConfig @entity { - gasForCreation: Int! - gasForTransferToken: Int! - gasForCloseAuction: Int! - gasForDeleteCollection: Int! - gasForGetTokenInfo: Int! - timeBetweenCreateCollections: Int! + gasForCreation: BigInt! + gasForTransferToken: BigInt! + gasForCloseAuction: BigInt! + gasForDeleteCollection: BigInt! + gasForGetTokenInfo: BigInt! + timeBetweenCreateCollections: BigInt! royaltyToMarketplaceForMint: Int! royaltyToMarketplaceForTrade: Int! feePerUploadedFile: BigInt! diff --git a/indexer/src/model/generated/marketplaceConfig.model.ts b/indexer/src/model/generated/marketplaceConfig.model.ts index bfd8fbb..293ca25 100644 --- a/indexer/src/model/generated/marketplaceConfig.model.ts +++ b/indexer/src/model/generated/marketplaceConfig.model.ts @@ -17,23 +17,41 @@ export class MarketplaceConfig { @PrimaryColumn_() id!: string; - @Column_('int4', { nullable: false }) - gasForCreation!: number; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + gasForCreation!: bigint; - @Column_('int4', { nullable: false }) - gasForTransferToken!: number; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + gasForTransferToken!: bigint; - @Column_('int4', { nullable: false }) - gasForCloseAuction!: number; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + gasForCloseAuction!: bigint; - @Column_('int4', { nullable: false }) - gasForDeleteCollection!: number; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + gasForDeleteCollection!: bigint; - @Column_('int4', { nullable: false }) - gasForGetTokenInfo!: number; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + gasForGetTokenInfo!: bigint; - @Column_('int4', { nullable: false }) - timeBetweenCreateCollections!: number; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + timeBetweenCreateCollections!: bigint; @Column_('int4', { nullable: false }) royaltyToMarketplaceForMint!: number; diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index 3b29f4c..3fecac6 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -29,12 +29,12 @@ export enum NftMarketplaceEventType { export type Initialized = { type: NftMarketplaceEventType.Initialized; - gasForCreation: number | null; - gasForTransferToken: number | null; - gasForCloseAuction: number | null; - gasForDeleteCollection: number | null; - gasForGetTokenInfo: number | null; - timeBetweenCreateCollections: number | null; + gasForCreation: bigint | null; + gasForTransferToken: bigint | null; + gasForCloseAuction: bigint | null; + gasForDeleteCollection: bigint | null; + gasForGetTokenInfo: bigint | null; + timeBetweenCreateCollections: bigint | null; feePerUploadedFile: bigint | null; royaltyToMarketplaceForTrade: number | null; royaltyToMarketplaceForMint: number | null; @@ -148,12 +148,12 @@ export type AdminDeleted = { export type ConfigUpdated = { type: NftMarketplaceEventType.ConfigUpdated; - gasForCreation: number | null; - gasForTransferToken: number | null; - gasForCloseAuction: number | null; - gasForDeleteCollection: number | null; - gasForGetTokenInfo: number | null; - timeBetweenCreateCollections: number | null; + gasForCreation: bigint | null; + gasForTransferToken: bigint | null; + gasForCloseAuction: bigint | null; + gasForDeleteCollection: bigint | null; + gasForGetTokenInfo: bigint | null; + timeBetweenCreateCollections: bigint | null; feePerUploadedFile: bigint | null; royaltyToMarketplaceForTrade: number | null; royaltyToMarketplaceForMint: number | null; @@ -407,26 +407,26 @@ export function getMarketplaceEvent( if (event.configUpdated) { return { type: NftMarketplaceEventType.ConfigUpdated, - gasForCreation: safeUnwrapToNumber( + gasForCreation: safeUnwrapToBigInt( safeUnwrapOptional(event.configUpdated.gasForCreation), ), - gasForTransferToken: safeUnwrapToNumber( + gasForTransferToken: safeUnwrapToBigInt( safeUnwrapOptional( event.configUpdated.gasForTransferToken, ), ), - gasForCloseAuction: safeUnwrapToNumber( + gasForCloseAuction: safeUnwrapToBigInt( safeUnwrapOptional(event.configUpdated.gasForCloseAuction), ), - gasForDeleteCollection: safeUnwrapToNumber( + gasForDeleteCollection: safeUnwrapToBigInt( safeUnwrapOptional( event.configUpdated.gasForDeleteCollection, ), ), - gasForGetTokenInfo: safeUnwrapToNumber( + gasForGetTokenInfo: safeUnwrapToBigInt( safeUnwrapOptional(event.configUpdated.gasForGetTokenInfo), ), - timeBetweenCreateCollections: safeUnwrapToNumber( + timeBetweenCreateCollections: safeUnwrapToBigInt( safeUnwrapOptional( event.configUpdated.timeBetweenCreateCollections, ), @@ -459,24 +459,24 @@ export function getMarketplaceEvent( if (event.initialized) { return { type: NftMarketplaceEventType.Initialized, - gasForCreation: safeUnwrapToNumber( + gasForCreation: safeUnwrapToBigInt( safeUnwrapOptional(event.initialized.gasForCreation), ), - gasForTransferToken: safeUnwrapToNumber( + gasForTransferToken: safeUnwrapToBigInt( safeUnwrapOptional(event.initialized.gasForTransferToken), ), - gasForCloseAuction: safeUnwrapToNumber( + gasForCloseAuction: safeUnwrapToBigInt( safeUnwrapOptional(event.initialized.gasForCloseAuction), ), - gasForDeleteCollection: safeUnwrapToNumber( + gasForDeleteCollection: safeUnwrapToBigInt( safeUnwrapOptional( event.initialized.gasForDeleteCollection, ), ), - gasForGetTokenInfo: safeUnwrapToNumber( + gasForGetTokenInfo: safeUnwrapToBigInt( safeUnwrapOptional(event.initialized.gasForGetTokenInfo), ), - timeBetweenCreateCollections: safeUnwrapToNumber( + timeBetweenCreateCollections: safeUnwrapToBigInt( event.initialized.timeBetweenCreateCollections, ), minimumTransferValue: safeUnwrapToBigInt( From f5cf3b72a41d7784d36f008b44efd17f1d206d2c Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 26 Feb 2024 15:14:38 +0300 Subject: [PATCH 44/50] add new fields to configs --- indexer/db/migrations/1708949622123-Data.js | 13 ++++ indexer/schema.graphql | 2 + .../generated/marketplaceConfig.model.ts | 12 ++++ indexer/src/types/marketplace.events.ts | 61 ++++++++----------- 4 files changed, 51 insertions(+), 37 deletions(-) create mode 100644 indexer/db/migrations/1708949622123-Data.js diff --git a/indexer/db/migrations/1708949622123-Data.js b/indexer/db/migrations/1708949622123-Data.js new file mode 100644 index 0000000..50cc304 --- /dev/null +++ b/indexer/db/migrations/1708949622123-Data.js @@ -0,0 +1,13 @@ +module.exports = class Data1708949622123 { + name = 'Data1708949622123' + + async up(db) { + await db.query(`ALTER TABLE "marketplace_config" ADD "minimum_value_for_trade" numeric NOT NULL DEFAULT 0`) + await db.query(`ALTER TABLE "marketplace_config" ADD "minimum_value_for_mint" numeric NOT NULL DEFAULT 0`) + } + + async down(db) { + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "minimum_value_for_trade"`) + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "minimum_value_for_mint"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index d75aa09..dce8325 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -21,6 +21,8 @@ type MarketplaceConfig @entity { royaltyToMarketplaceForTrade: Int! feePerUploadedFile: BigInt! minimumTransferValue: BigInt! + minimumValueForTrade: BigInt! + minimumValueForMint: BigInt! msInBlock: Int! marketplace: Marketplace! } diff --git a/indexer/src/model/generated/marketplaceConfig.model.ts b/indexer/src/model/generated/marketplaceConfig.model.ts index 293ca25..9783340 100644 --- a/indexer/src/model/generated/marketplaceConfig.model.ts +++ b/indexer/src/model/generated/marketplaceConfig.model.ts @@ -71,6 +71,18 @@ export class MarketplaceConfig { }) minimumTransferValue!: bigint; + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + minimumValueForTrade!: bigint; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + minimumValueForMint!: bigint; + @Column_('int4', { nullable: false }) msInBlock!: number; diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index 3fecac6..dbb11d6 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -29,17 +29,12 @@ export enum NftMarketplaceEventType { export type Initialized = { type: NftMarketplaceEventType.Initialized; - gasForCreation: bigint | null; - gasForTransferToken: bigint | null; - gasForCloseAuction: bigint | null; - gasForDeleteCollection: bigint | null; - gasForGetTokenInfo: bigint | null; timeBetweenCreateCollections: bigint | null; feePerUploadedFile: bigint | null; royaltyToMarketplaceForTrade: number | null; royaltyToMarketplaceForMint: number | null; - minimumTransferValue: bigint | null; - msInBlock: number | null; + minimumValueForTrade: bigint | null; + minimumValueForMint: bigint | null; }; export type NewCollectionAdded = { @@ -159,6 +154,8 @@ export type ConfigUpdated = { royaltyToMarketplaceForMint: number | null; minimumTransferValue: bigint | null; msInBlock: number | null; + minimumValueForTrade: bigint | null; + minimumValueForMint: bigint | null; }; export type NftMarketplaceEvent = @@ -184,15 +181,10 @@ export interface NftMarketplaceEventPlain extends Enum { initialized: { timeBetweenCreateCollections: u64; feePerUploadedFile: u128; - minimumTransferValue: u128; royaltyToMarketplaceForTrade: u16; royaltyToMarketplaceForMint: u16; - gasForCreation: Option; - gasForTransferToken: Option; - gasForCloseAuction: Option; - gasForDeleteCollection: Option; - gasForGetTokenInfo: Option; - msInBlock: Option; + minimumValueForTrade: u128; + minimumValueForMint: u128; }; newCollectionAdded: { codeId: CodeId; @@ -280,6 +272,8 @@ export interface NftMarketplaceEventPlain extends Enum { feePerUploadedFile: Option; royaltyToMarketplaceForTrade: Option; royaltyToMarketplaceForMint: Option; + minimumValueForTrade: Option; + minimumValueForMint: Option; }; } @@ -454,40 +448,33 @@ export function getMarketplaceEvent( event.configUpdated.royaltyToMarketplaceForMint, ), ), + minimumValueForTrade: safeUnwrapToBigInt( + safeUnwrapOptional( + event.configUpdated.minimumValueForTrade, + ), + ), + minimumValueForMint: safeUnwrapToBigInt( + safeUnwrapOptional( + event.configUpdated.minimumValueForMint, + ), + ), }; } if (event.initialized) { return { type: NftMarketplaceEventType.Initialized, - gasForCreation: safeUnwrapToBigInt( - safeUnwrapOptional(event.initialized.gasForCreation), - ), - gasForTransferToken: safeUnwrapToBigInt( - safeUnwrapOptional(event.initialized.gasForTransferToken), - ), - gasForCloseAuction: safeUnwrapToBigInt( - safeUnwrapOptional(event.initialized.gasForCloseAuction), - ), - gasForDeleteCollection: safeUnwrapToBigInt( - safeUnwrapOptional( - event.initialized.gasForDeleteCollection, - ), - ), - gasForGetTokenInfo: safeUnwrapToBigInt( - safeUnwrapOptional(event.initialized.gasForGetTokenInfo), - ), timeBetweenCreateCollections: safeUnwrapToBigInt( event.initialized.timeBetweenCreateCollections, ), - minimumTransferValue: safeUnwrapToBigInt( - event.initialized.minimumTransferValue, - ), - msInBlock: safeUnwrapToNumber( - safeUnwrapOptional(event.initialized.msInBlock), - ), feePerUploadedFile: safeUnwrapToBigInt( event.initialized.feePerUploadedFile, ), + minimumValueForTrade: safeUnwrapToBigInt( + event.initialized.minimumValueForTrade, + ), + minimumValueForMint: safeUnwrapToBigInt( + event.initialized.minimumValueForMint, + ), royaltyToMarketplaceForTrade: safeUnwrapToNumber( event.initialized.royaltyToMarketplaceForTrade, ), From 28122c307bff8d1e2545d9f9211f595b9e7ff999 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Mon, 26 Feb 2024 20:25:28 +0300 Subject: [PATCH 45/50] add new fields to configs --- indexer/src/types/marketplace.events.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index dbb11d6..da145f1 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -30,11 +30,9 @@ export enum NftMarketplaceEventType { export type Initialized = { type: NftMarketplaceEventType.Initialized; timeBetweenCreateCollections: bigint | null; - feePerUploadedFile: bigint | null; royaltyToMarketplaceForTrade: number | null; royaltyToMarketplaceForMint: number | null; minimumValueForTrade: bigint | null; - minimumValueForMint: bigint | null; }; export type NewCollectionAdded = { @@ -180,11 +178,9 @@ export type NftMarketplaceEvent = export interface NftMarketplaceEventPlain extends Enum { initialized: { timeBetweenCreateCollections: u64; - feePerUploadedFile: u128; royaltyToMarketplaceForTrade: u16; royaltyToMarketplaceForMint: u16; minimumValueForTrade: u128; - minimumValueForMint: u128; }; newCollectionAdded: { codeId: CodeId; @@ -466,15 +462,9 @@ export function getMarketplaceEvent( timeBetweenCreateCollections: safeUnwrapToBigInt( event.initialized.timeBetweenCreateCollections, ), - feePerUploadedFile: safeUnwrapToBigInt( - event.initialized.feePerUploadedFile, - ), minimumValueForTrade: safeUnwrapToBigInt( event.initialized.minimumValueForTrade, ), - minimumValueForMint: safeUnwrapToBigInt( - event.initialized.minimumValueForMint, - ), royaltyToMarketplaceForTrade: safeUnwrapToNumber( event.initialized.royaltyToMarketplaceForTrade, ), From b1eb1a88096171b5a42fe41a5304404bd71dc982 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Tue, 27 Feb 2024 12:38:07 +0300 Subject: [PATCH 46/50] fix update collection type --- .../src/processing/marketplace/new-collection-added.handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/src/processing/marketplace/new-collection-added.handler.ts b/indexer/src/processing/marketplace/new-collection-added.handler.ts index b7476e6..e58826d 100644 --- a/indexer/src/processing/marketplace/new-collection-added.handler.ts +++ b/indexer/src/processing/marketplace/new-collection-added.handler.ts @@ -21,7 +21,7 @@ export class NewCollectionAddedHandler implements INftMarketplaceEventHandler { await storage.setCollectionType( new CollectionType({ ...(existingCollectionType ?? {}), - id: codeId, + id: typeName, description: typeDescription, type: typeName, metaUrl: metaLink, From d0698574c952450c2be0096d9dc033612ecc7faf Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Wed, 28 Feb 2024 19:57:29 +0300 Subject: [PATCH 47/50] update configs --- indexer/db/migrations/1709139070805-Data.js | 13 ++++++++++ indexer/schema.graphql | 2 ++ .../generated/marketplaceConfig.model.ts | 9 +++++++ indexer/src/types/marketplace.events.ts | 25 +++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 indexer/db/migrations/1709139070805-Data.js diff --git a/indexer/db/migrations/1709139070805-Data.js b/indexer/db/migrations/1709139070805-Data.js new file mode 100644 index 0000000..1f82da2 --- /dev/null +++ b/indexer/db/migrations/1709139070805-Data.js @@ -0,0 +1,13 @@ +module.exports = class Data1709139070805 { + name = 'Data1709139070805' + + async up(db) { + await db.query(`ALTER TABLE "marketplace_config" ADD "max_creator_royalty" integer NOT NULL DEFAULT 0`) + await db.query(`ALTER TABLE "marketplace_config" ADD "max_number_of_images" numeric NOT NULL DEFAULT 0`) + } + + async down(db) { + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "max_creator_royalty"`) + await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "max_number_of_images"`) + } +} diff --git a/indexer/schema.graphql b/indexer/schema.graphql index dce8325..329404b 100644 --- a/indexer/schema.graphql +++ b/indexer/schema.graphql @@ -25,6 +25,8 @@ type MarketplaceConfig @entity { minimumValueForMint: BigInt! msInBlock: Int! marketplace: Marketplace! + maxCreatorRoyalty: Int! + maxNumberOfImages: BigInt! } type MarketplaceEvent @entity { diff --git a/indexer/src/model/generated/marketplaceConfig.model.ts b/indexer/src/model/generated/marketplaceConfig.model.ts index 9783340..68d28a5 100644 --- a/indexer/src/model/generated/marketplaceConfig.model.ts +++ b/indexer/src/model/generated/marketplaceConfig.model.ts @@ -89,4 +89,13 @@ export class MarketplaceConfig { @Index_() @ManyToOne_(() => Marketplace, { nullable: true }) marketplace!: Marketplace; + + @Column_('int4', { nullable: false }) + maxCreatorRoyalty!: number; + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + maxNumberOfImages!: bigint; } diff --git a/indexer/src/types/marketplace.events.ts b/indexer/src/types/marketplace.events.ts index da145f1..7abb034 100644 --- a/indexer/src/types/marketplace.events.ts +++ b/indexer/src/types/marketplace.events.ts @@ -33,6 +33,9 @@ export type Initialized = { royaltyToMarketplaceForTrade: number | null; royaltyToMarketplaceForMint: number | null; minimumValueForTrade: bigint | null; + feePerUploadedFile: bigint | null; + maxCreatorRoyalty: number | null; + maxNumberOfImages: bigint | null; }; export type NewCollectionAdded = { @@ -154,6 +157,8 @@ export type ConfigUpdated = { msInBlock: number | null; minimumValueForTrade: bigint | null; minimumValueForMint: bigint | null; + maxCreatorRoyalty: number | null; + maxNumberOfImages: bigint | null; }; export type NftMarketplaceEvent = @@ -181,6 +186,9 @@ export interface NftMarketplaceEventPlain extends Enum { royaltyToMarketplaceForTrade: u16; royaltyToMarketplaceForMint: u16; minimumValueForTrade: u128; + feePerUploadedFile: u128; + maxCreatorRoyalty: u16; + maxNumberOfImages: u64; }; newCollectionAdded: { codeId: CodeId; @@ -270,6 +278,8 @@ export interface NftMarketplaceEventPlain extends Enum { royaltyToMarketplaceForMint: Option; minimumValueForTrade: Option; minimumValueForMint: Option; + maxCreatorRoyalty: Option; + maxNumberOfImages: Option; }; } @@ -454,6 +464,12 @@ export function getMarketplaceEvent( event.configUpdated.minimumValueForMint, ), ), + maxCreatorRoyalty: safeUnwrapToNumber( + safeUnwrapOptional(event.configUpdated.maxCreatorRoyalty), + ), + maxNumberOfImages: safeUnwrapToBigInt( + safeUnwrapOptional(event.configUpdated.maxNumberOfImages), + ), }; } if (event.initialized) { @@ -471,6 +487,15 @@ export function getMarketplaceEvent( royaltyToMarketplaceForMint: safeUnwrapToNumber( event.initialized.royaltyToMarketplaceForMint, ), + feePerUploadedFile: safeUnwrapToBigInt( + event.initialized.feePerUploadedFile, + ), + maxCreatorRoyalty: safeUnwrapToNumber( + event.initialized.maxCreatorRoyalty, + ), + maxNumberOfImages: safeUnwrapToBigInt( + event.initialized.maxNumberOfImages, + ), }; } } From 7ea83a8653468f572848701ce178a24a75571782 Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 29 Feb 2024 10:38:38 +0300 Subject: [PATCH 48/50] fix admins --- indexer/src/processing/marketplace/admin-added.handler.ts | 3 ++- indexer/src/processing/marketplace/initialized.handler.ts | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/indexer/src/processing/marketplace/admin-added.handler.ts b/indexer/src/processing/marketplace/admin-added.handler.ts index 2397e9d..d5bf75d 100644 --- a/indexer/src/processing/marketplace/admin-added.handler.ts +++ b/indexer/src/processing/marketplace/admin-added.handler.ts @@ -12,10 +12,11 @@ export class AdminAddedHandler implements INftMarketplaceEventHandler { ): Promise { const { users } = event; const marketplace = storage.getMarketplace(); + const newAdmins = new Set([...marketplace.admins, ...users]); await storage.setMarketplace( new Marketplace({ ...marketplace, - admins: [...marketplace.admins, ...users], + admins: Array.from(newAdmins.values()), }), ); } diff --git a/indexer/src/processing/marketplace/initialized.handler.ts b/indexer/src/processing/marketplace/initialized.handler.ts index dc6d5df..4f28a94 100644 --- a/indexer/src/processing/marketplace/initialized.handler.ts +++ b/indexer/src/processing/marketplace/initialized.handler.ts @@ -1,6 +1,6 @@ import { EntitiesService } from '../entities.service'; import { INftMarketplaceEventHandler } from './nft-marketplace.handler'; -import { MarketplaceConfig } from '../../model'; +import { Marketplace, MarketplaceConfig } from '../../model'; import { EventInfo } from '../event-info.type'; import { Initialized } from '../../types/marketplace.events'; @@ -13,6 +13,12 @@ export class MarketplaceInitializedHandler storage: EntitiesService, ): Promise { const marketplace = storage.getMarketplace(); + await storage.setMarketplace( + new Marketplace({ + ...marketplace, + admins: [eventInfo.destination], + }), + ); await storage.setMarketplaceConfig( new MarketplaceConfig({ ...(marketplace.config || {}), From 33536082a69c29a7bbaea40187412791affc7dfe Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 29 Feb 2024 16:41:02 +0300 Subject: [PATCH 49/50] merge migrations --- indexer/db/migrations/1707311416201-Data.js | 15 --------- indexer/db/migrations/1707389319792-Data.js | 11 ------- indexer/db/migrations/1707392979676-Data.js | 27 ---------------- indexer/db/migrations/1707395758567-Data.js | 13 -------- indexer/db/migrations/1707469641353-Data.js | 17 ---------- indexer/db/migrations/1707479217496-Data.js | 11 ------- indexer/db/migrations/1707926335271-Data.js | 11 ------- indexer/db/migrations/1708174915413-Data.js | 11 ------- indexer/db/migrations/1708614382580-Data.js | 15 --------- indexer/db/migrations/1708938587449-Data.js | 31 ------------------- indexer/db/migrations/1708939752324-Data.js | 25 --------------- indexer/db/migrations/1708949622123-Data.js | 13 -------- indexer/db/migrations/1709139070805-Data.js | 13 -------- ...64292143-Data.js => 1709213989375-Data.js} | 14 ++++----- 14 files changed, 7 insertions(+), 220 deletions(-) delete mode 100644 indexer/db/migrations/1707311416201-Data.js delete mode 100644 indexer/db/migrations/1707389319792-Data.js delete mode 100644 indexer/db/migrations/1707392979676-Data.js delete mode 100644 indexer/db/migrations/1707395758567-Data.js delete mode 100644 indexer/db/migrations/1707469641353-Data.js delete mode 100644 indexer/db/migrations/1707479217496-Data.js delete mode 100644 indexer/db/migrations/1707926335271-Data.js delete mode 100644 indexer/db/migrations/1708174915413-Data.js delete mode 100644 indexer/db/migrations/1708614382580-Data.js delete mode 100644 indexer/db/migrations/1708938587449-Data.js delete mode 100644 indexer/db/migrations/1708939752324-Data.js delete mode 100644 indexer/db/migrations/1708949622123-Data.js delete mode 100644 indexer/db/migrations/1709139070805-Data.js rename indexer/db/migrations/{1705664292143-Data.js => 1709213989375-Data.js} (79%) diff --git a/indexer/db/migrations/1707311416201-Data.js b/indexer/db/migrations/1707311416201-Data.js deleted file mode 100644 index 4c463ee..0000000 --- a/indexer/db/migrations/1707311416201-Data.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = class Data1707311416201 { - name = 'Data1707311416201' - - async up(db) { - await db.query(`ALTER TABLE "marketplace" ADD "address" text NOT NULL default ''`) - await db.query(`ALTER TABLE "marketplace" ADD "metadata" text NOT NULL default ''`) - await db.query(`ALTER TABLE "marketplace" ADD "nft_metadata" text NOT NULL default ''`) - } - - async down(db) { - await db.query(`ALTER TABLE "marketplace" DROP COLUMN "address"`) - await db.query(`ALTER TABLE "marketplace" DROP COLUMN "metadata"`) - await db.query(`ALTER TABLE "marketplace" DROP COLUMN "nft_metadata"`) - } -} diff --git a/indexer/db/migrations/1707389319792-Data.js b/indexer/db/migrations/1707389319792-Data.js deleted file mode 100644 index 72b9a0f..0000000 --- a/indexer/db/migrations/1707389319792-Data.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = class Data1707389319792 { - name = 'Data1707389319792' - - async up(db) { - await db.query(`ALTER TABLE "collection" ADD "additional_links" text`) - } - - async down(db) { - await db.query(`ALTER TABLE "collection" DROP COLUMN "additional_links"`) - } -} diff --git a/indexer/db/migrations/1707392979676-Data.js b/indexer/db/migrations/1707392979676-Data.js deleted file mode 100644 index 8c978d2..0000000 --- a/indexer/db/migrations/1707392979676-Data.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = class Data1707392979676 { - name = 'Data1707392979676' - - async up(db) { - await db.query(`ALTER TABLE "collection" ALTER COLUMN "admin" SET NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "name" SET NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "description" SET NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "payment_for_mint" SET NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "royalty" SET NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "collection_logo" SET NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "collection_banner" SET NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "created_at" SET NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "tags" SET NOT NULL`) - } - - async down(db) { - await db.query(`ALTER TABLE "collection" ALTER COLUMN "admin" DROP NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "name" DROP NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "description" DROP NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "payment_for_mint" DROP NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "royalty" DROP NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "collection_logo" DROP NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "collection_banner" DROP NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "created_at" DROP NOT NULL`) - await db.query(`ALTER TABLE "collection" ALTER COLUMN "tags" DROP NOT NULL`) - } -} diff --git a/indexer/db/migrations/1707395758567-Data.js b/indexer/db/migrations/1707395758567-Data.js deleted file mode 100644 index eced619..0000000 --- a/indexer/db/migrations/1707395758567-Data.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = class Data1707395758567 { - name = 'Data1707395758567' - - async up(db) { - await db.query(`ALTER TABLE "collection" DROP COLUMN "additional_links"`) - await db.query(`ALTER TABLE "collection" ADD "additional_links" jsonb`) - } - - async down(db) { - await db.query(`ALTER TABLE "collection" ADD "additional_links" text`) - await db.query(`ALTER TABLE "collection" DROP COLUMN "additional_links"`) - } -} diff --git a/indexer/db/migrations/1707469641353-Data.js b/indexer/db/migrations/1707469641353-Data.js deleted file mode 100644 index 035d870..0000000 --- a/indexer/db/migrations/1707469641353-Data.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = class Data1707469641353 { - name = 'Data1707469641353' - - async up(db) { - await db.query(`ALTER TABLE "collection" DROP COLUMN "transferable"`) - await db.query(`ALTER TABLE "collection" ADD "transferable" numeric`) - await db.query(`ALTER TABLE "collection" DROP COLUMN "sellable"`) - await db.query(`ALTER TABLE "collection" ADD "sellable" numeric`) - } - - async down(db) { - await db.query(`ALTER TABLE "collection" ADD "transferable" boolean`) - await db.query(`ALTER TABLE "collection" DROP COLUMN "transferable"`) - await db.query(`ALTER TABLE "collection" ADD "sellable" boolean`) - await db.query(`ALTER TABLE "collection" DROP COLUMN "sellable"`) - } -} diff --git a/indexer/db/migrations/1707479217496-Data.js b/indexer/db/migrations/1707479217496-Data.js deleted file mode 100644 index 1db0dfa..0000000 --- a/indexer/db/migrations/1707479217496-Data.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = class Data1707479217496 { - name = 'Data1707479217496' - - async up(db) { - await db.query(`ALTER TABLE "auction" ADD "end_timestamp" TIMESTAMP WITH TIME ZONE`) - } - - async down(db) { - await db.query(`ALTER TABLE "auction" DROP COLUMN "end_timestamp"`) - } -} diff --git a/indexer/db/migrations/1707926335271-Data.js b/indexer/db/migrations/1707926335271-Data.js deleted file mode 100644 index 656c25e..0000000 --- a/indexer/db/migrations/1707926335271-Data.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = class Data1707926335271 { - name = 'Data1707926335271' - - async up(db) { - await db.query(`ALTER TABLE "nft" ADD "minted_by" text NOT NULL`) - } - - async down(db) { - await db.query(`ALTER TABLE "nft" DROP COLUMN "minted_by"`) - } -} diff --git a/indexer/db/migrations/1708174915413-Data.js b/indexer/db/migrations/1708174915413-Data.js deleted file mode 100644 index cd577ac..0000000 --- a/indexer/db/migrations/1708174915413-Data.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = class Data1708174915413 { - name = 'Data1708174915413' - - async up(db) { - await db.query(`ALTER TABLE "collection" ADD "permission_to_mint" text array`) - } - - async down(db) { - await db.query(`ALTER TABLE "collection" DROP COLUMN "permission_to_mint"`) - } -} diff --git a/indexer/db/migrations/1708614382580-Data.js b/indexer/db/migrations/1708614382580-Data.js deleted file mode 100644 index ce4e9c6..0000000 --- a/indexer/db/migrations/1708614382580-Data.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = class Data1708614382580 { - name = 'Data1708614382580' - - async up(db) { - await db.query(`ALTER TABLE "marketplace_config" ADD "royalty_to_marketplace_for_mint" integer`) - await db.query(`ALTER TABLE "marketplace_config" ADD "royalty_to_marketplace_for_trade" integer`) - await db.query(`ALTER TABLE "marketplace_config" ADD "fee_per_uploaded_file" numeric`) - } - - async down(db) { - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "royalty_to_marketplace_for_mint"`) - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "royalty_to_marketplace_for_trade"`) - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "fee_per_uploaded_file"`) - } -} diff --git a/indexer/db/migrations/1708938587449-Data.js b/indexer/db/migrations/1708938587449-Data.js deleted file mode 100644 index 83b4982..0000000 --- a/indexer/db/migrations/1708938587449-Data.js +++ /dev/null @@ -1,31 +0,0 @@ -module.exports = class Data1708938587449 { - name = 'Data1708938587449' - - async up(db) { - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_creation" TYPE int USING (COALESCE("gas_for_creation", 0)), ALTER COLUMN "gas_for_creation" SET DEFAULT 0, ALTER COLUMN "gas_for_creation" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_transfer_token" TYPE int USING (COALESCE("gas_for_transfer_token", 0)), ALTER COLUMN "gas_for_transfer_token" SET DEFAULT 0, ALTER COLUMN "gas_for_transfer_token" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_close_auction" TYPE int USING (COALESCE("gas_for_close_auction", 0)), ALTER COLUMN "gas_for_close_auction" SET DEFAULT 0, ALTER COLUMN "gas_for_close_auction" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_delete_collection" TYPE int USING (COALESCE("gas_for_delete_collection", 0)), ALTER COLUMN "gas_for_delete_collection" SET DEFAULT 0, ALTER COLUMN "gas_for_delete_collection" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_get_token_info" TYPE int USING (COALESCE("gas_for_get_token_info", 0)), ALTER COLUMN "gas_for_get_token_info" SET DEFAULT 0, ALTER COLUMN "gas_for_get_token_info" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "time_between_create_collections" TYPE int USING (COALESCE("time_between_create_collections", 0)), ALTER COLUMN "time_between_create_collections" SET DEFAULT 0, ALTER COLUMN "time_between_create_collections" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "royalty_to_marketplace_for_mint" TYPE int USING (COALESCE("royalty_to_marketplace_for_mint", 0)), ALTER COLUMN "royalty_to_marketplace_for_mint" SET DEFAULT 0, ALTER COLUMN "royalty_to_marketplace_for_mint" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "royalty_to_marketplace_for_trade" TYPE int USING (COALESCE("royalty_to_marketplace_for_trade", 0)), ALTER COLUMN "royalty_to_marketplace_for_trade" SET DEFAULT 0, ALTER COLUMN "royalty_to_marketplace_for_trade" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "fee_per_uploaded_file" TYPE numeric USING (COALESCE("fee_per_uploaded_file", 0)), ALTER COLUMN "fee_per_uploaded_file" SET DEFAULT 0, ALTER COLUMN "fee_per_uploaded_file" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "minimum_transfer_value" TYPE numeric USING (COALESCE("minimum_transfer_value", 0)), ALTER COLUMN "minimum_transfer_value" SET DEFAULT 0, ALTER COLUMN "minimum_transfer_value" SET NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "ms_in_block" TYPE int USING (COALESCE("ms_in_block", 0)), ALTER COLUMN "ms_in_block" SET DEFAULT 0, ALTER COLUMN "ms_in_block" SET NOT NULL`) - } - - async down(db) { - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_creation" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_transfer_token" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_close_auction" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_delete_collection" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_get_token_info" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "time_between_create_collections" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "royalty_to_marketplace_for_mint" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "royalty_to_marketplace_for_trade" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "fee_per_uploaded_file" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "minimum_transfer_value" DROP NOT NULL`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "ms_in_block" DROP NOT NULL`) - } -} diff --git a/indexer/db/migrations/1708939752324-Data.js b/indexer/db/migrations/1708939752324-Data.js deleted file mode 100644 index 42c2d1e..0000000 --- a/indexer/db/migrations/1708939752324-Data.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = class Data1708939752324 { - name = 'Data1708939752324' - - async up(db) { - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_creation" TYPE numeric`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_transfer_token" TYPE numeric`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_close_auction" TYPE numeric`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_delete_collection" TYPE numeric`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "gas_for_get_token_info" TYPE numeric`) - await db.query(`ALTER TABLE "marketplace_config" ALTER COLUMN "time_between_create_collections" TYPE numeric`) - } - - async down(db) { - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_creation"`) - await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_creation" integer NOT NULL DEFAULT '0'`) - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_transfer_token"`) - await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_transfer_token" integer NOT NULL DEFAULT '0'`) - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_close_auction"`) - await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_close_auction" integer NOT NULL DEFAULT '0'`) - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_delete_collection"`) - await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_delete_collection" integer NOT NULL DEFAULT '0'`) - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "gas_for_get_token_info"`) - await db.query(`ALTER TABLE "marketplace_config" ADD "gas_for_get_token_info" integer NOT NULL DEFAULT '0'`) - } -} diff --git a/indexer/db/migrations/1708949622123-Data.js b/indexer/db/migrations/1708949622123-Data.js deleted file mode 100644 index 50cc304..0000000 --- a/indexer/db/migrations/1708949622123-Data.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = class Data1708949622123 { - name = 'Data1708949622123' - - async up(db) { - await db.query(`ALTER TABLE "marketplace_config" ADD "minimum_value_for_trade" numeric NOT NULL DEFAULT 0`) - await db.query(`ALTER TABLE "marketplace_config" ADD "minimum_value_for_mint" numeric NOT NULL DEFAULT 0`) - } - - async down(db) { - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "minimum_value_for_trade"`) - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "minimum_value_for_mint"`) - } -} diff --git a/indexer/db/migrations/1709139070805-Data.js b/indexer/db/migrations/1709139070805-Data.js deleted file mode 100644 index 1f82da2..0000000 --- a/indexer/db/migrations/1709139070805-Data.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = class Data1709139070805 { - name = 'Data1709139070805' - - async up(db) { - await db.query(`ALTER TABLE "marketplace_config" ADD "max_creator_royalty" integer NOT NULL DEFAULT 0`) - await db.query(`ALTER TABLE "marketplace_config" ADD "max_number_of_images" numeric NOT NULL DEFAULT 0`) - } - - async down(db) { - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "max_creator_royalty"`) - await db.query(`ALTER TABLE "marketplace_config" DROP COLUMN "max_number_of_images"`) - } -} diff --git a/indexer/db/migrations/1705664292143-Data.js b/indexer/db/migrations/1709213989375-Data.js similarity index 79% rename from indexer/db/migrations/1705664292143-Data.js rename to indexer/db/migrations/1709213989375-Data.js index cd8300a..af35405 100644 --- a/indexer/db/migrations/1705664292143-Data.js +++ b/indexer/db/migrations/1709213989375-Data.js @@ -1,8 +1,8 @@ -module.exports = class Data1705664292143 { - name = 'Data1705664292143' +module.exports = class Data1709213989375 { + name = 'Data1709213989375' async up(db) { - await db.query(`CREATE TABLE "marketplace_config" ("id" character varying NOT NULL, "gas_for_creation" integer, "gas_for_transfer_token" integer, "gas_for_close_auction" integer, "gas_for_delete_collection" integer, "gas_for_get_token_info" integer, "time_between_create_collections" integer, "minimum_transfer_value" numeric, "ms_in_block" integer, "marketplace_id" character varying, CONSTRAINT "PK_73c68d1a502db50c13ff91f8ec3" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "marketplace_config" ("id" character varying NOT NULL, "gas_for_creation" numeric NOT NULL, "gas_for_transfer_token" numeric NOT NULL, "gas_for_close_auction" numeric NOT NULL, "gas_for_delete_collection" numeric NOT NULL, "gas_for_get_token_info" numeric NOT NULL, "time_between_create_collections" numeric NOT NULL, "royalty_to_marketplace_for_mint" integer NOT NULL, "royalty_to_marketplace_for_trade" integer NOT NULL, "fee_per_uploaded_file" numeric NOT NULL, "minimum_transfer_value" numeric NOT NULL, "minimum_value_for_trade" numeric NOT NULL, "minimum_value_for_mint" numeric NOT NULL, "ms_in_block" integer NOT NULL, "max_creator_royalty" integer NOT NULL, "max_number_of_images" numeric NOT NULL, "marketplace_id" character varying, CONSTRAINT "PK_73c68d1a502db50c13ff91f8ec3" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_49bd93aa35746a6971bb299ce3" ON "marketplace_config" ("marketplace_id") `) await db.query(`CREATE TABLE "collection_type" ("id" character varying NOT NULL, "description" text NOT NULL, "type" text NOT NULL, "meta_url" text NOT NULL, "meta_str" text NOT NULL, "marketplace_id" character varying, CONSTRAINT "PK_75c673f46e25c52205fae22130c" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_be423ee528eb245b57165bd597" ON "collection_type" ("marketplace_id") `) @@ -12,18 +12,18 @@ module.exports = class Data1705664292143 { await db.query(`CREATE INDEX "IDX_8524438f82167bcb795bcb8663" ON "sale" ("nft_id") `) await db.query(`CREATE TABLE "bid" ("id" character varying NOT NULL, "bidder" text NOT NULL, "price" numeric NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "auction_id" character varying, CONSTRAINT "PK_ed405dda320051aca2dcb1a50bb" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_9e594e5a61c0f3cb25679f6ba8" ON "bid" ("auction_id") `) - await db.query(`CREATE TABLE "auction" ("id" character varying NOT NULL, "owner" text NOT NULL, "min_price" numeric NOT NULL, "new_owner" text, "last_price" numeric, "status" text NOT NULL, "duration_ms" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "nft_id" character varying, CONSTRAINT "PK_9dc876c629273e71646cf6dfa67" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "auction" ("id" character varying NOT NULL, "owner" text NOT NULL, "min_price" numeric NOT NULL, "new_owner" text, "last_price" numeric, "status" text NOT NULL, "duration_ms" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "end_timestamp" TIMESTAMP WITH TIME ZONE, "block_number" integer NOT NULL, "nft_id" character varying, CONSTRAINT "PK_9dc876c629273e71646cf6dfa67" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_cfb47e97e60c9d1462576f85a8" ON "auction" ("nft_id") `) await db.query(`CREATE TABLE "offer" ("id" character varying NOT NULL, "owner" text NOT NULL, "price" numeric NOT NULL, "status" text NOT NULL, "creator" text NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "nft_id" character varying, CONSTRAINT "PK_57c6ae1abe49201919ef68de900" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_71609884f4478ed41be6672a66" ON "offer" ("nft_id") `) - await db.query(`CREATE TABLE "nft" ("id" character varying NOT NULL, "owner" text NOT NULL, "name" text NOT NULL, "description" text NOT NULL, "id_in_collection" integer NOT NULL, "media_url" text NOT NULL, "approved_account" text, "metadata" text, "on_sale" boolean NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "collection_id" character varying, CONSTRAINT "PK_8f46897c58e23b0e7bf6c8e56b0" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "nft" ("id" character varying NOT NULL, "owner" text NOT NULL, "name" text NOT NULL, "minted_by" text NOT NULL, "description" text NOT NULL, "id_in_collection" integer NOT NULL, "media_url" text NOT NULL, "approved_account" text, "metadata" text, "on_sale" boolean NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "collection_id" character varying, CONSTRAINT "PK_8f46897c58e23b0e7bf6c8e56b0" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_ffe58aa05707db77c2f20ecdbc" ON "nft" ("collection_id") `) - await db.query(`CREATE TABLE "collection" ("id" character varying NOT NULL, "admin" text, "name" text, "description" text, "user_mint_limit" numeric, "tokens_limit" numeric, "payment_for_mint" numeric, "royalty" integer, "collection_logo" text, "collection_banner" text, "transferable" boolean, "approvable" boolean, "burnable" boolean, "sellable" boolean, "attendable" boolean, "created_at" TIMESTAMP WITH TIME ZONE, "tags" text array, "marketplace_id" character varying, "type_id" character varying, CONSTRAINT "PK_ad3f485bbc99d875491f44d7c85" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "collection" ("id" character varying NOT NULL, "admin" text NOT NULL, "name" text NOT NULL, "description" text NOT NULL, "additional_links" jsonb, "user_mint_limit" numeric, "tokens_limit" numeric, "payment_for_mint" numeric NOT NULL, "royalty" integer NOT NULL, "collection_logo" text NOT NULL, "collection_banner" text NOT NULL, "transferable" numeric, "approvable" boolean, "burnable" boolean, "sellable" numeric, "attendable" boolean, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL, "tags" text array NOT NULL, "permission_to_mint" text array, "marketplace_id" character varying, "type_id" character varying, CONSTRAINT "PK_ad3f485bbc99d875491f44d7c85" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_4698f01445e4833a95f214f862" ON "collection" ("marketplace_id") `) await db.query(`CREATE INDEX "IDX_75c673f46e25c52205fae22130" ON "collection" ("type_id") `) await db.query(`CREATE TABLE "marketplace_event" ("id" character varying NOT NULL, "type" text NOT NULL, "raw" text NOT NULL, "block_number" integer NOT NULL, "tx_hash" text NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "marketplace_id" character varying, CONSTRAINT "PK_805265912d311b94048601bd286" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_7fb5589ddd0a773530e3b05af0" ON "marketplace_event" ("marketplace_id") `) - await db.query(`CREATE TABLE "marketplace" ("id" character varying NOT NULL, "admins" text array NOT NULL, "config_id" character varying, CONSTRAINT "PK_d9c9a956a1a45b27b56db53bfc8" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "marketplace" ("id" character varying NOT NULL, "admins" text array NOT NULL, "address" text NOT NULL, "metadata" text NOT NULL, "nft_metadata" text NOT NULL, "config_id" character varying, CONSTRAINT "PK_d9c9a956a1a45b27b56db53bfc8" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_73c68d1a502db50c13ff91f8ec" ON "marketplace" ("config_id") `) await db.query(`ALTER TABLE "marketplace_config" ADD CONSTRAINT "FK_49bd93aa35746a6971bb299ce37" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) await db.query(`ALTER TABLE "collection_type" ADD CONSTRAINT "FK_be423ee528eb245b57165bd597b" FOREIGN KEY ("marketplace_id") REFERENCES "marketplace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) From 8c9bd7c42e908f1876bfb816656a8c341892fd8b Mon Sep 17 00:00:00 2001 From: Aydar Farrakhov Date: Thu, 29 Feb 2024 17:59:17 +0300 Subject: [PATCH 50/50] remove marketplace interval --- .../marketplace/initialized.handler.ts | 16 +++++++++++++++- indexer/src/processing/storage/local.storage.ts | 1 - 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/indexer/src/processing/marketplace/initialized.handler.ts b/indexer/src/processing/marketplace/initialized.handler.ts index 4f28a94..5d452a5 100644 --- a/indexer/src/processing/marketplace/initialized.handler.ts +++ b/indexer/src/processing/marketplace/initialized.handler.ts @@ -21,7 +21,21 @@ export class MarketplaceInitializedHandler ); await storage.setMarketplaceConfig( new MarketplaceConfig({ - ...(marketplace.config || {}), + feePerUploadedFile: 0n, + gasForCloseAuction: 0n, + gasForDeleteCollection: 0n, + gasForGetTokenInfo: 0n, + gasForTransferToken: 0n, + maxCreatorRoyalty: 0, + maxNumberOfImages: 0n, + minimumTransferValue: 0n, + minimumValueForMint: 0n, + minimumValueForTrade: 0n, + msInBlock: 0, + royaltyToMarketplaceForMint: 0, + royaltyToMarketplaceForTrade: 0, + timeBetweenCreateCollections: 0n, + gasForCreation: 0n, ...Object.fromEntries( Object.entries(event).filter(([, value]) => value !== null), ), diff --git a/indexer/src/processing/storage/local.storage.ts b/indexer/src/processing/storage/local.storage.ts index f4d7032..cc582de 100644 --- a/indexer/src/processing/storage/local.storage.ts +++ b/indexer/src/processing/storage/local.storage.ts @@ -50,7 +50,6 @@ export class LocalStorage implements IStorage { } await this.loadEntities(); this.initialized = true; - setInterval(() => this.loadMarketplace(), 10 * 1000); // 10 seconds } setStore(store: Store) {