diff --git a/.gitignore b/.gitignore index a36d9d8..b626bc9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,12 @@ # Bot -.env +.env* .build/ # Terraform .terraform/ terraform.tfstate terraform.tfstate.backup -values.auto.tfvars \ No newline at end of file +values.auto.tfvars + +# Ansible +inventory.cfg \ No newline at end of file diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl index 9244a4f..329b1a7 100644 --- a/.terraform.lock.hcl +++ b/.terraform.lock.hcl @@ -24,3 +24,25 @@ provider "registry.terraform.io/digitalocean/digitalocean" { "zh:fbe5edf5337adb7360f9ffef57d02b397555b6a89bba68d1b60edfec6e23f02c", ] } + +provider "registry.terraform.io/linode/linode" { + version = "2.13.0" + constraints = "2.13.0" + hashes = [ + "h1:bsdPJRav766kmjV62GdSnOmaZTfmSMcLNbKyWS9+5Ms=", + "zh:25776adaba8c01251f02326b356e960f5e7ea1bf5f7e60b3b598792a0a3b5b4f", + "zh:30bc848498bcf2ad1366ea32068c2983d982140669aa507bb7a21714fe5f6beb", + "zh:32b5078f3defe920d611da19ff53139cbdff7de74a19238a9611d206255d5eb8", + "zh:32b69e72ed06273550888b5fa6c53b05f37d6fb42aa898b1981e0e40d5332cd3", + "zh:7b1df46d734b461b006f2fc92a8f8e4e810afa5458c50f2016ee99e1541f6a4b", + "zh:7eda947ae4aefd486e758d6f86985607c9764ea55556aacf8a9fcc78780fa6d0", + "zh:832ec3adf887bcbbff99021ca1518e44f51e1c6af0d7fe639ceddc92921df130", + "zh:8cd1dfd9edcdd9432ce567981dc653cc2cdedf6349513614493c37485533d519", + "zh:a5cf20563230d2180fd48a1716315f7ccfb20d8e12eceb29609135122a2a07db", + "zh:b8d66ae8c6fbd31cea8cfc15f8160e3e00b6d79f8afcdd2b88ccbe63c3bbc34e", + "zh:da0a28bde0bf5ac818fc07c7ab1136e7dfb46efa98fd38e1450104582d629f96", + "zh:dc611263577f1ee319a229fb2e47d1ab5ad99cfab8eb4d43c09afcafefb00f1d", + "zh:e23355243d5c024caec26f072035b67707f09ee1231361168919023d2ca15c65", + "zh:e51d4813a58e79bc953c77db295e23a8abf0f8c21afcfc6401dc1010b9613a48", + ] +} diff --git a/Dockerfile b/Dockerfile index 72429f1..603567d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,14 @@ -FROM public.ecr.aws/bitnami/node:16 +FROM public.ecr.aws/bitnami/node:18 RUN apt-get install git ENV NODE_ENV=production RUN npm install -g yarn RUN npm install -g typescript +RUN npm install -g ts-node WORKDIR /app -COPY package.json ./ - -RUN yarn install COPY . . +RUN yarn install RUN yarn build RUN yarn install --production diff --git a/README.md b/README.md index 47c8629..de5436b 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,111 @@ > Keeper Bots in the Drift Protocol keep the protocol operational by performing automated actions as autonomous off-chain agents. Keepers are rewarded depending on the duties that they perform. -This repository contains tools to build, run and monitor Keeper bots for Drift on Solana. - +This repository contains tools to build, run and monitor Drift Keeper bots on Solana. +Checkout my article about all that stuff: https://nitro.dcentral.systems/drift-keeper-bot + More information: - https://github.com/drift-labs/keeper-bots-v2/ - https://docs.drift.trade/keeper-bots - https://docs.drift.trade/tutorial-order-matching-bot +--- + +## Components + +This repository contains several components for automation and monitoring of Drift Keeper bots: + +- Keeper Bot +- Wallet-Tracker +- User-Tracker +- Auto-Swap +- Panopticon + +### Keeper-Bot + +The Keeper-Bot is the core component of this whole thing. +It performs off-chain actions for the Drift Protocol and receives rewards in USDC. A portion of SOL is required to pay for transaction fees. +While there are several types of bots for Drift, this repository is focused on order matching a.k.a filler bots that tries to match orders in the decentralized orderbook. +This repository only serves as a build and deploy stack for the official bot of this source repository: https://github.com/drift-labs/keeper-bots-v2/. + +```mermaid + stateDiagram-v2 + Terraform --> Linode + Terraform --> DigitalOcean + Linode --> Keeper_1 + Linode --> Keeper_2 + DigitalOcean --> Keeper_3 + DigitalOcean --> Keeper_4 +``` + +### Wallet-Tracker + +As the name suggests, this component tracks the current SOL and USDC onchain balance of a given wallet, as well as the current SOL price from Jupiter. +Everything is conveniently exportes as Prometheus metrics and will be scraped by the `Panopticon`. + + +```mermaid + stateDiagram-v2 + WalletTracker --> Solana + WalletTracker --> Jupiter + Solana --> USDC_Balance + Solana --> SOL_Balance + Jupiter --> SOL_Price + +``` + +### User-Tracker + +This component tracks the current SOL and USDC balance in the wallet as well as total collateral and unrealized PNL on Drift. + + +```mermaid + stateDiagram-v2 + UserTracker --> Solana + UserTracker --> Drift + Solana --> USDC_Balance + Solana --> SOL_Balance + Drift --> Total_Collateral + Drift --> Unrealized_PNL + +``` + +### Auto-Swap + +The Auto-Swap is resposible of keeping the bot afloat by automatically swapping a portion of the profits to SOL in order to pay for transaction fees. +It periodically checks if a configurable amount of USDC collateral is available on your Drift account. If this amount is reached,it withdraws all collateral and swaps a configurable portion of the profits to SOL using Jupiter. +Altough it is possible to configure the swap ratio so that you can make profits in both SOL and USDC. this only seems to work on "slow days". With crazy market fluctuation and high trading volume, consider that you might pay a lot of fees. + +```mermaid + stateDiagram-v2 + [*] --> checkBalance + checkBalance --> [*]:threshold\nnot reached + checkBalance --> withdraw: threshold\nreached + withdraw --> withdraw: try 3x + withdraw --> [*]: backoff + withdraw --> swap + swap --> swap: try 3x + swap --> [*] +``` + +Known problem: when Solana is congested, the autoswap routine fails a lot, as the `withdraw` method seems to be somehow unstable. + +### Panopticon + +This is basically the monitoring stack consisting of a Prometheus and Grafana instance. +As every bot is accompanied by a Prometheus instance, the Prometheus of the Panopticon is configured to scrape the `/federate` endpoint of all available instances to centralize monitoring of all servers, bots and wallets. + +```mermaid + stateDiagram-v2 + Panopticon --> WalletTracker + Panopticon --> /federate + /federate --> NodeExporter + /federate --> Keeper + +``` + +--- + ## Prerequisites - Docker, Docker-Compose @@ -17,58 +115,141 @@ More information: - Jito Private Key for auth to block engine API (optional) - Terraform (optional) - DigitalOcean API Key (optional) +- Linode API Key (optional) Drift account is setup according to: https://docs.drift.trade/keeper-bots. The account can also be set up using the DEX app: https://app.drift.trade/. -## Configure +## Build + +In order to build all components and push them to the Docker registry, simply run: + +``` +./ctl.sh build all +./ctl.sh push all +``` + +## Run Locally Create .env file from example and configure all environment variables. ``` cp example.env .env +cp example.env.monitoring .env.monitoring +cp example.env.autoswap .env.autoswap +cp example.env.user-metrics .env.user-metrics ``` -Adjust `config.yaml` as you please. - -## Build - -Clone the [keeper-bots-v2](https://github.com/drift-labs/keeper-bots-v2/) repository and build the Docker image. +Adjust `config.yaml` as you please (e.g. configure Jito). +Then just run the bot. ``` -./ctl.sh keeper build -``` - -## Run - -Run the bot. - -``` -docker compose up +./ctl.sh run ``` ## Deploy -Provision a DigitalOcean Droplet and deploy Keeper Bot with current configuration (.env and config.yaml). -By default ~/.ssh/id_rsa.pub is added to DigitalOcean and the Droplet. +Provision DigitalOcean and Linode instances using Terraform. +By default ~/.ssh/id_rsa.pub is added to the root account of each server. + +First, create a `values.auto.tfvars` with all your secrets: ``` -./ctl.sh droplet provision +do_token = "your-token" +linode_token = "your-token" +bot = { + wallet_address = "your-wallet-address" + rpc_endpoint = "https://your-endpoint" + ws_endpoint = "wss://your-ws-endpoint" + keeper_private_key = "[123,456...789]" + jito_private_key = "[123,456...789]" +} +monitoring = { + grafana_user = "admin" + grafana_password = "grafana" + prometheus_password = "prompass" +} ``` -Wait until Droplet is up and the `droplet_ip` is printed. You may connect to the Droplet using +If you want to configure custom servers, you may also add them to your values file: ``` -./ctl.sh droplet connect +linode_instances = [ + { + label = "DK-LN-AMS" + group = "keeper" + image = "linode/ubuntu23.10" + region = "nl-ams" + type = "g6-standard-1" + ntp_server = "ntp.amsterdam.jito.wtf" + jito_block_engine_url = "amsterdam.mainnet.block-engine.jito.wtf" + use_jito = true + } +] +digitalocean_instances = [ + { + label = "DK-DO-FRA" + image = "ubuntu-23-10-x64" + region = "fra1" + type = "s-1vcpu-1gb" + ntp_server = "ntp.frankfurt.jito.wtf" + jito_block_engine_url = "frankfurt.mainnet.block-engine.jito.wtf" + use_jito = true + } +] +``` + +If no custom instances are provided, the default set from `variables.tf` will be used: +- Linode g6-nanode-1 in Amsterdam (NL) +- Linode g6-nanode-1 in Osaka (JP) +- DigitalOcean s-1vcpu-1gb in Frankfurt (DE) +- DigitalOcean s-1vcpu-1gb in New York (US) + +At the time of writing, this setup will cost 22$. + +Provision the infrastructure: + +``` +./ctl.sh infra provision +``` + +Wait until all instances are up and the `instances` output is printed. You may connect to any server using + +``` +./ctl.sh infra connect ``` In case somethin went wrong with the provisioning, check the cloud-init-output log at `/var/log/cloud-init-output.log`. +## RPC Providers + +In order for Keeper bots to run smoothly, you need to choose a suitable RPC provider that allows all method calls (e.g. getProgramAccounts, etc.). + +Checkout https://solana.com/rpc + +Helius and ExtrNode are quite suitable with reasonable pricing. + +## Geo-Locating Nodes + +When deploying multiple bots all around the globe, consider placing the machines near your RPC provider and other Solana nodes: +https://solanacompass.com/statistics/decentralization + +Keep in mind, not all Linode datacenters support the `Metadata Service` required to apply the cloud-init config. Check the availability here: https://www.linode.com/docs/products/compute/compute-instances/guides/metadata/#availability + +## Maintenance + +There are several Ansible playbooks to maintain the servers and the app that can be selected and run through the ctl.sh. + +``` +./ctl.sh infra playbook +``` + ## Metrics There are several metrics endpoints available that are periodically scraped by Prometheus: - http://keeper:9464/metrics - http://wallet-tracker:3000/metrics +- http://user-tracker:3000/metrics - http://node-exporter:9100/metrics A Grafana dashboard is exposed on http://localhost:3000 with default username/password: admin/grafana. diff --git a/ansible/app-configure.yaml b/ansible/app-configure.yaml new file mode 100644 index 0000000..1639037 --- /dev/null +++ b/ansible/app-configure.yaml @@ -0,0 +1,24 @@ +- hosts: bots + remote_user: root + become: true + tasks: + - name: Stop Containers + shell: | + cd /app/bot + docker-compose down + - name: Configure Grafana + copy: + src: ../grafana + dest: /app/bot + #- name: Configure Prometheus + # copy: + # src: ../prometheus + # dest: /app/bot + #- name: Configure Bot + # copy: + # src: ../config.yaml + # dest: /app/bot + - name: Start Containers + shell: | + cd /app/bot + sudo -u keeper -g bot -- docker-compose up -d \ No newline at end of file diff --git a/ansible/app-reset.yaml b/ansible/app-reset.yaml new file mode 100644 index 0000000..9c09ca6 --- /dev/null +++ b/ansible/app-reset.yaml @@ -0,0 +1,9 @@ +- hosts: bots + remote_user: root + become: true + tasks: + - name: Reset Containers + shell: | + cd /app/bot + docker-compose down -v + sudo -u keeper -g bot -- docker-compose up -d \ No newline at end of file diff --git a/ansible/app-upgrade.yaml b/ansible/app-upgrade.yaml new file mode 100644 index 0000000..d8cfb87 --- /dev/null +++ b/ansible/app-upgrade.yaml @@ -0,0 +1,10 @@ +- hosts: bots + remote_user: root + become: true + tasks: + - name: Upgrade Containers + shell: | + cd /app/bot + docker-compose down + docker-compose pull + sudo -u keeper -g bot -- docker-compose up -d \ No newline at end of file diff --git a/ansible/system-reboot.yaml b/ansible/system-reboot.yaml new file mode 100644 index 0000000..ff23999 --- /dev/null +++ b/ansible/system-reboot.yaml @@ -0,0 +1,6 @@ +- hosts: bots + remote_user: root + become: true + tasks: + - name: Reboot + reboot: \ No newline at end of file diff --git a/ansible/system-upgrade.yaml b/ansible/system-upgrade.yaml new file mode 100644 index 0000000..20e29fb --- /dev/null +++ b/ansible/system-upgrade.yaml @@ -0,0 +1,10 @@ +- hosts: bots + remote_user: root + become: true + tasks: + - name: Upgrade System + shell: | + apt update + apt upgrade -y + - name: Reboot + reboot: \ No newline at end of file diff --git a/auto-swap/.gitignore b/auto-swap/.gitignore new file mode 100644 index 0000000..2d7ec5c --- /dev/null +++ b/auto-swap/.gitignore @@ -0,0 +1,2 @@ +.env +node_modules/ diff --git a/auto-swap/Dockerfile b/auto-swap/Dockerfile new file mode 100644 index 0000000..b4eee42 --- /dev/null +++ b/auto-swap/Dockerfile @@ -0,0 +1,7 @@ +FROM node:18 + +WORKDIR /app +COPY package.json ./ +RUN npm install +COPY src src +CMD ["npm", "start"] \ No newline at end of file diff --git a/auto-swap/README.md b/auto-swap/README.md new file mode 100644 index 0000000..9cc670b --- /dev/null +++ b/auto-swap/README.md @@ -0,0 +1,18 @@ +# Auto-Swap + +## Configuration + +- PRIVATE_KEY: Either use the PRIVATE_KEY or PRIVATE_KEY_FILE variable to set your Solana private key +- SWAP_THRESHOLD: min amount of USDC in Drift account to initiate the swap. Default: 10 +- SWAP_RATION: ratio to which the swap should be executed. E.g. 0.5 = 50% of USDC will be swapped to SOL. Default: 0.5 +- AUTOSWA_INTERVAL: Time in ms of the interval to check if SWAP_THRESHOLD is reached. Default: 60000 + +Example: `.env` file: +``` +RPC_ENDPOINT=https://your-rpc-endpoint +PRIVATE_KEY="[123,456,...789]" +#PRIVATE_KEY_FILE=~/.config/solana/bot.json +SWAP_THRESHOLD=2 +SWAP_RATIO=0.6 +AUTOSWAP_INTERVAL=60000 +``` diff --git a/auto-swap/package-lock.json b/auto-swap/package-lock.json new file mode 100644 index 0000000..2113217 --- /dev/null +++ b/auto-swap/package-lock.json @@ -0,0 +1,1694 @@ +{ + "name": "auto-swap", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "auto-swap", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@drift-labs/sdk": "2.74.0-beta.0", + "@solana/web3.js": "^1.89.1", + "bigint-buffer": "^1.1.5", + "dotenv": "^16.4.4" + } + }, + "node_modules/@babel/runtime": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@coral-xyz/anchor": { + "version": "0.28.1-beta.2", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.28.1-beta.2.tgz", + "integrity": "sha512-xreUcOFF8+IQKWOBUrDKJbIw2ftpRVybFlEPVrbSlOBCbreCWrQ5754Gt9cHIcuBDAzearCDiBqzsGQdNgPJiw==", + "dependencies": { + "@coral-xyz/borsh": "^0.28.0", + "@noble/hashes": "^1.3.1", + "@solana/web3.js": "^1.68.0", + "base64-js": "^1.5.1", + "bn.js": "^5.1.2", + "bs58": "^4.0.1", + "buffer-layout": "^1.2.2", + "camelcase": "^6.3.0", + "cross-fetch": "^3.1.5", + "crypto-hash": "^1.3.0", + "eventemitter3": "^4.0.7", + "pako": "^2.0.3", + "snake-case": "^3.0.4", + "superstruct": "^0.15.4", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=11" + } + }, + "node_modules/@coral-xyz/borsh": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.28.0.tgz", + "integrity": "sha512-/u1VTzw7XooK7rqeD7JLUSwOyRSesPUk0U37BV9zK0axJc1q0nRbKFGFLYCQ16OtdOJTTwGfGp11Lx9B45bRCQ==", + "dependencies": { + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@solana/web3.js": "^1.68.0" + } + }, + "node_modules/@drift-labs/sdk": { + "version": "2.74.0-beta.0", + "resolved": "https://registry.npmjs.org/@drift-labs/sdk/-/sdk-2.74.0-beta.0.tgz", + "integrity": "sha512-VqZSDFMJTYcQ7K+D25C3xlPSY50d6ywWFdSxmXlzXnjLSKze2okBxmXDjXhy0nguemadU2pUMJxv6Z1VGf15RA==", + "dependencies": { + "@coral-xyz/anchor": "0.28.1-beta.2", + "@ellipsis-labs/phoenix-sdk": "^1.4.2", + "@project-serum/serum": "^0.13.38", + "@pythnetwork/client": "2.5.3", + "@solana/spl-token": "^0.3.7", + "@solana/web3.js": "1.73.2", + "strict-event-emitter-types": "^2.0.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@drift-labs/sdk/node_modules/@solana/web3.js": { + "version": "1.73.2", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.73.2.tgz", + "integrity": "sha512-9WACF8W4Nstj7xiDw3Oom22QmrhBh0VyZyZ7JvvG3gOxLWLlX3hvm5nPVJOGcCE/9fFavBbCUb5A6CIuvMGdoA==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@noble/ed25519": "^1.7.0", + "@noble/hashes": "^1.1.2", + "@noble/secp256k1": "^1.6.3", + "@solana/buffer-layout": "^4.0.0", + "agentkeepalive": "^4.2.1", + "bigint-buffer": "^1.1.5", + "bn.js": "^5.0.0", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.1", + "fast-stable-stringify": "^1.0.0", + "jayson": "^3.4.4", + "node-fetch": "2", + "rpc-websockets": "^7.5.0", + "superstruct": "^0.14.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@drift-labs/sdk/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/@drift-labs/sdk/node_modules/buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz", + "integrity": "sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==", + "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/@drift-labs/sdk/node_modules/jayson": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.7.0.tgz", + "integrity": "sha512-tfy39KJMrrXJ+mFcMpxwBvFDetS8LAID93+rycFglIQM4kl3uNR3W4lBLE/FFhsoUCEox5Dt2adVpDm/XtebbQ==", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "lodash": "^4.17.20", + "uuid": "^8.3.2", + "ws": "^7.4.5" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@drift-labs/sdk/node_modules/superstruct": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", + "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" + }, + "node_modules/@ellipsis-labs/phoenix-sdk": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@ellipsis-labs/phoenix-sdk/-/phoenix-sdk-1.4.5.tgz", + "integrity": "sha512-vEYgMXuV5/mpnpEi+VK4HO8f6SheHtVLdHHlULBiDN1eECYmL67gq+/cRV7Ar6jAQ7rJZL7xBxhbUW5kugMl6A==", + "dependencies": { + "@metaplex-foundation/beet": "^0.7.1", + "@metaplex-foundation/rustbin": "^0.3.1", + "@metaplex-foundation/solita": "^0.12.2", + "@solana/spl-token": "^0.3.7", + "@types/node": "^18.11.13", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^5.0.0" + } + }, + "node_modules/@ellipsis-labs/phoenix-sdk/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/@ellipsis-labs/phoenix-sdk/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/@metaplex-foundation/beet": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/beet/-/beet-0.7.2.tgz", + "integrity": "sha512-K+g3WhyFxKPc0xIvcIjNyV1eaTVJTiuaHZpig7Xx0MuYRMoJLLvhLTnUXhFdR5Tu2l2QSyKwfyXDgZlzhULqFg==", + "dependencies": { + "ansicolors": "^0.3.2", + "assert": "^2.1.0", + "bn.js": "^5.2.0", + "debug": "^4.3.3" + } + }, + "node_modules/@metaplex-foundation/beet-solana": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/beet-solana/-/beet-solana-0.3.1.tgz", + "integrity": "sha512-tgyEl6dvtLln8XX81JyBvWjIiEcjTkUwZbrM5dIobTmoqMuGewSyk9CClno8qsMsFdB5T3jC91Rjeqmu/6xk2g==", + "dependencies": { + "@metaplex-foundation/beet": ">=0.1.0", + "@solana/web3.js": "^1.56.2", + "bs58": "^5.0.0", + "debug": "^4.3.4" + } + }, + "node_modules/@metaplex-foundation/beet-solana/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/@metaplex-foundation/beet-solana/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/@metaplex-foundation/rustbin": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/rustbin/-/rustbin-0.3.5.tgz", + "integrity": "sha512-m0wkRBEQB/8krwMwKBvFugufZtYwMXiGHud2cTDAv+aGXK4M90y0Hx67/wpu+AqqoQfdV8VM9YezUOHKD+Z5kA==", + "dependencies": { + "debug": "^4.3.3", + "semver": "^7.3.7", + "text-table": "^0.2.0", + "toml": "^3.0.0" + } + }, + "node_modules/@metaplex-foundation/solita": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/solita/-/solita-0.12.2.tgz", + "integrity": "sha512-oczMfE43NNHWweSqhXPTkQBUbap/aAiwjDQw8zLKNnd/J8sXr/0+rKcN5yJIEgcHeKRkp90eTqkmt2WepQc8yw==", + "dependencies": { + "@metaplex-foundation/beet": "^0.4.0", + "@metaplex-foundation/beet-solana": "^0.3.0", + "@metaplex-foundation/rustbin": "^0.3.0", + "@solana/web3.js": "^1.36.0", + "camelcase": "^6.2.1", + "debug": "^4.3.3", + "js-sha256": "^0.9.0", + "prettier": "^2.5.1", + "snake-case": "^3.0.4", + "spok": "^1.4.3" + }, + "bin": { + "solita": "dist/src/cli/solita.js" + } + }, + "node_modules/@metaplex-foundation/solita/node_modules/@metaplex-foundation/beet": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/beet/-/beet-0.4.0.tgz", + "integrity": "sha512-2OAKJnLatCc3mBXNL0QmWVQKAWK2C7XDfepgL0p/9+8oSx4bmRAFHFqptl1A/C0U5O3dxGwKfmKluW161OVGcA==", + "dependencies": { + "ansicolors": "^0.3.2", + "bn.js": "^5.2.0", + "debug": "^4.3.3" + } + }, + "node_modules/@noble/curves": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", + "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/ed25519": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.3.tgz", + "integrity": "sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@project-serum/anchor": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.11.1.tgz", + "integrity": "sha512-oIdm4vTJkUy6GmE6JgqDAuQPKI7XM4TPJkjtoIzp69RZe0iAD9JP2XHx7lV1jLdYXeYHqDXfBt3zcq7W91K6PA==", + "dependencies": { + "@project-serum/borsh": "^0.2.2", + "@solana/web3.js": "^1.17.0", + "base64-js": "^1.5.1", + "bn.js": "^5.1.2", + "bs58": "^4.0.1", + "buffer-layout": "^1.2.0", + "camelcase": "^5.3.1", + "crypto-hash": "^1.3.0", + "eventemitter3": "^4.0.7", + "find": "^0.3.0", + "js-sha256": "^0.9.0", + "pako": "^2.0.3", + "snake-case": "^3.0.4", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=11" + } + }, + "node_modules/@project-serum/anchor/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@project-serum/borsh": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@project-serum/borsh/-/borsh-0.2.5.tgz", + "integrity": "sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q==", + "dependencies": { + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@solana/web3.js": "^1.2.0" + } + }, + "node_modules/@project-serum/serum": { + "version": "0.13.65", + "resolved": "https://registry.npmjs.org/@project-serum/serum/-/serum-0.13.65.tgz", + "integrity": "sha512-BHRqsTqPSfFB5p+MgI2pjvMBAQtO8ibTK2fYY96boIFkCI3TTwXDt2gUmspeChKO2pqHr5aKevmexzAcXxrSRA==", + "dependencies": { + "@project-serum/anchor": "^0.11.1", + "@solana/spl-token": "^0.1.6", + "@solana/web3.js": "^1.21.0", + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@project-serum/serum/node_modules/@solana/spl-token": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.1.8.tgz", + "integrity": "sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@solana/web3.js": "^1.21.0", + "bn.js": "^5.1.0", + "buffer": "6.0.3", + "buffer-layout": "^1.2.0", + "dotenv": "10.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@project-serum/serum/node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@pythnetwork/client": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@pythnetwork/client/-/client-2.5.3.tgz", + "integrity": "sha512-NBLxPnA6A3tZb/DYUooD4SO63UJ70s9DzzFPGXcQNBR9itcycp7aaV+UA5oUPloD/4UHL9soo2fRuDVur0gmhA==", + "dependencies": { + "@solana/web3.js": "^1.30.2", + "assert": "^2.0.0", + "buffer": "^6.0.1" + } + }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", + "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@solana/buffer-layout-utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz", + "integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/web3.js": "^1.32.0", + "bigint-buffer": "^1.1.5", + "bignumber.js": "^9.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@solana/codecs-core": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-JCz7mKjVKtfZxkuDtwMAUgA7YvJcA2BwpZaA1NOLcted4OMC4Prwa3DUe3f3181ixPYaRyptbF0Ikq2MbDkYEA==" + }, + "node_modules/@solana/codecs-data-structures": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-sLpjL9sqzaDdkloBPV61Rht1tgaKq98BCtIKRuyscIrmVPu3wu0Bavk2n/QekmUzaTsj7K1pVSniM0YqCdnEBw==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508", + "@solana/codecs-numbers": "2.0.0-experimental.8618508" + } + }, + "node_modules/@solana/codecs-numbers": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-EXQKfzFr3CkKKNzKSZPOOOzchXsFe90TVONWsSnVkonO9z+nGKALE0/L9uBmIFGgdzhhU9QQVFvxBMclIDJo2Q==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508" + } + }, + "node_modules/@solana/codecs-strings": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-b2yhinr1+oe+JDmnnsV0641KQqqDG8AQ16Z/x7GVWO+AWHMpRlHWVXOq8U1yhPMA4VXxl7i+D+C6ql0VGFp0GA==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508", + "@solana/codecs-numbers": "2.0.0-experimental.8618508" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22" + } + }, + "node_modules/@solana/options": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-fy/nIRAMC3QHvnKi63KEd86Xr/zFBVxNW4nEpVEU2OT0gCEKwHY4Z55YHf7XujhyuM3PNpiBKg/YYw5QlRU4vg==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508", + "@solana/codecs-numbers": "2.0.0-experimental.8618508" + } + }, + "node_modules/@solana/spl-token": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.11.tgz", + "integrity": "sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ==", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/buffer-layout-utils": "^0.2.0", + "@solana/spl-token-metadata": "^0.1.2", + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.88.0" + } + }, + "node_modules/@solana/spl-token-metadata": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@solana/spl-token-metadata/-/spl-token-metadata-0.1.2.tgz", + "integrity": "sha512-hJYnAJNkDrtkE2Q41YZhCpeOGU/0JgRFXbtrtOuGGeKc3pkEUHB9DDoxZAxx+XRno13GozUleyBi0qypz4c3bw==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508", + "@solana/codecs-data-structures": "2.0.0-experimental.8618508", + "@solana/codecs-numbers": "2.0.0-experimental.8618508", + "@solana/codecs-strings": "2.0.0-experimental.8618508", + "@solana/options": "2.0.0-experimental.8618508", + "@solana/spl-type-length-value": "0.1.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.87.6" + } + }, + "node_modules/@solana/spl-type-length-value": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz", + "integrity": "sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA==", + "dependencies": { + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.91.1", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.91.1.tgz", + "integrity": "sha512-cPgjZXm688oM9cULvJ8u2VH6Qp5rvptE1N1VODVxn2mAbpZsWrvWNPjmASkMYT/HzyrtqFkPvFdSHg8Xjt7aQA==", + "dependencies": { + "@babel/runtime": "^7.23.4", + "@noble/curves": "^1.2.0", + "@noble/hashes": "^1.3.3", + "@solana/buffer-layout": "^4.0.1", + "agentkeepalive": "^4.5.0", + "bigint-buffer": "^1.1.5", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.3", + "fast-stable-stringify": "^1.0.0", + "jayson": "^4.1.0", + "node-fetch": "^2.7.0", + "rpc-websockets": "^7.5.1", + "superstruct": "^0.14.2" + } + }, + "node_modules/@solana/web3.js/node_modules/superstruct": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", + "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "18.19.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.24.tgz", + "integrity": "sha512-eghAz3gnbQbvnHqB+mgB2ZR3aH6RhdEmHGS48BnV75KceQPHqabkxKI0BbUSsqhqy2Ddhc2xD/VAR9ySZd57Lw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "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/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "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/bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.3.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.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/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "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-layout": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", + "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==", + "engines": { + "node": ">=4.5" + } + }, + "node_modules/bufferutil": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", + "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/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/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/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/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/crypto-hash": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/crypto-hash/-/crypto-hash-1.3.0.tgz", + "integrity": "sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fast-stable-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", + "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==" + }, + "node_modules/fastestsmallesttextencoderdecoder": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", + "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", + "peer": true + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/find": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", + "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", + "dependencies": { + "traverse-chain": "~0.1.0" + } + }, + "node_modules/find-process": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", + "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", + "dependencies": { + "chalk": "^4.0.0", + "commander": "^5.1.0", + "debug": "^4.1.1" + }, + "bin": { + "find-process": "bin/find-process.js" + } + }, + "node_modules/find-process/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "engines": { + "node": ">= 6" + } + }, + "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/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/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/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.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "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.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.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/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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-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-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jayson": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz", + "integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "uuid": "^8.3.2", + "ws": "^7.4.5" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "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==" + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "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/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/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "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/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "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.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.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/rpc-websockets": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.9.0.tgz", + "integrity": "sha512-DwKewQz1IUA5wfLvgM8wDpPRcr+nWSxuFxx5CbrI2z/MyyZ4nXLM86TvIA+cI1ZAdqC8JIBR1mZR55dzaLU+Hw==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "eventemitter3": "^4.0.7", + "uuid": "^8.3.2", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + } + }, + "node_modules/rpc-websockets/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "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/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/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/spok": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/spok/-/spok-1.5.5.tgz", + "integrity": "sha512-IrJIXY54sCNFASyHPOY+jEirkiJ26JDqsGiI0Dvhwcnkl0PEWi1PSsrkYql0rzDw8LFVTcA7rdUCAJdE2HE+2Q==", + "dependencies": { + "ansicolors": "~0.3.2", + "find-process": "^1.4.7" + } + }, + "node_modules/strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==" + }, + "node_modules/superstruct": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.15.5.tgz", + "integrity": "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==" + }, + "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/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "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==" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/traverse-chain": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", + "integrity": "sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg==" + }, + "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/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/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, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "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/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-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "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/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/auto-swap/package.json b/auto-swap/package.json new file mode 100644 index 0000000..9add9c4 --- /dev/null +++ b/auto-swap/package.json @@ -0,0 +1,18 @@ +{ + "name": "auto-swap", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "node --no-warnings=ExperimentalWarning src/main.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@drift-labs/sdk": "2.78.0-beta.0", + "@solana/web3.js": "^1.89.1", + "bigint-buffer": "^1.1.5", + "dotenv": "^16.4.4" + } +} diff --git a/auto-swap/src/_main.js b/auto-swap/src/_main.js new file mode 100644 index 0000000..695a955 --- /dev/null +++ b/auto-swap/src/_main.js @@ -0,0 +1,310 @@ +require('dotenv').config() +const web3 = require("@solana/web3.js"); +const drift = require("@drift-labs/sdk"); + +const LAMPORTS_PER_SOL = 1000000000; +const AUTOSWAP_INTERVAL = process.env.AUTOSWAP_INTERVAL || 1000 * 60; + +const USDC_MARKET = 0; +const SOL_MARKET = 1; + +const SWAP_RATIO = process.env.SWAP_RATIO || 0.5; +const SWAP_THRESHOLD = process.env.SWAP_THRESHOLD || 10; + +const USDC_INT = 1000000; + +const SOL_MINT_ADDRESS = 'So11111111111111111111111111111111111111112'; +const USDC_MINT_ADDRESS = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; + +const USDC_MINT_PUBLIC_KEY = new web3.PublicKey(USDC_MINT_ADDRESS); +const keyPairFile = process.env.PRIVATE_KEY || process.env.PRIVATE_KEY_FILE; +const wallet = new drift.Wallet(drift.loadKeypair(keyPairFile)); +const connection = new web3.Connection(process.env.RPC_ENDPOINT); + +const thresholdReached = (amount) => amount / USDC_INT > SWAP_THRESHOLD; + +const driftClient = new drift.DriftClient({ + connection, + wallet, + env: 'mainnet-beta', + activeSubAccountId: 0, + subAccountIds: [0], +}); + +const sleep = (ms) => { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +const log = (msg) => { + console.log(`[${new Date().toISOString()}] ${msg}`) +}; + +const quoteNumber = (val) => { + return drift.convertToNumber(val, drift.QUOTE_PRECISION); +} + +const baseNumber = (val) => { + return drift.convertToNumber(val, drift.BASE_PRECISION); +} + +const quoteUsdcSol = async (amount) => { + const quoteUrl = `https://quote-api.jup.ag/v6/quote?inputMint=${USDC_MINT_ADDRESS}&outputMint=${SOL_MINT_ADDRESS}&amount=${amount}&slippageBps=50`; + const quoteResponse = await ( + await fetch(quoteUrl) + ).json(); + return quoteResponse; +} + +const getWalletBalance = async (connection, publicKey) => { + const lamportsBalance = await connection.getBalance(publicKey); + return lamportsBalance / LAMPORTS_PER_SOL; +}; + +const getUsdcBalance = async (connection, publicKey) => { + const balance = await connection.getParsedTokenAccountsByOwner( + publicKey, { mint: USDC_MINT_PUBLIC_KEY } + ); + return balance.value[0]?.account.data.parsed.info.tokenAmount.uiAmount; +}; + +const printInfo = async (user) => { + let usdcInAccount = quoteNumber(user.getTokenAmount(USDC_MARKET)); + let solInWallet = await getWalletBalance(connection, wallet.publicKey); + let usdcWallet = await getUsdcBalance(connection, wallet.publicKey) + + log(`USDC in account: ${usdcInAccount}`); + log(`USDC in wallet: ${usdcWallet}`); + log(`SOL in wallet: ${solInWallet}`); +}; + +const calcSwapAmount = (usdcInAccount) => { + return usdcInAccount * SWAP_RATIO; +}; + +const getSerializedTransaction = async (quote) => { + return await ( + await fetch('https://quote-api.jup.ag/v6/swap', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + quoteResponse: quote, + userPublicKey: wallet.publicKey.toString(), + wrapAndUnwrapSol: true, + dynamicComputeUnitLimit: true, // allow dynamic compute limit instead of max 1,400,000 + prioritizationFeeLamports: 'auto' // capped at 5,000,000 lamports / 0.005 SOL. + }) + }) + ).json(); +}; + +const signTransaction = (swapTransaction) => { + const swapTransactionBuf = Buffer.from(swapTransaction, 'base64'); + var transaction = web3.VersionedTransaction.deserialize(swapTransactionBuf); + transaction.sign([wallet.payer]); + return transaction; +}; + +const sendTransaction = async (transaction) => { + const rawTransaction = transaction.serialize() + return connection.sendRawTransaction(rawTransaction, { + skipPreflight: false, + preflightCommitment: 'confirmed', + // Maximum number of times for the RPC node to retry sending the transaction to the leader. + // If this parameter is not provided, the RPC node will retry the transaction until it is finalized or until the blockhash expires. + //maxRetries: 0 + }) + +}; + +const withdraw = async (marketIndex, withdrawAmount) => { + const amount = driftClient.convertToSpotPrecision(marketIndex, withdrawAmount); + const associatedTokenAccount = await driftClient.getAssociatedTokenAccount(marketIndex); + const reduceOnly = true; + return driftClient.withdraw( + amount, + marketIndex, + associatedTokenAccount, + reduceOnly + ); +}; + +const signAndSendTx = async (quote) => { + let tx = await getSerializedTransaction(quote); + let signedTx = signTransaction(tx.swapTransaction); + return sendTransaction(signedTx); +}; + +const confirmTx = async (txSig) => { + const latestBlockHash = await connection.getLatestBlockhash(); + return connection.confirmTransaction({ + blockhash: latestBlockHash.blockhash, + lastValidBlockHeight: latestBlockHash.lastValidBlockHeight, + signature: txSig, + }, 'confirmed'); +}; + +const run2 = async () => { + + await driftClient.subscribe(); + const user = driftClient.getUser(); + + // force markets to be included + driftClient.perpMarketLastSlotCache.set(SOL_MARKET, Number.MAX_SAFE_INTEGER); + driftClient.perpMarketLastSlotCache.set(USDC_MARKET, Number.MAX_SAFE_INTEGER); + + log('---------------------------------') + log("DriftClient initialized") + log(`Swap Ratio: ${SWAP_RATIO}`); + log(`Swap Threshold: ${SWAP_THRESHOLD} USDC`); + printInfo(user); + + let swapInProgress = false; + + let lastUsdcInAccount = await connection.getBalance(publicKey); + let lastSolInWallet = await getWalletBalance(connection, wallet.publicKey); + + setInterval(async () => { + if (!swapInProgress) { + let currentUsdcInAccount = await connection.getBalance(publicKey); + let currentSolInWallet = await getWalletBalance(connection, wallet.publicKey); + + let differenceSol = lastSolInWallet - currentSolInWallet; + let differenceUsdc = currentUsdcInAccount - lastUsdcInAccount; + + await quoteUsdcSol(differenceUsdc) + .then(quote => { + log(`Swap: ${differenceUsdc / USDC_INT}$ to ${quote.outAmount / LAMPORTS_PER_SOL} SOL`); + //return signAndSendTx(quote); + }) + lastUsdcInAccount = currentUsdcInAccount; + } + }, AUTOSWAP_INTERVAL); +}; + +const run = async () => { + + await driftClient.subscribe(); + const user = driftClient.getUser(); + + // force markets to be included + driftClient.perpMarketLastSlotCache.set(SOL_MARKET, Number.MAX_SAFE_INTEGER); + driftClient.perpMarketLastSlotCache.set(USDC_MARKET, Number.MAX_SAFE_INTEGER); + + log('---------------------------------') + log("DriftClient initialized") + log(`Swap Ratio: ${SWAP_RATIO}`); + log(`Swap Threshold: ${SWAP_THRESHOLD} USDC`); + printInfo(user); + + let swapInProgress = false; + + setInterval(async () => { + if (!swapInProgress) { + try { + let usdcInAccount = user.getTokenAmount(USDC_MARKET); + let swapAmount = Math.floor(calcSwapAmount(usdcInAccount)); + + if (thresholdReached(usdcInAccount)) { + log('---------------------------------') + printInfo(user); + swapInProgress = true; + + let withdrawSuccessful = false; + let withdrawRetries = 0; + let maxWithdrawRetries = 3; + while (!withdrawSuccessful && withdrawRetries < maxWithdrawRetries) { + log(`Withdraw from exchange`); + await withdraw(USDC_MARKET, quoteNumber(user.getTokenAmount(USDC_MARKET))) + .then(async (txSig) => { + log(`Confirm withdraw: https://solscan.io/tx/${txSig}`); + return confirmTx(txSig); + }, (error) => { + throw `Withdraw TX failed: ${error}`; + }) + .then((confirmResult) => { + if (confirmResult.value.err) { + throw `Withdraw not confirmed`; + } else { + log(`Withdraw confirmed`); + withdrawSuccessful = true; + } + }) + .catch(error => { + withdrawRetries++; + log(`Withdraw failed (${withdrawRetries}/${maxWithdrawRetries}): ${error}`); + // TODO check if withdraw was still somehow successfull + // it sometimes happens and we're then stuck in the loop + }); + } + + //backoff & try again in next iteration + if (withdrawRetries === maxWithdrawRetries) { + log('Withdraw failed - check if account balance changed and the withdraw actualy did not fail'); + let currentUsdcInAccount = user.getTokenAmount(USDC_MARKET); + if(currentUsdcInAccount < usdcInAccount) { + log('Withdraw seemed to went through - continue with swap'); + } else { + log('Withdraw really failed - backoff & try again in next iteration'); + swapInProgress = false; + return; + } + } + + let swapSuccessful = false + let swapRetries = 0; + let maxSwapRetries = 3; + while (!swapSuccessful && swapRetries < maxSwapRetries) { + // TODO calculate fresh swapAmount every iteration as collateral may has increased in the mean time + await quoteUsdcSol(swapAmount) + .then(quote => { + log(`Swap: ${swapAmount / USDC_INT}$ to ${quote.outAmount / LAMPORTS_PER_SOL} SOL`); + return signAndSendTx(quote); + }) + .then(async txSig => { + log(`Confirm swap: https://solscan.io/tx/${txSig}`); + return confirmTx(txSig); + }) + .then(confirmResult => { + if (confirmResult.value.err) { + throw `Confirm swap failed ${confirmResult.value.err}`; + } else { + log('Swap successful') + log('---------------------------------') + swapInProgress = false; + swapSuccessful = true; + } + }) + .catch(error => { + swapRetries++; + log(`FAAAAAIL (${swapRetries}/${maxSwapRetries}): ${error}`); + }) + sleep(1000); + } + + //backoff & try again in next iteration + if (swapRetries === maxSwapRetries) { + log('Swap failed - backoff & try again in next iteration'); + swapInProgress = false; + return; + } + + + + } else { + log(`Waiting to reach threshold - current balance on DEX: ${usdcInAccount / USDC_INT} USDC`); + swapInProgress = false; + } + } catch (error) { + log(error); + swapInProgress = false; + } + } else { + log('Swap in progress') + } + }, AUTOSWAP_INTERVAL); + +}; + +run2(); diff --git a/auto-swap/src/main.js b/auto-swap/src/main.js new file mode 100644 index 0000000..8a351ea --- /dev/null +++ b/auto-swap/src/main.js @@ -0,0 +1,272 @@ +require('dotenv').config() +const web3 = require("@solana/web3.js"); +const drift = require("@drift-labs/sdk"); + +const LAMPORTS_PER_SOL = 1000000000; +const AUTOSWAP_INTERVAL = process.env.AUTOSWAP_INTERVAL || 1000 * 60; + +const USDC_MARKET = 0; +const SOL_MARKET = 1; + +const SWAP_RATIO = process.env.SWAP_RATIO || 0.5; +const SWAP_THRESHOLD = process.env.SWAP_THRESHOLD || 10; + +const USDC_INT = 1000000; + +const SOL_MINT_ADDRESS = 'So11111111111111111111111111111111111111112'; +const USDC_MINT_ADDRESS = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; + +const USDC_MINT_PUBLIC_KEY = new web3.PublicKey(USDC_MINT_ADDRESS); +const keyPairFile = process.env.PRIVATE_KEY || process.env.PRIVATE_KEY_FILE; +const wallet = new drift.Wallet(drift.loadKeypair(keyPairFile)); +const connection = new web3.Connection(process.env.RPC_ENDPOINT); + +const thresholdReached = (amount) => amount / USDC_INT > SWAP_THRESHOLD; + +const driftClient = new drift.DriftClient({ + connection, + wallet, + env: 'mainnet-beta', + activeSubAccountId: 0, + subAccountIds: [0], +}); + +const sleep = (ms) => { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +const log = (msg) => { + console.log(`[${new Date().toISOString()}] ${msg}`) +}; + +const quoteNumber = (val) => { + return drift.convertToNumber(val, drift.QUOTE_PRECISION); +} + +const baseNumber = (val) => { + return drift.convertToNumber(val, drift.BASE_PRECISION); +} + +const quoteUsdcSol = async (amount) => { + const quoteUrl = `https://quote-api.jup.ag/v6/quote?inputMint=${USDC_MINT_ADDRESS}&outputMint=${SOL_MINT_ADDRESS}&amount=${amount}&slippageBps=50`; + const quoteResponse = await ( + await fetch(quoteUrl) + ).json(); + return quoteResponse; +} + +const getWalletBalance = async (connection, publicKey) => { + const lamportsBalance = await connection.getBalance(publicKey); + return lamportsBalance / LAMPORTS_PER_SOL; +}; + +const getUsdcBalance = async (connection, publicKey) => { + const balance = await connection.getParsedTokenAccountsByOwner( + publicKey, { mint: USDC_MINT_PUBLIC_KEY } + ); + return balance.value[0]?.account.data.parsed.info.tokenAmount.uiAmount; +}; + +const printInfo = async (user) => { + let usdcInAccount = quoteNumber(user.getTokenAmount(USDC_MARKET)); + let solInWallet = await getWalletBalance(connection, wallet.publicKey); + let usdcWallet = await getUsdcBalance(connection, wallet.publicKey) + + log(`USDC in account: ${usdcInAccount}`); + log(`USDC in wallet: ${usdcWallet}`); + log(`SOL in wallet: ${solInWallet}`); +}; + +const calcSwapAmount = (usdcInAccount) => { + return usdcInAccount * SWAP_RATIO; +}; + +const getSerializedTransaction = async (quote) => { + return await ( + await fetch('https://quote-api.jup.ag/v6/swap', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + quoteResponse: quote, + userPublicKey: wallet.publicKey.toString(), + wrapAndUnwrapSol: true, + dynamicComputeUnitLimit: true, // allow dynamic compute limit instead of max 1,400,000 + prioritizationFeeLamports: 'auto' // capped at 5,000,000 lamports / 0.005 SOL. + }) + }) + ).json(); +}; + +const signTransaction = (swapTransaction) => { + const swapTransactionBuf = Buffer.from(swapTransaction, 'base64'); + var transaction = web3.VersionedTransaction.deserialize(swapTransactionBuf); + transaction.sign([wallet.payer]); + return transaction; +}; + +const sendTransaction = async (transaction) => { + const rawTransaction = transaction.serialize() + return connection.sendRawTransaction(rawTransaction, { + skipPreflight: false, + preflightCommitment: 'confirmed', + // Maximum number of times for the RPC node to retry sending the transaction to the leader. + // If this parameter is not provided, the RPC node will retry the transaction until it is finalized or until the blockhash expires. + //maxRetries: 0 + }) + +}; + +const withdraw = async (marketIndex, withdrawAmount) => { + const amount = driftClient.convertToSpotPrecision(marketIndex, withdrawAmount); + const associatedTokenAccount = await driftClient.getAssociatedTokenAccount(marketIndex); + const reduceOnly = true; + return driftClient.withdraw( + amount, + marketIndex, + associatedTokenAccount, + reduceOnly + ); +}; + +const signAndSendTx = async (quote) => { + let tx = await getSerializedTransaction(quote); + let signedTx = signTransaction(tx.swapTransaction); + return sendTransaction(signedTx); +}; + +const confirmTx = async (txSig) => { + const latestBlockHash = await connection.getLatestBlockhash(); + return connection.confirmTransaction({ + blockhash: latestBlockHash.blockhash, + lastValidBlockHeight: latestBlockHash.lastValidBlockHeight, + signature: txSig, + }, 'confirmed'); +}; + +const run = async () => { + + await driftClient.subscribe(); + const user = driftClient.getUser(); + + // force markets to be included + driftClient.perpMarketLastSlotCache.set(SOL_MARKET, Number.MAX_SAFE_INTEGER); + driftClient.perpMarketLastSlotCache.set(USDC_MARKET, Number.MAX_SAFE_INTEGER); + + log('---------------------------------') + log("DriftClient initialized") + log(`Swap Ratio: ${SWAP_RATIO}`); + log(`Swap Threshold: ${SWAP_THRESHOLD} USDC`); + printInfo(user); + + let swapInProgress = false; + + setInterval(async () => { + if (!swapInProgress) { + try { + let usdcInAccount = user.getTokenAmount(USDC_MARKET); + let swapAmount = Math.floor(calcSwapAmount(usdcInAccount)); + + if (thresholdReached(usdcInAccount)) { + log('---------------------------------') + printInfo(user); + swapInProgress = true; + + let withdrawSuccessful = false; + let withdrawRetries = 0; + let maxWithdrawRetries = 3; + while (!withdrawSuccessful && withdrawRetries < maxWithdrawRetries) { + log(`Withdraw from exchange`); + await withdraw(USDC_MARKET, quoteNumber(user.getTokenAmount(USDC_MARKET))) + .then(async (txSig) => { + log(`Confirm withdraw: https://solscan.io/tx/${txSig}`); + return confirmTx(txSig); + }, (error) => { + throw `Withdraw TX failed: ${error}`; + }) + .then((confirmResult) => { + if (confirmResult.value.err) { + throw `Withdraw not confirmed`; + } else { + log(`Withdraw confirmed`); + withdrawSuccessful = true; + } + }) + .catch(error => { + withdrawRetries++; + log(`Withdraw failed (${withdrawRetries}/${maxWithdrawRetries}): ${error}`); + // TODO check if withdraw was still somehow successfull + // it sometimes happens and we're then stuck in the loop + }); + } + + //backoff & try again in next iteration + if (withdrawRetries === maxWithdrawRetries) { + log('Withdraw failed - check if account balance changed and the withdraw actualy did not fail'); + let currentUsdcInAccount = user.getTokenAmount(USDC_MARKET); + if(currentUsdcInAccount < usdcInAccount) { + log('Withdraw seemed to went through - continue with swap'); + } else { + log('Withdraw really failed - backoff & try again in next iteration'); + swapInProgress = false; + return; + } + } + + let swapSuccessful = false + let swapRetries = 0; + let maxSwapRetries = 3; + while (!swapSuccessful && swapRetries < maxSwapRetries) { + // TODO calculate fresh swapAmount every iteration as collateral may has increased in the mean time + await quoteUsdcSol(swapAmount) + .then(quote => { + log(`Swap: ${swapAmount / USDC_INT}$ to ${quote.outAmount / LAMPORTS_PER_SOL} SOL`); + return signAndSendTx(quote); + }) + .then(async txSig => { + log(`Confirm swap: https://solscan.io/tx/${txSig}`); + return confirmTx(txSig); + }) + .then(confirmResult => { + if (confirmResult.value.err) { + throw `Confirm swap failed ${confirmResult.value.err}`; + } else { + log('Swap successful') + log('---------------------------------') + swapInProgress = false; + swapSuccessful = true; + } + }) + .catch(error => { + swapRetries++; + log(`FAAAAAIL (${swapRetries}/${maxSwapRetries}): ${error}`); + }) + sleep(1000); + } + + //backoff & try again in next iteration + if (swapRetries === maxSwapRetries) { + log('Swap failed - backoff & try again in next iteration'); + swapInProgress = false; + return; + } + + + + } else { + log(`Waiting to reach threshold - current balance on DEX: ${usdcInAccount / USDC_INT} USDC`); + swapInProgress = false; + } + } catch (error) { + log(error); + swapInProgress = false; + } + } else { + log('Swap in progress') + } + }, AUTOSWAP_INTERVAL); + +}; + +run(); diff --git a/cloud-config.yaml b/cloud-config.yaml deleted file mode 100644 index bf8bb76..0000000 --- a/cloud-config.yaml +++ /dev/null @@ -1,49 +0,0 @@ -#cloud-config -groups: - - ubuntu: [root,sys] - - docker - - bot - -users: - - default - - name: keeper - gecos: keeper - shell: /bin/bash - primary_group: bot - sudo: ALL=(ALL) NOPASSWD:ALL - groups: users, admin, docker - lock_passwd: false - -packages: - - apt-transport-https - - ca-certificates - - curl - - gnupg-agent - - software-properties-common - - chrony - - docker.io - - docker-compose - -ntp: - enabled: true - ntp_client: chrony - servers: - - ${ntp_server} - -runcmd: - - git clone https://github.com/0x1d/drift-keeper /app/bot - - mv /app/.env /app/bot/.env - - mv /app/config.yaml /app/bot/config.yaml - - cd /app/bot && sudo -u keeper -g bot -- docker-compose up -d - -write_files: - - path: /app/.env - encoding: b64 - owner: root:root - permissions: '0750' - content: ${env_file} - - path: /app/config.yaml - encoding: b64 - owner: root:root - permissions: '0750' - content: ${config_file} \ No newline at end of file diff --git a/cloud-init/cloud-config.yaml b/cloud-init/cloud-config.yaml new file mode 100644 index 0000000..837e0ea --- /dev/null +++ b/cloud-init/cloud-config.yaml @@ -0,0 +1,71 @@ +#cloud-config +groups: + - ubuntu: [root,sys] + - docker + - bot + +users: + - default + - name: keeper + gecos: keeper + shell: /bin/bash + primary_group: bot + sudo: ALL=(ALL) NOPASSWD:ALL + groups: users, admin, docker + lock_passwd: false + +packages: + - apt-transport-https + - ca-certificates + - curl + - gnupg-agent + - software-properties-common + - chrony + - docker.io + - docker-compose + +ntp: + enabled: true + ntp_client: chrony + servers: + - ${ntp_server} + +runcmd: + - systemctl stop snapd && systemctl disable snapd + - git clone -b feature/scaling https://github.com/0x1d/drift-keeper /app/bot + - cp -rT /transfer /app/bot && rm -rf /transfer + - chown -R keeper:bot /app/bot + - cd /app/bot && sudo -u keeper -g bot -- docker-compose up -d + +write_files: + - path: /transfer/.env + encoding: b64 + owner: root:root + permissions: '0750' + content: ${env_file} + - path: /transfer/.env.monitoring + encoding: b64 + owner: root:root + permissions: '0750' + content: ${env_monitoring_file} + - path: /transfer/config.yaml + encoding: b64 + owner: root:root + permissions: '0750' + content: ${config_file} + - path: /transfer/prometheus/prometheus.yml + encoding: b64 + owner: root:root + permissions: '0750' + content: ${prometheus_config_file} + - path: /transfer/prometheus/web.yml + encoding: b64 + owner: root:root + permissions: '0750' + content: ${prometheus_web_file} + - path: /transfer/docker-compose.yaml + encoding: b64 + owner: root:root + permissions: '0750' + content: ${docker_compose_file} + \ No newline at end of file diff --git a/config.yaml b/config.yaml index 00125ee..b80e92c 100644 --- a/config.yaml +++ b/config.yaml @@ -56,7 +56,7 @@ global: eventSubscriberPollingInterval: 5000 bulkAccountLoaderPollingInterval: 5000 - useJito: false + useJito: true jitoBlockEngineUrl: jitoAuthPrivateKey: diff --git a/ctl.sh b/ctl.sh index b3f7218..565989c 100755 --- a/ctl.sh +++ b/ctl.sh @@ -5,38 +5,143 @@ API_ENDPOINT=https://api.mainnet-beta.solana.com/ source .env -function keeper { - function build { +## +## Usage: ./ctl.sh COMMAND SUBCOMMAND +## +## ~> build +## all Build all images +## keeper Build bot image +## tracker Build wallet-tracker image +## autoswap Build auto-swap image +## +## ~> push +## all Push all images to Docker registry +## keeper Push bot image to Docker registry +## tracker Push tracker image to Docker registry +## autoswap Push auto-swaü image to Docker registry +## +## ~> run +## all Run the complete stack locally +## autoswap Run Auto-Swap locally +## +## ~> infra +## plan Plan infrastructure change +## provision Provision infrastructure +## hosts Show list of servers +## connect Connect to a server +## playbook Run a maintenance playbook +## +## ~> balance +## sol Show SOL balance +## usdc Show USDC balance +## + +RED="31" +GREEN="32" +GREENBLD="\e[1;${GREEN}m" +REDBOLD="\e[1;${RED}m" +REDITALIC="\e[3;${RED}m" +EC="\e[0m" + +function info { + printf "\n${GREENBLD}Wallet Address:\t$WALLET_ADDRESS${EC}\n" + printf "${GREENBLD}Environment:\t$ENV${EC}\n" + sed -n 's/^##//p' ctl.sh +} + +function build { + function all { + build keeper + build tracker + } + function keeper { mkdir -p .build git clone https://github.com/drift-labs/keeper-bots-v2 -b mainnet-beta .build/keeper-bots-v2 + #pushd .build/keeper-bots-v2 + # git checkout 21fd791d142490fe033b5e25719927c106a0aaf2 + #popd docker build -f Dockerfile -t ${DOCKER_IMAGE} .build/keeper-bots-v2 rm -rf .build } - function push { - docker push ${DOCKER_IMAGE} - } - ${@:-} -} - -function tracker { - function build { + function tracker { pushd wallet-tracker docker build -t ${DOCKER_IMAGE_WALLET_TRACKER} . popd } - function push { - docker push ${DOCKER_IMAGE_WALLET_TRACKER} + function autoswap { + pushd auto-swap + docker build -t ${DOCKER_IMAGE_AUTO_SWAP} . + popd + } + function metrics { + pushd user-metrics + docker build -t ${DOCKER_IMAGE_USER_METRICS} . + popd } ${@:-} } -function droplet { +function push { + function all { + push keeper + push tracker + } + function keeper { + docker push ${DOCKER_IMAGE} + } + function tracker { + docker push ${DOCKER_IMAGE_WALLET_TRACKER} + } + function autoswap { + docker push ${DOCKER_IMAGE_AUTO_SWAP} + } + function metrics { + docker push ${DOCKER_IMAGE_USER_METRICS} + } + ${@:-} +} + +function run { + function all { + docker compose up + } + function autoswap { + pushd auto-swap + npm start + popd + } + function metircs { + pushd user-metrics + npm start + popd + } + ${@:-} +} + +function infra { + function plan { + terraform init + terraform plan + } function provision { terraform init terraform apply + echo "[bots]" > inventory.cfg + terraform output -json | jq --raw-output ' .instances.value | to_entries[] | .value' >> inventory.cfg + } + function hosts { + terraform output -json | jq --raw-output '.instances.value | to_entries[] | [.key, .value] | @tsv' } function connect { - ssh root@$(terraform output -raw droplet_ip) + infra hosts \ + | fzf --height=~50 \ + | awk '{print $2}' \ + | xargs -o ssh -l root $@ + } + function playbook { + pushd ansible + ansible-playbook --ssh-common-args='-o StrictHostKeyChecking=accept-new' -i ../inventory.cfg $(fzf --height=~10) + popd } ${@:-} } @@ -77,4 +182,18 @@ function balance { ${@:-} } -${@:-} \ No newline at end of file +function repl { + clear + cat motd + info + echo -e "\n${REDBOLD}Enter command...${EC}" + read -p '~> '; + clear + cat motd + ./ctl.sh ${REPLY} + printf "\n" + read -p "Press any key to continue." + repl +} + +${@:-info} \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 7051acc..423e6c8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -2,25 +2,29 @@ version: '3' services: - # --------------------------------------------------- - # Bot - # --------------------------------------------------- keeper: image: ${DOCKER_IMAGE} restart: unless-stopped env_file: .env volumes: - ./config.yaml:/app/config.yaml - - # --------------------------------------------------- - # Monitoring - # --------------------------------------------------- + auto-swap: + image: ${DOCKER_IMAGE_AUTO_SWAP} + build: + context: auto-swap + env_file: .env.autoswap + restart: unless-stopped wallet-tracker: image: ${DOCKER_IMAGE_WALLET_TRACKER} build: context: wallet-tracker env_file: .env restart: unless-stopped + user-metrics: + image: wirelos/user-metrics:0.1.0 + env_file: .env.user-metrics + restart: unless-stopped + prometheus: image: prom/prometheus container_name: prometheus @@ -51,12 +55,10 @@ services: grafana: image: grafana/grafana container_name: grafana + env_file: .env.monitoring ports: - 3000:3000 restart: unless-stopped - environment: - - GF_SECURITY_ADMIN_USER=admin - - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD} volumes: - ./grafana/provisioning:/etc/grafana/provisioning - ./grafana/dashboards:/var/lib/grafana/dashboards diff --git a/example.env b/example.env index 36bacfc..241a29b 100644 --- a/example.env +++ b/example.env @@ -1,12 +1,11 @@ # Build Settings DOCKER_IMAGE=wirelos/drift-keeper:mainnet-beta +DOCKER_IMAGE_AUTO_SWAP=wirelos/auto-swap:0.1.0 +DOCKER_IMAGE_WALLET_TRACKER=wirelos/solana-wallet-tracker:0.1.0 # Shell Utils WALLET_ADDRESS=h5XjtA..... -# Grafana Settings -GRAFANA_ADMIN_PASSWORD=grafana - # Drift Config ENV=mainnet-beta KEEPER_PRIVATE_KEY="[123,345,...]" @@ -24,7 +23,6 @@ ENDPOINT=http://178.63.126.77:8899 # Teraswitch2 US #ENDPOINT=http://74.118.139.68:8899 - # ExtrNode #ENDPOINT=https://solana-mainnet.rpc.extrnode.com/your-api-key #WS_ENDPOINT=wss://solana-mainnet.rpc.extrnode.com/your-api-key diff --git a/example.env.autoswap b/example.env.autoswap new file mode 100644 index 0000000..8e6f00b --- /dev/null +++ b/example.env.autoswap @@ -0,0 +1,6 @@ +RPC_ENDPOINT=https://your-rpc-endpoint +PRIVATE_KEY="[123,456,...789]" +#PRIVATE_KEY_FILE=~/.config/solana/bot.json +SWAP_THRESHOLD=2 +SWAP_RATIO=0.6 +AUTOSWAP_INTERVAL=60000 \ No newline at end of file diff --git a/example.env.monitoring b/example.env.monitoring new file mode 100644 index 0000000..45ba714 --- /dev/null +++ b/example.env.monitoring @@ -0,0 +1,3 @@ +GF_SECURITY_ADMIN_USER=admin +GF_SECURITY_ADMIN_PASSWORD=grafana +PROMETHEUS_PASSWORD=prompass \ No newline at end of file diff --git a/example.env.user-metrics b/example.env.user-metrics new file mode 100644 index 0000000..673daef --- /dev/null +++ b/example.env.user-metrics @@ -0,0 +1,3 @@ +RPC_ENDPOINT=https://your-rpc-endpoint +PRIVATE_KEY="[123,456,...789]" +#PRIVATE_KEY_FILE=~/.config/solana/bot.json \ No newline at end of file diff --git a/grafana/dashboards/drift-keeper.json b/grafana/dashboards/drift-keeper.json index 1a49037..1c27044 100644 --- a/grafana/dashboards/drift-keeper.json +++ b/grafana/dashboards/drift-keeper.json @@ -82,10 +82,11 @@ "fields": "", "values": false }, + "showPercentChange": false, "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.2.3", + "pluginVersion": "10.4.2", "targets": [ { "datasource": { @@ -115,7 +116,7 @@ "fieldConfig": { "defaults": { "color": { - "mode": "continuous-RdYlGr" + "mode": "thresholds" }, "mappings": [], "thresholds": { @@ -124,10 +125,6 @@ { "color": "green", "value": null - }, - { - "color": "red", - "value": 80 } ] }, @@ -154,10 +151,11 @@ "fields": "", "values": false }, + "showPercentChange": false, "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.2.3", + "pluginVersion": "10.4.2", "targets": [ { "datasource": { @@ -226,10 +224,11 @@ "fields": "", "values": false }, + "showPercentChange": false, "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.2.3", + "pluginVersion": "10.4.2", "targets": [ { "datasource": { @@ -260,8 +259,9 @@ "fieldConfig": { "defaults": { "color": { - "mode": "continuous-GrYlRd" + "mode": "continuous-RdYlGr" }, + "displayName": "${__field.labels.walletShort}", "mappings": [], "thresholds": { "mode": "absolute", @@ -291,7 +291,7 @@ "colorMode": "value", "graphMode": "area", "justifyMode": "auto", - "orientation": "auto", + "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" @@ -299,10 +299,11 @@ "fields": "", "values": false }, + "showPercentChange": false, "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.2.3", + "pluginVersion": "10.4.2", "targets": [ { "datasource": { @@ -311,7 +312,7 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "sol_balance", + "expr": "sol_balance{job=\"user\"}", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, @@ -335,6 +336,7 @@ "color": { "mode": "continuous-RdYlGr" }, + "displayName": "${__field.labels.walletShort}", "mappings": [], "thresholds": { "mode": "absolute", @@ -364,7 +366,7 @@ "colorMode": "value", "graphMode": "area", "justifyMode": "auto", - "orientation": "auto", + "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" @@ -372,10 +374,11 @@ "fields": "", "values": false }, + "showPercentChange": false, "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.2.3", + "pluginVersion": "10.4.2", "targets": [ { "datasource": { @@ -408,6 +411,7 @@ "color": { "mode": "continuous-RdYlGr" }, + "displayName": "${__field.labels.walletShort}", "mappings": [], "thresholds": { "mode": "absolute", @@ -437,7 +441,7 @@ "colorMode": "value", "graphMode": "area", "justifyMode": "auto", - "orientation": "auto", + "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" @@ -445,10 +449,11 @@ "fields": "", "values": false }, + "showPercentChange": false, "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.2.3", + "pluginVersion": "10.4.2", "targets": [ { "datasource": { @@ -457,7 +462,7 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "usdc_balance", + "expr": "usdc_balance{job=\"user\"}", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, @@ -492,8 +497,8 @@ "overrides": [] }, "gridPos": { - "h": 6, - "w": 24, + "h": 5, + "w": 12, "x": 0, "y": 6 }, @@ -534,7 +539,7 @@ "layout": "auto" }, "tooltip": { - "show": false, + "mode": "single", "showColorScale": false, "yHistogram": false }, @@ -543,7 +548,7 @@ "reverse": false } }, - "pluginVersion": "10.2.3", + "pluginVersion": "10.4.2", "targets": [ { "datasource": { @@ -569,13 +574,238 @@ "title": "Activity", "type": "heatmap" }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "SOL" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 12, + "y": 6 + }, + "id": 23, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "diff" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_balance{job=\"user\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Change", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 16, + "y": 6 + }, + "id": 24, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "diff" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_usdc_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Change in USDC", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 20, + "y": 6 + }, + "id": 25, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "diff" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "usdc_balance{job=\"user\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "USDC Change", + "type": "stat" + }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, - "y": 12 + "y": 11 }, "id": 17, "panels": [], @@ -591,7 +821,7 @@ "fieldConfig": { "defaults": { "color": { - "mode": "continuous-GrYlRd" + "mode": "continuous-RdYlGr" }, "custom": { "axisBorderShow": false, @@ -622,9 +852,10 @@ "mode": "none" }, "thresholdsStyle": { - "mode": "off" + "mode": "dashed" } }, + "displayName": "${__field.labels.walletShort}", "mappings": [], "thresholds": { "mode": "absolute", @@ -635,7 +866,7 @@ }, { "color": "red", - "value": 80 + "value": 0.1 } ] } @@ -643,18 +874,21 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 10, "w": 8, "x": 0, - "y": 13 + "y": 12 }, "id": 20, "options": { "legend": { - "calcs": [], + "calcs": [ + "lastNotNull", + "diff" + ], "displayMode": "list", "placement": "bottom", - "showLegend": false + "showLegend": true }, "tooltip": { "mode": "single", @@ -669,7 +903,7 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "sol_balance", + "expr": "sol_balance{job=\"wallet\"}", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, @@ -721,9 +955,10 @@ "mode": "none" }, "thresholdsStyle": { - "mode": "off" + "mode": "dashed" } }, + "displayName": "${__field.labels.walletShort}", "mappings": [], "thresholds": { "mode": "absolute", @@ -734,7 +969,15 @@ }, { "color": "red", - "value": 80 + "value": 10 + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "#6ED0E0", + "value": 30 } ] } @@ -742,18 +985,21 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 10, "w": 8, "x": 8, - "y": 13 + "y": 12 }, "id": 18, "options": { "legend": { - "calcs": [], + "calcs": [ + "lastNotNull", + "diff" + ], "displayMode": "list", "placement": "bottom", - "showLegend": false + "showLegend": true }, "tooltip": { "mode": "single", @@ -823,6 +1069,7 @@ "mode": "off" } }, + "displayName": "${__field.labels.walletShort}", "mappings": [], "thresholds": { "mode": "absolute", @@ -841,18 +1088,21 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 10, "w": 8, "x": 16, - "y": 13 + "y": 12 }, "id": 19, "options": { "legend": { - "calcs": [], + "calcs": [ + "lastNotNull", + "diff" + ], "displayMode": "list", "placement": "bottom", - "showLegend": false + "showLegend": true }, "tooltip": { "mode": "single", @@ -867,7 +1117,7 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "usdc_balance", + "expr": "usdc_balance{job=\"wallet\"}", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, @@ -886,7 +1136,7 @@ "h": 1, "w": 24, "x": 0, - "y": 21 + "y": 22 }, "id": 11, "panels": [], @@ -935,7 +1185,7 @@ "mode": "off" } }, - "displayName": "${__field.labels.authority}", + "displayName": "${__field.labels.walletShort}", "mappings": [], "thresholds": { "mode": "absolute", @@ -955,15 +1205,18 @@ "overrides": [] }, "gridPos": { - "h": 13, + "h": 10, "w": 12, "x": 0, - "y": 22 + "y": 23 }, "id": 7, "options": { "legend": { - "calcs": [], + "calcs": [ + "lastNotNull", + "diff" + ], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -1037,7 +1290,7 @@ "mode": "off" } }, - "displayName": "${__field.labels.authority}", + "displayName": "${__field.labels.walletShort}", "mappings": [], "thresholds": { "mode": "absolute", @@ -1057,15 +1310,18 @@ "overrides": [] }, "gridPos": { - "h": 13, + "h": 10, "w": 12, "x": 12, - "y": 22 + "y": 23 }, "id": 8, "options": { "legend": { - "calcs": [], + "calcs": [ + "lastNotNull", + "diff" + ], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -1097,17 +1353,125 @@ "title": "Unrealized PNL", "type": "timeseries" }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr", + "seriesBy": "last" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 5, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "Price", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD" + }, + "overrides": [] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 33 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "diff" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_price", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Price", + "type": "timeseries" + }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, - "y": 35 + "y": 46 }, - "id": 10, + "id": 30, "panels": [], - "title": "Order Matching", + "title": "JITO", "type": "row" }, { @@ -1138,7 +1502,7 @@ "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, - "pointSize": 1, + "pointSize": 2, "scaleDistribution": { "type": "linear" }, @@ -1152,7 +1516,7 @@ "mode": "off" } }, - "displayName": "${__field.labels.instance}", + "displayName": "${__field.labels.type}", "mappings": [], "thresholds": { "mode": "absolute", @@ -1171,22 +1535,18 @@ "overrides": [] }, "gridPos": { - "h": 12, - "w": 12, + "h": 8, + "w": 8, "x": 0, - "y": 36 + "y": 47 }, - "id": 15, + "id": 27, "options": { "legend": { - "calcs": [ - "lastNotNull" - ], + "calcs": [], "displayMode": "list", "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true + "showLegend": true }, "tooltip": { "mode": "single", @@ -1201,7 +1561,7 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "successful_fills_total", + "expr": "jito_bundle_count", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, @@ -1211,7 +1571,7 @@ "useBackend": false } ], - "title": "Successful Fills Total", + "title": "Bundle Count", "type": "timeseries" }, { @@ -1242,7 +1602,7 @@ "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, - "pointSize": 1, + "pointSize": 2, "scaleDistribution": { "type": "linear" }, @@ -1256,7 +1616,8 @@ "mode": "off" } }, - "displayName": "${__field.labels.instance}", + "displayName": "${__field.labels.job}", + "fieldMinMax": false, "mappings": [], "thresholds": { "mode": "absolute", @@ -1275,22 +1636,21 @@ "overrides": [] }, "gridPos": { - "h": 12, - "w": 12, - "x": 12, - "y": 36 + "h": 8, + "w": 8, + "x": 8, + "y": 47 }, - "id": 1, + "id": 28, "options": { "legend": { "calcs": [ - "lastNotNull" + "lastNotNull", + "max" ], "displayMode": "list", "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true + "showLegend": true }, "tooltip": { "mode": "single", @@ -1305,7 +1665,7 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "attempted_fills_total", + "expr": "jito_bundles_accepted", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, @@ -1315,7 +1675,7 @@ "useBackend": false } ], - "title": "Attempted Fills Total", + "title": "Bundles Accepted", "type": "timeseries" }, { @@ -1326,19 +1686,41 @@ "fieldConfig": { "defaults": { "color": { - "mode": "continuous-BlPu" + "mode": "palette-classic" }, "custom": { - "fillOpacity": 50, - "gradientMode": "hue", + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, - "lineWidth": 1 + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 2, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } }, - "displayName": "${__field.labels.instance}", + "displayName": "${__field.labels.type}", "mappings": [], "thresholds": { "mode": "absolute", @@ -1349,31 +1731,30 @@ }, { "color": "red", - "value": 5 + "value": 80 } ] - }, - "unit": "ms" + } }, "overrides": [] }, "gridPos": { - "h": 12, - "w": 12, - "x": 0, - "y": 48 + "h": 8, + "w": 8, + "x": 16, + "y": 47 }, - "id": 5, + "id": 29, "options": { - "bucketOffset": 0, - "combine": false, "legend": { - "calcs": [ - "lastNotNull" - ], + "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" } }, "targets": [ @@ -1384,9 +1765,9 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "rate(try_fill_duration_histogram_sum[$__rate_interval])", + "expr": "jito_dropped_bundle", "fullMetaSearch": false, - "includeNullMetadata": false, + "includeNullMetadata": true, "instant": false, "legendFormat": "__auto", "range": true, @@ -1394,103 +1775,404 @@ "useBackend": false } ], - "title": "Attempted Fill Duration", - "type": "histogram" + "title": "Bundles Dropped", + "type": "timeseries" }, { - "datasource": { - "type": "prometheus", - "uid": "PBFA97CFB590B2093" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-BlPu" - }, - "custom": { - "fillOpacity": 50, - "gradientMode": "hue", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1 - }, - "displayName": "${__field.labels.instance}", - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 5 - } - ] - }, - "unit": "ms" - }, - "overrides": [] - }, + "collapsed": true, "gridPos": { - "h": 12, - "w": 12, - "x": 12, - "y": 48 + "h": 1, + "w": 24, + "x": 0, + "y": 55 }, - "id": 14, - "options": { - "bucketOffset": 0, - "combine": false, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - } - }, - "targets": [ + "id": 10, + "panels": [ { "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(sdk_call_duration_histogram_sum[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "instant": false, - "legendFormat": "__auto", - "range": true, - "refId": "A", - "useBackend": false + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "${__field.labels.instance}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 56 + }, + "id": 15, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "successful_fills_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Successful Fills Total", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "${__field.labels.instance}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 56 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "attempted_fills_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Attempted Fills Total", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-BlPu" + }, + "custom": { + "fillOpacity": 50, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1 + }, + "displayName": "${__field.labels.instance}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 5 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 68 + }, + "id": 5, + "options": { + "bucketOffset": 0, + "combine": false, + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(try_fill_duration_histogram_sum[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Attempted Fill Duration", + "type": "histogram" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-BlPu" + }, + "custom": { + "fillOpacity": 50, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1 + }, + "displayName": "${__field.labels.instance}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 5 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 68 + }, + "id": 14, + "options": { + "bucketOffset": 0, + "combine": false, + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(sdk_call_duration_histogram_sum[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SDK Call Duration", + "type": "histogram" } ], - "title": "SDK Call Duration", - "type": "histogram" + "title": "Order Matching", + "type": "row" } ], - "refresh": "", + "refresh": "10s", "schemaVersion": 39, "tags": [], "templating": { "list": [] }, "time": { - "from": "now-15m", + "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Drift Keeper", "uid": "f4c3a630-ffd0-41c8-a36a-52e0771b77fb", - "version": 6, + "version": 2, "weekStart": "" } \ No newline at end of file diff --git a/grafana/provisioning/datasources/datasource.yml b/grafana/provisioning/datasources/datasource.yml index 9230003..6a874a8 100644 --- a/grafana/provisioning/datasources/datasource.yml +++ b/grafana/provisioning/datasources/datasource.yml @@ -10,4 +10,4 @@ datasources: basicAuth: true basicAuthUser: prom secureJsonData: - basicAuthPassword: prompass \ No newline at end of file + basicAuthPassword: ${PROMETHEUS_PASSWORD} \ No newline at end of file diff --git a/main.tf b/main.tf index e226c30..361698f 100644 --- a/main.tf +++ b/main.tf @@ -1,5 +1,9 @@ terraform { required_providers { + linode = { + source = "linode/linode" + version = "2.13.0" + } digitalocean = { source = "digitalocean/digitalocean" version = "~> 2.0" @@ -7,41 +11,110 @@ terraform { } } -variable "do_token" {} -variable "config" { - default = { - region = "ams3" - ntp_server = "ntp.amsterdam.jito.wtf" - docker_image = "wirelos/drift-keeper:mainnet-beta" - } -} - provider "digitalocean" { token = var.do_token } +provider "linode" { + token = var.linode_token +} + locals { - user_data = templatefile("cloud-config.yaml", { - ntp_server = var.config.ntp_server - env_file = base64encode(file(".env")) - config_file = base64encode(file("config.yaml")) - }) + monitoring_config = { + env = base64encode(templatefile("templates/monitoring/env.monitoring.tpl", var.monitoring)) + prometheus = base64encode(templatefile("templates/monitoring/prometheus/prometheus.yml.tpl", { + wallet_address = var.bot.wallet_address + })) + prometheus_web = base64encode(templatefile("templates/monitoring/prometheus/web.yml.tpl", { + prometheus_password_bcrypt = bcrypt(var.monitoring.prometheus_password) + })) + } + cloud_config = { for s in concat(var.linode_instances, var.digitalocean_instances) : s.label => templatefile("cloud-init/cloud-config.yaml", { + ntp_server = s.ntp_server + env_file = base64encode(templatefile("templates/bot/env.tpl", merge(var.bot, { + jito_block_engine_url = s.jito_block_engine_url + }))) + config_file = base64encode(templatefile("templates/bot/config.yaml.tpl", { + use_jito = s.use_jito + })) + env_monitoring_file = local.monitoring_config.env + prometheus_config_file = local.monitoring_config.prometheus + prometheus_web_file = local.monitoring_config.prometheus_web + docker_compose_file = base64encode(templatefile("templates/bot/docker-compose.yaml.tpl", { + docker_image = var.bot.docker_image + docker_image_wallet_tracker = var.bot.docker_image_wallet_tracker + })) + }) } +} + +resource "linode_sshkey" "master" { + label = "master-key" + ssh_key = chomp(file("~/.ssh/id_rsa.pub")) } resource "digitalocean_ssh_key" "default" { - name = "Keeper Key" - public_key = file("~/.ssh/id_rsa.pub") + name = "master-key" + public_key = chomp(file("~/.ssh/id_rsa.pub")) +} + +resource "linode_instance" "keeper" { + for_each = { for s in var.linode_instances : s.label => s } + label = each.key + image = each.value.image + group = each.value.group + region = each.value.region + type = each.value.type + authorized_keys = [linode_sshkey.master.ssh_key] + metadata { + user_data = base64encode(local.cloud_config[each.key]) + } + lifecycle { + ignore_changes = [ + metadata + ] + } } resource "digitalocean_droplet" "keeper" { - image = "ubuntu-23-10-x64" - name = "drift-keeper" - region = var.config.region - size = "s-1vcpu-1gb-intel" + for_each = { for s in var.digitalocean_instances : s.label => s } + image = each.value.image + name = each.key + region = each.value.region + size = each.value.type ssh_keys = [digitalocean_ssh_key.default.fingerprint] - user_data = local.user_data + user_data = local.cloud_config[each.key] + lifecycle { + ignore_changes = [ + user_data + ] + } } -output "droplet_ip" { - value = digitalocean_droplet.keeper.ipv4_address +output "instances" { + value = merge( + tomap({ for k, v in linode_instance.keeper : k => v.ip_address }), + tomap({ for k, v in digitalocean_droplet.keeper : k => v.ipv4_address }) + ) +} + + +output "panopticonf" { + value = templatefile("templates/monitoring/prometheus/panopticon.yml.tpl", { + user = "prom" + password = var.monitoring.prometheus_password + targets = <<-EOT + %{for k, v in merge( + tomap({ for k, v in linode_instance.keeper : k => v.ip_address }), + tomap({ for k, v in digitalocean_droplet.keeper : k => v.ipv4_address }) + )} + - targets: ['${v}:9090'] + labels: + server: ${k} + %{endfor} + EOT + }) +} + +output "configurations" { + value = local.cloud_config } diff --git a/motd b/motd new file mode 100644 index 0000000..08fd742 --- /dev/null +++ b/motd @@ -0,0 +1,11 @@ + +▓█████▄ ██▀███ ██▓ █████▒▄▄▄█████▓ ██ ▄█▀▓█████ ▓█████ ██▓███ ▓█████ ██▀███ +▒██▀ ██▌▓██ ▒ ██▒▓██▒▓██ ▒ ▓ ██▒ ▓▒ ██▄█▒ ▓█ ▀ ▓█ ▀ ▓██░ ██▒▓█ ▀ ▓██ ▒ ██▒ +░██ █▌▓██ ░▄█ ▒▒██▒▒████ ░ ▒ ▓██░ ▒░ ▓███▄░ ▒███ ▒███ ▓██░ ██▓▒▒███ ▓██ ░▄█ ▒ +░▓█▄ ▌▒██▀▀█▄ ░██░░▓█▒ ░ ░ ▓██▓ ░ ▓██ █▄ ▒▓█ ▄ ▒▓█ ▄ ▒██▄█▓▒ ▒▒▓█ ▄ ▒██▀▀█▄ +░▒████▓ ░██▓ ▒██▒░██░░▒█░ ▒██▒ ░ ▒██▒ █▄░▒████▒░▒████▒▒██▒ ░ ░░▒████▒░██▓ ▒██▒ + ▒▒▓ ▒ ░ ▒▓ ░▒▓░░▓ ▒ ░ ▒ ░░ ▒ ▒▒ ▓▒░░ ▒░ ░░░ ▒░ ░▒▓▒░ ░ ░░░ ▒░ ░░ ▒▓ ░▒▓░ + ░ ▒ ▒ ░▒ ░ ▒░ ▒ ░ ░ ░ ░ ░▒ ▒░ ░ ░ ░ ░ ░ ░░▒ ░ ░ ░ ░ ░▒ ░ ▒░ + ░ ░ ░ ░░ ░ ▒ ░ ░ ░ ░ ░ ░░ ░ ░ ░ ░░ ░ ░░ ░ + ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ + ░ diff --git a/panopticon/docker-compose.yaml b/panopticon/docker-compose.yaml new file mode 100644 index 0000000..c32c6be --- /dev/null +++ b/panopticon/docker-compose.yaml @@ -0,0 +1,27 @@ +version: '3' + +services: + + prometheus: + image: prom/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.config.file=/etc/prometheus/web.yml' + ports: + - 9090:9090 + restart: unless-stopped + volumes: + - ./prometheus:/etc/prometheus + - prom_data:/prometheus + grafana: + image: grafana/grafana + env_file: .env.monitoring + ports: + - 3000:3000 + restart: unless-stopped + volumes: + - ./grafana/provisioning:/etc/grafana/provisioning + - ./grafana/dashboards:/var/lib/grafana/dashboards + +volumes: + prom_data: diff --git a/panopticon/example.env.monitoring b/panopticon/example.env.monitoring new file mode 100644 index 0000000..45ba714 --- /dev/null +++ b/panopticon/example.env.monitoring @@ -0,0 +1,3 @@ +GF_SECURITY_ADMIN_USER=admin +GF_SECURITY_ADMIN_PASSWORD=grafana +PROMETHEUS_PASSWORD=prompass \ No newline at end of file diff --git a/panopticon/grafana/dashboards/drift-keeper.json b/panopticon/grafana/dashboards/drift-keeper.json new file mode 100644 index 0000000..300f9ab --- /dev/null +++ b/panopticon/grafana/dashboards/drift-keeper.json @@ -0,0 +1,1877 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "panels": [], + "title": "Summary", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "total_collateral", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Total Collateral", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 13, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "diff" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "total_collateral", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Profit", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 8, + "y": 1 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "unrealized_pnl", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Unrealized PNL", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "SOL", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 12, + "y": 1 + }, + "id": 16, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Balance", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 16, + "y": 1 + }, + "id": 21, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_usdc_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Balance in USDC", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 20, + "y": 1 + }, + "id": 22, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "usdc_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "USDC Balance", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + }, + "fieldMinMax": false, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 12, + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "count" + }, + "yBuckets": { + "mode": "count" + } + }, + "cellGap": 1, + "cellValues": { + "unit": "currencyUSD" + }, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Viridis", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "none", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "hidden", + "reverse": false + } + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "exemplar": false, + "expr": "unrealized_pnl", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Activity", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "SOL", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 12, + "y": 6 + }, + "id": 23, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "diff" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Change", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 16, + "y": 6 + }, + "id": 24, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "diff" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_usdc_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Change in USDC", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 20, + "y": 6 + }, + "id": 25, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "diff" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "usdc_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "USDC Change", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 17, + "panels": [], + "title": "Wallet", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 2, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "dashed" + } + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0.1 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 0, + "y": 12 + }, + "id": 20, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "diff" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Balance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 2, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "dashed" + } + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 10 + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "#6ED0E0", + "value": 30 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 8, + "y": 12 + }, + "id": 18, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "diff" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_usdc_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Balance in USDC", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 2, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "${__field.labels.walletShort}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 16, + "y": 12 + }, + "id": 19, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "diff" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "usdc_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "USDC Balance", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 11, + "panels": [], + "title": "Profit & Loss", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 2, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "${__field.labels.authority}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "diff" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.2.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "total_collateral", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Total Collateral", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 2, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "${__field.labels.authority}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "diff" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.2.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "unrealized_pnl", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Unrealized PNL", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr", + "seriesBy": "last" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 5, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "Price", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "currencyUSD", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 33 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "diff" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sol_price", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SOL Price", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 10, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "${__field.labels.instance}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 15, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "successful_fills_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Successful Fills Total", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "displayName": "${__field.labels.instance}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "attempted_fills_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Attempted Fills Total", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-BlPu" + }, + "custom": { + "fillOpacity": 50, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1 + }, + "displayName": "${__field.labels.instance}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 5 + } + ] + }, + "unit": "ms", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 5, + "options": { + "bucketOffset": 0, + "combine": false, + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(try_fill_duration_histogram_sum[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Attempted Fill Duration", + "type": "histogram" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-BlPu" + }, + "custom": { + "fillOpacity": 50, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1 + }, + "displayName": "${__field.labels.instance}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 5 + } + ] + }, + "unit": "ms", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 14, + "options": { + "bucketOffset": 0, + "combine": false, + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(sdk_call_duration_histogram_sum[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "SDK Call Duration", + "type": "histogram" + } + ], + "title": "Order Matching", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Drift Keeper", + "uid": "f4c3a630-ffd0-41c8-a36a-52e0771b77fb", + "version": 6, + "weekStart": "" +} \ No newline at end of file diff --git a/panopticon/grafana/dashboards/node-resources.json b/panopticon/grafana/dashboards/node-resources.json new file mode 100644 index 0000000..9b794d0 --- /dev/null +++ b/panopticon/grafana/dashboards/node-resources.json @@ -0,0 +1,1011 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Node resources overview provided from Prometheus nodeExporter metrics", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 13702, + "graphTooltip": 0, + "id": 2, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "- *Load* - CPU capasity used (load average for last 1 minute divided by CPU cores count)\n- *CPU* - CPU usage\n- *Memory* - memory usage\n- *Filesystem* - filesystem usage\n- *Disk read* - maximum among all disks read rate\n- *Dist write* - maximum among all disks write rate\n- *Net recv* - maximum among all NIC's receive rate\n- *Net trans* - maximum among all NIC's transmit rate\n- *Net sock* - used network sockets \n- *TCP estab* - TCP established connections\n- *TCP tw* - TCP sockets in TIME-WAIT status", + "fieldConfig": { + "defaults": { + "custom": { + "align": "left", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false, + "minWidth": 50 + }, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "CPU" + }, + "properties": [ + { + "id": "unit", + "value": "percent" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "basic", + "type": "gauge" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 70 + }, + { + "color": "red", + "value": 90 + } + ] + } + }, + { + "id": "custom.width", + "value": 160 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Memory" + }, + "properties": [ + { + "id": "unit", + "value": "percent" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "basic", + "type": "gauge" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 85 + }, + { + "color": "red", + "value": 98 + } + ] + } + }, + { + "id": "custom.width", + "value": 170 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Filesystem" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "basic", + "type": "gauge" + } + }, + { + "id": "unit", + "value": "percent" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 75 + }, + { + "color": "red", + "value": 90 + } + ] + } + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Details", + "url": "https://grafana.rcrtv.net/d/2UgUicaGk/node-exporter-full?viewPanel=280&orgId=1&from=now-7d&to=now&var-job=${job}&var-hostname=${__data.fields.Hostname}" + } + ] + }, + { + "id": "custom.width", + "value": 167 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Disk read" + }, + "properties": [ + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 10485760 + }, + { + "color": "red", + "value": 31457280 + } + ] + } + }, + { + "id": "custom.width", + "value": 91 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Disk write" + }, + "properties": [ + { + "id": "unit", + "value": "Bps" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 10485760 + }, + { + "color": "red", + "value": 31457280 + } + ] + } + }, + { + "id": "custom.width", + "value": 90 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "TCP estab" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 8000 + }, + { + "color": "red", + "value": 15000 + } + ] + } + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.width", + "value": 82 + }, + { + "id": "decimals", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "TCP tw" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + } + ] + } + }, + { + "id": "custom.width", + "value": 85 + }, + { + "id": "decimals", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Net recv" + }, + "properties": [ + { + "id": "unit", + "value": "bps" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 524288000 + }, + { + "color": "red", + "value": 943718400 + } + ] + } + }, + { + "id": "custom.width", + "value": 90 + }, + { + "id": "decimals", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Net trans" + }, + "properties": [ + { + "id": "unit", + "value": "bps" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 524288000 + }, + { + "color": "red", + "value": 943718400 + } + ] + } + }, + { + "id": "custom.width", + "value": 89 + }, + { + "id": "decimals", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Datacenter" + }, + "properties": [ + { + "id": "custom.width", + "value": 101 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Node" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "View details in new tab", + "url": "https://grafana.rcrtv.net/d/2UgUicaGk/node-exporter-full?var-job=${job}&var-hostname=${__value.text}" + } + ] + }, + { + "id": "custom.width", + "value": 129 + }, + { + "id": "custom.filterable", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Load" + }, + "properties": [ + { + "id": "unit", + "value": "percent" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "basic", + "type": "gauge" + } + }, + { + "id": "thresholds", + "value": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 80 + }, + { + "color": "red", + "value": 100 + } + ] + } + }, + { + "id": "custom.width", + "value": 176 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Net sock" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" + } + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 30000 + }, + { + "color": "red", + "value": 60000 + } + ] + } + }, + { + "id": "custom.width", + "value": 78 + } + ] + } + ] + }, + "gridPos": { + "h": 19, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 187, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Load" + } + ] + }, + "pluginVersion": "10.2.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "node_uname_info{job=~\"$job\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "__auto", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "(1 - avg(rate(node_cpu_seconds_total{job=~\"$job\",mode=\"idle\"}[$__rate_interval])) by (server)) * 100", + "format": "table", + "instant": true, + "interval": "1m", + "legendFormat": "", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "(1 - (node_memory_MemAvailable_bytes{job=~\"$job\"} / (node_memory_MemTotal_bytes{job=~\"$job\"}))) * 100", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "max((1 - (node_filesystem_free_bytes{job=~\"$job\"} / node_filesystem_size_bytes{job=~\"$job\"})) * 100) by (server)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(rate(node_disk_read_bytes_total{job=~\"$job\"}[$__rate_interval])) by (server)", + "format": "table", + "instant": true, + "interval": "1m", + "legendFormat": "", + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(rate(node_disk_written_bytes_total{job=~\"$job\"}[$__rate_interval])) by (server)", + "format": "table", + "instant": true, + "interval": "1m", + "legendFormat": "", + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "node_netstat_Tcp_CurrEstab{job=~\"$job\"} - 0", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "node_sockstat_TCP_tw{job=~\"$job\"} - 0", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "J" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(rate(node_network_receive_bytes_total{job=~\"$job\"}[$__rate_interval])*8) by (server)", + "format": "table", + "instant": true, + "interval": "1m", + "legendFormat": "", + "refId": "K" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "max(rate(node_network_transmit_bytes_total{job=~\"$job\"}[$__rate_interval])*8) by (server)", + "format": "table", + "instant": true, + "interval": "1m", + "legendFormat": "", + "refId": "L" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "avg(node_load1{job=~\"$job\"} * 100) by (instance) / count (node_cpu_seconds_total{job=~\"$job\", mode=\"system\"}) by (server)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "M" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "node_sockstat_sockets_used{job=~\"$job\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "N" + } + ], + "title": "Node resources usage ", + "transformations": [ + { + "id": "seriesToColumns", + "options": { + "byField": "server", + "mode": "outer" + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time 1": true, + "Time 10": true, + "Time 11": true, + "Time 12": true, + "Time 13": true, + "Time 14": true, + "Time 2": true, + "Time 3": true, + "Time 4": true, + "Time 5": true, + "Time 6": true, + "Time 7": true, + "Time 8": true, + "Time 9": true, + "Value #A": true, + "Value #B": true, + "Value #C": false, + "Value #E": true, + "__name__ 1": true, + "__name__ 2": true, + "__name__ 3": true, + "datacenter 1": true, + "datacenter 2": true, + "datacenter 3": true, + "datacenter 4": true, + "datacenter 5": true, + "datacenter 6": true, + "domainname": true, + "hostname 2": true, + "hostname 3": true, + "hostname 4": true, + "hostname 5": true, + "hostname 6": true, + "instance": true, + "instance 1": true, + "instance 2": true, + "instance 3": true, + "job 1": true, + "job 2": true, + "job 3": true, + "job 4": true, + "job 5": true, + "job 6": true, + "machine": true, + "nodename": true, + "release": true, + "sysname": true, + "version": true + }, + "includeByName": {}, + "indexByName": { + "Time": 35, + "Time 10": 32, + "Time 11": 34, + "Time 2": 19, + "Time 3": 22, + "Time 4": 25, + "Time 5": 26, + "Time 6": 27, + "Time 7": 28, + "Time 8": 29, + "Time 9": 30, + "Value #A": 11, + "Value #C": 1, + "Value #D": 2, + "Value #F": 3, + "Value #G": 4, + "Value #H": 5, + "Value #I": 9, + "Value #J": 10, + "Value #K": 6, + "Value #L": 7, + "Value #N": 8, + "__name__ 1": 12, + "__name__ 2": 20, + "domainname": 13, + "instance": 24, + "instance 2": 37, + "instance 3": 38, + "instance 4": 39, + "instance 5": 40, + "job": 36, + "job 2": 21, + "job 3": 23, + "job 4": 31, + "job 5": 33, + "machine": 14, + "nodename": 15, + "release": 16, + "server": 0, + "sysname": 17, + "version": 18 + }, + "renameByName": { + "Difference": "Core-LA1", + "Value #A": "", + "Value #B": "LA1", + "Value #C": "CPU", + "Value #D": "Memory", + "Value #E": "Cores", + "Value #F": "Filesystem", + "Value #G": "Disk read", + "Value #H": "Disk write", + "Value #I": "TCP estab", + "Value #J": "TCP tw", + "Value #K": "Net recv", + "Value #L": "Net trans", + "Value #M": "Load", + "Value #N": "Net sock", + "datacenter 1": "DC", + "hostname 1": "Node" + } + } + } + ], + "transparent": true, + "type": "table" + } + ], + "refresh": "15s", + "schemaVersion": 39, + "tags": [ + "prometheus", + "nodeExporter" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(node_uname_info, job)", + "hide": 2, + "includeAll": true, + "label": "Job", + "multi": true, + "name": "job", + "options": [], + "query": { + "query": "label_values(node_uname_info, job)", + "refId": "Prometheus-job-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "hidden": false, + "now": true, + "refresh_intervals": [ + "15s", + "30s", + "1m", + "5m", + "15m", + "30m" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Node Resources Overview", + "uid": "gbGKmy-Gz", + "version": 8, + "weekStart": "" + } \ No newline at end of file diff --git a/panopticon/grafana/provisioning/dashboards/providers.yml b/panopticon/grafana/provisioning/dashboards/providers.yml new file mode 100644 index 0000000..ab60a0a --- /dev/null +++ b/panopticon/grafana/provisioning/dashboards/providers.yml @@ -0,0 +1,24 @@ +apiVersion: 1 + +providers: + # an unique provider name. Required + - name: 'a unique provider name' + # Org id. Default to 1 + orgId: 1 + # name of the dashboard folder. + folder: '' + # folder UID. will be automatically generated if not specified + folderUid: '' + # provider type. Default to 'file' + type: file + # disable dashboard deletion + disableDeletion: false + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 10 + # allow updating provisioned dashboards from the UI + allowUiUpdates: true + options: + # path to dashboard files on disk. Required when using the 'file' type + path: /var/lib/grafana/dashboards + # use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: true \ No newline at end of file diff --git a/panopticon/grafana/provisioning/datasources/datasource.yml b/panopticon/grafana/provisioning/datasources/datasource.yml new file mode 100644 index 0000000..6a874a8 --- /dev/null +++ b/panopticon/grafana/provisioning/datasources/datasource.yml @@ -0,0 +1,13 @@ +apiVersion: 1 + +datasources: +- name: Prometheus + type: prometheus + url: http://prometheus:9090 + isDefault: true + access: proxy + editable: true + basicAuth: true + basicAuthUser: prom + secureJsonData: + basicAuthPassword: ${PROMETHEUS_PASSWORD} \ No newline at end of file diff --git a/panopticon/prometheus/prometheus.yml b/panopticon/prometheus/prometheus.yml new file mode 100644 index 0000000..c103d82 --- /dev/null +++ b/panopticon/prometheus/prometheus.yml @@ -0,0 +1,29 @@ +global: + scrape_interval: 60s + scrape_timeout: 10s + evaluation_interval: 15s +alerting: + alertmanagers: + - static_configs: + - targets: [] + scheme: http + timeout: 10s + api_version: v1 +scrape_configs: + - job_name: 'federate' + scrape_interval: 60s + + honor_labels: true + metrics_path: '/federate' + + basic_auth: + username: '${user}' + password: '${password}' + + params: + 'match[]': + - '{instance="node-exporter:9100"}' + - '{__name__=~"up:.*"}' + + static_configs: + ${targets} diff --git a/panopticon/prometheus/web.yml b/panopticon/prometheus/web.yml new file mode 100644 index 0000000..91b08ed --- /dev/null +++ b/panopticon/prometheus/web.yml @@ -0,0 +1,4 @@ +basic_auth_users: + # bcrypt "prompass" + # e.g. htpasswd -bnBC 10 "" prompass | tr -d ':\n' + prom: $2y$10$oWtHm79bh0D1CnNC4brGiOU7y6MbYa6cgklF/g6ek9YZYkgXfeOIu \ No newline at end of file diff --git a/prometheus/prometheus.yml b/prometheus/prometheus.yml index 8a85015..599556c 100644 --- a/prometheus/prometheus.yml +++ b/prometheus/prometheus.yml @@ -19,6 +19,12 @@ scrape_configs: static_configs: - targets: - wallet-tracker:3000 +- job_name: user + scrape_interval: 60s + metrics_path: /metrics + static_configs: + - targets: + - user-metrics:3000 - job_name: keeper honor_timestamps: true scrape_interval: 15s diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..785c67d --- /dev/null +++ b/shell.nix @@ -0,0 +1,11 @@ +let + unstable = import (fetchTarball https://nixos.org/channels/nixos-unstable/nixexprs.tar.xz) { }; +in +{ pkgs ? import { } }: +pkgs.mkShell { + buildInputs = with pkgs; [ + ansible + terraform + solana-cli + ]; +} diff --git a/templates/bot/config.yaml.tpl b/templates/bot/config.yaml.tpl new file mode 100644 index 0000000..3c760d2 --- /dev/null +++ b/templates/bot/config.yaml.tpl @@ -0,0 +1,233 @@ +global: + # devnet or mainnet-beta + driftEnv: mainnet-beta + + # RPC endpoint to use + endpoint: + + # Custom websocket endpoint to use (if null will be determined from `endpoint``) + # Note: the default wsEndpoint value simply replaces http(s) with ws(s), so if + # your RPC provider requires a special path (i.e. /ws) for websocket connections + # you must set this. + wsEndpoint: + + # optional if you want to use helius' global priority fee method AND `endpoint` is not + # already a helius url. + heliusEndpoint: + + # `solana` or `helius`. If `helius` `endpoint` must be a helius RPC, or `heliusEndpoint` + # must be set + # solana: uses https://solana.com/docs/rpc/http/getrecentprioritizationfees + # helius: uses https://docs.helius.dev/solana-rpc-nodes/alpha-priority-fee-api + priorityFeeMethod: solana + + # skips preflight checks on sendTransaciton, default is false. + # this will speed up tx sending, but may increase SOL paid due to failed txs landing + # on chain + txSkipPreflight: false + + # max priority fee to use, in micro lamports + # i.e. a fill that uses 500_000 CUs will spend: + # 500_000 * 10_000 * 1e-6 * 1e-9 = 0.000005 SOL on priority fees + # this is on top of the 0.000005 SOL base fee, so 0.000010 SOL total + maxPriorityFeeMicroLamports: 10000 + + # Private key to use to sign transactions. + # will load from KEEPER_PRIVATE_KEY env var if null + keeperPrivateKey: + + initUser: false # initialize user on startup + testLiveness: false # test liveness, by failing liveness test after 1 min + + # Force deposit this amount of USDC to collateral account, the program will + # end after the deposit transaction is sent + #forceDeposit: 1000 + + websocket: false # use websocket for account loading and events (limited support) + eventSubscriber: false # disables event subscriber (heavy RPC demand), this is primary used for counting fills + runOnce: false # Set true to run once and exit, useful for testing or one off bot runs + debug: false # Enable debug logging + txSenderType: "fast" + + # subaccountIDs to load, if null will load subaccount 0 (default). + # Even if bot specific configs requires subaccountIDs, you should still + # specify it here, since we load the subaccounts before loading individual + # bots. + # subaccounts: + # - 0 + # - 1 + # - 2 + + eventSubscriberPollingInterval: 5000 + bulkAccountLoaderPollingInterval: 5000 + + useJito: ${use_jito} + # one of: ['non-jito-only', 'jito-only', 'hybrid']. + # * non-jito-only: will only send txs to RPC when there is no active jito leader + # * jito-only: will only send txs via bundle when there is an active jito leader + # * hybrid: will attempt to send bundles when active jito leader, and use RPC when not + # hybrid may not work well if using high throughput bots such as a filler depending on infra limitations. + jitoStrategy: jito-only + # the minimum tip to pay + jitoMinBundleTip: 10000 + # the maximum tip to pay (will pay this once jitoMaxBundleFailCount is hit) + jitoMaxBundleTip: 100000 + # the number of failed bundles (accepted but not landed) before tipping the max tip + jitoMaxBundleFailCount: 200 + # the tip multiplier to use when tipping the max tip + # controls superlinearity (1 = linear, 2 = slightly-superlinear, 3 = more-superlinear, ...) + jitoTipMultiplier: 3 + jitoBlockEngineUrl: + jitoAuthPrivateKey: + + # which subaccounts to load, if null will load subaccount 0 (default) + subaccounts: + +# perpMarketIndexes: +# - 1 + +# Which bots to run, be careful with this, running multiple bots in one instance +# might use more resources than expected. +# Bot specific configs are below +enabledBots: + # Perp order filler bot + - fillerLite + + # Spot order filler bot + #- spotFiller + + # Trigger bot (triggers trigger orders) + #- trigger + + # Liquidator bot, liquidates unhealthy positions by taking over the risk (caution, you should manage risk here) + # - liquidator + + # Example maker bot that participates in JIT auction (caution: you will probably lose money) + # - jitMaker + + # Example maker bot that posts floating oracle orders + #- floatingMaker + + # settles PnLs for the insurance fund (may want to run with runOnce: true) + # - ifRevenueSettler + + # settles negative PnLs for users (may want to run with runOnce: true) + # - userPnlSettler + + # - markTwapCrank + + # below are bot configs +botConfigs: + + fillerLite: + botId: "fillerLite" + dryRun: false + fillerPollingInterval: 6000 + metricsPort: 9464 + revertOnFailure: true + simulateTxForCUEstimate: true + + filler: + botId: "filler" + dryRun: false + fillerPollingInterval: 6000 + metricsPort: 9464 + + # will revert a transaction during simulation if a fill fails, this will save on tx fees, + # and be friendlier for use with services like Jito. + # Default is true + revertOnFailure: true + + # calls simulateTransaction before sending to get an accurate CU estimate + # as well as stop before sending the transaction (Default is true) + simulateTxForCUEstimate: true + + spotFiller: + botId: "spot-filler" + dryRun: false + fillerPollingInterval: 6000 + metricsPort: 9465 + revertOnFailure: true + simulateTxForCUEstimate: true + + liquidator: + botId: "liquidator" + dryRun: false + metricsPort: 9466 + # if true will NOT attempt to sell off any inherited positions + disableAutoDerisking: false + # if true will swap spot assets on jupiter if the price is better + useJupiter: true + # null will handle all markets + perpMarketIndicies: + spotMarketIndicies: + + # this replaces perpMarketIndicies and spotMarketIndicies by allowing you to specify + # which subaccount is responsible for liquidating markets + # Markets are defined on perpMarkets.ts and spotMarkets.ts on the protocol codebase + # Note: you must set global.subaccounts with all the subaccounts you want to load + perpSubAccountConfig: + 0: + # subaccount 0 will watch perp markets 0 and 1 + - 0 + - 1 + spotSubAccountConfig: + 0: + # subaccount 0 will watch all spot markets + + # max slippage (from oracle price) to incur allow when derisking + maxSlippagePct: 0.05 + + # what algo to use for derisking. Options are "market" or "twap" + deriskAlgo: "market" + + # if deriskAlgo == "twap", must supply these as well + # twapDurationSec: 300 # overall duration of to run the twap algo. Aims to derisk the entire position over this duration + + # Minimum deposit amount to try to liquidiate, per spot market, in lamports. + # If null, or a spot market isn't here, it will liquidate any amount + # See perpMarkets.ts on the protocol codebase for the indices + minDepositToLiq: + 1: 10 + 2: 1000 + + # Filter out un-liquidateable accounts that just create log noise + excludedAccounts: + - 9CJLgd5f9nmTp7KRV37RFcQrfEmJn6TU87N7VQAe2Pcq + - Edh39zr8GnQFNYwyvxhPngTJHrr29H3vVup8e8ZD4Hwu + + # max % of collateral to spend when liquidating a user. In percentage terms (0.5 = 50%) + maxPositionTakeoverPctOfCollateral: 0.5 + + # sends a webhook notification (slack, discord, etc.) when a liquidation is attempted (can be noisy due to partial liquidations) + notifyOnLiquidation: true + + trigger: + botId: "trigger" + dryRun: false + metricsPort: 9465 + + markTwapCrank: + botId: "mark-twap-cranker" + dryRun: false + metricsPort: 9465 + crankIntervalToMarketIndicies: + 15000: + - 0 + - 1 + - 2 + 60000: + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + - 16 diff --git a/templates/bot/docker-compose-aio.yaml.tpl b/templates/bot/docker-compose-aio.yaml.tpl new file mode 100644 index 0000000..f1c4916 --- /dev/null +++ b/templates/bot/docker-compose-aio.yaml.tpl @@ -0,0 +1,60 @@ +version: '3' + +services: + keeper: + image: ${docker_image} + restart: unless-stopped + env_file: .env + volumes: + - ./config.yaml:/app/config.yaml + wallet-tracker: + image: ${docker_image_wallet_tracker} + build: + context: wallet-tracker + env_file: .env + restart: unless-stopped + user-metrics: + image: wirelos/user-metrics:0.1.0 + env_file: .env + restart: unless-stopped + + prometheus: + image: prom/prometheus + container_name: prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.config.file=/etc/prometheus/web.yml' + ports: + - 9090:9090 + restart: unless-stopped + volumes: + - ./prometheus:/etc/prometheus + - prom_data:/prometheus + node-exporter: + image: prom/node-exporter:latest + container_name: node-exporter + restart: unless-stopped + volumes: + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /:/rootfs:ro + command: + - '--path.procfs=/host/proc' + - '--path.rootfs=/rootfs' + - '--path.sysfs=/host/sys' + - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)' + expose: + - 9100 + grafana: + image: grafana/grafana + container_name: grafana + env_file: .env.monitoring + ports: + - 3000:3000 + restart: unless-stopped + volumes: + - ./grafana/provisioning:/etc/grafana/provisioning + - ./grafana/dashboards:/var/lib/grafana/dashboards + +volumes: + prom_data: diff --git a/templates/bot/docker-compose.yaml.tpl b/templates/bot/docker-compose.yaml.tpl new file mode 100644 index 0000000..07d73ef --- /dev/null +++ b/templates/bot/docker-compose.yaml.tpl @@ -0,0 +1,9 @@ +version: '3' + +services: + keeper: + image: ${docker_image} + restart: unless-stopped + env_file: .env + volumes: + - ./config.yaml:/app/config.yaml diff --git a/templates/bot/env.tpl b/templates/bot/env.tpl new file mode 100644 index 0000000..b1f772f --- /dev/null +++ b/templates/bot/env.tpl @@ -0,0 +1,13 @@ +DOCKER_IMAGE=wirelos/drift-keeper:mainnet-beta +DOCKER_IMAGE_WALLET_TRACKER=wirelos/solana-wallet-tracker:latest + +ENV=mainnet-beta +ENDPOINT=${rpc_endpoint} +RPC_ENDPOINT=${rpc_endpoint} +WS_ENDPOINT=${ws_endpoint} + +WALLET_ADDRESS=${wallet_address} +KEEPER_PRIVATE_KEY="${keeper_private_key}" +PRIVATE_KEY="${keeper_private_key}" +JITO_BLOCK_ENGINE_URL=${jito_block_engine_url} +JITO_AUTH_PRIVATE_KEY="${jito_private_key}" \ No newline at end of file diff --git a/templates/monitoring/env.monitoring.tpl b/templates/monitoring/env.monitoring.tpl new file mode 100644 index 0000000..1b55bf6 --- /dev/null +++ b/templates/monitoring/env.monitoring.tpl @@ -0,0 +1,3 @@ +GF_SECURITY_ADMIN_USER=${grafana_user} +GF_SECURITY_ADMIN_PASSWORD=${grafana_password} +PROMETHEUS_PASSWORD=${prometheus_password} \ No newline at end of file diff --git a/templates/monitoring/prometheus/panopticon.yml.tpl b/templates/monitoring/prometheus/panopticon.yml.tpl new file mode 100644 index 0000000..c103d82 --- /dev/null +++ b/templates/monitoring/prometheus/panopticon.yml.tpl @@ -0,0 +1,29 @@ +global: + scrape_interval: 60s + scrape_timeout: 10s + evaluation_interval: 15s +alerting: + alertmanagers: + - static_configs: + - targets: [] + scheme: http + timeout: 10s + api_version: v1 +scrape_configs: + - job_name: 'federate' + scrape_interval: 60s + + honor_labels: true + metrics_path: '/federate' + + basic_auth: + username: '${user}' + password: '${password}' + + params: + 'match[]': + - '{instance="node-exporter:9100"}' + - '{__name__=~"up:.*"}' + + static_configs: + ${targets} diff --git a/templates/monitoring/prometheus/prometheus.yml.tpl b/templates/monitoring/prometheus/prometheus.yml.tpl new file mode 100644 index 0000000..46ccb6f --- /dev/null +++ b/templates/monitoring/prometheus/prometheus.yml.tpl @@ -0,0 +1,42 @@ +global: + scrape_interval: 60s + scrape_timeout: 10s + evaluation_interval: 15s +alerting: + alertmanagers: + - static_configs: + - targets: [] + scheme: http + timeout: 10s + api_version: v1 +scrape_configs: +- job_name: node + static_configs: + - targets: ['node-exporter:9100'] +- job_name: keeper + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - keeper:9464 +- job_name: wallet + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics/${wallet_address} + scheme: http + static_configs: + - targets: + - wallet-tracker:3000 +- job_name: user + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - user-metrics:3000 \ No newline at end of file diff --git a/templates/monitoring/prometheus/web.yml.tpl b/templates/monitoring/prometheus/web.yml.tpl new file mode 100644 index 0000000..29f543d --- /dev/null +++ b/templates/monitoring/prometheus/web.yml.tpl @@ -0,0 +1,2 @@ +basic_auth_users: + prom: ${prometheus_password_bcrypt} \ No newline at end of file diff --git a/user-metrics/.gitignore b/user-metrics/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/user-metrics/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/user-metrics/Dockerfile b/user-metrics/Dockerfile new file mode 100644 index 0000000..b4eee42 --- /dev/null +++ b/user-metrics/Dockerfile @@ -0,0 +1,7 @@ +FROM node:18 + +WORKDIR /app +COPY package.json ./ +RUN npm install +COPY src src +CMD ["npm", "start"] \ No newline at end of file diff --git a/user-metrics/package-lock.json b/user-metrics/package-lock.json new file mode 100644 index 0000000..aa78f27 --- /dev/null +++ b/user-metrics/package-lock.json @@ -0,0 +1,2278 @@ +{ + "name": "dex-metrics", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dex-metrics", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@drift-labs/sdk": "2.78.0-beta.0", + "@solana/web3.js": "^1.89.1", + "bigint-buffer": "^1.1.5", + "dotenv": "^16.4.4", + "express": "^4.18.2", + "prom-client": "^15.1.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", + "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@coral-xyz/anchor": { + "version": "0.28.1-beta.2", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.28.1-beta.2.tgz", + "integrity": "sha512-xreUcOFF8+IQKWOBUrDKJbIw2ftpRVybFlEPVrbSlOBCbreCWrQ5754Gt9cHIcuBDAzearCDiBqzsGQdNgPJiw==", + "dependencies": { + "@coral-xyz/borsh": "^0.28.0", + "@noble/hashes": "^1.3.1", + "@solana/web3.js": "^1.68.0", + "base64-js": "^1.5.1", + "bn.js": "^5.1.2", + "bs58": "^4.0.1", + "buffer-layout": "^1.2.2", + "camelcase": "^6.3.0", + "cross-fetch": "^3.1.5", + "crypto-hash": "^1.3.0", + "eventemitter3": "^4.0.7", + "pako": "^2.0.3", + "snake-case": "^3.0.4", + "superstruct": "^0.15.4", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=11" + } + }, + "node_modules/@coral-xyz/borsh": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.28.0.tgz", + "integrity": "sha512-/u1VTzw7XooK7rqeD7JLUSwOyRSesPUk0U37BV9zK0axJc1q0nRbKFGFLYCQ16OtdOJTTwGfGp11Lx9B45bRCQ==", + "dependencies": { + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@solana/web3.js": "^1.68.0" + } + }, + "node_modules/@drift-labs/sdk": { + "version": "2.78.0-beta.0", + "resolved": "https://registry.npmjs.org/@drift-labs/sdk/-/sdk-2.78.0-beta.0.tgz", + "integrity": "sha512-Z/+NY15Du9zRjA9ExIZFsNhxwE0OY5JGdfiu5wPk2mjRmOneEu71sltu5Z+yA89z8nGw/s0oZKdAsQnUZLzX6A==", + "dependencies": { + "@coral-xyz/anchor": "0.28.1-beta.2", + "@ellipsis-labs/phoenix-sdk": "^1.4.2", + "@project-serum/serum": "^0.13.38", + "@pythnetwork/client": "2.5.3", + "@solana/spl-token": "^0.3.7", + "@solana/web3.js": "1.73.2", + "strict-event-emitter-types": "^2.0.0", + "uuid": "^8.3.2", + "zstddec": "^0.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@drift-labs/sdk/node_modules/@solana/web3.js": { + "version": "1.73.2", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.73.2.tgz", + "integrity": "sha512-9WACF8W4Nstj7xiDw3Oom22QmrhBh0VyZyZ7JvvG3gOxLWLlX3hvm5nPVJOGcCE/9fFavBbCUb5A6CIuvMGdoA==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@noble/ed25519": "^1.7.0", + "@noble/hashes": "^1.1.2", + "@noble/secp256k1": "^1.6.3", + "@solana/buffer-layout": "^4.0.0", + "agentkeepalive": "^4.2.1", + "bigint-buffer": "^1.1.5", + "bn.js": "^5.0.0", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.1", + "fast-stable-stringify": "^1.0.0", + "jayson": "^3.4.4", + "node-fetch": "2", + "rpc-websockets": "^7.5.0", + "superstruct": "^0.14.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@drift-labs/sdk/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/@drift-labs/sdk/node_modules/buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz", + "integrity": "sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==", + "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/@drift-labs/sdk/node_modules/jayson": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.7.0.tgz", + "integrity": "sha512-tfy39KJMrrXJ+mFcMpxwBvFDetS8LAID93+rycFglIQM4kl3uNR3W4lBLE/FFhsoUCEox5Dt2adVpDm/XtebbQ==", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "lodash": "^4.17.20", + "uuid": "^8.3.2", + "ws": "^7.4.5" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@drift-labs/sdk/node_modules/superstruct": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", + "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" + }, + "node_modules/@ellipsis-labs/phoenix-sdk": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@ellipsis-labs/phoenix-sdk/-/phoenix-sdk-1.4.5.tgz", + "integrity": "sha512-vEYgMXuV5/mpnpEi+VK4HO8f6SheHtVLdHHlULBiDN1eECYmL67gq+/cRV7Ar6jAQ7rJZL7xBxhbUW5kugMl6A==", + "dependencies": { + "@metaplex-foundation/beet": "^0.7.1", + "@metaplex-foundation/rustbin": "^0.3.1", + "@metaplex-foundation/solita": "^0.12.2", + "@solana/spl-token": "^0.3.7", + "@types/node": "^18.11.13", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^5.0.0" + } + }, + "node_modules/@ellipsis-labs/phoenix-sdk/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/@ellipsis-labs/phoenix-sdk/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/@metaplex-foundation/beet": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/beet/-/beet-0.7.2.tgz", + "integrity": "sha512-K+g3WhyFxKPc0xIvcIjNyV1eaTVJTiuaHZpig7Xx0MuYRMoJLLvhLTnUXhFdR5Tu2l2QSyKwfyXDgZlzhULqFg==", + "dependencies": { + "ansicolors": "^0.3.2", + "assert": "^2.1.0", + "bn.js": "^5.2.0", + "debug": "^4.3.3" + } + }, + "node_modules/@metaplex-foundation/beet-solana": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/beet-solana/-/beet-solana-0.3.1.tgz", + "integrity": "sha512-tgyEl6dvtLln8XX81JyBvWjIiEcjTkUwZbrM5dIobTmoqMuGewSyk9CClno8qsMsFdB5T3jC91Rjeqmu/6xk2g==", + "dependencies": { + "@metaplex-foundation/beet": ">=0.1.0", + "@solana/web3.js": "^1.56.2", + "bs58": "^5.0.0", + "debug": "^4.3.4" + } + }, + "node_modules/@metaplex-foundation/beet-solana/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/@metaplex-foundation/beet-solana/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/@metaplex-foundation/rustbin": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/rustbin/-/rustbin-0.3.5.tgz", + "integrity": "sha512-m0wkRBEQB/8krwMwKBvFugufZtYwMXiGHud2cTDAv+aGXK4M90y0Hx67/wpu+AqqoQfdV8VM9YezUOHKD+Z5kA==", + "dependencies": { + "debug": "^4.3.3", + "semver": "^7.3.7", + "text-table": "^0.2.0", + "toml": "^3.0.0" + } + }, + "node_modules/@metaplex-foundation/solita": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/solita/-/solita-0.12.2.tgz", + "integrity": "sha512-oczMfE43NNHWweSqhXPTkQBUbap/aAiwjDQw8zLKNnd/J8sXr/0+rKcN5yJIEgcHeKRkp90eTqkmt2WepQc8yw==", + "dependencies": { + "@metaplex-foundation/beet": "^0.4.0", + "@metaplex-foundation/beet-solana": "^0.3.0", + "@metaplex-foundation/rustbin": "^0.3.0", + "@solana/web3.js": "^1.36.0", + "camelcase": "^6.2.1", + "debug": "^4.3.3", + "js-sha256": "^0.9.0", + "prettier": "^2.5.1", + "snake-case": "^3.0.4", + "spok": "^1.4.3" + }, + "bin": { + "solita": "dist/src/cli/solita.js" + } + }, + "node_modules/@metaplex-foundation/solita/node_modules/@metaplex-foundation/beet": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@metaplex-foundation/beet/-/beet-0.4.0.tgz", + "integrity": "sha512-2OAKJnLatCc3mBXNL0QmWVQKAWK2C7XDfepgL0p/9+8oSx4bmRAFHFqptl1A/C0U5O3dxGwKfmKluW161OVGcA==", + "dependencies": { + "ansicolors": "^0.3.2", + "bn.js": "^5.2.0", + "debug": "^4.3.3" + } + }, + "node_modules/@noble/curves": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", + "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/ed25519": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.3.tgz", + "integrity": "sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@opentelemetry/api": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", + "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@project-serum/anchor": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.11.1.tgz", + "integrity": "sha512-oIdm4vTJkUy6GmE6JgqDAuQPKI7XM4TPJkjtoIzp69RZe0iAD9JP2XHx7lV1jLdYXeYHqDXfBt3zcq7W91K6PA==", + "dependencies": { + "@project-serum/borsh": "^0.2.2", + "@solana/web3.js": "^1.17.0", + "base64-js": "^1.5.1", + "bn.js": "^5.1.2", + "bs58": "^4.0.1", + "buffer-layout": "^1.2.0", + "camelcase": "^5.3.1", + "crypto-hash": "^1.3.0", + "eventemitter3": "^4.0.7", + "find": "^0.3.0", + "js-sha256": "^0.9.0", + "pako": "^2.0.3", + "snake-case": "^3.0.4", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=11" + } + }, + "node_modules/@project-serum/anchor/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@project-serum/borsh": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@project-serum/borsh/-/borsh-0.2.5.tgz", + "integrity": "sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q==", + "dependencies": { + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@solana/web3.js": "^1.2.0" + } + }, + "node_modules/@project-serum/serum": { + "version": "0.13.65", + "resolved": "https://registry.npmjs.org/@project-serum/serum/-/serum-0.13.65.tgz", + "integrity": "sha512-BHRqsTqPSfFB5p+MgI2pjvMBAQtO8ibTK2fYY96boIFkCI3TTwXDt2gUmspeChKO2pqHr5aKevmexzAcXxrSRA==", + "dependencies": { + "@project-serum/anchor": "^0.11.1", + "@solana/spl-token": "^0.1.6", + "@solana/web3.js": "^1.21.0", + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@project-serum/serum/node_modules/@solana/spl-token": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.1.8.tgz", + "integrity": "sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@solana/web3.js": "^1.21.0", + "bn.js": "^5.1.0", + "buffer": "6.0.3", + "buffer-layout": "^1.2.0", + "dotenv": "10.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@project-serum/serum/node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@pythnetwork/client": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@pythnetwork/client/-/client-2.5.3.tgz", + "integrity": "sha512-NBLxPnA6A3tZb/DYUooD4SO63UJ70s9DzzFPGXcQNBR9itcycp7aaV+UA5oUPloD/4UHL9soo2fRuDVur0gmhA==", + "dependencies": { + "@solana/web3.js": "^1.30.2", + "assert": "^2.0.0", + "buffer": "^6.0.1" + } + }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", + "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@solana/buffer-layout-utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz", + "integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/web3.js": "^1.32.0", + "bigint-buffer": "^1.1.5", + "bignumber.js": "^9.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@solana/codecs-core": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-JCz7mKjVKtfZxkuDtwMAUgA7YvJcA2BwpZaA1NOLcted4OMC4Prwa3DUe3f3181ixPYaRyptbF0Ikq2MbDkYEA==" + }, + "node_modules/@solana/codecs-data-structures": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-sLpjL9sqzaDdkloBPV61Rht1tgaKq98BCtIKRuyscIrmVPu3wu0Bavk2n/QekmUzaTsj7K1pVSniM0YqCdnEBw==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508", + "@solana/codecs-numbers": "2.0.0-experimental.8618508" + } + }, + "node_modules/@solana/codecs-numbers": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-EXQKfzFr3CkKKNzKSZPOOOzchXsFe90TVONWsSnVkonO9z+nGKALE0/L9uBmIFGgdzhhU9QQVFvxBMclIDJo2Q==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508" + } + }, + "node_modules/@solana/codecs-strings": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-b2yhinr1+oe+JDmnnsV0641KQqqDG8AQ16Z/x7GVWO+AWHMpRlHWVXOq8U1yhPMA4VXxl7i+D+C6ql0VGFp0GA==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508", + "@solana/codecs-numbers": "2.0.0-experimental.8618508" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22" + } + }, + "node_modules/@solana/options": { + "version": "2.0.0-experimental.8618508", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.0.0-experimental.8618508.tgz", + "integrity": "sha512-fy/nIRAMC3QHvnKi63KEd86Xr/zFBVxNW4nEpVEU2OT0gCEKwHY4Z55YHf7XujhyuM3PNpiBKg/YYw5QlRU4vg==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508", + "@solana/codecs-numbers": "2.0.0-experimental.8618508" + } + }, + "node_modules/@solana/spl-token": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.11.tgz", + "integrity": "sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ==", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/buffer-layout-utils": "^0.2.0", + "@solana/spl-token-metadata": "^0.1.2", + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.88.0" + } + }, + "node_modules/@solana/spl-token-metadata": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@solana/spl-token-metadata/-/spl-token-metadata-0.1.2.tgz", + "integrity": "sha512-hJYnAJNkDrtkE2Q41YZhCpeOGU/0JgRFXbtrtOuGGeKc3pkEUHB9DDoxZAxx+XRno13GozUleyBi0qypz4c3bw==", + "dependencies": { + "@solana/codecs-core": "2.0.0-experimental.8618508", + "@solana/codecs-data-structures": "2.0.0-experimental.8618508", + "@solana/codecs-numbers": "2.0.0-experimental.8618508", + "@solana/codecs-strings": "2.0.0-experimental.8618508", + "@solana/options": "2.0.0-experimental.8618508", + "@solana/spl-type-length-value": "0.1.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.87.6" + } + }, + "node_modules/@solana/spl-type-length-value": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz", + "integrity": "sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA==", + "dependencies": { + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.91.4", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.91.4.tgz", + "integrity": "sha512-zconqecIcBqEF6JiM4xYF865Xc4aas+iWK5qnu7nwKPq9ilRYcn+2GiwpYXqUqqBUe0XCO17w18KO0F8h+QATg==", + "dependencies": { + "@babel/runtime": "^7.23.4", + "@noble/curves": "^1.2.0", + "@noble/hashes": "^1.3.3", + "@solana/buffer-layout": "^4.0.1", + "agentkeepalive": "^4.5.0", + "bigint-buffer": "^1.1.5", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.3", + "fast-stable-stringify": "^1.0.0", + "jayson": "^4.1.0", + "node-fetch": "^2.7.0", + "rpc-websockets": "^7.5.1", + "superstruct": "^0.14.2" + } + }, + "node_modules/@solana/web3.js/node_modules/superstruct": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", + "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "18.19.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", + "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dependencies": { + "@types/node": "*" + } + }, + "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/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "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/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==" + }, + "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/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "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/bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.3.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bintrees": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" + }, + "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/body-parser/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/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "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-layout": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", + "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==", + "engines": { + "node": ">=4.5" + } + }, + "node_modules/bufferutil": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", + "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", + "hasInstallScript": true, + "optional": 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.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/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/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/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/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/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "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/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/crypto-hash": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/crypto-hash/-/crypto-hash-1.3.0.tgz", + "integrity": "sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "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/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/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "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/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": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.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/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/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fast-stable-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", + "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==" + }, + "node_modules/fastestsmallesttextencoderdecoder": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", + "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", + "peer": true + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "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/finalhandler/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/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", + "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", + "dependencies": { + "traverse-chain": "~0.1.0" + } + }, + "node_modules/find-process": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", + "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", + "dependencies": { + "chalk": "^4.0.0", + "commander": "^5.1.0", + "debug": "^4.1.1" + }, + "bin": { + "find-process": "bin/find-process.js" + } + }, + "node_modules/find-process/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "engines": { + "node": ">= 6" + } + }, + "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/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/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/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/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.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "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.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.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/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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-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-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jayson": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz", + "integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "uuid": "^8.3.2", + "ws": "^7.4.5" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "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==" + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "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/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/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/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/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/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/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "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/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "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.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "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.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.5", + "define-properties": "^1.2.1", + "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/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, + "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-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/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prom-client": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.1.tgz", + "integrity": "sha512-GVA2H96QCg2q71rjc3VYvSrVG7OpnJxyryC7dMzvfJfpJJHzQVwF3TJLfHzKORcwJpElWs1TwXLthlJAFJxq2A==", + "dependencies": { + "@opentelemetry/api": "^1.4.0", + "tdigest": "^0.1.1" + }, + "engines": { + "node": "^16 || ^18 || >=20" + } + }, + "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/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/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/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/rpc-websockets": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.9.0.tgz", + "integrity": "sha512-DwKewQz1IUA5wfLvgM8wDpPRcr+nWSxuFxx5CbrI2z/MyyZ4nXLM86TvIA+cI1ZAdqC8JIBR1mZR55dzaLU+Hw==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "eventemitter3": "^4.0.7", + "uuid": "^8.3.2", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + } + }, + "node_modules/rpc-websockets/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "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/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/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "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/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/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "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.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "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/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/spok": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/spok/-/spok-1.5.5.tgz", + "integrity": "sha512-IrJIXY54sCNFASyHPOY+jEirkiJ26JDqsGiI0Dvhwcnkl0PEWi1PSsrkYql0rzDw8LFVTcA7rdUCAJdE2HE+2Q==", + "dependencies": { + "ansicolors": "~0.3.2", + "find-process": "^1.4.7" + } + }, + "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/strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==" + }, + "node_modules/superstruct": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.15.5.tgz", + "integrity": "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==" + }, + "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/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/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "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==" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "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/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/traverse-chain": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", + "integrity": "sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg==" + }, + "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/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/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/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/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, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "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": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "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/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/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-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "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/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/zstddec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz", + "integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==" + } + } +} diff --git a/user-metrics/package.json b/user-metrics/package.json new file mode 100644 index 0000000..f4b280b --- /dev/null +++ b/user-metrics/package.json @@ -0,0 +1,20 @@ +{ + "name": "dex-metrics", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "node --no-warnings=ExperimentalWarning src/main.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.18.2", + "prom-client": "^15.1.0", + "@drift-labs/sdk": "2.78.0-beta.0", + "@solana/web3.js": "^1.89.1", + "bigint-buffer": "^1.1.5", + "dotenv": "^16.4.4" + } +} diff --git a/user-metrics/src/main.js b/user-metrics/src/main.js new file mode 100644 index 0000000..ca755a0 --- /dev/null +++ b/user-metrics/src/main.js @@ -0,0 +1,94 @@ +require('dotenv').config() +const web3 = require("@solana/web3.js"); +const drift = require("@drift-labs/sdk"); +const express = require('express'); +const { createMetrics } = require('./metrics'); + + +const LAMPORTS_PER_SOL = 1000000000; + +const USDC_INT = 1000000; + +const USDC_MARKET = 0; +const SOL_MARKET = 1; + +const SOL_MINT_ADDRESS = 'So11111111111111111111111111111111111111112'; +const USDC_MINT_ADDRESS = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; + +const USDC_MINT_PUBLIC_KEY = new web3.PublicKey(USDC_MINT_ADDRESS); +const keyPairFile = process.env.PRIVATE_KEY || process.env.PRIVATE_KEY_FILE; +const wallet = new drift.Wallet(drift.loadKeypair(keyPairFile)); +const connection = new web3.Connection(process.env.RPC_ENDPOINT); + +const [registry, metrics] = createMetrics(); + +const app = express(); + +const driftClient = new drift.DriftClient({ + connection, + wallet, + env: 'mainnet-beta', + activeSubAccountId: 0, + subAccountIds: [0], +}); + +const log = (msg) => { + console.log(`[${new Date().toISOString()}] ${msg}`) +}; + +const trimWalletAddress = (walletAddress) => { + return `${walletAddress.slice(0,4)}...${walletAddress.slice(walletAddress.length-4, walletAddress.length)}`; +} + + +const quoteNumber = (val) => { + return drift.convertToNumber(val, drift.QUOTE_PRECISION); +} + +const baseNumber = (val) => { + return drift.convertToNumber(val, drift.BASE_PRECISION); +} + +const getWalletBalance = async (connection, publicKey) => { + const lamportsBalance = await connection.getBalance(publicKey); + return lamportsBalance / LAMPORTS_PER_SOL; +}; + +const getUsdcBalance = async (connection, publicKey) => { + const balance = await connection.getParsedTokenAccountsByOwner( + publicKey, { mint: USDC_MINT_PUBLIC_KEY } + ); + return balance.value[0]?.account.data.parsed.info.tokenAmount.uiAmount; +}; + +const init = async() => { + await driftClient.subscribe(); + log('DriftClient initialized'); + ready = true; +}; + +let ready = false; + +app.get('/metrics', async (req, res) => { + res.setHeader('Content-Type', registry.contentType); + registry.resetMetrics(); + + if(ready){ + let user = driftClient.getUser(); + let label = { wallet: wallet.publicKey.toString(), walletShort: trimWalletAddress(wallet.publicKey.toString()) }; + + metrics.totalCollateral.set(label, quoteNumber(user.getTotalCollateral())); + metrics.unrealizedPNL.set(label, quoteNumber(user.getUnrealizedPNL())); + metrics.solBalance.set(label, await getWalletBalance(connection, wallet.publicKey)); + metrics.usdcBalance.set(label, await getUsdcBalance(connection, wallet.publicKey)); + } + + res.send(await registry.metrics()); + +}); + +app.listen(3000, () => { + log("Server is running on port 3000"); + init(); +}); + diff --git a/user-metrics/src/metrics.js b/user-metrics/src/metrics.js new file mode 100644 index 0000000..7892b1f --- /dev/null +++ b/user-metrics/src/metrics.js @@ -0,0 +1,42 @@ +const client = require('prom-client'); + +const createMetrics = () => { + const registry = new client.Registry(); + + const solBalanceMetric = new client.Gauge({ + name: "sol_balance", + help: "SOL Balance", + labelNames: ['wallet','walletShort'] + }); + const usdcBalanceMetric = new client.Gauge({ + name: "usdc_balance", + help: "USDC Balance", + labelNames: ['wallet','walletShort'] + }); + const totalCollateralMetric = new client.Gauge({ + name: "total_collateral", + help: "Total Collateral", + labelNames: ['wallet','walletShort'] + }); + const unrealizedPNLMetric = new client.Gauge({ + name: "unrealized_pnl", + help: "Unrealized PNL", + labelNames: ['wallet','walletShort'] + }); + + registry.registerMetric(usdcBalanceMetric); + registry.registerMetric(solBalanceMetric); + registry.registerMetric(totalCollateralMetric); + registry.registerMetric(unrealizedPNLMetric); + + return [registry, { + usdcBalance: usdcBalanceMetric, + solBalance: solBalanceMetric, + totalCollateral: totalCollateralMetric, + unrealizedPNL: unrealizedPNLMetric + }]; +}; + +module.exports = { + createMetrics +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..ba26857 --- /dev/null +++ b/variables.tf @@ -0,0 +1,88 @@ +variable "do_token" { + description = "DigitalOcean access token" + type = string + default = "" +} + +variable "linode_token" { + description = "Linode access token" + type = string + default = "" +} + +variable "bot" { + description = "Bot configuration" + type = object({ + wallet_address = string + rpc_endpoint = string + ws_endpoint = string + keeper_private_key = string + jito_private_key = string + docker_image = string + docker_image_wallet_tracker = string + }) +} + +variable "monitoring" { + description = "Monitoring configuration" + default = { + grafana_user = "admin" + grafana_password = "grafana" + prometheus_password = "prompass" + } + type = object({ + grafana_user = string + grafana_password = string + prometheus_password = string + }) +} + +variable "linode_instances" { + description = "List of server configurations for Linode" + default = [ + { + label = "DK-LN-AMS" + group = "keeper" + image = "linode/ubuntu23.10" + region = "nl-ams" + type = "g6-nanode-1" + ntp_server = "ntp.amsterdam.jito.wtf" + jito_block_engine_url = "amsterdam.mainnet.block-engine.jito.wtf" + use_jito = true + }, + { + label = "DK-LN-OSA" + group = "keeper" + image = "linode/ubuntu23.10" + region = "jp-osa" + type = "g6-nanode-1" + ntp_server = "ntp.tokyo.jito.wtf" + jito_block_engine_url = "tokyo.mainnet.block-engine.jito.wtf" + use_jito = true + }, + ] +} + +variable "digitalocean_instances" { + description = "List of server configurations for DigitalOcean" + default = [ + { + label = "DK-DO-FRA" + image = "ubuntu-23-10-x64" + region = "fra1" + type = "s-1vcpu-1gb" + ntp_server = "ntp.frankfurt.jito.wtf" + jito_block_engine_url = "frankfurt.mainnet.block-engine.jito.wtf" + use_jito = true + }, + { + label = "DK-DO-NYC" + image = "ubuntu-23-10-x64" + region = "nyc1" + type = "s-1vcpu-1gb" + ntp_server = "ntp.ny.jito.wtf" + jito_block_engine_url = "ny.mainnet.block-engine.jito.wtf" + use_jito = true + } + ] +} diff --git a/wallet-tracker/.gitignore b/wallet-tracker/.gitignore index 82d30cc..c2658d7 100644 --- a/wallet-tracker/.gitignore +++ b/wallet-tracker/.gitignore @@ -1,2 +1 @@ - node_modules/ diff --git a/wallet-tracker/README.md b/wallet-tracker/README.md new file mode 100644 index 0000000..10a8fd3 --- /dev/null +++ b/wallet-tracker/README.md @@ -0,0 +1,18 @@ +# Wallet-Tracker + +## Endpoints + +Metrics: /metrics/:wallet-address? +If a `wallet-address` is provided in the URL, the app will fetch the metrics states from the given address. + +If only 1 wallet needs to be tracked, it is also possible to set the `WALLET_ADDRESS` environment variable and just call the `/metrics` path. + +## Metrics + +Jupiter: +- SOL Price + +Solana: +- SOL Balance +- USDC Balance +- SOL Balance in USDC \ No newline at end of file diff --git a/wallet-tracker/src/main.js b/wallet-tracker/src/main.js index fbacb26..d32b0a8 100644 --- a/wallet-tracker/src/main.js +++ b/wallet-tracker/src/main.js @@ -3,24 +3,35 @@ const { createMetrics } = require('./metrics'); const { loadWalletBalance, loadUSDCBalance, loadSolanaMarketData, extractWalletBalance, extractUSDCBalance, extractSOLPrice } = require('./solana'); const WALLET_ADDRESS = process.env.WALLET_ADDRESS; -const [registry, usdcBalanceMetric, solBalanceMetric, solUsdcBalanceMetric] = createMetrics(); +const [registry, usdcBalanceMetric, solBalanceMetric, solUsdcBalanceMetric, solPriceMetric] = createMetrics(); const app = express(); -app.get('/metrics', async (req, res) => { +const trimWalletAddress = (walletAddress) => { + return `${walletAddress.slice(0,4)}...${walletAddress.slice(walletAddress.length-4, walletAddress.length)}`; +} + +app.get('/metrics/:addr?', async (req, res) => { + const walletAddress = req.params.addr || WALLET_ADDRESS; + console.log(`Gathering metrics for ${walletAddress}`); res.setHeader('Content-Type', registry.contentType); + + registry.resetMetrics(); let [solBalance, usdcBalance, marketData] = await Promise.all([ - loadWalletBalance(WALLET_ADDRESS), - loadUSDCBalance(WALLET_ADDRESS), + loadWalletBalance(walletAddress), + loadUSDCBalance(walletAddress), loadSolanaMarketData()]); - solBalanceMetric.set({ wallet: WALLET_ADDRESS}, extractWalletBalance(solBalance)); - usdcBalanceMetric.set({ wallet: WALLET_ADDRESS}, extractUSDCBalance(usdcBalance)); - solUsdcBalanceMetric.set({ wallet: WALLET_ADDRESS}, extractWalletBalance(solBalance) * extractSOLPrice(marketData)); - + let label = { wallet: walletAddress, walletShort: trimWalletAddress(walletAddress) }; + + solBalanceMetric.set(label, extractWalletBalance(solBalance)); + usdcBalanceMetric.set(label, extractUSDCBalance(usdcBalance)); + solUsdcBalanceMetric.set(label, extractWalletBalance(solBalance) * extractSOLPrice(marketData)); + solPriceMetric.set(extractSOLPrice(marketData)); + res.send(await registry.metrics()); }); app.listen(3000, () => { console.log("Server is running on port 3000"); -}); +}); \ No newline at end of file diff --git a/wallet-tracker/src/metrics.js b/wallet-tracker/src/metrics.js index 385551c..316714a 100644 --- a/wallet-tracker/src/metrics.js +++ b/wallet-tracker/src/metrics.js @@ -6,26 +6,32 @@ const createMetrics = () => { const solBalanceMetric = new client.Gauge({ name: "sol_balance", help: "SOL Balance", - labelNames: ['wallet'] + labelNames: ['wallet','walletShort'] }); const usdcBalanceMetric = new client.Gauge({ name: "usdc_balance", help: "USDC Balance", - labelNames: ['wallet'] + labelNames: ['wallet','walletShort'] }); const solUsdcBalanceMetric = new client.Gauge({ name: "sol_usdc_balance", help: "SOL Balance in USDC", - labelNames: ['wallet'] + labelNames: ['wallet','walletShort'] + }); + + const solPriceMetric = new client.Gauge({ + name: "sol_price", + help: "SOL Price in USDC" }); registry.registerMetric(usdcBalanceMetric); registry.registerMetric(solBalanceMetric); registry.registerMetric(solUsdcBalanceMetric); + registry.registerMetric(solPriceMetric); - return [registry, usdcBalanceMetric, solBalanceMetric, solUsdcBalanceMetric]; + return [registry, usdcBalanceMetric, solBalanceMetric, solUsdcBalanceMetric, solPriceMetric]; }; module.exports = { createMetrics -} \ No newline at end of file +}