From 5fd8d8fcd1e41c9ca4ea5c9cd854e3da6398bd49 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Sun, 1 Jun 2025 16:18:04 -0700 Subject: [PATCH] Adding llm-bch-dex.md for AI consuption --- llm-bch-dex.md | 26701 ++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 24565 ---------------------------------------- swarm.key | 3 - 3 files changed, 26701 insertions(+), 24568 deletions(-) create mode 100644 llm-bch-dex.md delete mode 100644 package-lock.json delete mode 100644 swarm.key diff --git a/llm-bch-dex.md b/llm-bch-dex.md new file mode 100644 index 0000000..da0e4e2 --- /dev/null +++ b/llm-bch-dex.md @@ -0,0 +1,26701 @@ +Project Path: bch-dex + +Source Tree: + +``` +bch-dex +├── PEDIGREE.md +├── index.js +├── logs +│ └── README.md +├── src +│ ├── adapters +│ │ ├── wallet.adapter.js +│ │ ├── contact.js +│ │ ├── index.js +│ │ ├── logapi.js +│ │ ├── nodemailer.js +│ │ ├── wallet.js +│ │ ├── localdb +│ │ │ ├── index.js +│ │ │ ├── models +│ │ │ │ ├── users.js +│ │ │ │ ├── offer.js +│ │ │ │ ├── order.js +│ │ │ │ └── entry.js +│ │ │ └── order-pagination.js +│ │ ├── p2wdb-adapter.js +│ │ ├── wlogger.js +│ │ ├── json-files.js +│ │ ├── nostr.js +│ │ ├── admin.js +│ │ ├── passport.js +│ │ ├── webhook.js +│ │ ├── fullstack-jwt.js +│ │ ├── bch.js +│ │ └── ipfs +│ │ ├── index.js +│ │ ├── ipfs-coord.js +│ │ └── ipfs.js +│ ├── controllers +│ │ ├── index.js +│ │ ├── rest-api +│ │ │ ├── index.js +│ │ │ ├── offer +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ ├── contact +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ ├── usage +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ ├── logs +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ ├── order +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ ├── middleware +│ │ │ │ ├── error.js +│ │ │ │ └── validators.js +│ │ │ ├── auth +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ ├── users +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ ├── entry +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ ├── p2wdb +│ │ │ │ ├── index.js +│ │ │ │ └── controller.js +│ │ │ └── ipfs +│ │ │ ├── index.js +│ │ │ └── controller.js +│ │ ├── json-rpc +│ │ │ ├── index.js +│ │ │ ├── rate-limit.js +│ │ │ ├── auth +│ │ │ │ └── index.js +│ │ │ ├── users +│ │ │ │ └── index.js +│ │ │ ├── validators.js +│ │ │ └── about +│ │ │ └── index.js +│ │ └── timer-controllers.js +│ ├── use-cases +│ │ ├── index.js +│ │ ├── offer +│ │ │ ├── index.js +│ │ │ └── retry-queue.js +│ │ ├── usage-use-cases.js +│ │ ├── order.js +│ │ ├── user.js +│ │ └── entry.js +│ └── entities +│ ├── offer.js +│ ├── order.js +│ ├── user.js +│ └── entry.js +├── test +│ ├── unit +│ │ ├── adapters +│ │ │ ├── nostr.adapter.unit.js +│ │ │ ├── webhook.adapter.unit.js +│ │ │ ├── ipfs.adapter.unit.js +│ │ │ ├── ipfs-index.adapter.unit.js +│ │ │ ├── order-pagination.unit.js +│ │ │ ├── users.adapter.unit.js +│ │ │ ├── passport.adapter.unit.js +│ │ │ ├── wlogger.adapter.unit.js +│ │ │ ├── logapi.adapter.unit.js +│ │ │ ├── contact.adapter.unit.js +│ │ │ ├── bch.adapter.unit.js +│ │ │ ├── nodemailer.adapter.unit.js +│ │ │ ├── wallet.unit.js +│ │ │ ├── p2wdb.adapter.unit.js +│ │ │ ├── json-files.adapter.unit.js +│ │ │ ├── wallet.adapter.unit.js +│ │ │ ├── adapters-index-unit.js +│ │ │ ├── fullstack-jwt.adapter.unit.js +│ │ │ └── ipfs-coord.adapter.unit.js +│ │ ├── README.md +│ │ ├── misc +│ │ │ ├── server-unit.js +│ │ │ ├── config-unit.js +│ │ │ └── passport.unit.js +│ │ ├── controllers +│ │ │ ├── rest-api +│ │ │ │ ├── offer +│ │ │ │ │ ├── offer.rest.router.unit.js +│ │ │ │ │ └── offer.rest.controller.unit.js +│ │ │ │ ├── contact +│ │ │ │ │ ├── contact.rest.controller.unit.js +│ │ │ │ │ └── contact.rest.router.unit.js +│ │ │ │ ├── usage +│ │ │ │ │ ├── usage.rest.controller.unit.js +│ │ │ │ │ └── usage.rest.router.unit.js +│ │ │ │ ├── logs +│ │ │ │ │ ├── logs.rest.router.unit.js +│ │ │ │ │ └── logs.rest.controller.unit.js +│ │ │ │ ├── order +│ │ │ │ │ ├── order.rest.controller.unit.js +│ │ │ │ │ └── order.rest.router.unit.js +│ │ │ │ ├── middleware +│ │ │ │ │ ├── error-unit.js +│ │ │ │ │ └── validators-unit.js +│ │ │ │ ├── auth +│ │ │ │ │ ├── auth.rest.controller.unit.js +│ │ │ │ │ └── auth.rest.router.unit.js +│ │ │ │ ├── users +│ │ │ │ │ ├── users.rest.router.unit.js +│ │ │ │ │ └── users.rest.controller.unit.js +│ │ │ │ ├── rest.controller.unit.js +│ │ │ │ ├── entry +│ │ │ │ │ ├── entry.rest.router.unit.js +│ │ │ │ │ └── entry.rest.controller.unit.js +│ │ │ │ ├── README.md +│ │ │ │ └── ipfs +│ │ │ │ ├── ipfs.rest.controller.unit.js +│ │ │ │ └── ipfs.rest.router.unit.js +│ │ │ ├── controllers.unit.js +│ │ │ ├── json-rpc +│ │ │ │ ├── auth.json-rpc.controller.unit.js +│ │ │ │ ├── a14-rate-limits.js +│ │ │ │ ├── a12-validators.unit.js +│ │ │ │ ├── a10-rpc.unit.js +│ │ │ │ ├── users.json-rpc-controller.unit.js +│ │ │ │ └── about.json-rpc.controller.unit.js +│ │ │ └── timer-controllers.unit.js +│ │ ├── use-cases +│ │ │ ├── offer.use-case.unit.js +│ │ │ ├── users.use-case.unit.js +│ │ │ ├── order.use-case.unit.js +│ │ │ ├── usage.use-case.unit.js +│ │ │ ├── entry.use-case.unit.js +│ │ │ └── index.use-case.unit.js +│ │ ├── entities +│ │ │ ├── order.entity.unit.js +│ │ │ ├── entry.entity.unit.js +│ │ │ ├── user.entity.unit.js +│ │ │ └── offer.entity.unit.js +│ │ └── mocks +│ │ ├── ipfs-mock.js +│ │ ├── adapters +│ │ │ ├── index.js +│ │ │ ├── fake-log +│ │ │ └── wallet.js +│ │ ├── ctx-mock.js +│ │ ├── log-api-mock.js +│ │ ├── helia-mock.js +│ │ ├── use-cases +│ │ │ ├── index.js +│ │ │ └── offer-mock-data.js +│ │ ├── bchjs-mock.js +│ │ ├── nostr-mock.js +│ │ ├── app-mock.js +│ │ └── ipfs-coord-mock.js +│ ├── e2e +│ │ ├── automated +│ │ │ ├── a10-offer.rest-e2e.js +│ │ │ ├── a01-auth.rest-e2e.js +│ │ │ ├── a08-validators.rest-e2e.js +│ │ │ ├── a10-usage.rest-e2e.js +│ │ │ ├── README.md +│ │ │ ├── a09-admin.rest-e2e.js +│ │ │ ├── a06-logapi.rest-e2e.js +│ │ │ ├── a04-contact.rest-e2e.js +│ │ │ └── a02-users.rest-e2e.js +│ │ └── manual +│ │ ├── 02-take-offer.js +│ │ └── 01-create-order.js +│ ├── integration +│ │ ├── adapters +│ │ │ ├── bch-adapter-integration.js +│ │ │ ├── p2wdb-adapter-integration.js +│ │ │ └── wallet-adapter-integration.js +│ │ └── use-cases +│ │ └── offer-use-case-integration.js +│ └── utils +│ └── test-utils.js +├── bin +│ └── server.js +├── README.md +├── shell-scripts +│ ├── ipfs-service-provider-generic.sh +│ ├── ipfs-service-provider-relay.sh +│ └── local-external-ipfs-node.sh +├── production +│ ├── rpi-docker +│ │ ├── cleanup-images.sh +│ │ ├── bch-dex-ui +│ │ │ └── Dockerfile +│ │ ├── bch-dex +│ │ │ ├── start-production.sh +│ │ │ └── Dockerfile +│ │ ├── docker-compose.yml +│ │ └── p2wdb +│ │ ├── start-production.sh +│ │ ├── dummyapp.js +│ │ └── Dockerfile +│ ├── scripts +│ │ ├── fullstack-sweep-wallet.js +│ │ ├── bulk-sweep-wallet.js +│ │ ├── sweep-wallet.js +│ │ ├── sweep-nfts.js +│ │ ├── create-wallet.js +│ │ ├── create-order.js +│ │ └── list-addrs.js +│ └── docker +│ ├── cleanup-images.sh +│ ├── bch-dex-ui +│ │ └── Dockerfile +│ ├── bch-dex +│ │ ├── start-production.sh +│ │ ├── dummy-app.js +│ │ └── Dockerfile +│ └── docker-compose.yml +├── util +│ ├── orders +│ │ ├── deleteOrders.js +│ │ └── getOrders.js +│ ├── users +│ │ ├── delete-all-test-users.js +│ │ ├── production +│ │ │ ├── createUser.js +│ │ │ └── getUsers.js +│ │ ├── createUsers.js +│ │ └── dev +│ │ ├── createUser.js +│ │ └── getUsers.js +│ ├── README.md +│ ├── wipe-test-db.js +│ ├── wallet +│ │ ├── sweep-funds2.js +│ │ └── sweep-funds.js +│ ├── offers +│ │ ├── getOffers.js +│ │ └── deleteOffers.js +│ └── wipe-db.md +├── CONTRIBUTING.md +├── LICENSE.md +├── install-mongo.sh +├── dev-docs +│ ├── README.md +│ ├── diagrams +│ │ ├── rest-api-subcomponents.dia +│ │ ├── software-interaction.dia +│ │ ├── swap-workflow.png +│ │ ├── swap-workflow.dia +│ │ ├── rest-api-subcomponents.png +│ │ └── software-interaction.png +│ └── specification.md +├── examples +│ └── README.md +├── apidoc.json +├── config +│ ├── index.js +│ ├── logs +│ │ └── index.html +│ ├── passport.js +│ └── env +│ ├── common.js +│ ├── production.js +│ ├── development.js +│ └── test.js +├── package.json +└── tools + └── burn-and-write.js + +``` + +`/home/trout/work/psf/code/bch-dex/PEDIGREE.md`: + +```md +# Pedigree + +This repository was forked from [koa-api-boilerplate](https://github.com/christroutner/koa-api-boilerplate). Code changes from that upstream repository is frequently pulled in and merged to this repository. + +``` + +`/home/trout/work/psf/code/bch-dex/index.js`: + +```js +import Server from './bin/server.js' +const server = new Server() + +process.on('unhandledRejection', (reason, promise) => { + console.log(`Handling ${reason.code} error. stack: `, reason) +}) + +server.startServer() + +``` + +`/home/trout/work/psf/code/bch-dex/logs/README.md`: + +```md +This directory will hold the Winston daily logs. Any files saved to this directory will be ignored by Git. + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/wallet.adapter.js`: + +```js +/* + Wallet adapter. This library instantiates minimal-slp-wallet based on different + configuration settings. That single instance of minimal-slp-wallet is then + easily passed around the rest of this application. +*/ + +// Global npm libraries +import BchWallet from 'minimal-slp-wallet' + +// Local libraries +import config from '../../config/index.js' +import JsonFiles from './json-files.js' + +class Wallet { + constructor (localConfig = {}) { + // Encapsulate dependencies + this.config = config + this.BchWallet = BchWallet + this.jsonFiles = new JsonFiles() + + // Bind 'this' object to all subfunctions + this.instanceWalletWithoutInitialization = this.instanceWalletWithoutInitialization.bind(this) + this._instanceWallet = this._instanceWallet.bind(this) + this.openWallet = this.openWallet.bind(this) + this.instanceWallet = this.instanceWallet.bind(this) + this.incrementNextAddress = this.incrementNextAddress.bind(this) + this.getKeyPair = this.getKeyPair.bind(this) + this.optimize = this.optimize.bind(this) + this.getBalance = this.getBalance.bind(this) + } + + // This is used for initializing the wallet, without waiting to update the wallet + // UTXOs from the blockchain. + // This is useful when the wallet is simply needed to make calls to the blockchain, + // and there is no need to hydrate it with UTXO data. + async instanceWalletWithoutInitialization (walletData = {}, advancedConfig = {}) { + try { + // Use the apiToken from the config settings, if one is not passed-in at + // run-time. + if (!advancedConfig.apiToken) { + advancedConfig.apiToken = this.config.apiToken + } + + // If an authentication password is passed in the config, add it. + if (this.config.authPass) { + advancedConfig.authPass = this.config.authPass + } + + // Detect and configure different blockchain infrastructure settings. + if (this.config.walletInterface === 'web2') { + advancedConfig.interface = 'rest-api' + advancedConfig.restURL = this.config.apiServer + } else { + // By default use the web3 Cash Stack (https://cashstack.info) + advancedConfig.interface = 'consumer-api' + advancedConfig.restURL = this.config.apiServer + } + + // console.log('advancedConfig setting when creating wallet: ', advancedConfig) + + // Instantiate minimal-slp-wallet. + if (walletData.mnemonic) { + // Instance the wallet using the mnemonic passed in to this function. + console.log('Mnemonic provided to wallet library from calling function.') + this.bchWallet = await this._instanceWallet(walletData.mnemonic, advancedConfig) + } else if (this.config.mnemonic) { + // Otherwise use the mnemonic in the config setting or passed as an environment variable. + console.log('Mnemonic retrieved from config file or environment variable.') + this.bchWallet = await this._instanceWallet(this.config.mnemonic, advancedConfig) + } else { + // If no mnemonic is provided, then generate a new mnemonic to create the wallet. + console.log('New mnemonic generated.') + this.bchWallet = await this._instanceWallet(undefined, advancedConfig) + } + + // Wait for wallet to initialize. + await this.bchWallet.walletInfoPromise + console.log('BCH wallet initialized.') + console.log(`Wallet address: ${this.bchWallet.walletInfo.cashAddress}`) + console.log(`Wallet mnemonic: ${this.bchWallet.walletInfo.mnemonic}`) + + return this.bchWallet + } catch (err) { + console.error('Error in instanceWalletWithoutInitialization()') + throw err + } + } + + // This function is used for easier mocking of unit tests. + async _instanceWallet (mnemonic, config) { + const wallet = new this.BchWallet(mnemonic, config) + await wallet.walletInfoPromise + + return wallet + } + + // Open the wallet file, or create one if the file doesn't exist. + // Does not instance the wallet. The output of this function is expected to + // be passed to instanceWallet(). + async openWallet (advancedConfig = {}) { + try { + let walletData + + // Try to open the wallet.json file. + try { + walletData = await this.jsonFiles.readJSON(this.config.walletFile) + walletData = walletData.wallet + } catch (err) { + // Create a new wallet file if one does not already exist. + console.log('Wallet file not found. Creating new wallet.json file.') + + // Create a new wallet. + // No-Update flag creates wallet without making any network calls. + const walletInstance = await this.instanceWalletWithoutInitialization({}, advancedConfig) + + walletData = walletInstance.walletInfo + + // Add the nextAddress property + walletData.nextAddress = 1 + + // Write the wallet data to the JSON file. + await this.jsonFiles.writeJSON({ wallet: walletData }, this.config.walletFile) + } + + // console.log('walletData: ', walletData) + return walletData + } catch (err) { + console.error('Error in openWallet()') + throw err + } + } + + // Create an instance of minimal-slp-wallet. Same as + // instanceWalletWithoutInitialization(), but waits for the wallet to initialize + // its UTXOs (wallet balance and tokens). + async instanceWallet (walletData = {}, advancedConfig = {}) { + try { + // Instance the wallet without initialization. + await this.instanceWalletWithoutInitialization(walletData, advancedConfig) + + // Initialize the wallet + await this.bchWallet.initialize() + + return this.bchWallet + } catch (err) { + console.error('Error in wallet.js/instanceWallet()') + throw err + } + } + + // Increments the 'nextAddress' property in the wallet file. This property + // indicates the HD index that should be used to generate a key pair for + // storing funds for Offers. + // This function opens the wallet file, increments the nextAddress property, + // then saves the change to the wallet file. + async incrementNextAddress () { + try { + const walletData = await this.openWallet() + + await this.instanceWalletWithoutInitialization(walletData) + + walletData.nextAddress++ + // console.log('walletData finish: ', walletData) + + await this.jsonFiles.writeJSON({ wallet: walletData }, this.config.walletFile) + + // Update the working instance of the wallet. + this.bchWallet.walletInfo.nextAddress++ + // console.log('this.bchWallet.walletInfo: ', this.bchWallet.walletInfo) + + return walletData.nextAddress + } catch (err) { + console.error('Error in incrementNextAddress()') + throw err + } + } + + // This method returns an object that contains a private key WIF, public address, + // and the index of the HD wallet that the key pair was generated from. + // TODO: Allow input integer. If input is used, use that as the index. If no + // input is provided, then call incrementNextAddress(). + async getKeyPair (hdIndex = 0) { + try { + if (!hdIndex) { + // Increment the HD index and generate a new key pair. + hdIndex = await this.incrementNextAddress() + } + + const mnemonic = this.bchWallet.walletInfo.mnemonic + + // root seed buffer + const rootSeed = await this.bchWallet.bchjs.Mnemonic.toSeed(mnemonic) + const masterHDNode = this.bchWallet.bchjs.HDNode.fromSeed(rootSeed) + + // HDNode of BIP44 account + // const account = this.bchWallet.bchjs.HDNode.derivePath(masterHDNode, "m/44'/245'/0'") + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + const cashAddress = this.bchWallet.bchjs.HDNode.toCashAddress(childNode) + console.log('Generating a new key pair for cashAddress: ', cashAddress) + + const wif = this.bchWallet.bchjs.HDNode.toWIF(childNode) + + const outObj = { + cashAddress, + wif, + hdIndex + } + return outObj + } catch (err) { + console.error('Error in getKeyPair()') + throw err + } + } + + // Optimize the wallet by consolidating the UTXOs. + async optimize () { + const UTXO_THREASHOLD = 7 + // Do a dry-run first to see if there are enough UTXOs worth consolidating. + const dryRunOut = await this.bchWallet.optimize(true) + if (dryRunOut.bchUtxoCnt > UTXO_THREASHOLD) { + // Consolidate BCH UTXOs if the count is above the threashold. + const txids = await this.bchWallet.optimize() + console.log(`Wallet optimized with these return values: ${JSON.stringify(txids, null, 2)}`) + } + return true + } + + // Get the balance of the wallet in sats and PSF tokens. + // This function is called by the GET /entry/balance controller. + async getBalance () { + const balance = await this.bchWallet.getBalance() + // console.log('balance: ', balance) + const tokens = await this.bchWallet.listTokens() + // console.log('tokens: ', tokens) + // Find the array entry for the PSF token + const psfTokens = tokens.find(x => x.tokenId === '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0') + // console.log('psfTokens: ', psfTokens) + let psfBalance = 0 + if (psfTokens) { + psfBalance = psfTokens.qty + } + const outObj = { + satBalance: balance, + psfBalance, + success: true + } + return outObj + } +} + +export default Wallet + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/contact.js`: + +```js +/* + Business logic for the /contact endpoint. +*/ + +/* eslint-disable no-useless-escape */ +import config from '../../config/index.js' +import NodeMailer from '../adapters/nodemailer.js' +import wlogger from '../adapters/wlogger.js' + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +const nodemailer = new NodeMailer() + +let _this + +class ContactLib { + constructor () { + _this = this + _this.config = config + _this.nodemailer = nodemailer + } + + async sendEmail (emailObj) { + try { + // Validate input + if (!emailObj.email || typeof emailObj.email !== 'string') { + throw new Error("Property 'email' must be a string!") + } + + if (!emailObj.formMessage || typeof emailObj.formMessage !== 'string') { + throw new Error("Property 'formMessage' must be a string!") + } + + // If an email list exists, the email will be sended to that list + // otherwhise will be sended by default to the variable "_this.config.emailUser" + let _to = [_this.config.emailUser] + + // Email list is optional + if (emailObj.emailList) { + if ( + !Array.isArray(emailObj.emailList) || + !emailObj.emailList.length > 0 + ) { + throw new Error("Property 'emailList' must be a array of emails!") + } else { + _to = emailObj.emailList + } + } + + console.log(`Trying send message to : ${_to}`) + + emailObj.subject = 'Someone wants contact with you.' + emailObj.to = _to + + const result = await _this.nodemailer.sendEmail(emailObj) + return result + } catch (err) { + wlogger.error('Error in lib/contact.js/sendEmail()') + throw err + } + } +} +export default ContactLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/index.js`: + +```js +/* + This is a top-level library that encapsulates all the additional Adapters. + The concept of Adapters comes from Clean Architecture: + https://troutsblog.com/blog/clean-architecture +*/ + +// Public NPM libraries +import BCHJS from '@psf/bch-js' + +// Load individual adapter libraries. +import IPFSAdapter from './ipfs/index.js' +import LocalDB from './localdb/index.js' +import LogsAPI from './logapi.js' +import Passport from './passport.js' +import Nodemailer from './nodemailer.js' +// const { wlogger } = require('./wlogger') +import JSONFiles from './json-files.js' +import FullStackJWT from './fullstack-jwt.js' +import config from '../../config/index.js' +// import Wallet from './wallet.adapter.js' + +import BCHAdapter from './bch.js' +import WalletAdapter from './wallet.js' +import P2wdbAdapter from './p2wdb-adapter.js' +import Webhook from './webhook.js' +import NostrAdapter from './nostr.js' + +class Adapters { + constructor (localConfig = {}) { + // Encapsulate dependencies + this.ipfs = new IPFSAdapter() + this.localdb = new LocalDB() + this.logapi = new LogsAPI() + this.passport = new Passport() + this.nodemailer = new Nodemailer() + this.jsonFiles = new JSONFiles() + this.bchjs = new BCHJS() + localConfig.bchjs = this.bchjs + this.bch = new BCHAdapter() + this.config = config + this.wallet = new WalletAdapter() + localConfig.bchWallet = this.wallet.bchWallet + this.p2wdb = new P2wdbAdapter(localConfig) + this.webhook = new Webhook() + this.nostr = new NostrAdapter(this.config) + + // this.wallet = new Wallet(localConfig) + + // Get a valid JWT API key and instance bch-js. + this.fullStackJwt = new FullStackJWT(config) + } + + async start () { + try { + // let apiToken + if (this.config.getJwtAtStartup) { + // Get a JWT token and instantiate bch-js with it. Then pass that instance + // to all the rest of the apps controllers and adapters. + // apiToken = await this.fullStackJwt.getJWT() + // Instantiate bch-js with the JWT token, and overwrite the placeholder for bch-js. + this.bchjs = await this.fullStackJwt.instanceBchjs() + } + + // Create a default instance of minimal-slp-wallet without initializing it + // (without retrieving the wallets UTXOs). This instance will be overwritten + // if the operator has configured BCH payments. + console.log('\nCreating default startup wallet. This wallet may be overwritten.') + // await this.wallet.instanceWalletWithoutInitialization({}, { apiToken }) + this.bchjs = this.wallet.bchWallet.bchjs + + // Start the IPFS node. + // Do not start these adapters if this is an e2e test. + // if (this.config.env !== 'test') { + // await this.ipfs.start() + // } + + // Open the wallet file + const walletData = await this.wallet.openWallet() + await this.nostr.start(walletData.privateKey) + + // console.log('walletData: ', walletData) + + if (this.config.env !== 'test') { + // Instance the wallet. + await this.wallet.instanceWallet(walletData, this.bchjs) + + // Wait until a webhook is established with the P2WDB + // await this.webhook.waitUntilSuccess(this.config.webhookTarget) + + // Overwrite instances of wallet used by P2WDB lib. + this.p2wdb.bchWallet = this.wallet.bchWallet + this.p2wdb.bchjs = this.wallet.bchWallet.bchjs + + if (this.config.useIpfs) { + await this.ipfs.start() + } + } else { + // These lines are here to ensure code coverage hits 100%. + console.log('Not starting IPFS node since this is an e2e test.') + } + + console.log('Async Adapters have been started.') + + return true + } catch (err) { + console.error('Error in adapters/index.js/start()') + throw err + } + } +} + +export default Adapters + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/logapi.js`: + +```js +import lineReader from 'line-reader' +import fs from 'fs' + +import config from '../../config/index.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' + +let _this +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +class LogsApi { + constructor () { + _this = this + _this.fs = fs + _this.lineReader = lineReader + _this.config = config + } + + async getLogs (password) { + try { + // console.log('entering getLogs()') + _this.password = password + // console.log(`password: ${password}`) + + // Password matches the password set in the config file. + if (password === _this.config.logPass) { + // Generate the full path and file name for the current log file. + const fullPath = _this.generateFileName() + // console.log(`fullPath: ${JSON.stringify(fullPath, null, 2)}`) + + // Throw an error if the file does not exist. + if (!_this.fs.existsSync(fullPath)) { + return { + success: false, + data: 'file does not exist' + } + } else { + // Read in the data from the log file. + const data = await _this.readLines(fullPath) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + // Filter the logs before passing them to the front end. + const filteredData = _this.filterLogs(data) + + return { + success: true, + data: filteredData + } + } + + // Password does not match password in config file. + } else { + return { + success: false + } + } + } catch (err) { + console.error('Error in lib/logapi.js/getLogs()') + throw err + } + } + + // Sorts the log data by their timestamp. Returns the LIMIT or less elements. + filterLogs (data, LIMIT = 100) { + try { + if (!Array.isArray(data)) { + throw new Error('Data must be array') + } + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + // const LIMIT = 100 // Max number of entries to return. + + // Sort the elements by date. + data.sort(function (a, b) { + let dateA = new Date(a.timestamp) + dateA = dateA.getTime() + + let dateB = new Date(b.timestamp) + dateB = dateB.getTime() + + return dateB - dateA + }) + + // Limit the number of elements. + if (data.length > LIMIT) { + return data.slice(0, LIMIT) + } + + // else + return data + } catch (err) { + console.error('Error in lib/logapi.js/filterLogs()') + throw err + } + } + + generateFileName () { + try { + const now = new Date() + let thisDate = now.getDate() + thisDate = ('0' + thisDate).slice(-2) + + let thisMonth = now.getMonth() + 1 + thisMonth = ('0' + thisMonth).slice(-2) + // console.log(`thisMonth: ${thisMonth}`) + + const thisYear = now.getFullYear() + + const filename = `koa-${ + _this.config.env + }-${thisYear}-${thisMonth}-${thisDate}.log` + // console.log(`filename: ${filename}`) + const logDir = `${__dirname.toString()}/../../logs/` + const fullPath = `${logDir}${filename}` + // console.log(`fullPath: ${fullPath}`) + + return fullPath + } catch (err) { + console.error('Error in lib/logapi.js/generateFileName()') + throw err + } + } + + // Promise based read-file + /* readFile (path, opts = 'utf8') { + return new Promise((resolve, reject) => { + _this.fs.readFile(path, opts, (err, data) => { + if (err) reject(err) + else resolve(data) + }) + }) + } */ + + // Returns an array with each element containing a line of the file. + readLines (filename) { + return new Promise((resolve, reject) => { + try { + if (!filename || typeof filename !== 'string') { + throw new Error('filename must be a string') + } + + console.log('readLines() filename: ', filename) + + // Throw an error if the file does not exist. + if (!_this.fs.existsSync(filename)) { + throw new Error('file does not exist') + } + + const data = [] + + // let i = 0 + + _this.lineReader.eachLine(filename, function (line, last) { + try { + data.push(JSON.parse(line)) + + // Uncomment to display the raw data in each line of the winston log file. + // console.log(`line ${i}: ${line}`) + // i++ + + if (last) return resolve(data) + } catch (err) { + // console.log('err: ', err) + if (last) return resolve(data) + } + }) + } catch (err) { + console.log('Error in lib/logapi.js/readLines()') + return reject(err) + } + }) + } +} + +export default LogsApi + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/nodemailer.js`: + +```js +/* + A library for controlling the sending of email. +*/ + +'use strict' +import nodemailer from 'nodemailer' + +import config from '../../config/index.js' +import wlogger from './wlogger.js' + +let _this + +class NodeMailer { + constructor () { + this.nodemailer = nodemailer + this.config = config + + _this = this + _this.transporter = _this.createTransporter() + } + + // Define an email server 'transport' for nodemailer + createTransporter () { + const transporter = _this.nodemailer.createTransport({ + host: _this.config.emailServer, + port: 587, + secure: false, // true for 465, false for other ports + auth: { + user: _this.config.emailUser, // generated ethereal user + pass: _this.config.emailPassword // generated ethereal password + } + }) + return transporter + } + + // Handles the sending of data via email. + async sendEmail (data) { + try { + // Validate input + if (!data.email || typeof data.email !== 'string') { + throw new Error("Property 'email' must be a string!") + } + + if (!data.to || !Array.isArray(data.to)) { + throw new Error("Property 'to' must be a array!") + } + + await _this.validateEmailArray(data.to) + + if (!data.formMessage || typeof data.formMessage !== 'string') { + throw new Error("Property 'formMessage' must be a string!") + } + + if (!data.subject || typeof data.subject !== 'string') { + throw new Error("Property 'subject' must be a string!") + } + + // Use the provided html or use a default html generated from the input data + + const html = data.htmlData || _this.getHtmlFromObject(data) + const sendObj = { + // from: `${data.email}`, // sender address + from: data.email, + to: data.to, // list of receivers + // subject: `Pearson ${subject}`, // Subject line + subject: data.subject, + // html: 'This is a test email' // html body + html + } + + // send mail with defined transport object + const info = await _this.transporter.sendMail(sendObj) + console.log('Message sent: %s', info.messageId) + + return info + } catch (err) { + wlogger.error('Error in lib/nodemailer.js/sendEmail()') + throw err + } + } + + async validateEmailArray (emailList) { + try { + if (!emailList || !Array.isArray(emailList)) { + throw new Error("Property 'emailList' must be a array!") + } + // Email list can't be empty + if (!emailList.length > 0) { + throw new Error("Property 'emailList' cant be empty!") + } + + return true + } catch (err) { + wlogger.error('Error in lib/nodemailer.js/validateEmailArray()') + throw err + } + } + + // get the email html from object + getHtmlFromObject (objectData) { + try { + if (!objectData || typeof objectData !== 'object') { + throw new Error("Property 'objectData' must be a object!") + } + if (!objectData.subject) { + throw new Error("Property 'subject' must be a string!") + } + if (!objectData.formMessage) { + throw new Error("Property 'formMessage' must be a string!") + } + + const obj = {} + Object.assign(obj, objectData) + + // neccesary data + const msg = obj.formMessage.replace(/(\r\n|\n|\r)/g, '
') + const now = new Date() + const subject = obj.subject + + // Delete unneccesary data if it exist + delete obj.to + delete obj.subject + delete obj.from + delete obj.emailList + delete obj.formMessage + + const bodyJson = obj + bodyJson.message = msg + + // Html body + let htmlBody = '' + + // maps the object and converts it into html format + Object.keys(bodyJson).forEach(function (key) { + htmlBody += `${key}: ${bodyJson[key]}
` + }) + + const defaultHtmlData = `

${subject}:

+

+ time: ${now.toLocaleString()}
+ ${htmlBody} +

` + + return defaultHtmlData + } catch (error) { + wlogger.error('Error in lib/nodemailer.js/getHtmlFromObject()') + throw error + } + } +} + +export default NodeMailer + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/wallet.js`: + +```js +/* + Adapter library for working with a wallet. + This library is specific to bch-dex. The other wallet adapter library is + inherited from ipfs-service-provider. +*/ + +// Public npm libraries +import BchWallet from 'minimal-slp-wallet' +import BchTokenSweep from 'bch-token-sweep/index.js' +import bitcoinJs from 'bitcoincashjs-lib' +import RetryQueue from '@chris.troutner/retry-queue' + +// Local libraries +import JsonFiles from './json-files.js' +import config from '../../config/index.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +const WALLET_FILE = `${__dirname.toString()}/../../wallet.json` +// const PROOF_OF_BURN_QTY = 0.01 +// const P2WDB_TOKEN_ID = +// '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0' + +const advancedConfig = {} + +class WalletAdapter { + constructor (localConfig = {}) { + // Encapsulate dependencies + this.jsonFiles = new JsonFiles() + this.WALLET_FILE = WALLET_FILE + this.config = config + this.bitcoinJs = bitcoinJs + this.BchWallet = BchWallet + this.bchWallet = {} // Will be replaced when initialized. + // this.advancedConfig = localConfig.advancedConfig + this.retryQueue = new RetryQueue({ + concurrency: 1, + attempts: 5, + retryPeriod: 5000 + }) + + // Bind the 'this' object + this.openWallet = this.openWallet.bind(this) + this.instanceWallet = this.instanceWallet.bind(this) + this.incrementNextAddress = this.incrementNextAddress.bind(this) + this.getKeyPair = this.getKeyPair.bind(this) + this.generateSignature = this.generateSignature.bind(this) + this.generatePartialTx = this.generatePartialTx.bind(this) + this.moveTokens = this.moveTokens.bind(this) + this.moveBch = this.moveBch.bind(this) + this.deseralizeTx = this.deseralizeTx.bind(this) + this.completeTx = this.completeTx.bind(this) + this.reclaimTokens = this.reclaimTokens.bind(this) + this.moveTokensFromCustomWallet = this.moveTokensFromCustomWallet.bind(this) + } + + // Open the wallet file, or create one if the file doesn't exist. + // Does not instance the wallet. The output of this function is expected to + // be passed to instanceWallet(). + async openWallet () { + try { + let walletData + + // Try to open the wallet.json file. + try { + // console.log('this.WALLET_FILE: ', this.WALLET_FILE) + walletData = await this.jsonFiles.readJSON(this.WALLET_FILE) + } catch (err) { + // Create a new wallet file if one does not already exist. + console.log('Wallet file not found. Creating new wallet.json file.') + + // Create a new wallet. + // No-Update flag creates wallet without making any network calls. + const walletInstance = new this.BchWallet(undefined, { noUpdate: true }) + + // Wait for wallet to initialize. + await walletInstance.walletInfoPromise + + walletData = walletInstance.walletInfo + + // Add the nextAddress property + walletData.nextAddress = 1 + + // Write the wallet data to the JSON file. + await this.jsonFiles.writeJSON(walletData, this.WALLET_FILE) + } + + // console.log('walletData: ', walletData) + + return walletData + } catch (err) { + console.error('Error in openWallet()') + throw err + } + } + + // Create an instance of minimal-slp-wallet. Use data in the wallet.json file, + // and pass the bch-js information to the minimal-slp-wallet library. + async instanceWallet (walletData) { + try { + // console.log(`instanceWallet() walletData: ${JSON.stringify(walletData, null, 2)}`) + + // TODO: throw error if wallet data is not passed in. + if (!walletData.mnemonic) { + throw new Error('Wallet data is not formatted correctly. Can not read mnemonic in wallet file!') + } + + // const advancedConfig = {} + console.log(`Using FullStack.cash: ${this.config.useFullStackCash}`) + if (this.config.useFullStackCash) { + advancedConfig.interface = 'rest-api' + advancedConfig.restURL = this.config.apiServer + advancedConfig.apiToken = this.config.apiToken + } else { + advancedConfig.interface = 'consumer-api' + advancedConfig.restURL = this.config.consumerUrl + } + + // Instantiate minimal-slp-wallet. + this.bchWallet = new this.BchWallet(walletData.mnemonic, advancedConfig) + + // Wait for wallet to initialize. + await this.bchWallet.walletInfoPromise + await this.bchWallet.initialize() + console.log(`BCH wallet initialized. Wallet address: ${this.bchWallet.walletInfo.cashAddress}`) + // console.log(`this.bchWallet.walletInfo: ${JSON.stringify(this.bchWallet.walletInfo, null, 2)}`) + + return this.bchWallet + } catch (err) { + console.error('Error in instanceWallet()') + throw err + } + } + + // Increments the 'nextAddress' property in the wallet file. This property + // indicates the HD index that should be used to generate a key pair for + // storing funds for Offers. + // This function opens the wallet file, increments the nextAddress property, + // then saves the change to the wallet file. + async incrementNextAddress () { + try { + const walletData = await this.openWallet() + // console.log('original walletdata: ', walletData) + + walletData.nextAddress++ + + // console.log('walletData finish: ', walletData) + await this.jsonFiles.writeJSON(walletData, this.WALLET_FILE) + + // Update the working instance of the wallet. + this.bchWallet.walletInfo.nextAddress++ + // console.log('this.bchWallet.walletInfo: ', this.bchWallet.walletInfo) + + return walletData.nextAddress + } catch (err) { + console.error('Error in incrementNextAddress()') + throw err + } + } + + // This method returns an object that contains a private key WIF, public address, + // and the index of the HD wallet that the key pair was generated from. + // TODO: Allow input integer. If input is used, use that as the index. If no + // input is provided, then call incrementNextAddress(). + async getKeyPair (hdIndex = 0) { + try { + if (!hdIndex) { + // Increment the HD index and generate a new key pair. + hdIndex = await this.incrementNextAddress() + } + + const mnemonic = this.bchWallet.walletInfo.mnemonic + + // root seed buffer + const rootSeed = await this.bchWallet.bchjs.Mnemonic.toSeed(mnemonic) + + const masterHDNode = this.bchWallet.bchjs.HDNode.fromSeed(rootSeed) + + // HDNode of BIP44 account + // const account = this.bchWallet.bchjs.HDNode.derivePath(masterHDNode, "m/44'/245'/0'") + + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + + const cashAddress = this.bchWallet.bchjs.HDNode.toCashAddress(childNode) + console.log('Generating a new key pair for cashAddress: ', cashAddress) + + const wif = this.bchWallet.bchjs.HDNode.toWIF(childNode) + + const outObj = { + cashAddress, + wif, + hdIndex + } + + return outObj + } catch (err) { + console.error('Error in getKeyPair()') + throw err + } + } + + // Generate a cryptographic signature, required to write to the P2WDB. + async generateSignature (message) { + try { + // TODO: Add input validation for message. + + const privKey = this.bchWallet.walletInfo.privateKey + + // console.log('privKey: ', privKey) + // console.log('flags.data: ', flags.data) + + const signature = this.bchWallet.bchjs.BitcoinCash.signMessageWithPrivKey( + privKey, + message + ) + + return signature + } catch (err) { + console.error('Error in generateSignature()') + throw err + } + } + + // Generate a partial transcation to *take* a 'sell' offer. + async generatePartialTx (offerInfo, utxoInfo) { + try { + console.log(`offerInfo: ${JSON.stringify(offerInfo, null, 2)}`) + + const bchjs = this.bchWallet.bchjs + + // instance of transaction builder + const transactionBuilder = new bchjs.TransactionBuilder() + + // Get a payment UTXO. + // TODO: Create a segregated UTXO. + // const bchUtxos = this.bchWallet.utxos.utxoStore.bchUtxos + // const paymentUtxo = await bchjs.Utxo.findBiggestUtxo(bchUtxos) + // console.log('paymentUtxo: ', paymentUtxo) + + // Get token info on the offered UTXO + const txData = await this.bchWallet.getTxData([offerInfo.utxoTxid]) + console.log(`txData: ${JSON.stringify(txData, null, 2)}`) + + // Construct the UTXO being offered for sale. + const offeredUtxo = { + txid: offerInfo.utxoTxid, + vout: offerInfo.utxoVout, + tokenId: offerInfo.tokenId, + decimals: txData[0].tokenDecimals, + tokenQty: offerInfo.numTokens.toString() + } + console.log(`offeredUtxo: ${JSON.stringify(offeredUtxo, null, 2)}`) + + // Build First part of the collaborative Tx a.k.a. Alice + // Generate the OP_RETURN code. + let slpSendObj + if (offerInfo.tokenType === 65) { + // Type 65 NFT + + slpSendObj = bchjs.SLP.NFT1.generateNFTChildSendOpReturn( + [offeredUtxo], + offerInfo.numTokens.toString() + ) + console.log(`slpOutputs: ${slpSendObj.outputs}`) + } else if (offerInfo.tokenType === 1) { + // Type 1 fungible token + + slpSendObj = bchjs.SLP.TokenType1.generateSendOpReturn( + [offeredUtxo], + offerInfo.numTokens.toString() + ) + console.log(`slpOutputs: ${slpSendObj.outputs}`) + } else { + throw new Error(`Unknown token type of ${offerInfo.tokenType}. Can not create Counter Offer.`) + } + const slpData = slpSendObj.script + + // Currently this app only supports a single SLP token UTXO for exact + // token quantities (no token change). e.g. 1 UTXO representing the + // exact number of 'numTokens' + if (slpSendObj.outputs > 1) { + console.log('WARNING: choose one UTXO with all tokens to exchange') + return + } + + // Calculate sats needed to pay the offer. + const satsNeeded = offerInfo.numTokens * parseInt(offerInfo.rateInBaseUnit) + if (isNaN(satsNeeded)) throw new Error('Can not calculate needed sats') + + // Calculate miner fees. + // Get byte count (minimum 2 inputs, 3 outputs) + // const opReturnBufLength = slpData.byteLength + 32 // add padding + // const byteCount = + // bchjs.BitcoinCash.getByteCount({ P2PKH: 2 }, { P2PKH: 4 }) + + // opReturnBufLength + // const totalSatsNeeded = byteCount + satsNeeded + // console.log(`satoshis needed: ${satsNeeded}`) + + // One last check to ensure the app wallet has enough BCH to complete + // the trade. + // if (totalSatsNeeded > paymentUtxo.value) { + // console.log(`Selected payment UTXO is not big enough. Sats needed: ${totalSatsNeeded}, UTXO value: ${paymentUtxo.value}`) + // } + + // add UTXO for sale (STILL CANNOT SPEND - not signed yet) + transactionBuilder.addInput(offerInfo.utxoTxid, offerInfo.utxoVout) + + // add payment UTXO + // transactionBuilder.addInput(paymentUtxo.tx_hash, paymentUtxo.tx_pos) + transactionBuilder.addInput(utxoInfo.txid, utxoInfo.vout) + + // const originalAmount = paymentUtxo.value + const dust = 546 + // const remainder = originalAmount - satsNeeded - dust // exchange fee + token UTXO dust + + // Add the SLP OP_RETURN data as the first output. + transactionBuilder.addOutput(slpData, 0) + + const buyerAddr = this.bchWallet.walletInfo.legacyAddress + // console.log(`buyAddr: ${JSON.stringify(buyAddr, null, 2)}`) + + // Send dust transaction representing tokens being sent. + transactionBuilder.addOutput( + buyerAddr, + dust + ) + + // Get seller address + const sellerAddr = offerInfo.makerAddr + + // Send payment to the offer side + transactionBuilder.addOutput(sellerAddr, satsNeeded) + + // Send the BCH change back to the buyer + // if (remainder > 550) { + // transactionBuilder.addOutput(buyerAddr, remainder) + // } + + // const buyerECPair = bchjs.ECPair.fromWIF(this.bchWallet.walletInfo.privateKey) + const buyerECPair = bchjs.ECPair.fromWIF(utxoInfo.wif) + + // Sign the buyers input UTXO for spending. + transactionBuilder.sign( + 1, + buyerECPair, + null, + transactionBuilder.hashTypes.SIGHASH_ALL, + utxoInfo.sats + ) + + const tx = transactionBuilder.transaction.buildIncomplete() + + const hex = tx.toHex() + // console.log('hex: ', hex) + + return hex + } catch (err) { + console.error('Error in wallet.js/generatePartialTx(): ', err) + throw err + } + + // return true + } + + // Move tokens to an address controlled by the HD wallet, to generate a + // segregated UTXO. + async moveTokens (inObj = {}) { + try { + const { tokenId, qty } = inObj + + const keyPair = await this.getKeyPair() + console.log('keyPair: ', keyPair) + + const receiver = { + address: keyPair.cashAddress, + tokenId, + qty + } + + // Update the UTXO store of the wallet. + await this.bchWallet.initialize() + + // Get the token type of the token being moved. + // Combine Fungible and NFT token UTXOs. + let tokenUtxos = this.bchWallet.utxos.utxoStore.slpUtxos.type1.tokens.concat( + this.bchWallet.utxos.utxoStore.slpUtxos.nft.tokens) + // Get token UTXOs that match the token in the order. + tokenUtxos = tokenUtxos.filter( + x => x.tokenId === tokenId + ) + + const txid = await this.bchWallet.sendTokens(receiver, 3) + + const utxoInfo = { + txid, + vout: 1, + hdIndex: keyPair.hdIndex, + tokenType: tokenUtxos[0].tokenType + } + + return utxoInfo + } catch (err) { + console.error('Error in wallet.js/moveTokens()') + throw err + } + } + + // Move a quanity of BCH to an address controlled by the HD wallet, to + // generate a segregated UTXO. + async moveBch (amountSat) { + try { + const keyPair = await this.getKeyPair() + console.log('keyPair: ', keyPair) + + const receivers = [{ + address: keyPair.cashAddress, + amountSat + }] + console.log(`receivers: ${JSON.stringify(receivers, null, 2)}`) + + // Update the UTXO store of the wallet. + await this.bchWallet.getUtxos() + + const txid = await this.bchWallet.send(receivers) + + const utxoInfo = { + txid, + vout: 0, + hdIndex: keyPair.hdIndex, + wif: keyPair.wif + } + + return utxoInfo + } catch (err) { + console.error('Error in wallet.js/moveBch()') + throw err + } + } + + // Deserialize a hex string representing a partial TX. Returns an object + // representing the transaction. + async deseralizeTx (txHex) { + try { + // Ensure the URL points at FullStack.cash, since the web 3 infra does not + // yet support this call. + const oldUrl = this.bchWallet.bchjs.RawTransactions.restURL + this.bchWallet.bchjs.RawTransactions.restURL = 'https://api.fullstack.cash/v5/' + + // Use a full node to deserialize the transaction. + const txObj2 = await this.bchWallet.bchjs.RawTransactions.decodeRawTransaction(txHex) + // console.log(`txObj2: ${JSON.stringify(txObj2, null, 2)}`) + + // Restore the old URL. + this.bchWallet.bchjs.RawTransactions.restURL = oldUrl + + return txObj2 + } catch (err) { + console.error('Error in wallet.js/deserializeTx()') + throw err + } + } + + // Complete the partially signed transaction by signing the first input, + // then broadcasting the transaction to the network. + async completeTx (hex, hdIndex) { + try { + // Input validation + if (!hex || typeof hex !== 'string') { + throw new Error('hex must be a string!') + } + if (typeof hdIndex !== 'number' || hdIndex < 0) { + throw new Error('hdIndex must be a non-negative number!') + } + // console.log('hex: ', hex) + console.log('completeTx() hdIndex: ', hdIndex) + + const bchjs = this.bchWallet.bchjs + + // instance of transaction builder + // const transactionBuilder = new bchjs.TransactionBuilder() + + // Convert the hex string version of the transaction into a Buffer. + // const paymentBuffer = Buffer.from(hex, 'hex') + + // Generate a Transaction object from the transaction binary data. + // const csTransaction = this.bitcoinJs.Transaction.fromBuffer(paymentBuffer) + const csTransaction = this.bitcoinJs.Transaction.fromHex(hex) + // console.log(`payment tx: ${JSON.stringify(csTransaction, null, 2)}`) + + // Instantiate the Transaction Builder. + const csTransactionBuilder = this.bitcoinJs.TransactionBuilder.fromTransaction( + csTransaction, + 'mainnet' + ) + // const csTransactionBuilder = bchjs.TransactionBuilder.fromTransaction( + // csTransaction, + // 'mainnet' + // ) + + console.log('completeTx() this.walletInfo: ', this.walletInfo) + + // Get the keypair for the address used in the Order + const keyPair = await this.getKeyPair(hdIndex) + console.log(`maker keyPair: ${JSON.stringify(keyPair, null, 2)}`) + const makerECPair = bchjs.ECPair.fromWIF(keyPair.wif) + + // Assumption: segregated UTXO has a value of 546 sats. It might be better + // to explicitly look this data up via the blockchain. + const dust = 546 + + // Coutnersign the Maker's input, representing the tokens for sale. + csTransactionBuilder.sign( + 0, + makerECPair, + null, + this.bitcoinJs.Transaction.SIGHASH_ALL, + // csTransactionBuilder.hashTypes.SIGHASH_ALL, + dust + ) + + // build tx + const csTx = csTransactionBuilder.build() + + // output rawhex + const csTxHex = csTx.toHex() + console.log(`Fully signed Tx hex: ${csTxHex}`) + + // Debug: Display the fully signed TX + const txObj = await this.deseralizeTx(csTxHex) + console.log(`Final tx: ${JSON.stringify(txObj, null, 2)}`) + + // return csTxHex + + // Broadcast transaction to the network + // const txid = await this.bchWallet.ar.sendTx(csTxHex) + const txid = await this.retryQueue.addToQueue(this.bchWallet.broadcast, { hex: csTxHex }) + console.log('completeTx() txid: ', txid) + + return txid + } catch (err) { + console.error('Error in wallet.js/completeTx()') + throw err + } + } + + // Given an Order database object, this function sends the tokens from the + // HD index where they are stored, back to the root address of the wallet. + async reclaimTokens (orderData) { + try { + // Get the key pair from the Order. + const keyPair = await this.getKeyPair(orderData.hdIndex) + console.log('keyPair: ', keyPair) + + // Instantiate the wallet using the private key of the Order. + // const tempWallet = new this.BchWallet(keyPair.wif, advancedConfig) + // await tempWallet.initialize() + + // Send the tokens from the Order to the root address. + // const receiver = { + // address: this.bchWallet.walletInfo.address, + // tokenId: orderData.tokenId, + // qty: orderData.numTokens + // } + // console.log('receiver: ', receiver) + // + // const txid = await tempWallet.sendTokens(receiver) + + // Sweep the tokens to the root address. + const sweeper = new BchTokenSweep( + keyPair.wif, + this.bchWallet.walletInfo.privateKey, + this.bchWallet, + 550, + this.bchWallet.walletInfo.cashAddress + ) + await sweeper.populateObjectFromNetwork() + const hex = await sweeper.sweepTo(this.bchWallet.walletInfo.cashAddress) + const txid = await this.bchWallet.ar.sendTx(hex) + + return txid + } catch (err) { + console.error('Error in wallet.js/reclaimTokens()') + throw err + } + } + + async moveTokensFromCustomWallet (inObj = {}) { + try { + const { tokenId, qty, wallet } = inObj + // Input validation + if (!tokenId || typeof tokenId !== 'string') { + throw new Error('tokenId must be a string!') + } + if (!qty) { + throw new Error('qty must be a number!') + } + if (!wallet) { + throw new Error('wallet is required!') + } + + const keyPair = await this.getKeyPair() + console.log('keyPair: ', keyPair) + + const receiver = { + address: keyPair.cashAddress, + tokenId, + qty + } + console.log('receiver: ', receiver) + + // Update the UTXO store of the wallet. + await wallet.initialize() + + // Get the token type of the token being moved. + // Combine Fungible and NFT token UTXOs. + let tokenUtxos = wallet.utxos.utxoStore.slpUtxos.type1.tokens.concat( + wallet.utxos.utxoStore.slpUtxos.nft.tokens) + // Get token UTXOs that match the token in the order. + tokenUtxos = tokenUtxos.filter( + x => x.tokenId === tokenId + ) + + const txid = await wallet.sendTokens(receiver, 3) + const utxoInfo = { + txid, + vout: 1, + hdIndex: keyPair.hdIndex, + tokenType: tokenUtxos[0].tokenType + } + + return utxoInfo + } catch (err) { + console.error('Error in wallet.js/moveTokensFromCustomWallet()') + throw err + } + } +} + +export default WalletAdapter + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/localdb/index.js`: + +```js +/* + This library encapsulates code concerned with MongoDB and Mongoose models. +*/ + +// Load Mongoose models. +import Users from './models/users.js' +import Entries from './models/entry.js' +import Order from './models/order.js' +import Offer from './models/offer.js' + +class LocalDB { + constructor () { + // Encapsulate dependencies + this.Users = Users + this.Entry = Entries + this.Order = Order + this.Offer = Offer + } +} + +export default LocalDB + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/localdb/models/users.js`: + +```js +// Global npm libraries +import mongoose from 'mongoose' +import bcrypt from 'bcryptjs' +import jwt from 'jsonwebtoken' + +// Local libraries +import config from '../../../../config/index.js' + +const User = new mongoose.Schema({ + type: { type: String, default: 'user' }, + name: { type: String }, + username: { type: String }, + password: { type: String, required: true }, + mnemonic: { type: String, required: true }, + email: { + type: String, + required: true, + unique: true + } +}) + +// Before saving, convert the password to a hash. +User.pre('save', async function preSave (next) { + const user = this + + if (!user.isModified('password')) { + return next() + } + + const salt = await bcrypt.genSalt(10) + const hash = await bcrypt.hash(user.password, salt) + + user.password = hash + + next(null) +}) + +// Validate the password by comparing to the saved hash. +User.methods.validatePassword = async function validatePassword (password) { + const user = this + + const isMatch = await bcrypt.compare(password, user.password) + + return isMatch +} + +// Generate a JWT token. +User.methods.generateToken = function generateToken () { + const user = this + + const token = jwt.sign({ id: user.id }, config.token) + // console.log(`config.token: ${config.token}`) + // console.log(`generated token: ${token}`) + return token +} + +// export default mongoose.model('user', User) +export default mongoose.model('user', User) + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/localdb/models/offer.js`: + +```js +import mongoose from 'mongoose' + +const Offer = new mongoose.Schema({ + + // Token data + tokenId: { type: String }, + utxoTxid: { type: String }, + utxoVout: { type: Number }, + ticker: { type: String, default: '' }, + tokenType: { type: Number }, + + // Trade data + buyOrSell: { type: String }, + numTokens: { type: Number }, + rateInBaseUnit: { type: String }, + minUnitsToExchange: { type: String }, + p2wdbTxid: { type: String }, + p2wdbHash: { type: String }, + offerStatus: { type: String }, + makerAddr: { type: String }, + + // Authentication data + signature: { type: String }, + sigMsg: { type: String }, + + // Utility data + timestamp: { type: Number }, + globalTimestamp: { type: String }, + localTimestamp: { type: String }, + displayCategory: { type: String }, + nsfw: { type: Boolean, default: false }, + flags: { type: Array }, + + // SWaP Protocol Properties + lokadId: { type: String }, + messageType: { type: Number }, + messageClass: { type: Number }, + nostrEventId: { type: String } // Nostr Event Id. + +}) + +export default mongoose.model('offer', Offer) + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/localdb/models/order.js`: + +```js +/* + Order Model. Orders are 'internal' to the system and track the HD wallet index + that contains funds for that Order. This is in contrast to Offers, which + are 'external' to the system and mirrored by every instance of bch-dex. + + See the dev-docs/specification.md for details on each property. +*/ + +import mongoose from 'mongoose' + +const Order = new mongoose.Schema({ + // Token data + tokenId: { type: String, required: true }, + utxoTxid: { type: String, required: true }, + utxoVout: { type: Number, required: true }, + ticker: { type: String, required: true }, + tokenType: { type: Number, required: true }, + + // Trade data + buyOrSell: { type: String, required: true }, + numTokens: { type: Number, required: true }, + rateInBaseUnit: { type: String, required: true }, + minUnitsToExchange: { type: String }, + p2wdbTxid: { type: String }, + p2wdbHash: { type: String }, + makerAddr: { type: String, required: true }, + + // Authentication data + signature: { type: String }, + sigMsg: { type: String }, + offerBchAddr: { type: String }, + offerPubKey: { type: String }, + + // Wallet Data + hdIndex: { type: Number, required: true }, // HD index address holding the UTXO for this offer. + + // SWaP Protocol Properties + lokadId: { type: String }, + messageType: { type: Number }, + messageClass: { type: Number }, + nostrEventId: { type: String, required: true }, // Nostr Event Id. + + // Additional properties found in createOrder + dataType: { type: String, required: true } +}) + +export default mongoose.model('order', Order) + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/localdb/models/entry.js`: + +```js +import mongoose from 'mongoose' + +const Entry = new mongoose.Schema({ + entry: { type: String }, + description: { type: String }, + slpAddress: { type: String }, + signature: { type: String }, + category: { type: String }, + balance: { type: Number }, + merit: { type: Number } +}) + +export default mongoose.model('entry', Entry) + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/localdb/order-pagination.js`: + +```js +/* + Adapter for the Order database model. Provides pagination when retrieving + orders from the datatabase. +*/ + +import Order from './models/order.js' + +// let _this + +class OrderPagination { + constructor (localConfig = {}) { + // Encapsulate dependencies + this.Order = Order + // _this = this + } + + // Read all entries in the P2WDB. + async readAll (page = 0) { + try { + const ENTRIES_PER_PAGE = 20 + + // Pull data from MongoDB. + // Get all entries in the database. + const data = await this.Order.find({}) + // Sort entries so newest entries show first. + .sort('-timestamp') + // Skip to the start of the selected page. + .skip(page * ENTRIES_PER_PAGE) + // Only return 20 results. + .limit(ENTRIES_PER_PAGE) + + // console.log('data: ', data) + + return data + } catch (err) { + console.error('Error in order-pagination.js/readAll()') + throw err + } + } +} + +export default OrderPagination + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/p2wdb-adapter.js`: + +```js +/* + Adapter library for interacting with the P2WDB +*/ + +// Public npm libraries. +import axios from 'axios' + +import P2WDB from 'p2wdb-esm' + +// Local libraries +import config from '../../config/index.js' +const { Write, Read } = P2WDB + +class P2wdbAdapter { + constructor (localConfig = {}) { + // Dependency injection + this.bchWallet = localConfig.bchWallet + if (!this.bchWallet) { + throw new Error('Must pass an instance of minimal-slp-wallet as bchWallet when instantiating p2wdb.js adapter.') + } + + // Encapsulate dependencies + this.axios = axios + this.config = config + this.Write = Write + this.Read = Read + this.bchjs = this.bchWallet.bchjs + + // Allow the localConfig to overwrite the config file values. + this.p2wdbURL = localConfig.p2wdbURL || config.p2wdbUrl + + // Bind the 'this' object to all functions + this.write = this.write.bind(this) + this.checkForSufficientFunds = this.checkForSufficientFunds.bind(this) + } + + // Write some data to the P2WDB + async write (inputObj = {}) { + try { + const { appId = 'test', data = {}, wif } = inputObj + + if (typeof wif !== 'string' || !wif) { + throw new Error('wif input must be a private key starting with the letter L or K') + } + + const p2write = this.instantiateWriteLib(wif) + + const result = await p2write.postEntry(data, appId) + + return result.hash + } catch (err) { + console.error('Error in p2wdb.js/write()') + throw err + } + } + + // Instantiate the Write library with a WIF, handling the various config + // settings. + instantiateWriteLib (wif) { + try { + if (!wif) { + throw new Error('WIF input required when calling instantiateWriteLib()') + } + + // Object used to configure the Write library. + let configObj = {} + + if (this.config.useFullStackCash) { + // Use web 2 infrastructure. + // bch-js and FullStack.cash + + configObj = { + wif, + serverURL: this.p2wdbURL, + restURL: this.bchjs.restURL, + apiToken: this.bchjs.apiToken, + bchWallet: this.bchWallet + } + } else { + // Use web 3 infrastructure. + // ipfs-bch-wallet-consumer and bch-consumer library + + configObj = { + wif, + serverURL: this.p2wdbURL, + interface: 'consumer-api', + restURL: this.config.consumerUrl, + bchWallet: this.bchWallet + } + } + + const write = new this.Write(configObj) + + return write + } catch (err) { + console.error('Error in p2wdb-adapter.js/instantitateWriteLib()') + throw err + } + } + + // Returns a promise that resolves to true or false, to indicate if the + // WIF controls the required funds to write to the P2WDB. + async checkForSufficientFunds (wif) { + try { + if (typeof wif !== 'string' || !wif) { + throw new Error('invalid wif to check for funds') + } + + // Instatiate the Write library + const p2write = this.instantiateWriteLib(wif) + + return await p2write.checkForSufficientFunds() + } catch (err) { + console.error('Error in p2wdb.js/checkForSufficientFunds()') + throw err + } + } +} + +export default P2wdbAdapter + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/wlogger.js`: + +```js +/* + Instantiates and configures the Winston logging library. This utitlity library + can be called by other parts of the application to conveniently tap into the + logging library. +*/ + +'use strict' + +// Global npm libraries +import winston from 'winston' +import 'winston-daily-rotate-file' + +// Local libraries +import config from '../../config/index.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +class Wlogger { + constructor (localConfig = {}) { + this.config = config + + // Configure daily-rotation transport. + this.transport = new winston.transports.DailyRotateFile({ + filename: `${__dirname.toString()}/../../logs/koa-${ + this.config.env + }-%DATE%.log`, + datePattern: 'YYYY-MM-DD', + zippedArchive: false, + maxSize: '1m', // 1 megabyte + maxFiles: '5d', // 5 days + format: winston.format.combine( + winston.format.timestamp(), + winston.format.json() + ) + }) + + this.transport.on('rotate', this.notifyRotation) + + // This controls what goes into the log FILES + this.wlogger = winston.createLogger({ + level: 'verbose', + format: winston.format.json(), + transports: [ + // + // - Write to all logs with level `info` and below to `combined.log` + // - Write all logs error (and below) to `error.log`. + // + // new winston.transports.File({ filename: 'logs/error.log', level: 'error' }), + // new winston.transports.File({ filename: 'logs/combined.log' }) + this.transport + ] + }) + } + + notifyRotation (oldFilename, newFilename) { + // this.wlogger.info('Rotating log files') + console.log('Rotating log files') + } + + outputToConsole () { + this.wlogger.add( + new winston.transports.Console({ + format: winston.format.simple(), + level: 'info' + }) + ) + } +} + +const logger = new Wlogger() + +// Allow the logger to write to the console. +logger.outputToConsole() + +const wlogger = logger.wlogger + +export { wlogger as default, Wlogger } +// export default wlogger + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/json-files.js`: + +```js +/* + A utility file for reading and writing JSON files. +*/ + +import fs from 'fs' + +let _this + +class JsonFiles { + constructor () { + this.fs = fs + + _this = this + } + + // Writes out a JSON file of any object passed to the function. + // This is used for testing. + writeJSON (obj, fileName) { + return new Promise(function (resolve, reject) { + try { + if (!obj) { + throw new Error('obj property is required') + } + if (!fileName || typeof fileName !== 'string') { + throw new Error('fileName property must be a string') + } + const fileStr = JSON.stringify(obj, null, 2) + + _this.fs.writeFile(fileName, fileStr, function (err) { + if (err) { + console.error('Error while trying to write file: ') + throw err + } else { + // console.log(`${fileName} written successfully!`) + return resolve() + } + }) + } catch (err) { + console.error( + 'Error trying to write out object in util.js/_writeJSON().' + ) + return reject(err) + } + }) + } + + readJSON (fileName) { + return new Promise(function (resolve, reject) { + try { + if (!fileName || typeof fileName !== 'string') { + throw new Error('fileName property must be a string') + } + + _this.fs.readFile(fileName, (err, data) => { + if (err) { + if (err.code === 'ENOENT') { + console.log('.json file not found!') + } else { + console.log(`err: ${JSON.stringify(err, null, 2)}`) + } + + // throw err + return reject(err) + } + + const obj = JSON.parse(data) + + return resolve(obj) + }) + } catch (err) { + console.error('Error trying to read JSON file in util.js/_readJSON().') + return reject(err) + } + }) + } +} + +export default JsonFiles + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/nostr.js`: + +```js +/* + Adapter library for working with Nostr. +*/ + +// Global npm libraries +import BchNostr from 'bch-nostr' +import { RelayPool } from 'nostr' +import RetryQueue from '@chris.troutner/retry-queue' +import * as nip19 from 'nostr-tools/nip19' + +class NostrAdapter { + constructor (localConfig = { nostrRelay: '', nostrTopic: '' }) { + this.relayWs = localConfig.nostrRelay // + this.topic = localConfig.nostrTopic + + if (!this.relayWs) { + throw new Error( + '"nostrRelay" must be passed when instantiate NostrAdapter' + ) + } + + if (!this.topic) { + throw new Error( + '"nostrTopic" must be passed when instantiate NostrAdapter' + ) + } + + // Encapsulate dependencies + this.bchNostr = new BchNostr() + this.RelayPool = RelayPool + this.retryQueue = new RetryQueue({ + concurrency: 1, + attempts: 5, + retryPeriod: 1000 + }) + + // Bind the 'this' object + this.start = this.start.bind(this) + this.post = this.post.bind(this) + this.read = this.read.bind(this) + this.eventId2note = this.eventId2note.bind(this) + } + + // Create nostr keys. + // NOTE: WIF must be provided in this function instead the constructor function + // we can provide it after app wallet creation. + async start (WIF) { + try { + if (!WIF || typeof WIF !== 'string') { + throw new Error('WIF must be a string!') + } + + const { privKeyBuf, nostrPubKey } = + this.bchNostr.keys.createNostrPubKeyFromWif({ wif: WIF }) + + this.privKeyBuf = privKeyBuf + this.nostrPubKey = nostrPubKey + + console.log(`Nostr Pub Key : ${nostrPubKey}`) + + return true + } catch (error) { + console.log(`Error in nostr.js/start() ${error.message} `) + throw error + } + } + + // Post a message over the instance-topic. + async post (msg = '') { + try { + if (!msg || typeof msg !== 'string') { + throw new Error('msg must be a string!') + } + + const inObj = { + kind: 867, + privKeyBuf: this.privKeyBuf, + nostrPubKey: this.nostrPubKey, + relayWs: this.relayWs, + msg, + tags: [['t', this.topic]] + } + const eventId = await this.retryQueue.addToQueue(this.bchNostr.post.uploadToNostr, inObj) + return eventId + } catch (error) { + console.log(`Error in nostr.js/post() ${error.message} `) + throw error + } + } + + // Read a message over the instance-topic. + async read (limit = 10) { + try { + if (typeof limit !== 'number' || limit < 1) { + throw new Error('Limit must be greater than 0') + } + + const relays = [this.relayWs] + const pool = this.RelayPool(relays) + + const nostrData = new Promise((resolve, reject) => { + const messages = [] + + pool.on('open', (relay) => { + // relay.subscribe('REQ', { ids: [eventId] }) + relay.subscribe('REQ', { limit, kinds: [867], '#t': [this.topic] }) + }) + + pool.on('eose', (relay) => { + relay.close() + resolve(messages) + }) + + pool.on('event', (relay, subId, ev) => { + // console.log('ev: ', ev) + messages.push({ content: ev.content, eventId: ev.id }) + }) + }) + + const messages = await nostrData + + return messages + } catch (error) { + console.log(`Error in nostr.js/read() ${error.message} `) + throw error + } + } + + // Convert an Event ID into a `noteabc..` syntax that Astral expects. + // This can be used to generate a link to Astral to display the post. + eventId2note (eventId) { + return nip19.noteEncode(eventId) + } +} + +export default NostrAdapter + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/admin.js`: + +```js +/* + A library for working with the system admin user. This is an auto-generated + account with 'admin' privledges, for interacting with private APIs. + + The admin account is regenerated every time the server is started. This improves + security by not having stale passwords for the account. The login information + and JWT token for the admin account is written to a JSON file, for easy + retrieval by other apps running on the server that may need admin privledges + to access private APIs. + + This library is really more of an Adapter to the internal systems default + admin user. It's not really a central Entity, which is why this library lives + in the Adapter directory. +*/ + +// Global npm libraries +import axios from 'axios' +import mongoose from 'mongoose' + +// Local libraries +import User from '../adapters/localdb/models/users.js' +import config from '../../config/index.js' +import JsonFiles from '../adapters/json-files.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +const jsonFiles = new JsonFiles() + +const JSON_FILE = `system-user-${config.env}.json` +const JSON_PATH = `${__dirname.toString()}../../config/${JSON_FILE}` + +const LOCALHOST = `http://localhost:${config.port}` +const context = {} + +let _this +class Admin { + constructor () { + this.axios = axios + this.User = User + this.config = config + this.jsonFiles = jsonFiles + this.context = context + + _this = this + } + + // Create the first user in the system. A 'admin' level system user that is + // used by the Listing Manager and test scripts, in order access private API + // functions. + async createSystemUser () { + try { + const context = { + email: 'system@system.com', + name: 'admin', + password: _this.config.adminPassword || _this._randomString(20), + type: 'admin', + mnemonic: 'spread ivory oval pioneer flash gap merit nerve simple image entire trouble' + } + // Check if the user already exists + let adminUser = await _this.User.findOne({ email: context.email }) + + if (adminUser) { + // Update the password + adminUser.password = context.password + } else { + // Create a new admin user + adminUser = new _this.User(context) + } + // Update context with the new user id and token + context.id = adminUser._id + context.token = await adminUser.generateToken() + + // Save the user + await adminUser.save() + + // Write the user data to the JSON file + await _this.jsonFiles.writeJSON(context, JSON_PATH) + + return context + } catch (error) { + console.log('Error in admin.js/createSystemUser()') + throw error + } + } + + async deleteExistingSystemUser () { + try { + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + + await mongoose.connect(config.database, { + useNewUrlParser: true, + useUnifiedTopology: true + }) + + await _this.User.deleteOne({ email: 'system@system.com' }) + return true + } catch (err) { + console.log('Error in admin.js/deleteExistingSystemUser()') + throw err + } + } + + async loginAdmin () { + // console.log(`loginAdmin() running.`) + let existingUser + + try { + // Read the exising file + existingUser = await _this.jsonFiles.readJSON(JSON_PATH) + // console.log(`existingUser: ${JSON.stringify(existingUser, null, 2)}`) + + // Log in as the user. + const options = { + method: 'POST', + url: `${LOCALHOST}/auth`, + headers: { + Accept: 'application/json' + }, + data: { + email: existingUser.email, + password: existingUser.password + } + } + const result = await _this.axios.request(options) + // console.log(`result1: ${JSON.stringify(result, null, 2)}`) + return result + } catch (err) { + console.error('Error in admin.js/loginAdmin().') + + // console.error(`existingUser: ${JSON.stringify(existingUser, null, 2)}`) + + throw err + } + } + + _randomString (length) { + let text = '' + const possible = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + for (let i = 0; i < length; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)) + } + return text + } +} + +export default Admin + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/passport.js`: + +```js +/* + koa-passport is an authorization library used for different authentication schemes. +*/ + +import passport from 'koa-passport' + +let _this +class Passport { + constructor () { + _this = this + this.passport = passport + } + + async authUser (ctx) { + return new Promise((resolve, reject) => { + try { + if (!ctx) throw new Error('ctx is required') + + _this.passport.authenticate('local', (err, user) => { + try { + if (err) throw err + + resolve(user) + } catch (err) { + return reject(err) + } + })(ctx, null) + } catch (err) { + return reject(err) + } + }) + } +} + +export default Passport + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/webhook.js`: + +```js +/* + The (Clean Architecture) Adapter for manageing a webhook connection to P2WDB. +*/ + +import config from '../../config/index.js' + +import axios from 'axios' + +let _this + +class WebHook { + constructor () { + _this = this + _this.config = config + _this.axios = axios + } + + // REST petition to create a webhook in p2wdb-service + async createWebhook (url) { + try { + if (!url || typeof url !== 'string') { + throw new Error('url must be a string') + } + + const endpoint = _this.config.webhookService + + const obj = { + appId: this.config.p2wdbAppId, + url + } + + const result = await axios.post(endpoint, obj) + + return result.data + } catch (err) { + console.log('Error in adapters/webhook/createWebHook()') + throw err + } + } + + // REST petition to delete a webhook in p2wdb-service + async deleteWebhook (url) { + try { + if (!url || typeof url !== 'string') { + throw new Error('url must be a string') + } + + const endpoint = _this.config.webhookService + + const obj = { + appId: this.config.p2wdbAppId, + url + } + + const result = await axios.delete(endpoint, { data: obj }) + + return result.data + } catch (err) { + console.log('Error in adapters/webhook/deleteWebHook()') + throw err + } + } + + // Returns a promise that will not resolve until a webhook has been successfully + // created with the P2WDB. + // Dev Note: This was created because establishing a webhook between bch-dex + // and the P2WDB at startup is critical. If it's not established, then bch-dex + // can not 'see' new Offers and Counter Offers. + async waitUntilSuccess (url) { + try { + let success = false + + do { + try { + // Delete an old webhook if it exists. + await this.deleteWebhook(this.config.webhookTarget) + } catch (err) { + /* exit quietly */ + // console.log('err deleting webhook: ', err) + } + + try { + await this.createWebhook(this.config.webhookTarget) + console.log('Webhook created') + success = true + } catch (err) { + const now = new Date() + console.log(`${now.toLocaleString()}: Error trying to create webhook with P2WDB. Trying again...`) + await sleep(2000) + } + } while (!success) + + return true + } catch (err) { + console.error('Error in webhook.js/waitUntilSuccess()') + throw err + } + } +} + +function sleep (ms) { + return new Promise(resolve => setTimeout(resolve, ms)) +} + +export default WebHook + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/fullstack-jwt.js`: + +```js +/* + A library of utility functions for working with FullStack.cash JWT tokens. + + Feel free to copy this library into your own app, as well as the unit tests + for this file. +*/ + +import JwtLib from 'jwt-bch-lib' + +import BCHJS from '@psf/bch-js' + +class FullStackJWT { + constructor (localConfig = {}) { + // Input Validation + this.authServer = localConfig.authServer + if (!this.authServer || typeof this.authServer !== 'string') { + throw new Error( + 'Must pass a url for the AUTH server when instantiating FullStackJWT class.' + ) + } + this.apiServer = localConfig.apiServer + if (!this.apiServer || typeof this.apiServer !== 'string') { + throw new Error( + 'Must pass a url for the API server when instantiating FullStackJWT class.' + ) + } + this.login = localConfig.fullstackLogin + if (!this.login || typeof this.login !== 'string') { + throw new Error( + 'Must pass a FullStack.cash login (email) instantiating FullStackJWT class.' + ) + } + this.password = localConfig.fullstackPassword + if (!this.password || typeof this.password !== 'string') { + throw new Error( + 'Must pass a FullStack.cash account password when instantiating FullStackJWT class.' + ) + } + + // Encapsulate dependencies + this.jwtLib = new JwtLib({ + // Overwrite default values with the values in the config file. + server: this.authServer, + login: this.login, + password: this.password + }) + + // State + this.apiToken = '' // Default value. + this.bchjs = {} + } + + // Get's a JWT token from FullStack.cash. + async getJWT () { + try { + // Log into the auth server. + await this.jwtLib.register() + + this.apiToken = this.jwtLib.userData.apiToken + if (!this.apiToken) { + throw new Error('This account does not have a JWT') + } + console.log(`Retrieved JWT token: ${this.apiToken}\n`) + + // Ensure the JWT token is valid to use. + const isValid = await this.jwtLib.validateApiToken() + + // Get a new token with the same API level, if the existing token is not + // valid (probably expired). + if (!isValid.isValid) { + this.apiToken = await this.jwtLib.getApiToken( + this.jwtLib.userData.apiLevel + ) + console.log( + `The JWT token was not valid. Retrieved new JWT token: ${this.apiToken}\n` + ) + } else { + console.log('JWT token is valid.\n') + } + + return this.apiToken + } catch (err) { + console.error( + `Error trying to log into ${this.server} and retrieve JWT token.` + ) + throw err + } + } + + // Create an instance of bchjs with the validated JWT token. Returns this + // instance of bch-js. + instanceBchjs () { + this.bchjs = new BCHJS({ + restURL: this.apiServer, + apiToken: this.apiToken + }) + + return this.bchjs + } +} + +export default FullStackJWT + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/bch.js`: + +```js +/* + This library contains methods for working with the BCHN and BCHA blockchains. +*/ + +// Public npm libraries +import BCHJS from '@psf/bch-js' + +import MsgLib from 'bch-message-lib' +import BchWallet from 'minimal-slp-wallet' + +class Bch { + constructor () { + // Encapsulate dependencies + this.bchjs = new BCHJS() + this.PSF_TOKEN_ID = + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0' + this.wallet = new BchWallet(undefined, { noUpdate: true }) + this.msgLib = new MsgLib({ wallet: this.wallet }) + } + + // Verify that the entry was signed by a specific BCH address. + _verifySignature (verifyObj) { + try { + // Expand the input object. + const { offerBchAddr, signature, sigMsg } = verifyObj + + // Convert to BCH address. + // const scrubbedAddr = this.bchjs.SLP.Address.toCashAddress(slpAddress) + + const isValid = this.bchjs.BitcoinCash.verifyMessage( + offerBchAddr, + signature, + sigMsg + ) + + return isValid + } catch (err) { + console.error('Error in bch.js/_verifySignature()') + throw err + } + } + + // Gets the total psf token balance + // async getPSFTokenBalance (slpAddress) { + // try { + // if (!slpAddress || typeof slpAddress !== 'string') { + // throw new Error('slpAddress must be a string') + // } + // let psfBalance = 0 + // const balances = await this.bchjs.SLP.Utils.balancesForAddress( + // slpAddress + // ) + // + // // Sums all the balances of all tokens + // // that match the psf token ID + // for (let i = 0; i < balances.length; i++) { + // if (balances[i].tokenId === this.PSF_TOKEN_ID) { + // psfBalance += balances[i].balance + // } + // } + // + // return psfBalance + // } catch (err) { + // console.error('Error in bch.js/getPSFTokenBalance()') + // throw err + // } + // } + + async getMerit (slpAddr) { + try { + if (!slpAddr || typeof slpAddr !== 'string') { + throw new Error('slpAddr must be a string') + } + const merit = await this.msgLib.merit.agMerit(slpAddr, this.PSF_TOKEN_ID) + return merit + } catch (error) { + console.error('error in bch.js/getMerit()') + throw error + } + } +} + +export default Bch + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/ipfs/index.js`: + +```js +/* + top-level IPFS library that combines the individual IPFS-based libraries. +*/ + +// Local libraries +import IpfsAdapter from './ipfs.js' + +import IpfsCoordAdapter from './ipfs-coord.js' +import config from '../../../config/index.js' + +class IPFS { + constructor (localConfig = {}) { + // Encapsulate dependencies + this.ipfsAdapter = new IpfsAdapter() + this.IpfsCoordAdapter = IpfsCoordAdapter + this.process = process + this.config = config + + this.ipfsCoordAdapter = {} // placeholder + + // Properties of this class instance. + this.isReady = false + } + + // Provides a global start() function that triggers the start() function in + // the underlying libraries. + async start () { + try { + // Start IPFS + await this.ipfsAdapter.start() + console.log('IPFS is ready.') + + // this.ipfs is a Promise that will resolve into an instance of an IPFS node. + this.ipfs = this.ipfsAdapter.ipfs + + // Start ipfs-coord + this.ipfsCoordAdapter = new this.IpfsCoordAdapter({ + ipfs: this.ipfs, + tcpPort: this.config.ipfsTcpPort, + wsPort: this.config.ipfsWsPort + }) + await this.ipfsCoordAdapter.start() + console.log('ipfs-coord is ready.') + + // Subscribe to the chat pubsub channel + await this.ipfsCoordAdapter.subscribeToChat() + + return true + } catch (err) { + console.error('Error in adapters/ipfs/index.js/start()') + + // If error is due to a lock file issue. Kill the process, so that + // Docker or pm2 has a chance to restart the service. + if (err.message.includes('Lock already being held')) { + this.process.exit(1) + } + + throw err + } + } + + // Get the status of this IPFS node. + // Create an object with different metrics about this IPFS node, then return + // the object. + getStatus () { + try { + const statusObj = { + ipfsId: this.ipfsCoordAdapter.ipfsCoord.thisNode.ipfsId, + multiAddrs: this.ipfsCoordAdapter.ipfsCoord.thisNode.ipfsMultiaddrs, + bchAddr: this.ipfsCoordAdapter.ipfsCoord.thisNode.bchAddr, + slpAddr: this.ipfsCoordAdapter.ipfsCoord.thisNode.slpAddr, + pubKey: this.ipfsCoordAdapter.ipfsCoord.thisNode.pubKey, + peers: this.ipfsCoordAdapter.ipfsCoord.thisNode.peerList.length, + relays: this.ipfsCoordAdapter.ipfsCoord.thisNode.relayData.length + } + + return statusObj + } catch (err) { + console.error('Error in ipfs-coord.js/getStatus()') + throw err + } + } + + // Get details on the other peers this node is connected to. + async getPeers (showAll) { + try { + const peerData = this.ipfsCoordAdapter.ipfsCoord.thisNode.peerData + // console.log(`peerData: ${JSON.stringify(peerData, null, 2)}`) + + let ipfsPeers = + await this.ipfsCoordAdapter.ipfsCoord.adapters.ipfs.getPeers() + // console.log('ipfsPeers: ', ipfsPeers) + + ipfsPeers = this._removeDuplicatePeers(ipfsPeers) + // console.log('filtered ipfsPeers: ', ipfsPeers) + + const peerDataOut = [] + + // Loop through each IPFS peer and hydrate it with data from the peerData. + for (let i = 0; i < ipfsPeers.length; i++) { + const thisPeer = { + peer: ipfsPeers[i] + } + + // if (!showAll) { + // // Delete properties that don't contain good info. + // delete thisPeer.muxer + // delete thisPeer.latency + // delete thisPeer.streams + // } + + // Get the ipfs-coord peer data for this peer. + let thisPeerData = peerData.filter((x) => + x.from.includes(thisPeer.peer) + ) + thisPeerData = thisPeerData[0] + // console.log('thisPeerData: ', thisPeerData) + + // Skip if peerData for this IPFS peer could not be found. + // if (!thisPeerData) continue + + try { + // console.log('thisPeerData: ', thisPeerData) + + // Add data to the IPFS peer data. + thisPeer.name = thisPeerData.data.jsonLd.name + thisPeer.protocol = thisPeerData.data.jsonLd.protocol + thisPeer.version = thisPeerData.data.jsonLd.version + thisPeer.connectionAddr = thisPeerData.data.connectionAddr + + if (showAll) { + // Add all the peer data. + thisPeer.peerData = thisPeerData + } + } catch (err) { + console.warn( + `warning: ${thisPeer.peer}: ${err.message}` + ) + } + + peerDataOut.push(thisPeer) + } + + return peerDataOut + } catch (err) { + console.error('Error in getPeers(): ', err) + throw err + } + } + + // Expects an array of peers and returns an array of peers with duplicates + // removed. + // This function is used by getPeers() + _removeDuplicatePeers (arr) { + // https://stackoverflow.com/questions/2218999/how-to-remove-all-duplicates-from-an-array-of-objects + return arr.filter((v, i, a) => a.findIndex((t) => t === v) === i) + } + + // Get data about the known Circuit Relays. Hydrate with data from peers list. + getRelays () { + try { + const relayData = this.ipfsCoordAdapter.ipfsCoord.thisNode.relayData + const peerData = this.ipfsCoordAdapter.ipfsCoord.thisNode.peerData + // console.log(`relayData: ${JSON.stringify(relayData, null, 2)}`) + // console.log(`peerData: ${JSON.stringify(peerData, null, 2)}`) + + for (let i = 0; i < relayData.length; i++) { + const thisRelay = relayData[i] + + // Find the peer that corresponds to this relay. + const thisPeer = peerData.filter((x) => + x.from.includes(thisRelay.ipfsId) + ) + // console.log('thisPeer: ', thisPeer) + + // If the peer couldn't be found, skip. + if (!thisPeer.length) { + thisRelay.name = '' + thisRelay.description = '' + continue + } + + thisRelay.name = thisPeer[0].data.jsonLd.name + thisRelay.description = thisPeer[0].data.jsonLd.description + } + + const v1Relays = this.config.v1Relays + + return { v2Relays: relayData, v1Relays } + } catch (err) { + console.error('Error in getRelays(): ', err) + throw err + } + } +} + +export default IPFS + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/ipfs/ipfs-coord.js`: + +```js +/* + Clean Architecture Adapter for ipfs-coord. + This library deals with ipfs-coord library so that the apps business logic + doesn't need to have any specific knowledge of the library. +*/ + +// Global npm libraries +// import IpfsCoord from 'ipfs-coord-esm' +import IpfsCoord from 'helia-coord' + +// import BCHJS from '@psf/bch-js'; +import SlpWallet from 'minimal-slp-wallet' +import { publicIpv4 } from 'public-ip' + +// Local libraries +import config from '../../../config/index.js' + +// const JSONRPC = require('../../controllers/json-rpc/') + +let _this + +class IpfsCoordAdapter { + constructor (localConfig = {}) { + // Dependency injection. + this.ipfs = localConfig.ipfs + if (!this.ipfs) { + throw new Error( + 'Instance of IPFS must be passed when instantiating ipfs-coord.' + ) + } + + // Encapsulate dependencies + this.IpfsCoord = IpfsCoord + this.ipfsCoord = {} + // this.bchjs = new BCHJS() + this.wallet = new SlpWallet() + this.config = config + this.publicIp = publicIpv4 + + // Properties of this class instance. + this.isReady = false + + _this = this + } + + async start () { + const circuitRelayInfo = {} + + // Wait for the BCH wallet to create the wallet. + await this.wallet.walletInfoPromise + + // If configured as a Circuit Relay, get the public IP addresses for this node. + if (this.config.isCircuitRelay) { + try { + const ip4 = await this.publicIp() + // const ip6 = await publicIp.v6() + + circuitRelayInfo.ip4 = ip4 + circuitRelayInfo.tcpPort = this.config.ipfsTcpPort + + // Domain used by browser-based secure websocket connections. + circuitRelayInfo.crDomain = this.config.crDomain + } catch (err) { + /* exit quietly */ + } + } + + const nullLog = () => {} + + const ipfsCoordOptions = { + ipfs: this.ipfs, + type: 'node.js', + // type: 'browser', + wallet: this.wallet, + // privateLog: console.log, // Default to console.log + privateLog: nullLog, + isCircuitRelay: this.config.isCircuitRelay, + circuitRelayInfo, + apiInfo: this.config.apiInfo, + announceJsonLd: this.config.announceJsonLd, + debugLevel: this.config.debugLevel, + v1Relays: this.config.v1Relays, + tcpPort: this.config.ipfsTcpPort + } + + // Production env uses external go-ipfs node. + // if (this.config.isProduction) { + // ipfsCoordOptions.nodeType = 'external' + // } + + this.ipfsCoord = new this.IpfsCoord(ipfsCoordOptions) + + // Wait for the ipfs-coord library to signal that it is ready. + await this.ipfsCoord.start() + + // Signal that this adapter is ready. + this.isReady = true + + return this.isReady + } + + // Expects router to be a function, which handles the input data from the + // pubsub channel. It's expected to be capable of routing JSON RPC commands. + attachRPCRouter (router) { + try { + _this.ipfsCoord.privateLog = router + _this.ipfsCoord.adapters.pubsub.privateLog = router + } catch (err) { + console.error('Error in attachRPCRouter()') + throw err + } + } + + // Subscribe to the chat pubsub channel + async subscribeToChat () { + // TODO: Allow user to replace nullog with their own log handler at startup. + const nullLog = () => {} + + await this.ipfsCoord.adapters.pubsub.subscribeToPubsubChannel( + this.config.chatPubSubChan, + nullLog, + this.ipfsCoord.thisNode + ) + } +} + +export default IpfsCoordAdapter + +``` + +`/home/trout/work/psf/code/bch-dex/src/adapters/ipfs/ipfs.js`: + +```js +/* + Clean Architecture Adapter for IPFS. + This library deals with IPFS so that the apps business logic doesn't need + to have any specific knowledge of the js-ipfs library. + + TODO: Add the external IP address to the list of multiaddrs advertised by + this node. See this GitHub Issue for details: + https://github.com/Permissionless-Software-Foundation/ipfs-service-provider/issues/38 +*/ + +// Global npm libraries +import { createHelia } from 'helia' +import fs from 'fs' +import { FsBlockstore } from 'blockstore-fs' +import { FsDatastore } from 'datastore-fs' +import { createLibp2p } from 'libp2p' +import { tcp } from '@libp2p/tcp' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +// import { bootstrap } from '@libp2p/bootstrap' +// import { identifyService } from 'libp2p/identify' +import { identify, identifyPush } from '@libp2p/identify' +import { circuitRelayServer, circuitRelayTransport } from '@libp2p/circuit-relay-v2' +// import { circuitRelayServer } from '@libp2p/circuit-relay-v2' +import { gossipsub } from '@chainsafe/libp2p-gossipsub' +import { webSockets } from '@libp2p/websockets' +import { publicIpv4 } from 'public-ip' +import { multiaddr } from '@multiformats/multiaddr' +import { webRTC, webRTCDirect } from '@libp2p/webrtc' +import { keychain } from '@libp2p/keychain' +import { unixfs } from '@helia/unixfs' +// import { generateKeyPairFromSeed } from '@libp2p/crypto/keys' +// import crypto from 'crypto' +import { ping } from '@libp2p/ping' +import { loadOrCreateSelfKey } from '@libp2p/config' + +// Local libraries +import config from '../../../config/index.js' +import JsonFiles from '../json-files.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) +// console.log('__dirname: ', __dirname) + +const ROOT_DIR = `${__dirname}../../../` +const IPFS_DIR = `${__dirname}../../../.ipfsdata/ipfs` + +class IpfsAdapter { + constructor (localConfig) { + // Encapsulate dependencies + this.config = config + this.fs = fs + this.createLibp2p = createLibp2p + this.publicIp = publicIpv4 + this.multiaddr = multiaddr + this.jsonFiles = new JsonFiles() + this.keychain = keychain + this.createHelia = createHelia + + // Properties of this class instance. + this.isReady = false + + // Bind 'this' object to all subfunctions + this.start = this.start.bind(this) + this.createNode = this.createNode.bind(this) + this.stop = this.stop.bind(this) + this.ensureBlocksDir = this.ensureBlocksDir.bind(this) + // this.getPrivateKey = this.getPrivateKey.bind(this) + this.getSeed = this.getSeed.bind(this) + } + + // Start an IPFS node. + async start () { + try { + // Ensure the directory structure exists that is needed by the IPFS node to store data. + this.ensureBlocksDir() + + // Create an IPFS node + const ipfs = await this.createNode() + // console.log('ipfs: ', ipfs) + + this.id = ipfs.libp2p.peerId.toString() + console.log('IPFS ID: ', this.id) + + // Attempt to guess our ip4 IP address. + const ip4 = await this.publicIp() + let detectedMultiaddr = `/ip4/${ip4}/tcp/${this.config.ipfsTcpPort}/p2p/${this.id}` + detectedMultiaddr = this.multiaddr(detectedMultiaddr) + + // Get the multiaddrs for the node. + const multiaddrs = ipfs.libp2p.getMultiaddrs() + multiaddrs.push(detectedMultiaddr) + console.log('Multiaddrs: ', multiaddrs) + + this.multiaddrs = multiaddrs + + // Signal that this adapter is ready. + this.isReady = true + + this.ipfs = ipfs + + return this.ipfs + } catch (err) { + console.error('Error in ipfs.js/start()') + + // If IPFS crashes because the /blocks directory is full, wipe the directory. + // if (err.message.includes('No space left on device')) { + // this.rmBlocksDir() + // } + + throw err + } + } + + // This function creates an IPFS node using Helia. + // It returns the node as an object. + async createNode () { + try { + // Create block and data stores. + const blockstore = new FsBlockstore(`${IPFS_DIR}/blockstore`) + const datastore = new FsDatastore(`${IPFS_DIR}/datastore`) + + // Get the private key. + // const privateKey = await this.getPrivateKey() + // console.log('privateKey: ', privateKey) + + // Create an identity + const keychainInit = { + selfKey: 'myKey', + pass: await this.getSeed() + } + const privateKey = await loadOrCreateSelfKey(datastore, keychainInit) + + // Configure services + const services = { + identify: identify(), + identifyPush: identifyPush(), + pubsub: gossipsub({ allowPublishToZeroTopicPeers: true }), + ping: ping(), + keychain: keychain(keychainInit) + } + if (this.config.isCircuitRelay) { + console.log('Helia (IPFS) node IS configured as Circuit Relay') + services.relay = circuitRelayServer({ // makes the node function as a relay server + hopTimeout: 30 * 1000, // incoming relay requests must be resolved within this time limit + reservations: { + maxReservations: 15, // how many peers are allowed to reserve relay slots on this server + reservationClearInterval: 300 * 1000, // how often to reclaim stale reservations + applyDefaultLimit: true, // whether to apply default data/duration limits to each relayed connection + defaultDurationLimit: 2 * 60 * 1000, // the default maximum amount of time a relayed connection can be open for + defaultDataLimit: BigInt(2 << 7) // the default maximum number of bytes that can be transferred over a relayed connection + }, + maxInboundHopStreams: 32, // how many inbound HOP streams are allow simultaneously + maxOutboundHopStreams: 64 // how many outbound HOP streams are allow simultaneously + }) + } else { + console.log('Helia (IPFS) node IS NOT configured as Circuit Relay') + } + + const transports = [ + tcp(), + webSockets(), + circuitRelayTransport({ + discoverRelays: 3, + reservationConcurrency: 3 + }), + webRTC(), + webRTCDirect() + ] + + // libp2p is the networking layer that underpins Helia + const libp2p = await this.createLibp2p({ + // peerId, + privateKey, + datastore, + addresses: { + listen: [ + '/ip4/127.0.0.1/tcp/0', + `/ip4/0.0.0.0/tcp/${this.config.ipfsTcpPort}`, + `/ip4/0.0.0.0/tcp/${this.config.ipfsWsPort}/ws`, + '/webrtc', + '/p2p-circuit' + ] + }, + transports, + connectionEncrypters: [ + noise() + ], + streamMuxers: [ + yamux() + ], + services + }) + + // create a Helia node + const helia = await this.createHelia({ + blockstore, + datastore, + libp2p + }) + + // Attach IPFS file system. + const fs = unixfs(helia) + helia.fs = fs + + return helia + } catch (err) { + console.error('Error creating Helia node: ', err) + + throw err + } + } + + async stop () { + await this.ipfs.stop() + + return true + } + + // Ensure that the directories exist to store blocks from the IPFS network. + // This function is called at startup, before the IPFS node is started. + ensureBlocksDir () { + try { + !this.fs.existsSync(`${ROOT_DIR}.ipfsdata`) && this.fs.mkdirSync(`${ROOT_DIR}.ipfsdata`) + + !this.fs.existsSync(`${IPFS_DIR}`) && this.fs.mkdirSync(`${IPFS_DIR}`) + + !this.fs.existsSync(`${IPFS_DIR}/blockstore`) && this.fs.mkdirSync(`${IPFS_DIR}/blockstore`) + + !this.fs.existsSync(`${IPFS_DIR}/datastore`) && this.fs.mkdirSync(`${IPFS_DIR}/datastore`) + + !this.fs.existsSync(`${IPFS_DIR}/datastore/pkcs8`) && this.fs.mkdirSync(`${IPFS_DIR}/datastore/pkcs8`) + + // !fs.existsSync(`${IPFS_DIR}/datastore/peers`) && fs.mkdirSync(`${IPFS_DIR}/datastore/peers`) + + return true + } catch (err) { + console.error('Error in adapters/ipfs.js/ensureBlocksDir(): ', err) + throw err + } + } + + // This function opens the seed used to generate the key for this IPFS peer. + // The seed is stored in a JSON file. If it doesn't exist, a new one is created. + async getSeed () { + try { + let seed + + const filename = `${IPFS_DIR}/seed.json` + + try { + // Try to read the JSON file containing the seed. + seed = await this.jsonFiles.readJSON(filename) + } catch (err) { + const seedNum = Math.floor(Math.random() * 1000000000000000000000) + seed = seedNum.toString() + + // Save the newly generated seed + await this.jsonFiles.writeJSON(seed, filename) + } + + // console.log('getSeed() seed: ', seed) + + return seed + } catch (err) { + console.error('Error in adapters/ipfs/ipfs.js/getSeed()') + throw err + } + } + + // Get the private key from disk, or generate a new one and save it, + // if it doesn't exist. + // async getPrivateKey () { + // try { + // const filename = `${IPFS_DIR}/privkey.json` + + // let privKeyHex + // try { + // // Try to read the JSON file containing the seed. + // privKeyHex = await this.jsonFiles.readJSON(filename) + // // console.log('saved privKeyHex: ', privKeyHex) + // } catch (err) { + // // Generate a new private key and save it to disk. + + // // Generate a new private key and save it to disk. + // const randomBuffer = crypto.randomBytes(32) + // // console.log('randomBuffer: ', randomBuffer) + + // privKeyHex = randomBuffer.toString('hex') + // // console.log('new privKeyHex: ', privKeyHex) + + // // Save the newly generated seed + // await this.jsonFiles.writeJSON(privKeyHex, filename) + // } + + // // Convert the saved hex string to a buffer. + // const privKeyBuf = Buffer.from(privKeyHex, 'hex') + + // // Convert the buffer to a Uint8Array 'seed' + // const seed = new Uint8Array(privKeyBuf.buffer, privKeyBuf.byteOffset, privKeyBuf.byteLength) + // // console.log('seed: ', seed) + + // // Generate a ED25519 key pair. + // const privKey = await generateKeyPairFromSeed('Ed25519', seed) + + // return privKey + // } catch (err) { + // console.error('Error in adapters/ipfs/ipfs.js/getPrivateKey(): ', err) + // throw err + // } + // } +} + +export default IpfsAdapter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/index.js`: + +```js +/* + This is a top-level library that encapsulates all the additional Controllers. + The concept of Controllers comes from Clean Architecture: + https://troutsblog.com/blog/clean-architecture +*/ + +// Public npm libraries. + +// Local libraries +import Adapters from '../adapters/index.js' +import JSONRPC from './json-rpc/index.js' +import UseCases from '../use-cases/index.js' +import RESTControllers from './rest-api/index.js' +import TimerControllers from './timer-controllers.js' +import config from '../../config/index.js' + +class Controllers { + constructor (localConfig = {}) { + // Encapsulate dependencies + this.adapters = new Adapters() + this.useCases = new UseCases({ adapters: this.adapters }) + this.timerControllers = new TimerControllers({ adapters: this.adapters, useCases: this.useCases }) + this.config = config + + // Bind 'this' object to all subfunction + this.initAdapters = this.initAdapters.bind(this) + this.initUseCases = this.initUseCases.bind(this) + this.attachRESTControllers = this.attachRESTControllers.bind(this) + this.attachControllers = this.attachControllers.bind(this) + this.attachRPCControllers = this.attachRPCControllers.bind(this) + } + + // Spin up any adapter libraries that have async startup needs. + async initAdapters () { + await this.adapters.start() + } + + // Run any Use Cases to startup the app. + async initUseCases () { + await this.useCases.start() + } + + // Top-level function for this library. + // Start the various Controllers and attach them to the app. + attachRESTControllers (app) { + const restControllers = new RESTControllers({ + adapters: this.adapters, + useCases: this.useCases + }) + + // Attach the REST API Controllers associated with the boilerplate code to the Koa app. + restControllers.attachRESTControllers(app) + } + + // Attach any other controllers other than REST API controllers. + async attachControllers (app) { + if (this.config.useIpfs) { + // Attach JSON RPC controllers + this.attachRPCControllers() + } + + // Attach and start the timer controllers + this.timerControllers.startTimers() + } + + // Add the JSON RPC router to the ipfs-coord adapter. + attachRPCControllers () { + const jsonRpcController = new JSONRPC({ + adapters: this.adapters, + useCases: this.useCases + }) + + // Attach the input of the JSON RPC router to the output of ipfs-coord. + this.adapters.ipfs.ipfsCoordAdapter.attachRPCRouter( + jsonRpcController.router + ) + } +} + +export default Controllers + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/index.js`: + +```js +/* + This index file for the Clean Architecture Controllers loads dependencies, + creates instances, and attaches the controller to REST API endpoints for + Koa. +*/ + +// Public npm libraries. + +// Local libraries +import AuthRESTController from './auth/index.js' +import UserRouter from './users/index.js' +import ContactRESTController from './contact/index.js' +import LogsRESTController from './logs/index.js' +import IpfsRESTController from './ipfs/index.js' +import config from '../../../config/index.js' +import EntryRouter from './entry/index.js' +import OfferRouter from './offer/index.js' +import OrderRouter from './order/index.js' +import P2WDBRouter from './p2wdb/index.js' +import UsageRESTController from './usage/index.js' + +class RESTControllers { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating REST Controller libraries.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating REST Controller libraries.' + ) + } + + // Bind 'this' object to all subfunctions. + this.attachRESTControllers = this.attachRESTControllers.bind(this) + + // Encapsulate dependencies + this.config = config + } + + attachRESTControllers (app) { + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + if (!this.config.noMongo) { + // Attach the REST API Controllers associated with the /auth route + const authRESTController = new AuthRESTController(dependencies) + authRESTController.attach(app) + + // Attach the REST API Controllers associated with the /user route + const userRouter = new UserRouter(dependencies) + userRouter.attach(app) + } + + // Attach the REST API Controllers associated with the /contact route + const contactRESTController = new ContactRESTController(dependencies) + contactRESTController.attach(app) + + // Attach the REST API Controllers associated with the /logs route + const logsRESTController = new LogsRESTController(dependencies) + logsRESTController.attach(app) + + // Attach the REST API Controllers associated with the /ipfs route + const ipfsRESTController = new IpfsRESTController(dependencies) + ipfsRESTController.attach(app) + + // Attach the REST API Controllers associated with the /entry route + const entryRouter = new EntryRouter(dependencies) + entryRouter.attach(app) + + const offerRouter = new OfferRouter(dependencies) + offerRouter.attach(app) + + const orderRouter = new OrderRouter(dependencies) + orderRouter.attach(app) + + const p2wdbRouter = new P2WDBRouter(dependencies) + p2wdbRouter.attach(app) + + // Attach the REST API Controllers associated with the /usage route + const usageRESTController = new UsageRESTController(dependencies) + usageRESTController.attach(app) + } +} + +export default RESTControllers + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/offer/index.js`: + +```js +/* + REST API library for /offer route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import OfferRESTControllerLib from './controller.js' + +let _this + +class OfferRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /offer REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /offer REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.offerRESTController = new OfferRESTControllerLib(dependencies) + + // Instantiate the router and set the base route. + const baseUrl = '/offer' + this.router = new Router({ prefix: baseUrl }) + + _this = this + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attached REST API controllers.' + ) + } + + // 12/3/24 CT: + // Note: The createOffer() path was used by a P2WDB webhook to generate an + // Offer from and Order. This has been deprecated and Offers are now created + // by a Timer Controller monitoring a Nostr topic. + + // Define the routes and attach the controller. + // this.router.post('/', _this.offerRESTController.createOffer) // Deprecated. + this.router.post('/take', _this.offerRESTController.takeOffer) + this.router.get('/list/all/:page', _this.offerRESTController.listOffers) + this.router.get('/list/nft/:page', _this.offerRESTController.listNftOffers) + this.router.get('/list/fungible/:page', _this.offerRESTController.listFungibleOffers) + + // Attach the Controller routes to the Koa app. + app.use(_this.router.routes()) + app.use(_this.router.allowedMethods()) + } +} + +export default OfferRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/offer/controller.js`: + +```js +/* + REST API Controller library for the /offer route +*/ + +import wlogger from '../../../adapters/wlogger.js' + +class OfferRESTControllerLib { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /offer REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /offer REST Controller.' + ) + } + + // Encapsulate dependencies + this.OfferModel = this.adapters.localdb.Offer + // this.userUseCases = this.useCases.user + + // Bind 'this' object to all subfunctions. + this.createOffer = this.createOffer.bind(this) + this.listOffers = this.listOffers.bind(this) + this.listNftOffers = this.listNftOffers.bind(this) + this.listFungibleOffers = this.listFungibleOffers.bind(this) + this.takeOffer = this.takeOffer.bind(this) + this.handleError = this.handleError.bind(this) + } + + // No api-doc documentation because this wont be a public endpoint + async createOffer (ctx) { + try { + console.log('body: ', ctx.request.body) + + const offerObj = ctx.request.body + + await this.useCases.offer.createOffer(offerObj) + + ctx.body = { + success: true + } + } catch (err) { + // console.log(`err.message: ${err.message}`) + // console.log('err: ', err) + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + // curl -X GET http://localhost:5700/offer/list/all/0 + async listOffers (ctx) { + try { + let page = ctx.params.page + if (!page) page = 0 + + const offers = await this.useCases.offer.listOffers(page) + + ctx.body = offers + } catch (err) { + console.log('Error in listOffers REST API handler: ', err) + this.handleError(ctx, err) + } + } + + // curl -X GET http://localhost:5700/offer/list/nft/0 + async listNftOffers (ctx) { + try { + let page = ctx.params.page + if (!page) page = 0 + + const offers = await this.useCases.offer.listNftOffers(page) + + ctx.body = offers + } catch (err) { + console.log('Error in listNftOffers REST API handler: ', err) + this.handleError(ctx, err) + } + } + + // curl -X GET http://localhost:5700/offer/list/fungible/0 + async listFungibleOffers (ctx) { + try { + let page = ctx.params.page + if (!page) page = 0 + + const offers = await this.useCases.offer.listFungibleOffers(page) + + ctx.body = offers + } catch (err) { + console.log('Error in Fungible REST API handler: ', err) + this.handleError(ctx, err) + } + } + + // Currently only supports 'sell' offers, and will only buy the 'numTokens' + // listed in the offer. + async takeOffer (ctx) { + try { + console.log('REST API controller, body: ', ctx.request.body) + + const nostrEventId = ctx.request.body.nostrEventId + + const { eventId, noteId } = await this.useCases.offer.takeOffer(nostrEventId) + + ctx.body = { eventId, noteId } + } catch (err) { + wlogger.error('Error in takeOffer() REST API handler.') + this.handleError(ctx, err) + } + } + + // DRY error handler + handleError (ctx, err) { + console.log('err', err.message) + // If an HTTP status is specified by the buisiness logic, use that. + if (err.status) { + if (err.message) { + ctx.throw(err.status, err.message) + } else { + ctx.throw(err.status) + } + } else { + // By default use a 422 error if the HTTP status is not specified. + ctx.throw(422, err.message) + } + } +} + +export default OfferRESTControllerLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/contact/index.js`: + +```js +/* + REST API library for /contact route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import ContactRESTControllerLib from './controller.js' + +class ContactRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating Contact REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating Contact REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.contactRESTController = new ContactRESTControllerLib(dependencies) + + // Instantiate the router and set the base route. + const baseUrl = '/contact' + this.router = new Router({ prefix: baseUrl }) + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attaching REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.post('/email', this.contactRESTController.email) + + // Attach the Controller routes to the Koa app. + app.use(this.router.routes()) + app.use(this.router.allowedMethods()) + } +} + +export default ContactRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/contact/controller.js`: + +```js +/* + Controller for the /contact REST API endpoints. +*/ + +/* eslint-disable no-useless-escape */ +import ContactLib from '../../../adapters/contact.js' + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +const contactLib = new ContactLib() + +let _this + +class ContactController { + constructor () { + _this = this + _this.contactLib = contactLib + } + + /** + * @api {post} /contact/email Send Email + * @apiName SendMail + * @apiGroup Contact + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X POST -d '{ "obj": { "email": "email@format.com", "formMessage": "a message" } }' localhost:5001/contact/email + * + * @apiParam {Object} obj object (required) + * @apiParam {String} obj.email Sender Email. + * @apiParam {String} obj.formMessage Message. + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * + * success:true + * + * } + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "status": 422, + * "error": "Unprocessable Entity" + * } + */ + async email (ctx) { + try { + const data = ctx.request.body + const emailObj = data.obj + await _this.contactLib.sendEmail(emailObj) + + ctx.body = { + success: true + } + } catch (err) { + _this.handleError(ctx, err) + } + } + + // DRY error handler + handleError (ctx, err) { + // If an HTTP status is specified by the buisiness logic, use that. + if (err.status) { + if (err.message) { + ctx.throw(err.status, err.message) + } else { + ctx.throw(err.status) + } + } else { + // By default use a 422 error if the HTTP status is not specified. + ctx.throw(422, err.message) + } + } +} +export default ContactController + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/usage/index.js`: + +```js +/* + REST API library for the /usage route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import UsageRESTControllerLib from './controller.js' +import Validators from '../middleware/validators.js' + +// let _this + +class UsageRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating IPFS REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating IPFS REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.usageRESTController = new UsageRESTControllerLib(dependencies) + this.validators = new Validators() + + // Instantiate the router and set the base route. + const baseUrl = '/usage' + this.router = new Router({ prefix: baseUrl }) + + // _this = this + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attaching REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.get('/', this.usageRESTController.getStatus) + this.router.get('/ips', this.usageRESTController.getTopIps) + this.router.get('/endpoints', this.usageRESTController.getTopEndpoints) + + // Attach the Controller routes to the Koa app. + app.use(this.router.routes()) + app.use(this.router.allowedMethods()) + } +} + +// module.exports = BchRouter +export default UsageRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/usage/controller.js`: + +```js +/* + REST API Controller library for the /usage route +*/ + +// Global npm libraries + +// Local libraries +import wlogger from '../../../adapters/wlogger.js' + +class UsageRESTControllerLib { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /usage REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /usage REST Controller.' + ) + } + + // Encapsulate dependencies + + // Bind 'this' object to all subfunctions + this.getStatus = this.getStatus.bind(this) + this.getTopIps = this.getTopIps.bind(this) + this.getTopEndpoints = this.getTopEndpoints.bind(this) + this.handleError = this.handleError.bind(this) + } + + /** + * @api {get} /usage Get status on IPFS infrastructure + * @apiPermission public + * @apiName GetUsageStatus + * @apiGroup REST Usage + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X GET localhost:5020/usage + * + */ + getStatus (ctx) { + try { + // const status = await this.adapters.ipfs.getStatus() + const status = this.useCases.usage.getRestSummary() + + ctx.body = { status } + } catch (err) { + wlogger.error('Error in usage/controller.js/getStatus(): ') + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + /** + * @api {get} /usage/ips Get top IP addresses consuming the REST API + * @apiPermission public + * @apiName GetUsageIPs + * @apiGroup REST Usage + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X GET localhost:5020/usage/ips + * + */ + getTopIps (ctx) { + try { + const ips = this.useCases.usage.getTopIps() + + ctx.body = { ips } + } catch (err) { + wlogger.error('Error in usage/controller.js/getTopIps(): ') + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + /** + * @api {get} /usage/endpoints Get top endpoints consumed from the REST API + * @apiPermission public + * @apiName GetUsageEndpoints + * @apiGroup REST Usage + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X GET localhost:5020/usage/endpoints + * + */ + getTopEndpoints (ctx) { + try { + const endpoints = this.useCases.usage.getTopEndpoints() + + ctx.body = { endpoints } + } catch (err) { + wlogger.error('Error in usage/controller.js/getTopEndpoints(): ') + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + // DRY error handler + handleError (ctx, err) { + // If an HTTP status is specified by the buisiness logic, use that. + if (err.status) { + if (err.message) { + ctx.throw(err.status, err.message) + } else { + ctx.throw(err.status) + } + } else { + // By default use a 422 error if the HTTP status is not specified. + ctx.throw(422, err.message) + } + } +} + +// module.exports = IpfsRESTControllerLib +export default UsageRESTControllerLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/logs/index.js`: + +```js +/* + REST API library for /logs route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import LogsRESTControllerLib from './controller.js' + +class LogsRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating Logs REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating Logs REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + this.logsRESTController = new LogsRESTControllerLib(dependencies) + + // Instantiate the router and set the base route. + const baseUrl = '/logs' + this.router = new Router({ prefix: baseUrl }) + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attaching REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.post('/', this.logsRESTController.getLogs) + + // Attach the Controller routes to the Koa app. + app.use(this.router.routes()) + app.use(this.router.allowedMethods()) + } +} + +export default LogsRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/logs/controller.js`: + +```js +import LogsApiLib from '../../../adapters/logapi.js' +const logsApiLib = new LogsApiLib() +let _this + +class LogsApi { + constructor () { + _this = this + _this.logsApiLib = logsApiLib + } + + /** + * @api {post} /logapi Parse and return the log files. + * @apiPermission public + * @apiName LogApi + * @apiGroup Logs + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X POST -d '{ "password": "secretpasas" }' localhost:5000/logapi + * + * @apiParam {String} password Password (required) + * + * @apiSuccess {Array} users User object + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name User name + * @apiSuccess {String} users.username User username + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "user": { + * "_id": "56bd1da600a526986cf65c80" + * "name": "John Doe" + * "username": "johndoe" + * } + * } + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "status": 422, + * "error": "Unprocessable Entity" + * } + */ + async getLogs (ctx) { + try { + // console.log('entering getLogs()') + + // Get the user-provided password. + const password = ctx.request.body.password + const result = await _this.logsApiLib.getLogs(password) + ctx.body = result + } catch (err) { + if (err && err.message) { + ctx.throw(422, err.message) + } else { + ctx.throw(500, 'Unhandled error') + } + } + } +} + +export default LogsApi + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/order/index.js`: + +```js +/* + REST API library for /order route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import OrderRESTControllerLib from './controller.js' +import Validators from '../middleware/validators.js' + +let _this + +class OrderRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /order REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /order REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.validators = new Validators() + this.orderRESTController = new OrderRESTControllerLib(dependencies) + + // Instantiate the router and set the base route. + const baseUrl = '/order' + this.router = new Router({ prefix: baseUrl }) + + this.createOrder = this.createOrder.bind(this) + _this = this + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attached REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.post('/', this.createOrder) + this.router.get('/list/all/:page', _this.orderRESTController.listOrders) + this.router.post('/delete', _this.orderRESTController.deleteOrder) + + // Attach the Controller routes to the Koa app. + app.use(_this.router.routes()) + app.use(_this.router.allowedMethods()) + } + + async createOrder (ctx, next) { + await _this.validators.ensureUser(ctx, next) + await _this.orderRESTController.createOrder(ctx, next) + } +} + +export default OrderRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/order/controller.js`: + +```js +/* + REST API Controller library for the /order route +*/ + +// const { wlogger } = require('../../../adapters/wlogger') + +let _this + +class OrderRESTControllerLib { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /order REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /order REST Controller.' + ) + } + + // Encapsulate dependencies + this.OrderModel = this.adapters.localdb.Order + // this.userUseCases = this.useCases.user + + _this = this + } + + // No api-doc documentation because this wont be a public endpoint + async createOrder (ctx) { + try { + // console.log('body: ', ctx.request.body) + + const orderObj = ctx.request.body.order + const user = ctx.state.user + orderObj.userId = user._id + console.log('orderObj: ', orderObj) + + const { eventId, noteId } = await _this.useCases.order.createOrder(orderObj) + + ctx.body = { eventId, noteId } + } catch (err) { + // console.log(`err.message: ${err.message}`) + // console.log('err: ', err) + // ctx.throw(422, err.message) + _this.handleError(ctx, err) + } + } + + // curl -X GET http://localhost:5700/order/list/all/0 + async listOrders (ctx) { + try { + let page = ctx.params.page + if (!page) page = 0 + + const offers = await _this.useCases.order.listOrders(page) + + ctx.body = offers + } catch (err) { + console.log('Error in listOrders REST API handler: ', err) + _this.handleError(ctx, err) + } + } + + // Delete an existing order by returning the token to the root address of + // the DEX wallet. + async deleteOrder (ctx) { + try { + // console.log('body: ', ctx.request.body) + + const nostrEventId = ctx.request.body.nostrEventId + // console.log('p2wdbHash: ', p2wdbHash) + + const txid = await _this.useCases.order.deleteOrder(nostrEventId) + + ctx.body = { txid } + } catch (err) { + // console.log(`err.message: ${err.message}`) + // console.log('err: ', err) + // ctx.throw(422, err.message) + _this.handleError(ctx, err) + } + } + + // DRY error handler + handleError (ctx, err) { + console.log('err', err) + + // If an HTTP status is specified by the buisiness logic, use that. + if (err.status) { + if (err.message) { + ctx.throw(err.status, err.message) + } else { + ctx.throw(err.status) + } + } else { + // By default use a 422 error if the HTTP status is not specified. + ctx.throw(422, err.message) + } + } +} + +export default OrderRESTControllerLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/middleware/error.js`: + +```js +export default function errorMiddleware () { + return async (ctx, next) => { + try { + await next() + } catch (err) { + ctx.status = err.status || 500 + ctx.body = err.message + ctx.app.emit('error', err, ctx) + } + } +}; + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/middleware/validators.js`: + +```js +/* + REST API validator middleware. + + These are a series of functions that ensure the user making a REST API + matches a user in the database (or not). In can do fine-grain user control + such as telling the difference between an admin, a normal user, and an + anonymous user. + + This middleware is used to gatekeep access to different REST API resources. + + CT 9/17/22: + This library was lightly refactored to make it work with the new unit tests. + This not and the commented code below can be deleted once it is verified that + this refactor did not result in any breaking changes. +*/ + +import User from '../../../adapters/localdb/models/users.js' + +import config from '../../../../config/index.js' +import jwt from 'jsonwebtoken' +import wlogger from '../../../adapters/wlogger.js' + +let _this + +class Validators { + constructor () { + this.User = User + this.jwt = jwt + this.config = config + + _this = this + } + + async ensureUser (ctx, next) { + try { + const token = _this.getToken(ctx) + + if (!token) { + throw new Error('Token could not be retrieved from header') + } + + let decoded = null + try { + // console.log(`token: ${JSON.stringify(token, null, 2)}`) + // console.log(`config: ${JSON.stringify(config, null, 2)}`) + decoded = _this.jwt.verify(token, config.token) + } catch (err) { + throw new Error('Could not verify JWT') + } + + ctx.state.user = await _this.User.findById(decoded.id, '-password') + + if (!ctx.state.user) { + // console.log('Err: Could not find user.') + throw new Error('Could not find user') + } + + // return next() + return true + } catch (error) { + // console.log('Ensure user error: ', error) + // console.log('ctx: ', ctx) + ctx.status = 401 + ctx.throw(401, error.message) + } + } + + // This funciton is almost identical to ensureUser, except at the end, it verifies + // that the 'type' associated with the user equals 'admin'. + async ensureAdmin (ctx, next) { + try { + // console.log(`getToken: ${typeof (getToken)}`) + const token = _this.getToken(ctx) + + if (!token) { + // console.log(`Err: Token not provided.`) + // ctx.throw(401) + throw new Error('Token could not be retrieved from header') + } + + let decoded = null + try { + // console.log(`token: ${JSON.stringify(token, null, 2)}`) + // console.log(`config: ${JSON.stringify(config, null, 2)}`) + decoded = _this.jwt.verify(token, config.token) + } catch (err) { + // console.log(`Err: Token could not be decoded: ${err}`) + // ctx.throw(401) + throw new Error('Could not verify JWT') + } + + ctx.state.user = await _this.User.findById(decoded.id, '-password') + if (!ctx.state.user) { + // console.log(`Err: Could not find user.`) + // ctx.throw(401) + throw new Error('Could not find user') + } + + if (ctx.state.user.type !== 'admin') { + // ctx.throw(401, 'not admin') + throw new Error('User is not an admin') + } + + // return next() + return true + } catch (error) { + ctx.status = 401 + ctx.throw(401, error.message) + } + } + + // This middleware ensures that the :id used in the API endpoint matches the + // the ID used in the JWT, or failing that, the ID used in the JWT matches + // an Admin user. This prevents situations like users updating other users + // profiles or non-admins deleting users. + async ensureTargetUserOrAdmin (ctx, next) { + try { + // console.log(`getToken: ${typeof (getToken)}`) + const token = _this.getToken(ctx) + + if (!token) { + // console.log(`Err: Token not provided.`) + // ctx.throw(401) + throw new Error('Token could not be retrieved from header') + } + + // The user ID targeted in this API call. + const targetId = ctx.params.id + // console.log(`targetId: ${JSON.stringify(targetId, null, 2)}`) + + let decoded = null + try { + // console.log(`token: ${JSON.stringify(token, null, 2)}`) + // console.log(`config: ${JSON.stringify(config, null, 2)}`) + decoded = _this.jwt.verify(token, config.token) + } catch (err) { + console.log(`Err: Token could not be decoded: ${err}`) + // ctx.throw(401) + throw new Error('Could not verify JWT') + } + + ctx.state.user = await _this.User.findById(decoded.id, '-password') + if (!ctx.state.user) { + // console.log(`Err: Could not find user.`) + // ctx.throw(401) + throw new Error('Could not find user') + } + // console.log('ctx.state.user: ', ctx.state.user) + + // console.log(`ctx.state.user: ${JSON.stringify(ctx.state.user, null, 2)}`) + // Ensure the calling user and the target user are the same. + + if (ctx.state.user._id.toString() !== targetId.toString()) { + wlogger.verbose( + `Calling user and target user do not match! Calling user: ${ctx.state.user._id}, Target user: ${targetId}` + ) + + // If they don't match, then the calling user better be an admin. + if (ctx.state.user.type !== 'admin') { + // ctx.throw(401, 'not admin') + throw new Error('User is not an admin') + } else { + wlogger.verbose("It's ok. The user is an admin.") + } + } + + // return next() + return true + } catch (error) { + // console.log('Error in ensureTargetUserOrAdmin(): ', error) + ctx.status = 401 + ctx.throw(401, error.message) + } + } + + getToken (ctx) { + const header = ctx.request.header.authorization + if (!header) { + return null + } + const parts = header.split(' ') + if (parts.length !== 2) { + return null + } + const scheme = parts[0] + const token = parts[1] + if (/^Bearer$/i.test(scheme)) { + return token + } + return null + } +} + +export default Validators + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/auth/index.js`: + +```js +/* + REST API library for auth route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import AuthRESTController from './controller.js' + +class AuthRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating PostEntry REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating PostEntry REST Controller.' + ) + } + + // Encapsulate dependencies. + this.authRESTController = new AuthRESTController(localConfig) + + // Instantiate the router and set the base route. + const baseUrl = '/auth' + this.router = new Router({ prefix: baseUrl }) + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attached REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.post('/', this.authRESTController.authUser) + + // Attach the Controller routes to the Koa app. + app.use(this.router.routes()) + app.use(this.router.allowedMethods()) + } +} + +export default AuthRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/auth/controller.js`: + +```js +import Passport from '../../../adapters/passport.js' +const passport = new Passport() + +let _this + +class AuthRESTController { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating Auth REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating Auth REST Controller.' + ) + } + + _this = this + this.passport = passport + } + + /** + * @apiDefine TokenError + * @apiError Unauthorized Invalid JWT token + * + * @apiErrorExample {json} Unauthorized-Error: + * HTTP/1.1 401 Unauthorized + * { + * "status": 401, + * "error": "Unauthorized" + * } + */ + + /** + * @api {post} /auth Authenticate user + * @apiName AuthUser + * @apiGroup Auth + * + * @apiParam {String} username User username. + * @apiParam {String} password User password. + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X POST -d '{ "username": "johndoe@gmail.com", "password": "foo" }' localhost:5000/auth + * + * @apiSuccess {Object} user User object + * @apiSuccess {ObjectId} user._id User id + * @apiSuccess {String} user.name User name + * @apiSuccess {String} user.username User username + * @apiSuccess {String} token Encoded JWT + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "user": { + * "_id": "56bd1da600a526986cf65c80" + * "username": "johndoe" + * }, + * "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" + * } + * + * @apiError Unauthorized Incorrect credentials + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 401 Unauthorized + * { + * "status": 401, + * "error": "Unauthorized" + * } + */ + async authUser (ctx, next) { + try { + // Retrieve the user from the database after they've proven the correct + // password. + const user = await _this.passport.authUser(ctx, next) + if (!user) { + ctx.throw(401) + } + + const token = user.generateToken() + + const response = user.toJSON() + + delete response.password + + ctx.body = { + token, + user: response + } + } catch (err) { + ctx.throw(401) + } + } +} + +export default AuthRESTController + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/users/index.js`: + +```js +/* + REST API library for /user route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import UserRESTControllerLib from './controller.js' + +import Validators from '../middleware/validators.js' + +import config from '../../../../config/index.js' + +let _this + +class UserRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating PostEntry REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating PostEntry REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.config = config + this.userRESTController = new UserRESTControllerLib(dependencies) + this.validators = new Validators() + + // Instantiate the router and set the base route. + const baseUrl = '/users' + this.router = new Router({ prefix: baseUrl }) + + _this = this + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attaching REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.post('/', this.createUser) + this.router.get('/', this.getAll) + this.router.get('/:id', this.getById) + this.router.put('/:id', this.updateUser) + this.router.delete('/:id', this.deleteUser) + + // Attach the Controller routes to the Koa app. + app.use(this.router.routes()) + app.use(this.router.allowedMethods()) + } + + async createUser (ctx, next) { + if (process.env.DISABLE_NEW_ACCOUNTS) { + await _this.validators.ensureAdmin(ctx, next) + } + await _this.userRESTController.createUser(ctx, next) + return true + } + + async getAll (ctx, next) { + await _this.validators.ensureAdmin(ctx, next) + await _this.userRESTController.getUsers(ctx, next) + } + + async getById (ctx, next) { + await _this.validators.ensureTargetUserOrAdmin(ctx, next) + await _this.userRESTController.getUser(ctx, next) + } + + async updateUser (ctx, next) { + await _this.validators.ensureTargetUserOrAdmin(ctx, next) + await _this.userRESTController.getUser(ctx, next) + await _this.userRESTController.updateUser(ctx, next) + } + + async deleteUser (ctx, next) { + await _this.validators.ensureTargetUserOrAdmin(ctx, next) + await _this.userRESTController.getUser(ctx, next) + await _this.userRESTController.deleteUser(ctx, next) + } +} + +export default UserRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/users/controller.js`: + +```js +/* + REST API Controller library for the /user route +*/ + +import wlogger from '../../../adapters/wlogger.js' + +let _this + +class UserRESTControllerLib { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /users REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /users REST Controller.' + ) + } + + // Encapsulate dependencies + this.UserModel = this.adapters.localdb.Users + // this.userUseCases = this.useCases.user + + _this = this + } + + /** + * @api {post} /users Create a new user + * @apiPermission user + * @apiName CreateUser + * @apiGroup REST Users + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X POST -d '{ "user": { "email": "email@format.com", "name": "my name", "password": "secretpasas" } }' localhost:5010/users + * + * @apiParam {Object} user User object (required) + * @apiParam {String} user.email Email + * @apiParam {String} user.password Password + * @apiParam {String} user.name name or handle + * + * @apiSuccess {Object} users User object + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name User name + * @apiSuccess {String} users.username User username + * @apiSuccess {String} users.email User email + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "user": { + * "_id": "56bd1da600a526986cf65c80" + * "name": "John Doe" + * "email": "email@format.com", + * "password": "somestrongpassword" + * } + * } + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "status": 422, + * "error": "Unprocessable Entity" + * } + */ + async createUser (ctx) { + try { + const userObj = ctx.request.body.user + + const { userData, token } = await _this.useCases.user.createUser(userObj) + // console.log('userData: ', userData) + // console.log('token: ', token) + + ctx.body = { + user: userData, + token + } + } catch (err) { + // console.log(`err.message: ${err.message}`) + // console.log('err: ', err) + // ctx.throw(422, err.message) + _this.handleError(ctx, err) + } + } + + /** + * @api {get} /users Get all users + * @apiPermission user + * @apiName GetUsers + * @apiGroup REST Users + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X GET localhost:5000/users + * + * @apiSuccess {Object[]} users Array of user objects + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name User name + * @apiSuccess {String} users.username User username + * @apiSuccess {String} users.email User email + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "users": [{ + * "_id": "56bd1da600a526986cf65c80" + * "name": "John Doe" + * "email": "email@format.com" + * }] + * } + * + * @apiUse TokenError + */ + async getUsers (ctx) { + try { + const users = await _this.useCases.user.getAllUsers() + + ctx.body = { users } + } catch (err) { + wlogger.error('Error in users/controller.js/getUsers(): ', err) + ctx.throw(422, err.message) + } + } + + /** + * @api {get} /users/:id Get user by id + * @apiPermission user + * @apiName GetUser + * @apiGroup REST Users + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X GET localhost:5010/users/56bd1da600a526986cf65c80 + * + * @apiSuccess {Object} users User object + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name User name + * @apiSuccess {String} users.username User username + * @apiSuccess {String} users.email User email + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "user": { + * "_id": "56bd1da600a526986cf65c80" + * "name": "John Doe" + * "email": "email@format.com" + * } + * } + * + * @apiUse TokenError + */ + async getUser (ctx, next) { + try { + const user = await _this.useCases.user.getUser(ctx.params) + + ctx.body = { + user + } + } catch (err) { + _this.handleError(ctx, err) + } + + if (next) { + return next() + } + } + + /** + * @api {put} /users/:id Update a user + * @apiPermission user + * @apiName UpdateUser + * @apiGroup REST Users + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X PUT -d '{ "user": { "name": "Cool new Name" } }' localhost:5000/users/56bd1da600a526986cf65c80 + * + * @apiParam {Object} user User object (required) + * @apiParam {String} user.name Name. + * @apiParam {String} user.email Email. + * @apiParam {String} user.password Password. (optional) + * + * @apiSuccess {Object} users User object + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name Updated name + * @apiSuccess {String} users.username Updated username + * @apiSuccess {String} users.email Updated email + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "user": { + * "_id": "56bd1da600a526986cf65c80" + * "name": "Cool new name" + * "email": "email@format.com" + * } + * } + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "status": 422, + * "error": "Unprocessable Entity" + * } + * + * @apiUse TokenError + */ + async updateUser (ctx) { + try { + const existingUser = ctx.body.user + const newData = ctx.request.body.user + + const user = await _this.useCases.user.updateUser(existingUser, newData) + + ctx.body = { + user + } + } catch (err) { + ctx.throw(422, err.message) + } + } + + /** + * @api {delete} /users/:id Delete a user + * @apiPermission user + * @apiName DeleteUser + * @apiGroup REST Users + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X DELETE localhost:5000/users/56bd1da600a526986cf65c80 + * + * @apiSuccess {StatusCode} 200 + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "success": true + * } + * + * @apiUse TokenError + */ + async deleteUser (ctx) { + try { + const user = ctx.body.user + + // await user.remove() + await _this.useCases.user.deleteUser(user) + + ctx.status = 200 + ctx.body = { + success: true + } + } catch (err) { + ctx.throw(422, err.message) + } + } + + // DRY error handler + handleError (ctx, err) { + // If an HTTP status is specified by the buisiness logic, use that. + if (err.status) { + if (err.message) { + ctx.throw(err.status, err.message) + } else { + ctx.throw(err.status) + } + } else { + // By default use a 422 error if the HTTP status is not specified. + ctx.throw(422, err.message) + } + } +} + +export default UserRESTControllerLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/entry/index.js`: + +```js +/* + REST API library for /entry route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import EntryRESTControllerLib from './controller.js' + +let _this + +class UserRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /entry REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /entry REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.entryRESTController = new EntryRESTControllerLib(dependencies) + + // Instantiate the router and set the base route. + const baseUrl = '/entry' + this.router = new Router({ prefix: baseUrl }) + + _this = this + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attaching REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.post('/', _this.entryRESTController.createEntry) + + // Attach the Controller routes to the Koa app. + app.use(_this.router.routes()) + app.use(_this.router.allowedMethods()) + } +} + +export default UserRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/entry/controller.js`: + +```js +/* + REST API Controller library for the /entry route +*/ + +// const { wlogger } = require('../../../adapters/wlogger') + +let _this + +class EntryRESTControllerLib { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /entry REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /entry REST Controller.' + ) + } + + // Encapsulate dependencies + this.EntryModel = this.adapters.localdb.Entry + // this.userUseCases = this.useCases.user + + _this = this + } + + // No api-doc documentation because this wont be a public endpoint + async createEntry (ctx) { + try { + console.log('body: ', ctx.request.body) + + const entryObj = ctx.request.body.entry + + const entry = await _this.useCases.entry.createEntry(entryObj) + + ctx.body = { entry } + } catch (err) { + // console.log(`err.message: ${err.message}`) + // console.log('err: ', err) + // ctx.throw(422, err.message) + _this.handleError(ctx, err) + } + } + + // DRY error handler + handleError (ctx, err) { + console.log('err', err.message) + // If an HTTP status is specified by the buisiness logic, use that. + if (err.status) { + if (err.message) { + ctx.throw(err.status, err.message) + } else { + ctx.throw(err.status) + } + } else { + // By default use a 422 error if the HTTP status is not specified. + ctx.throw(422, err.message) + } + } +} + +export default EntryRESTControllerLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/p2wdb/index.js`: + +```js +/* + REST API library for /p2wdb route. + This route handles incoming data from the P2WDB webhook, and routes the data + to the proper handler. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import P2WDBRESTControllerLib from './controller.js' + +let _this + +class P2WDBRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /p2wdb REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /p2wdb REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.p2wdbRESTController = new P2WDBRESTControllerLib(dependencies) + + // Instantiate the router and set the base route. + const baseUrl = '/p2wdb' + this.router = new Router({ prefix: baseUrl }) + + _this = this + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attached REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.post('/', _this.p2wdbRESTController.routeWebhook) + + // Attach the Controller routes to the Koa app. + app.use(_this.router.routes()) + app.use(_this.router.allowedMethods()) + } +} + +export default P2WDBRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/p2wdb/controller.js`: + +```js +/* + REST API Controller library for the /p2wdb route + This route handles incoming data from the P2WDB webhook, and routes the data + to the proper handler. +*/ + +// const { wlogger } = require('../../../adapters/wlogger') + +let _this + +class P2WDBRESTControllerLib { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /p2wdb REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /p2wdb REST Controller.' + ) + } + + // Encapsulate dependencies + // this.OrderModel = this.adapters.localdb.Order + // this.userUseCases = this.useCases.user + + _this = this + } + + // No api-doc documentation because this wont be a public endpoint + async routeWebhook (ctx) { + try { + console.log('p2wdb REST API handler: body: ', ctx.request.body) + + const dataType = ctx.request.body.data.dataType + + if (dataType.includes('counter')) { + // Detect and handle Counter Offers + console.log('counter-offer data detected.') + + const counterOffer = ctx.request.body + + await _this.useCases.offer.acceptCounterOffer(counterOffer) + + // + } else if (dataType.includes('offer')) { + // Detect and handle new Offers + console.log('offer data detected') + + const offerObj = ctx.request.body + await _this.useCases.offer.createOffer(offerObj) + + // + } else if (dataType.includes('flag')) { + // Detect and handle data generated by users flagging NSFW Offers. + const flagData = ctx.request.body + console.log('Flag type data received: ', flagData) + + // const p2wdbHash = flagData.p2wdbHash + await _this.useCases.offer.flagOffer(flagData) + } else { + console.log('Could not route P2WDB webhook data.') + } + + // const orderObj = ctx.request.body.order + // + // const hash = await _this.useCases.order.createOrder(orderObj) + // + // ctx.body = { hash } + + ctx.body = { + success: true + } + } catch (err) { + // console.log(`err.message: ${err.message}`) + // console.log('err: ', err) + // ctx.throw(422, err.message) + _this.handleError(ctx, err) + } + } + + // DRY error handler + handleError (ctx, err) { + console.log('err', err) + + // If an HTTP status is specified by the buisiness logic, use that. + if (err.status) { + if (err.message) { + ctx.throw(err.status, err.message) + } else { + ctx.throw(err.status) + } + } else { + // By default use a 422 error if the HTTP status is not specified. + ctx.throw(422, err.message) + } + } +} + +export default P2WDBRESTControllerLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/ipfs/index.js`: + +```js +/* + REST API library for the /ipfs route. +*/ + +// Public npm libraries. +import Router from 'koa-router' + +// Local libraries. +import IPFSRESTControllerLib from './controller.js' +import Validators from '../middleware/validators.js' + +// let _this + +class IpfsRouter { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating IPFS REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating IPFS REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.ipfsRESTController = new IPFSRESTControllerLib(dependencies) + this.validators = new Validators() + + // Instantiate the router and set the base route. + const baseUrl = '/ipfs' + this.router = new Router({ prefix: baseUrl }) + + // _this = this + } + + attach (app) { + if (!app) { + throw new Error( + 'Must pass app object when attaching REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.get('/', this.ipfsRESTController.getStatus) + this.router.post('/peers', this.ipfsRESTController.getPeers) + this.router.post('/relays', this.ipfsRESTController.getRelays) + this.router.post('/connect', this.ipfsRESTController.connect) + this.router.get('/node', this.ipfsRESTController.getThisNode) + + // Attach the Controller routes to the Koa app. + app.use(this.router.routes()) + app.use(this.router.allowedMethods()) + } +} + +// module.exports = BchRouter +export default IpfsRouter + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/rest-api/ipfs/controller.js`: + +```js +/* + REST API Controller library for the /ipfs route +*/ + +// Global npm libraries + +// Local libraries +import wlogger from '../../../adapters/wlogger.js' + +class IpfsRESTControllerLib { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating /ipfs REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating /ipfs REST Controller.' + ) + } + + // Encapsulate dependencies + // this.UserModel = this.adapters.localdb.Users + // this.userUseCases = this.useCases.user + + // Bind 'this' object to all subfunctions + this.getStatus = this.getStatus.bind(this) + this.getPeers = this.getPeers.bind(this) + this.getRelays = this.getRelays.bind(this) + this.handleError = this.handleError.bind(this) + this.connect = this.connect.bind(this) + this.getThisNode = this.getThisNode.bind(this) + } + + /** + * @api {get} /ipfs Get status on IPFS infrastructure + * @apiPermission public + * @apiName GetIpfsStatus + * @apiGroup REST BCH + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X GET localhost:5001/ipfs + * + */ + async getStatus (ctx) { + try { + const status = await this.adapters.ipfs.getStatus() + + ctx.body = { status } + } catch (err) { + wlogger.error('Error in ipfs/controller.js/getStatus(): ') + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + // Return information on IPFS peers this node is connected to. + async getPeers (ctx) { + try { + const showAll = ctx.request.body.showAll + + const peers = await this.adapters.ipfs.getPeers(showAll) + + ctx.body = { peers } + } catch (err) { + wlogger.error('Error in ipfs/controller.js/getPeers(): ') + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + // Get data about the known Circuit Relays. Hydrate with data from peers list. + async getRelays (ctx) { + try { + const relays = await this.adapters.ipfs.getRelays() + + ctx.body = { relays } + } catch (err) { + wlogger.error('Error in ipfs/controller.js/getRelays(): ') + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + async connect (ctx) { + try { + const multiaddr = ctx.request.body.multiaddr + const getDetails = ctx.request.body.getDetails + + // console.log('this.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs: ', this.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs) + const result = await this.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs.connectToPeer({ multiaddr, getDetails }) + // console.log('result: ', result) + + ctx.body = result + } catch (err) { + wlogger.error('Error in ipfs/controller.js/connect():', err) + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + /** + * @api {get} /ipfs/node Get a copy of the thisNode object from helia-coord + * @apiPermission public + * @apiName GetThisNode + * @apiGroup REST BCH + * + * @apiExample Example usage: + * curl -H "Content-Type: application/json" -X GET localhost:5001/ipfs/node + * + */ + async getThisNode (ctx) { + try { + const thisNode = this.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.thisNode + + ctx.body = { thisNode } + } catch (err) { + wlogger.error('Error in ipfs/controller.js/getThisNode(): ') + // ctx.throw(422, err.message) + this.handleError(ctx, err) + } + } + + // DRY error handler + handleError (ctx, err) { + // If an HTTP status is specified by the buisiness logic, use that. + if (err.status) { + if (err.message) { + ctx.throw(err.status, err.message) + } else { + ctx.throw(err.status) + } + } else { + // By default use a 422 error if the HTTP status is not specified. + ctx.throw(422, err.message) + } + } +} + +// module.exports = IpfsRESTControllerLib +export default IpfsRESTControllerLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/json-rpc/index.js`: + +```js +/* + This is the parent class library for the RPC controller. +*/ + +// Public npm libraries +import jsonrpc from 'jsonrpc-lite' + +// Local support libraries +import wlogger from '../../adapters/wlogger.js' + +import UserController from './users/index.js' +import AuthController from './auth/index.js' +import AboutController from './about/index.js' + +let _this + +class JSONRPC { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating JSON RPC Controllers.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating JSON RPC Controllers.' + ) + } + + // Encapsulate dependencies + this.ipfsCoord = this.adapters.ipfs.ipfsCoordAdapter.ipfsCoord + this.jsonrpc = jsonrpc + this.userController = new UserController(localConfig) + this.authController = new AuthController(localConfig) + this.aboutController = new AboutController() + + // Cache to store IDs of processed JSON RPC commands. Used to prevent + // duplicate processing. + this.msgCache = [] + this.MSG_CACHE_SIZE = 30 + + _this = this + } + + // This method takes a raw string of data from IPFS, parses it, and determins + // which controller to route the instruction to. + async router (str, from) { + try { + // console.log('router str: ', str) + console.log('JSON RPC router recieved data from: ', from) + + // Exit quietly if 'from' is not specified. + if (!from || typeof from !== 'string') { + wlogger.info( + 'Warning: Can not send JSON RPC response. Can not determine which peer this message came from.' + ) + return false + } + + // Attempt to parse the incoming data as a JSON RPC string. + const parsedData = _this.jsonrpc.parse(str) + // wlogger.debug(`parsedData: ${JSON.stringify(parsedData, null, 2)}`) + + // Exit quietly if the incoming string is an invalid JSON RPC string. + if (parsedData.type === 'invalid') { + wlogger.info('Rejecting invalid JSON RPC command.') + return false + } + + // Check for duplicate entries with same 'id' value. + const alreadyProcessed = _this._checkIfAlreadyProcessed(parsedData) + if (alreadyProcessed) { + return false + } else { + // console.log(`parsedData: ${JSON.stringify(parsedData, null, 2)}`) + + // This node will regularly ping known circuit relays with an /about + // JSON RPC call. These will be handled by ipfs-coord, but will percolate + // up to this library. Ignore these messages. + if ( + parsedData.type.includes('success') && + parsedData.payload.method === undefined + ) { + return false + } + + // Log the incoming JSON RPC command. + wlogger.info( + `JSON RPC received from ${from}, ID: ${parsedData.payload.id}, type: ${parsedData.type}, method: ${parsedData.payload.method}` + ) + } + + // Added the property "from" to the parsedData object; + // necessary for calculating rate limits (based on the IPFS ID). + parsedData.from = from + + // Default return string + let retObj = _this.defaultResponse() + + // Route the command to the appropriate route handler. + switch (parsedData.payload.method) { + case 'users': + retObj = await _this.userController.userRouter(parsedData) + break + case 'auth': + retObj = await _this.authController.authRouter(parsedData) + break + case 'about': + retObj = await _this.aboutController.aboutRouter(parsedData) + } + + // console.log('retObj: ', retObj) + + // Convert the returned object into a JSON RPC response string. + const retJson = _this.jsonrpc.success(parsedData.payload.id, { + method: parsedData.payload.method, + reciever: from, + value: retObj + }) + const retStr = JSON.stringify(retJson, null, 2) + // console.log('retStr: ', retStr) + + // Encrypt and publish the response to the originators private OrbitDB, + // if ipfs-coord has been initialized and the peers ID is registered. + + // console.log('responding to JSON RPC command') + const thisNode = _this.ipfsCoord.thisNode + // console.log('thisNode: ', thisNode) + + try { + await _this.ipfsCoord.useCases.peer.sendPrivateMessage( + from, + retStr, + thisNode + ) + } catch (err) { + console.log('sendPrivateMessage() err: ', err) + } + + // Return the response and originator. Useful for testing. + return { from, retStr } + } catch (err) { + // console.error('Error in rpc router(): ', err) + wlogger.error('Error in rpc router(): ', err) + // Do not throw error. This is a top-level function. + } + } + + // Checks the ID of the JSON RPC call, to see if the message has already been + // processed. Returns true if the ID exists in the cache of processed messages. + // If the ID is new, the function adds it to the cache and return false. + _checkIfAlreadyProcessed (data) { + try { + // console.log('data: ', data) + + const id = data.payload.id + + // Check if the hash is in the array of already processed message. + const alreadyProcessed = this.msgCache.includes(id) + + // Update the msgCache if this is a new message. + if (!alreadyProcessed) { + // Add the hash to the array. + this.msgCache.push(id) + + // If the array is at its max size, then remove the oldest element. + if (this.msgCache.length > this.MSG_CACHE_SIZE) { + this.msgCache.shift() + } + } + + return alreadyProcessed + } catch (err) { + console.error('Error in _checkIfAlreadyProcessed: ', err) + return true + } + } + + // The default JSON RPC response if the incoming command could not be routed. + defaultResponse () { + const errorObj = { + success: false, + status: 422, + message: 'Input does not match routing rules.' + } + + return errorObj + } +} + +export default JSONRPC + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/json-rpc/rate-limit.js`: + +```js +/* + Rate limit +*/ +/* eslint no-useless-catch: 0 */ + +// Local libraries +import { RateLimit as RateLimitLib } from 'koa2-ratelimit' + +class RateLimit { + constructor (options) { + // Encapsulate dependencies + this.RateLimitLib = RateLimitLib + + // Set default rate limit options. + this.defaultOptions = { + interval: { min: 1 }, + max: 60, + onLimitReached: this.onLimitReached + } + + // ctx obj + this.context = { + state: { + user: '' + }, + request: { + ip: '' + }, + user: '', + set: () => {} + } + + // console.log( + // `this.defaultOptions: ${JSON.stringify(this.defaultOptions, null, 2)}` + // ) + // console.log(`options: ${JSON.stringify(options, null, 2)}`) + + // Set rate limit settings. Default values are overwritten if user passes + // in an options object. + this.rateLimitOptions = Object.assign({}, this.defaultOptions, options) + // console.log( + // `this.rateLimitOptions: ${JSON.stringify(this.rateLimitOptions, null, 2)}` + // ) + this.rateLimit = this.RateLimitLib.middleware(this.rateLimitOptions) + } + + // This function is called when the user hits their rate limits. + onLimitReached () { + try { + const error = new Error() // Establish provided options as the default options. + error.message = 'Too many requests, please try again later.' + error.status = 429 + throw error + } catch (error) { + // console.log("Error in onLimitReached()", error) + throw error + } + } + + // This is the middleware function called by the router. + async limiter (from) { + try { + if (!from || typeof from !== 'string') { + throw new Error('from must be a string') + } + + // Set context.limiter + // This overrides the default koa behavior and adapts the rate limiter + // to work with the JSON RPC over IPFS. + this.context.state.user = from + this.context.request.ip = from + this.context.user = from + + await this.rateLimit(this.context, () => {}) + return true + } catch (error) { + console.error('Error in rate-limit.js/limiter()') + throw error + } + } +} + +export default RateLimit + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/json-rpc/auth/index.js`: + +```js +/* + This is the JSON RPC router for the users API +*/ + +// Public npm libraries +import jsonrpc from 'jsonrpc-lite' + +// Local libraries +// const AuthLib = require('../../lib/auth') +// const UserLib = require('../../../use-cases/user') +import wlogger from '../../../adapters/wlogger.js' + +import RateLimit from '../rate-limit.js' + +class AuthRPC { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating Auth JSON RPC Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating Auth JSON RPC Controller.' + ) + } + + // Encapsulate dependencies + // this.authLib = new AuthLib() + this.jsonrpc = jsonrpc + this.userLib = this.useCases.user + this.rateLimit = new RateLimit() + } + + // Top-level router for this library. All other methods in this class are for + // a specific endpoint. This method routes incoming calls to one of those + // methods. + async authRouter (rpcData) { + let endpoint = 'unknown' + + try { + // console.log('authRouter rpcData: ', rpcData) + + endpoint = rpcData.payload.params.endpoint + + // Route the call based on the requested endpoint. + switch (endpoint) { + case 'authUser': + await this.rateLimit.limiter(rpcData.from) + return await this.authUser(rpcData) + } + } catch (err) { + console.error('Error in AuthRPC/authRouter()') + // throw err + + return { + success: false, + status: 500, + message: err.message, + endpoint + } + } + } + + /** + * @api {JSON} /auth Get JWT Token + * @apiPermission public + * @apiName AuthUser + * @apiGroup JSON Auth + * + * @apiExample Example usage: + * {"jsonrpc":"2.0","id":"556","method":"auth","params":{ "endpoint": "authUser", "login": "test555@test.com", "password": "password"}} + * + * @apiParam {String} login Email(required). + * @apiParam {String} password Password(required). + * @apiParam {string} endpoint (required) + * + * @apiSuccess {Object} users User object + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name User name + * @apiSuccess {String} users.email User email + * @apiSuccess {String} token JWT. + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "jsonrpc": "2.0", + * "id": "556", + * "result": { + * "method": "auth", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "endpoint": "authUser", + * "userId": "607de52d426f3d3148b3a467", + * "userType": "user", + * "userName": "testy tester", + * "userEmail": "test555@test.com", + * "apiToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYwN2RlNTJkNDI2ZjNkMzE0OGIzYTQ2NyIsImlhdCI6MTYxODg2NTcwM30.acGe5ZiBAAcbOcPQDIhvc3z0KjnuYZd1Y5pJJJC9mJQ", + * "status": 200, + * "success": true, + * "message": "" + * } + * } + *} + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "jsonrpc": "2.0", + * "id": "556", + * "result": { + * "method": "auth", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "success": false, + * "status": 422, + * "message": "User not found", + * "endpoint": "authUser" + * } + * } + * } + */ + async authUser (rpcData) { + try { + // console.log('authUser rpcData: ', rpcData) + + if (!rpcData.payload.params.login) { + throw new Error('login must be specified') + } + if (!rpcData.payload.params.password) { + throw new Error('password must be specified') + } + + const login = rpcData.payload.params.login + const password = rpcData.payload.params.password + + const user = await this.userLib.authUser(login, password) + // console.log('user: ', user) + + const token = user.generateToken() + + const response = { + endpoint: 'authUser', + userId: user._id, + userType: user.type, + userName: user.name, + userEmail: user.email, + apiToken: token, + status: 200, + success: true, + message: '' + } + + return response + } catch (err) { + // console.error('Error in authUser()') + wlogger.error('Error in authUser(): ', err) + // throw err + + // Return an error response + return { + success: false, + status: 422, + message: err.message, + endpoint: 'authUser' + } + } + } +} + +export default AuthRPC + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/json-rpc/users/index.js`: + +```js +/* + This is the JSON RPC router for the users API +*/ + +// Public npm libraries +import jsonrpc from 'jsonrpc-lite' + +// Local libraries +// const UserLib = require('../../../use-cases/user') +import Validators from '../validators.js' + +import RateLimit from '../rate-limit.js' + +class UserRPC { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating User JSON RPC Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating User JSON RPC Controller.' + ) + } + + // Encapsulate dependencies + this.userLib = this.useCases.user + this.jsonrpc = jsonrpc + this.validators = new Validators(localConfig) + this.rateLimit = new RateLimit() + } + + // Top-level router for this library. All other methods in this class are for + // a specific endpoint. This method routes incoming calls to one of those + // methods. + async userRouter (rpcData) { + let endpoint = 'unknown' + try { + // console.log('userRouter rpcData: ', rpcData) + + endpoint = rpcData.payload.params.endpoint + let user + + // Route the call based on the value of the method property. + switch (endpoint) { + case 'createUser': + await this.rateLimit.limiter(rpcData.from) + return await this.createUser(rpcData) + + case 'getAllUsers': + await this.validators.ensureUser(rpcData) + await this.rateLimit.limiter(rpcData.from) + return await this.getAll(rpcData) + + case 'getUser': + user = await this.validators.ensureUser(rpcData) + await this.rateLimit.limiter(rpcData.from) + return await this.getUser(rpcData, user) + + case 'updateUser': + user = await this.validators.ensureTargetUserOrAdmin(rpcData) + await this.rateLimit.limiter(rpcData.from) + return await this.updateUser(rpcData, user) + + case 'deleteUser': + user = await this.validators.ensureTargetUserOrAdmin(rpcData) + await this.rateLimit.limiter(rpcData.from) + return await this.deleteUser(rpcData, user) + } + } catch (err) { + console.error('Error in UsersRPC/rpcRouter()') + // throw err + + return { + success: false, + status: err.status || 500, + message: err.message, + endpoint + } + } + } + + /** + * @api {JSON} /users Create a new user + * @apiPermission public + * @apiName CreateUser + * @apiGroup JSON Users + * + * @apiExample Example usage: + * {"jsonrpc":"2.0","id":"555","method":"users","params":{ "endpoint": "createUser", "email": "test555@test.com", "name": "testy tester", "password": "password"}} + * + * @apiParam {String} email Email(required). + * @apiParam {String} password Password(required). + * @apiParam {String} name name or handle(optional). + * @apiParam {string} endpoint (required) + + * @apiSuccess {Object} users User object + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name User name + * @apiSuccess {String} users.username User username + * @apiSuccess {String} users.email User email + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * { + * "jsonrpc": "2.0", + * "id": "555", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "userData": { + * "type": "user", + * "_id": "607dd3e6426f3d3148b3a466", + * "email": "test555@test.com", + * "name": "testy tester", + * "__v": 0 + * }, + * "token": "eyJhbGciOiJIUzI1NiIs1nR5cCI6IkpXVTJ9.eyJpZCI6IjYwN2RkM2U2NDI2ZjNkMzE0OGIzYTQ2NiIsImlhdCI6MTYxODg1ODk4Mn0.in4vzxDqqyCd7LpuhG3xlXeBqrJ5bp9GJPwhaoVzldI", + * "endpoint": "createUser", + * "success": true, + * "status": 200, + * "message": "" + * } + * } + *} + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "jsonrpc": "2.0", + * "id": "123", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "success": false, + * "status": 422, + * "message": "Unprocessable Entity", + * "endpoint": "getUser" + * } + * } + *} + */ + async createUser (rpcData) { + try { + // console.log('createUser rpcData: ', rpcData) + + const retObj = await this.userLib.createUser(rpcData.payload.params) + + // Add generic JSON RPC properties that every entry gets. + retObj.endpoint = 'createUser' + retObj.success = true + retObj.status = 200 + retObj.message = '' + + return retObj + } catch (err) { + // console.error('Error in createUser()') + // throw err + + // Return an error response + return { + success: false, + status: 422, + message: err.message, + endpoint: 'createUser' + } + } + } + + /** + * @api {JSON} /users Get all users + * @apiPermission public + * @apiName GetAllUsers + * @apiGroup JSON Users + * + * @apiExample Example usage: + * {"jsonrpc":"2.0","id":"555","method":"users","params":{ "endpoint": "getAllUsers", "apiToken": ""}} + * + * @apiParam {String} apiToken (required) + * @apiParam {string} endpoint (required) + * + * @apiSuccess {Object[]} users Array of user objects + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name User name + * @apiSuccess {String} users.username User username + * @apiSuccess {String} users.email User email + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "users": [ + * { + * "type": "user", + * "_id": "6070bc6da931e73d4d9e108d", + * "email": "test678@test.com", + * "name": "testy tester", + * "__v": 0 + * } + * ], + * "endpoint": "getAllUsers", + * "success": true, + * "status": 200, + * "message": "" + * } + * } + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "jsonrpc": "2.0", + * "id": "123", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "success": false, + * "status": 422, + * "message": "", + * "endpoint": "getAllUsers" + * } + * } + */ + // Get all Users. + async getAll () { + try { + const users = await this.userLib.getAllUsers() + + return { + users, + endpoint: 'getAllUsers', + success: true, + status: 200, + message: '' + } + } catch (err) { + // console.error('Error in getAll()') + // throw err + + // Return an error response + return { + success: false, + status: 422, + message: err.message, + endpoint: 'getAllUsers' + } + } + } + + /** + * @api {JSON} /users Get a user + * @apiPermission public + * @apiName GetAUser + * @apiGroup JSON Users + * + * @apiExample Example usage: + * {"jsonrpc":"2.0","id":"123","method":"users","params":{ "endpoint": "getUser", "apiToken": "", "userId": "<_id>"}} + * + * @apiParam {String} apiToken (required) + * @apiParam {String} userId (required) + * @apiParam {string} endpoint (required) + * + * @apiSuccess {Object[]} users Array of user objects + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name User name + * @apiSuccess {String} users.username User username + * @apiSuccess {String} users.email User email + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * result": { + * "jsonrpc": "2.0", + * "id": "123", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "user": { + * "type": "user", + * "_id": "607dd3e6426f3d3148b3a466", + * "email": "test555@test.com", + * "name": "testy tester", + * "__v": 0 + * }, + * "endpoint": "getUser", + * "success": true, + * "status": 200, + * "message": "" + * } + *} + * + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "jsonrpc": "2.0", + * "id": "123", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "success": false, + * "status": 422, + * "message": "Unprocessable Entity", + * "endpoint": "getUser" + * } + * } + * + */ + // Get a specific user. + async getUser (rpcData, userModel) { + try { + // console.log('getUser rpcData: ', rpcData) + + // Throw error if rpcData does not include 'userId' property for target user. + const userId = rpcData.payload.params.userId + + const user = await this.userLib.getUser({ id: userId }) + + return { + user, + endpoint: 'getUser', + success: true, + status: 200, + message: '' + } + } catch (err) { + // console.error('Error in getUser()') + // throw err + + // Return an error response + return { + success: false, + status: 422, + message: err.message, + endpoint: 'getUser' + } + } + } + + /** + * @api {JSON} /users Update a user + * @apiPermission public + * @apiName UpdateAUser + * @apiGroup JSON Users + * + * @apiExample Example usage: + * {"jsonrpc":"2.0","id":"123","method":"users","params":{ "endpoint": "updateUser", "apiToken": "", "userId": "<_id>", "name": "test999"}} + * + * @apiParam {String} apiToken (required) + * @apiParam {String} userId (required) + * @apiParam {string} endpoint (required) + * @apiParam {String} email Email(Optional). + * @apiParam {String} password Password(Optional). + * @apiParam {String} name name or handle(Optional). + * + * + * @apiSuccess {Object} users User object + * @apiSuccess {ObjectId} users._id User id + * @apiSuccess {String} user.type User type (admin or user) + * @apiSuccess {String} users.name Updated name + * @apiSuccess {String} users.username Updated username + * @apiSuccess {String} users.email Updated email + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * result": { + * "jsonrpc": "2.0", + * "id": "123", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "user": { + * "type": "user", + * "_id": "607dd3e6426f3d3148b3a466", + * "email": "test555@test.com", + * "name": "test001", + * "__v": 0 + * }, + * "endpoint": "updateUser", + * "success": true, + * "status": 200, + * "message": "" + * } + * } + *} + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "jsonrpc": "2.0", + * "id": "123", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "success": false, + * "status": 422, + * "message": "Unprocessable Entity.", + * "endpoint": "updateUser" + * } + * } + * } + * + */ + async updateUser (rpcData, userModel) { + try { + // console.log('updateUser rpcData: ', rpcData) + + const newData = rpcData.payload.params + + const user = await this.userLib.updateUser(userModel, newData) + + return { + user, + endpoint: 'updateUser', + success: true, + status: 200, + message: '' + } + } catch (err) { + // console.log('updateUser err: ', err) + + // Return an error response + return { + success: false, + status: 422, + message: err.message, + endpoint: 'updateUser' + } + } + } + + /** + * @api {JSON} /users Delete a user + * @apiPermission public + * @apiName DeleteAUser + * @apiGroup JSON Users + * + * + * @apiExample Example usage: + * {"jsonrpc":"2.0","id":"123","method":"users","params":{ "endpoint": "deleteUser", "userId": "<_id>", "apiToken": ""}} + * + * @apiParam {String} apiToken (required) + * @apiParam {String} userId (required) + * @apiParam {string} endpoint (required) + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * result": { + * "jsonrpc": "2.0", + * "id": "123", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "endpoint": "deleteUser", + * "success": true, + * "status": 200, + * "message": "" + * } + * } + *} + * + * @apiError UnprocessableEntity Missing required parameters + * + * @apiErrorExample {json} Error-Response: + * HTTP/1.1 422 Unprocessable Entity + * { + * "jsonrpc": "2.0", + * "id": "123", + * "result": { + * "method": "users", + * "reciever": "Qmc2uJhg7yrqaNaoTJRDkzrAyVe82e9JMFQcxrBUjbdXyC", + * "value": { + * "success": false, + * "status": 422, + * "message": "Unprocessable Entity", + * "endpoint": "deleteUser" + * } + * } + *} + * + * + */ + async deleteUser (rpcData, userModel) { + try { + // console.log('deleteUser rpcData: ', rpcData) + + await this.userLib.deleteUser(userModel) + + const retObj = { + endpoint: 'deleteUser', + success: true, + status: 200, + message: '' + } + + return retObj + } catch (err) { + // console.error('Error in deleteUser()') + // throw err + + // Return an error response + return { + success: false, + status: 422, + message: err.message, + endpoint: 'deleteUser' + } + } + } + + // TODO create deleteUser() +} + +export default UserRPC + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/json-rpc/validators.js`: + +```js +/* + Validators for the JSON RPC +*/ +/* eslint no-useless-catch: 0 */ + +// Public npm libraries +import jwt from 'jsonwebtoken' + +// Local libraries +import config from '../../../config/index.js' + +// const UserModel = require('../../adapters/localdb/models/users') + +class Validators { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating JSON RPC Validators library.' + ) + } + + // Encapsulate dependencies + this.config = config + this.jwt = jwt + this.UserModel = this.adapters.localdb.Users + } + + // Returns if user passes a valid JWT token that resolves to a valid user. + // Otherwise it throws an error. + async ensureUser (rpcData) { + try { + // console.log('rpcData: ', rpcData) + + const apiToken = rpcData.payload.params.apiToken + if (!apiToken) throw new Error('apiToken JWT required as a parameter') + + const decoded = this.jwt.verify(apiToken, this.config.token) + + const user = await this.UserModel.findById(decoded.id, '-password') + if (!user) throw new Error('User not found!') + + return user + } catch (err) { + // console.error('Error in ensureUser()') + throw err + } + } + + // This middleware ensures that the :id used in the API endpoint matches the + // the ID used in the JWT, or failing that, the ID used in the JWT matches + // an Admin user. This prevents situations like users updating other users + // profiles or non-admins deleting users. + async ensureTargetUserOrAdmin (rpcData) { + try { + // console.log('rpcData: ', rpcData) + + // Ensure the JWT is passed in. + const apiToken = rpcData.payload.params.apiToken + if (!apiToken) throw new Error('apiToken JWT required as a parameter') + + // Ensure a target user ID is provided. + const targetUserId = rpcData.payload.params.userId + if (!targetUserId) throw new Error('userId must be specified') + + // Decode the JWT token. + const decoded = this.jwt.verify(apiToken, this.config.token) + + // Get the user described by the JWT token. + const user = await this.UserModel.findById(decoded.id, '-password') + if (!user) throw new Error('User not found!') + + // If this current user is an admin, then quietly exit. + if (user.type === 'admin') return true + + // Throw an error if the JWT token does not match the targeted user. + if (user._id.toString() !== targetUserId) { + throw new Error('User is neither admin nor target user.') + } + + // Get the user model for the targeted User + const targetedUser = await this.UserModel.findById( + targetUserId, + '-password' + ) + + // Return the user model. + return targetedUser + } catch (error) { + // console.error('Error in ensureUser()') + throw error + } + } +} + +export default Validators + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/json-rpc/about/index.js`: + +```js +/* + This is the JSON RPC router for the users API + + CT 3/5/22: This library can probably be deleted. Handling of the /about endpoint + is now directly controlled by the ipfs-coord library. +*/ + +// Public npm libraries +import jsonrpc from 'jsonrpc-lite' + +// Local libraries +import config from '../../../../config/index.js' + +class AboutRPC { + constructor (localConfig) { + // Encapsulate dependencies + this.jsonrpc = jsonrpc + } + + /** + * @api {JSON} /about About IPFS Node + * @apiPermission public + * @apiName About + * @apiGroup JSON About + * + * @apiExample Example usage: + * {"jsonrpc":"2.0","id":"555","method":"about"} + * + * @apiDescription + * This endpoint can be customized so that users can retrieve information about + * your IPFS node and Service Provider application. This is a great place to + * put a website URL, an IPFS hash, an other basic information. + */ + + // This is the top-level router for this library. + // This is a bit different than other router libraries, because there is + // only one response, which is a string about this node. + async aboutRouter (rpcData) { + console.log('debugging: aboutRouter from ipfs-service-provider triggered') + + return { + success: true, + status: 200, + // message: aboutStr, + message: JSON.stringify(config.announceJsonLd), + endpoint: 'about' + } + } +} + +export default AboutRPC + +``` + +`/home/trout/work/psf/code/bch-dex/src/controllers/timer-controllers.js`: + +```js +/* + This Controller library is concerned with timer-based functions that are + kicked off periodically. +*/ + +import config from '../../config/index.js' + +class TimerControllers { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating Timer Controller libraries.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating Timer Controller libraries.' + ) + } + + this.debugLevel = localConfig.debugLevel + this.config = config + + // Bind 'this' object to all subfunctions + this.startTimers = this.startTimers.bind(this) + this.gcOrders = this.gcOrders.bind(this) + this.gcOffers = this.gcOffers.bind(this) + this.checkDupOffers = this.checkDupOffers.bind(this) + this.loadOffers = this.loadOffers.bind(this) + // Bind 'this' object to all subfunctions. + // this.exampleTimerFunc = this.exampleTimerFunc.bind(this) + this.cleanUsage = this.cleanUsage.bind(this) + + // State + this.gcOrdersInt = null + this.gcOffersInt = null + this.checkDupOffersInt = null + this.loadOffersInt = null + } + + // Start all the time-based controllers. + startTimers () { + this.gcOrdersInt = setInterval(this.gcOrders, 60000 * 5) + this.gcOffersInt = setInterval(this.gcOffers, 60000 * 5) + // this.checkDupOffersInt = setInterval(this.checkDupOffers, 60000 * 4.5) + this.loadOffersInt = setInterval(this.loadOffers, 60000 * 2) + // Any new timer control functions can be added here. They will be started + // when the server starts. + // this.optimizeWalletHandle = setInterval(this.exampleTimerFunc, 60000 * 60) + this.cleanUsageHandle = setInterval(this.cleanUsage, 60000 * 60) // 1 hour + + return true + } + + stopTimers () { + clearInterval(this.gcOrdersInt) + clearInterval(this.gcOffersInt) + // clearInterval(this.checkDupOffers) + clearInterval(this.optimizeWalletHandle) + clearInterval(this.cleanUsageHandle) + } + + // Garbage Collect the Orders. + gcOrders () { + try { + this.useCases.order.removeStaleOrders() + return true + } catch (err) { + // Do not throw an error. This is a top-level function. + console.log('Error in timer-controllers.js/gcOrders(): ', err) + return false + } + } + + // Garbage Collect the Offers. + gcOffers () { + try { + this.useCases.offer.removeStaleOffers() + return true + } catch (err) { + // Do not throw an error. This is a top-level function. + console.log('Error in timer-controllers.js/gcOffers(): ', err) + return false + } + } + + // Remove duplicate Offers + checkDupOffers () { + try { + this.useCases.offer.removeDuplicateOffers() + return true + } catch (err) { + // Do not throw an error. This is a top-level function. + console.log('Error in timer-controllers.js/checkDupOffers(): ', err) + return false + } + } + + // Load offers From nostr . + async loadOffers () { + try { + await this.useCases.offer.loadOffers() + return true + } catch (err) { + // Do not throw an error. This is a top-level function. + console.log('Error in timer-controllers.js/loadOffers(): ', err) + return false + } + } + + // Clean the usage state so that stats reflect the last 24 hours. + cleanUsage () { + try { + const now = new Date() + console.log(`cleanUsage() Timer Controller executing at ${now.toLocaleString()}`) + + this.useCases.usage.cleanUsage() + + return true + } catch (err) { + console.error('Error in time-controller.js/cleanUsage(): ', err) + + // Note: Do not throw an error. This is a top-level function. + return false + } + } +} + +export default TimerControllers + +``` + +`/home/trout/work/psf/code/bch-dex/src/use-cases/index.js`: + +```js +/* + This is a top-level library that encapsulates all the additional Use Cases. + The concept of Use Cases comes from Clean Architecture: + https://troutsblog.com/blog/clean-architecture +*/ + +// Local libraries +import UserUseCases from './user.js' +import EntryUseCases from './entry.js' +import OfferUseCases from './offer/index.js' +import OrderUseCases from './order.js' +import { UsageUseCases } from './usage-use-cases.js' + +class UseCases { + constructor (localConfig = {}) { + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of adapters must be passed in when instantiating Use Cases library.' + ) + } + + // console.log('use-cases/index.js localConfig: ', localConfig) + this.user = new UserUseCases(localConfig) + this.entry = new EntryUseCases(localConfig) + this.order = new OrderUseCases(localConfig) + localConfig.order = this.order + this.offer = new OfferUseCases(localConfig) + this.usage = new UsageUseCases(localConfig) + } + + // Run any startup Use Cases at the start of the app. + async start () { + console.log('Async Use Cases have been started.') + + return true + } +} + +export default UseCases + +``` + +`/home/trout/work/psf/code/bch-dex/src/use-cases/offer/index.js`: + +```js +/* + Use Case library for Offers. + + Offers are created by a webhook trigger from the P2WDB. Offers are a result of + new data in P2WDB. They differ from Offers, which are generated by a local + user. + + An Offer is created to match a local Offer, but it's created indirectly, as + a response to the webhook from the P2WDB. In this way, Offers generated from + local Offers are no different than Offers generated by other peers. + + A Counter Offer is created by calling the /take/:cid endpoint. It creates + a partially signed transaction. + */ + +// Global npm libraries +import axios from 'axios' +import RetryQueue from '@chris.troutner/retry-queue' + +// Local libraries +import OfferEntity from '../../entities/offer.js' +import config from '../../../config/index.js' + +const DEFAULT_ENTRIES_PER_PAGE = 20 +const NFT_ENTRIES_PER_PAGE = 6 +const FUNGIBLE_ENTRIES_PER_PAGE = 20 + +class OfferUseCases { + constructor (localConfig = {}) { + // console.log('User localConfig: ', localConfig) + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of adapters must be passed in when instantiating Offer Use Cases library.' + ) + } + this.orderUseCase = localConfig.order + if (!this.orderUseCase) { + throw new Error( + 'Instance of Order Use Cases must be passed in when instantiating Offer Use Cases library.' + ) + } + + // Encapsulate dependencies + this.config = config + this.axios = axios + this.offerEntity = new OfferEntity() + this.OfferModel = this.adapters.localdb.Offer + this.retryQueue = new RetryQueue({ retryPeriod: 1000, attempts: 3 }) + + // Bind 'this' object to functions + this.createOffer = this.createOffer.bind(this) + this.detectNsfw = this.detectNsfw.bind(this) + this.categorizeToken = this.categorizeToken.bind(this) + this.listOffers = this.listOffers.bind(this) + this.listNftOffers = this.listNftOffers.bind(this) + this.listFungibleOffers = this.listFungibleOffers.bind(this) + this.takeOffer = this.takeOffer.bind(this) + this.ensureFunds = this.ensureFunds.bind(this) + this.findOfferByEvent = this.findOfferByEvent.bind(this) + this.findOfferByTxid = this.findOfferByTxid.bind(this) + this.acceptCounterOffer = this.acceptCounterOffer.bind(this) + this.removeDuplicateOffers = this.removeDuplicateOffers.bind(this) + this.removeStaleOffers = this.removeStaleOffers.bind(this) + this.flagOffer = this.flagOffer.bind(this) + this.loadOffers = this.loadOffers.bind(this) + + // State + this.seenOffers = [] + this.seenCounterOffers = [] + } + + // This method is called by timer controller to load offers from a Nostr topic. + async createOffer (offerObj) { + try { + // console.log('Use Case createOffer(offerObj): ', offerObj) + + // Return if Offer already exists in database with the same utxo transaction id. + try { + await this.findOfferByTxid(offerObj.data.utxoTxid) + + // console.log('Offer already found in local database.') + return false + } catch (err) { /* exit quietly */ } + + // console.log('this.adapters.bchjs: ', this.adapters.bchjs) + + // Input Validation + // TODO: This is a hack. Find a better way to protect against the corner- + // case of counter-offers getting routed here. + // if (offerObj.data.dataType === 'counter-offer') { + // console.log('WARN: Counter Offer innappropriately routed to createOffer()') + // } + + // Quickly skip over offers that have already been processed. + const eventId = offerObj.data.nostrEventId + if (this.seenOffers.includes(eventId)) { + // console.log(`Offer with event ID ${eventId} already processed. Skipping.`) + return false + } + this.seenOffers.push(eventId) + + // Verify that UTXO in offer is unspent. If it is spent, then ignore the + // offer. + const utxo = { + tx_hash: offerObj.data.utxoTxid, + tx_pos: offerObj.data.utxoVout + } + // const utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo) + const utxoStatus = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.utxoIsValid, utxo) + // console.log('utxoStatus: ', utxoStatus) + // if (utxoStatus === null) return false + if (!utxoStatus) return false + + // A new offer gets a status of 'posted' + offerObj.data.offerStatus = 'posted' + + // Set timestamp + offerObj.timestamp = new Date().getTime() + + const offerEntity = this.offerEntity.validate(offerObj) + // console.log('offerEntity: ', offerEntity) + + console.log(`New Offer for token ID ${offerEntity.tokenId} detected from Nostr post ${eventId}`) + + // Get data about the token. + const tokenId = offerEntity.tokenId + // const tokenData = await this.adapters.wallet.bchWallet.getTokenData(tokenId) + const tokenData = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.getTokenData, tokenId) + // console.log(`tokenData: ${JSON.stringify(tokenData, null, 2)}`) + + // Generate a 'display category' for the token. This will allow the + // front end UI to figure out how to display the token. + const displayCategory = this.categorizeToken(offerEntity, tokenData) + console.log('displayCategory: ', displayCategory) + offerEntity.displayCategory = displayCategory + + // Detect if user set the NSFW flag. + // const nsfw = false + // nsfw = await this.retryQueue.addToQueue(this.detectNsfw, tokenData) + // offerEntity.nsfw = nsfw + + // Add offer to the local database. + const offerModel = new this.OfferModel(offerEntity) + await offerModel.save() + + return true + } catch (err) { + console.error('Error in createOffer()', err.message) + throw err + } + } + + // By default this function returns false, to indicate the NFT is safe for work. + // If the user who created the token sets the nsfw property in the mutable data, + // this function will return true. + async detectNsfw (tokenData) { + try { + let nsfw = false + + const mutableCid = tokenData.mutableData + + // If there is no mutable IPFS CID, then skip this token. + if (!mutableCid.includes('ipfs://')) return nsfw + + // Revove the ipfs:// prefix. + const cid = mutableCid.substring(7) + + // Retrieve the mutable data from Filecoin/IPFS. + // const url = `https://${cid}.ipfs.w3s.link/data.json` + let mutableData = {} + + try { + // Try the conventional data URL. + const url = `${this.config.ipfsGateway}${cid}/data.json` + const result = await this.axios.get(url) + mutableData = result.data + // console.log(`mutableData: ${JSON.stringify(mutableData, null, 2)}`) + } catch (err) { + // Try the newer data URL. + const url = `${this.config.ipfsGateway}${cid}` + const result = await this.axios.get(url) + mutableData = result.data + // console.log(`mutableData: ${JSON.stringify(mutableData, null, 2)}`) + } + console.log('mutableData: ', mutableData) + + // Logical tests + const hasNsfw = !!mutableData.nsfw + const nsfwSetTrue = mutableData.nsfw === true + const nsfwStringTrue = mutableData.nsfw === 'true' + const nsfwDetected = hasNsfw && (nsfwSetTrue || nsfwStringTrue) + // console.log(`hasNsfw: ${hasNsfw}, nsfwSetTrue: ${nsfwSetTrue}, nsfwStringTrue: ${nsfwStringTrue}, nsfwDetected: ${nsfwDetected}`) + + if (nsfwDetected) { + console.log('NSFW flag set as true') + nsfw = true + } + + return nsfw + } catch (err) { + console.error('Error in detectNsfw(): ', err) + return false + } + } + + // Categorize the token for display purposes. This will categorize a token + // into one of these categories: + // - nft + // - group + // - fungible + // - simple-nft + // + // The first three are easy to categorize. The simple-nft is a fungible token + // with a quantity of 1, decimals of 0, and no minting baton. Categorizing this + // type of token is the main reason why this function exists. + categorizeToken (offerData, tokenData) { + try { + // console.log(`categorizeToken(): ${JSON.stringify(offerData, null, 2)}`) + + // const tokenId = offerData.tokenId + // + // const tokenData = await this.adapters.wallet.bchWallet.getTokenData(tokenId) + // console.log(`tokenData: ${JSON.stringify(tokenData, null, 2)}`) + + if (tokenData.genesisData.type === 65) { + return 'nft' + } + + // Create a set of checks to detect a simple NFT + const isType1 = tokenData.genesisData.type === 1 + const hasNoMintingBaton = !tokenData.genesisData.mintBatonIsActive + const hasNoDecimals = !tokenData.genesisData.decimals + const hasQtyOfOne = parseInt(tokenData.genesisData.tokensInCirculationStr) === 1 + + if (isType1 && hasNoMintingBaton && hasNoDecimals && hasQtyOfOne) { + return 'simple-nft' + } + + if (isType1) return 'fungible' + + throw new Error(`Unknown token type: ${tokenData.genesisData.type}`) + } catch (err) { + console.error('Error in use-cases/offer/index.js categorizeToken(): ', err) + throw err + } + } + + async listOffers (page = 0) { + try { + const data = await this.OfferModel.find({}) + // Sort entries so newest entries show first. + .sort('-timestamp') + // Skip to the start of the selected page. + .skip(page * DEFAULT_ENTRIES_PER_PAGE) + // Only return 20 results. + .limit(DEFAULT_ENTRIES_PER_PAGE) + + return data + } catch (error) { + console.error('Error in use-cases/offer/listOffers()') + throw error + } + } + + async listNftOffers (page = 0, nsfw = false) { + try { + const data = await this.OfferModel.find({ + displayCategory: { $ne: 'fungible' }, + nsfw + }) + // Sort entries so newest entries show first. + .sort('-timestamp') + // Skip to the start of the selected page. + .skip(page * NFT_ENTRIES_PER_PAGE) + // Only return 20 results. + .limit(NFT_ENTRIES_PER_PAGE) + + // console.log('listNftOffers() returning this data: ', data) + + return data + } catch (error) { + console.error('Error in use-cases/offer/listNftOffers()') + throw error + } + } + + async listFungibleOffers (page = 0) { + try { + const data = await this.OfferModel.find({ displayCategory: 'fungible' }) + // Sort entries so newest entries show first. + .sort('-timestamp') + // Skip to the start of the selected page. + .skip(page * FUNGIBLE_ENTRIES_PER_PAGE) + // Only return 20 results. + .limit(FUNGIBLE_ENTRIES_PER_PAGE) + + // console.log('listFungibleOffers() returning this data: ', data) + + return data + } catch (error) { + console.error('Error in use-cases/offer/listFungibleOffers()') + throw error + } + } + + // Generate phase 2 of 3 - take the other side of an Offer. + // Based on this example: + // https://github.com/Permission=less-Software-Foundation/bch-js-examples/blob/master/bch/applications/collaborate/sell-slp/e2e-exchange/step2-purchase-tx.js + // + // Dev Note: Right now this use cases takes all the tokens offered. It does not + // provide functionality to take less than the total amount of tokens offered + // (offerInfo.numTokens). Taking less than the offered amount will be added + // in the future. + async takeOffer (eventId) { + try { + if (!eventId || typeof eventId !== 'string') throw new Error('eventId must be a string') + + // Get the Offer information + const offerInfo = await this.findOfferByEvent(eventId) + console.log(`offerInfo: ${JSON.stringify(offerInfo, null, 2)}`) + + // Ensure the offer is in a 'posted' state and not already 'taken' + if (!offerInfo.offerStatus || offerInfo.offerStatus !== 'posted') { + throw new Error('offer status is not "posted", so offer is dead and can not be countered.') + } + + // Verify that UTXO for sale is unspent. Abort if it's been spent. + const utxo = { + tx_hash: offerInfo.utxoTxid, + tx_pos: offerInfo.utxoVout + } + + // Note : should be added to retry-queue? + const utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo) + // console.log('utxoStatus: ', utxoStatus) + if (!utxoStatus) { + console.log(`utxo txid: ${offerInfo.utxoTxid}, vout: ${offerInfo.utxoVout}`) + + // TODO: Mark this Offer as 'dead' + + throw new Error('UTXO does not exist. Aborting.') + } + + // Ensure the app has enough funds to complete the trade. + await this.ensureFunds(offerInfo) + + // Get UTXOs. + // const utxos = this.adapters.wallet.bchWallet.utxos.utxoStore + // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`) + + // Calculate amount of sats to generate a counter offer. + let satsToMove = Math.ceil(offerInfo.numTokens * parseInt(offerInfo.rateInBaseUnit)) + console.log('satsToMove', satsToMove, offerInfo) + if (isNaN(satsToMove)) { + throw new Error('Could not calculate the amount of BCH to generate counter offer') + } + + // Add sats to cover mining fees and dust for token UTXO + satsToMove += 1000 + + // Move funds to create a segrated UTXO for taking the offer + const utxoInfo = await this.adapters.wallet.moveBch(satsToMove) + utxoInfo.sats = satsToMove + console.log('utxoInfo: ', utxoInfo) + + // Create a partially signed transaction. + // https://github.com/Permissionless-Software-Foundation/bch-js-examples/blob/master/bch/applications/collaborate/sell-slp/e2e-exchange/step2-purchase-tx.js#L59 + const partialTxHex = await this.adapters.wallet.generatePartialTx(offerInfo, utxoInfo) + console.log('partialTxHex: ', partialTxHex) + // return partialTxHex + + // Debug: Decode the transaction for manual QA + const txObj = await this.adapters.wallet.deseralizeTx(partialTxHex) + console.log(`partially-signed transaction: ${JSON.stringify(txObj, null, 2)}`) + + // Create valid Offer object + const takenOfferInfo = Object.assign({}, offerInfo) + takenOfferInfo.partialTxHex = partialTxHex + delete takenOfferInfo.nostrEventId + delete takenOfferInfo._id + takenOfferInfo.offerHash = offerInfo.nostrEventId + + // Add P2WDB specific flag for signaling that this is a new offer. + takenOfferInfo.dataType = 'counter-offer' + + // Write offer info to the P2WDB + // TODO: This will trigger the webhook. Find some way of triggering the + // webhook on new offers, but not on counteroffers + const nostrData = { + // wif: this.adapters.wallet.bchWallet.walletInfo.privateKey, + data: takenOfferInfo + // appId: this.config.p2wdbAppId + } + const resultEventId = await this.adapters.nostr.post(JSON.stringify(nostrData)) + + const noteId = this.adapters.nostr.eventId2note(resultEventId) + + // Delete the Offer from the database, so that the user doesn't attempt + // to take the offer more than once. + // offerInfo.remove() + + // Return the P2WDB CID + return { eventId: resultEventId, noteId } + + // return 'fake-hash' + } catch (err) { + console.error('Error in use-cases/offer/takeOffer(): ', err) + throw err + } + } + + // Ensure that the wallet has enough BCH and tokens to complete the requested + // trade. Will return true if it does. Will throw an error if it doesn't. + async ensureFunds (offerEntity) { + try { + // console.log('this.adapters.wallet: ', this.adapters.wallet.bchWallet) + // console.log(`walletInfo: ${JSON.stringify(this.adapters.wallet.bchWallet.walletInfo, null, 2)}`) + + await this.adapters.wallet.bchWallet.walletInfoPromise + // console.log(`utxos: ${JSON.stringify(this.adapters.wallet.bchWallet.utxos.utxoStore, null, 2)}`) + + // Refresh the wallet UTXOs + await this.adapters.wallet.bchWallet.initialize() + + // Ensure the app wallet has enough funds to write to the P2WDB. + // Note : this validation should be deprecated for nostr functionality? + // const wif = this.adapters.wallet.bchWallet.walletInfo.privateKey + // const canWriteToP2WDB = await this.adapters.p2wdb.checkForSufficientFunds(wif) + // if (!canWriteToP2WDB) throw new Error('App wallet does not have funds for writing to the P2WDB.') + + if (offerEntity.buyOrSell.includes('sell')) { + // Sell Offer + + // Calculate the sats needed + const satsNeeded = Math.ceil(offerEntity.numTokens * parseInt(offerEntity.rateInBaseUnit)) + if (isNaN(satsNeeded)) { + throw new Error('Could not calculate sats needed!') + } + + // Ensure the app wallet controlls enough BCH to pay for the tokens. + const balance = await this.adapters.wallet.bchWallet.getBalance() + console.log(`wallet balance: ${balance}, sats needed: ${satsNeeded}`) + const SATS_MARGIN = 5000 + if (satsNeeded + SATS_MARGIN > balance) { + throw new Error('App wallet does not control enough BCH to purchase the tokens.') + } + + // + } else { + // Buy Offer + throw new Error('Buy offers are not supported yet.') + } + + return true + } catch (err) { + console.error('Error in offer/index.js/ensureFunds()') + + // Debugging + try { + console.error(`Error with this address: ${this.adapters.wallet.bchWallet.walletInfo.cashAddress}`) + } catch (err) { /* exit quietly */ } + + throw err + } + } + + // Retrieve an Order model from the database. Find it by its event Id. + async findOfferByEvent (nostrEventId) { + try { + if (typeof nostrEventId !== 'string' || !nostrEventId) { + throw new Error('nostrEventId must be a string') + } + + const order = await this.OfferModel.findOne({ nostrEventId }) + + if (!order) { + throw new Error('offer not found') + } + + const orderObject = order.toObject() + // return this.offerEntity.validateFromModel(offerObject) + + return orderObject + } catch (err) { + console.error('Error in findOfferByEvent()') + throw err + } + } + + async findOfferByTxid (utxoTxid) { + // try { + // try { + if (typeof utxoTxid !== 'string' || !utxoTxid) { + throw new Error('utxoTxid must be a string') + } + + const offer = await this.OfferModel.findOne({ utxoTxid }) + + // TODO: Offer should be found by TXID, then if there is more than one + // result, they should be filtered by the vout property. That will leave + // one remaining UTXO. + + if (!offer) { + throw new Error('offer not found') + } + + return offer + // } catch (error) { + // // console.error('Error in use-cases/offer/findOfferByTxid(): ', error.message) + // throw error + // } + } + + // This function is called by the P2WDB webhook REST API handler. When a + // Counter Offer is passed to bch-dex by the P2WDB, the data is then passed + // to this function. It does due diligence on the Counter Offer, then signs + // and broadcasts the transaction to accept the Counter Offer. + async acceptCounterOffer (offerData) { + try { + // console.log(`acceptCounterOffer() offerData: ${JSON.stringify(offerData, null, 2)}`) + + // Quickly skip over offers that have already been processed. + const eventId = offerData.data.nostrEventId + if (this.seenOffers.includes(eventId)) { + // console.log(`Offer with event ID ${eventId} already processed. Skipping.`) + return false + } + + // See if this instance of bch-dex is managing the Order associated with + // the incoming Counter Offer. + + // Note : this should be handled by nostrEvent id or UtxoId? + // const orderHash = offerData.data.nostrEventId + let orderData = {} + try { + orderData = await this.orderUseCase.findOrderByUtxo(offerData) + console.log(`orderData: ${JSON.stringify(orderData, null, 2)}`) + } catch (err) { + console.log('Order matching this Counter Offer is not managed by this instance of bch-dex. Skipping.') + + // Add order to list of seen orders, so that we don't spent time trying to validate it again. + this.seenOffers.push(eventId) + + return 'N/A' + } + + // Verify that the UTXO for sale is valid. + let utxoStatus = null + try { + // Get the status of the UTXO associate with this Offer. + const utxo = { + tx_hash: offerData.data.utxoTxid, + tx_pos: offerData.data.utxoVout + } + // console.log(`Checking this UTXO: ${JSON.stringify(utxo, null, 2)}`) + + // utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo) + utxoStatus = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.utxoIsValid, utxo) + console.log('utxoStatus: ', utxoStatus) + } catch (err) { + console.log('acceptCounterOffer() err validating UTXO: ', err) + + // Handle corner case of bad-data in the Offer model. + if (err.isAxiosError) { + console.log('Error trying to contact wallet service: ', err) + return 'N/A' + } else { + return 'N/A' + } + } + + // If the Offer UTXO is spent, exit. + if (utxoStatus === false) { + // Add order to list of seen orders, so that we don't spent time trying to validate it again. + this.seenOffers.push(eventId) + + console.log(`Aborting Counter Offer from Event ID ${eventId}`) + console.log(`https://astral.psfoundation.info/${this.adapters.nostr.eventId2note(eventId)}`) + + return 'N/A' + } + + // Deserialize the partially signed transaction. + const txHex = offerData.data.partialTxHex + const txObj = await this.adapters.wallet.deseralizeTx(txHex) + console.log(`txObj: ${JSON.stringify(txObj, null, 2)}`) + + // Ensure the 3rd output (vout=2) contains the required amount of BCH. + const satsToReceive = Math.ceil(orderData.numTokens * parseInt(orderData.rateInBaseUnit)) + console.log('Ceil', satsToReceive) + if (isNaN(satsToReceive)) { + throw new Error('Could not calculate the amount of BCH offered in the Counter Offer') + } + const satsOut = this.adapters.wallet.bchWallet.bchjs.BitcoinCash.toSatoshi(txObj.vout[2].value) + const hasRequiredAmount = satsOut === satsToReceive + if (!hasRequiredAmount) { + throw new Error(`The Counter Offer has an output of ${satsOut}, which does not match the required ${satsToReceive} in the Offer.`) + } + + // Ensure the 3rd output (vout=2) is going to the maker address specified + // in the Offer. + const addrInCounterOffer = txObj.vout[2].scriptPubKey.addresses[0] + const makerAddr = orderData.makerAddr + const hasCorrectAddr = makerAddr === addrInCounterOffer + if (!hasCorrectAddr) { + throw new Error(`The Counter Offer has an output address of ${addrInCounterOffer}, which does not match the Maker address of ${makerAddr} in the Offer.`) + } + + // Sign and broadcast the transaction. + const txid = await this.adapters.wallet.completeTx(txHex, orderData.hdIndex) + console.log('txid: ', txid) + + return txid + } catch (err) { + console.error('Error in acceptCounterOffer(): ', err) + throw err + } + } + + // TODO: Write unit tests for this function, then add it to the Timer Controllers + // Looks for duplicate offers and removes the duplicate. + // Duplicates are checked for when an offer is created, and so should not + // exist. But emperical testing shows that they do. This function is called + // periodically by a timer, to clean up any duplicates that slipped through + // the cracks. + async removeDuplicateOffers () { + try { + const now = new Date() + console.log(`Starting removeDuplicateOffers() at ${now.toLocaleString()}`) + + let duplicateFound = false + + // Get all Offers in the database. + const offers = await this.OfferModel.find({}) + // console.log('offers: ', offers) + + const offerZcids = [] + + for (let i = 0; i < offers.length; i++) { + const thisOffer = offers[i] + + if (offerZcids.includes(thisOffer.p2wdbHash)) { + await thisOffer.remove() + duplicateFound = true + continue + } + + // Add the zcid to the array. + offerZcids.push(thisOffer.p2wdbHash) + } + + return duplicateFound + } catch (err) { + console.error('Error in removeDuplicateOffers()') + throw err + } + } + + // This function is called by the garbage collection timer controller. It + // checks the UTXO associated with each Offer in the database. If the UTXO + // has been spent, the Offer is deleted from the database. + async removeStaleOffers () { + try { + const now = new Date() + console.log(`Starting garbage collection for Offers at ${now.toLocaleString()}`) + + // Get all Offers in the database. + const offers = await this.OfferModel.find({}) + // console.log('offers: ', offers) + + // Loop through each Offer and ensure the UTXO is still valid. + for (let i = 0; i < offers.length; i++) { + const thisOffer = offers[i] + + let utxoStatus = null + try { + // Get the status of the UTXO associate with this Offer. + const utxo = { + tx_hash: thisOffer.utxoTxid, + tx_pos: thisOffer.utxoVout + } + // console.log(`Checking this UTXO: ${JSON.stringify(utxo, null, 2)}`) + + // utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo) + utxoStatus = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.utxoIsValid, utxo) + // console.log('utxoStatus: ', utxoStatus) + } catch (err) { + // Handle corner case of bad-data in the Offer model. + if (err.message && err.message.includes('txid needs to be a proper transaction ID')) { + console.log(`Deleting Offer with bad data: ${JSON.stringify(thisOffer, null, 2)}`) + await thisOffer.remove() + continue + } else if (err.isAxiosError) { + console.log('Error trying to contact wallet service: ', err) + continue + } else { + throw err + } + } + + // If the Offer UTXO is spent, delete the Offer model. + if (utxoStatus === false) { + // console.log('utxoStatus: ', utxoStatus) + console.log(`Spent UTXO detected. Deleting this Offer: ${JSON.stringify(thisOffer, null, 2)}`) + await thisOffer.remove() + } + + // If the Offer is older than 7 days, delete it. + const nowMs = now.getTime() + const eightWeeks = 1000 * 60 * 60 * 24 * 7 * 8 + const eightWeeksAgo = nowMs - eightWeeks + if (thisOffer.timestamp < eightWeeksAgo) { + console.log('Offer older than 8 weeks. Deleting.') + await thisOffer.remove() + } + } + } catch (err) { + console.error('Error in removeStaleOffers(): ', err) + throw err + } + } + + // Flag offers as NSFW. + async flagOffer (flagData = {}) { + try { + if (!flagData.data) throw new Error('"data" property is required') + + console.log(`flagData: ${JSON.stringify(flagData, null, 2)}`) + + const eventId = flagData.data.nostrEventId + + // Get the offer from the database. + const offer = await this.findOfferByEvent(eventId) + console.log(`Flagging this offer: ${JSON.stringify(offer, null, 2)}`) + + if (!offer) { + throw new Error(`Offer ${eventId} not found in the database.`) + } + + // Add the raw flag data to the database model. + offer.flags.push(flagData) + + // If flag count is 3 or more, mark the Offer as NSFW + const flagCnt = offer.flags.length + if (flagCnt >= 3) { + offer.nsfw = true + } + + // Save the updated offer data to the database. + await offer.save() + + return true + } catch (error) { + console.error('Error in flagOffer(): ', error) + throw error + } + } + + // Get offers data from nostr. + async loadOffers () { + try { + // Retrieve offers array. + const offers = await this.adapters.nostr.read() + // console.log('offers: ', offers) + + for (let i = 0; i < offers.length; i++) { + try { + const offer = offers[i] + + // offer data + const offerObj = JSON.parse(offer.content) + + // Append the Nostr Event ID to the offer object + offerObj.data.nostrEventId = offer.eventId + // console.log('loadOffers() offerObj: ', offerObj) + + if (offerObj.data.dataType === 'offer') { + // Try to create new offer + await this.createOffer(offerObj) + } + + if (offerObj.data.dataType === 'counter-offer') { + // console.log('Counter offer detected: ', offerObj) + // console.log('Counter offer detected: ', offerObj.data.nostrEventId) + console.log(`Counter offer detected: https://astral.psfoundation.info/${this.adapters.nostr.eventId2note(offerObj.data.nostrEventId)}`) + await this.acceptCounterOffer(offerObj) + } + + // Ignore the post if it doesn't fit the above filters. + } catch (error) { + /* exit quietly */ + } + } + } catch (error) { + console.error('Error in loadOffers(): ', error) + throw error + } + } +} + +export default OfferUseCases + +``` + +`/home/trout/work/psf/code/bch-dex/src/use-cases/offer/retry-queue.js`: + +```js +/* + This library leverages the p-retry and p-queue libraries, to create a + validation queue with automatic retry. + + New nodes syncing will attempt to rapidly validate a lot of entries. + A promise-based queue allows this to happen while respecting rate-limits + of the blockchain service provider. + + pay-to-write-access-controller.js depends on this library. +*/ + +// Global npm libraries +import PQueue from 'p-queue' +import pRetry from 'p-retry' + +let _this + +class RetryQueue { + constructor (localConfig = {}) { + if (!localConfig.bchjs) { + throw new Error( + 'Must pass instance of bch-js when instantiating RetryQueue Class.' + ) + } + this.bchjs = localConfig.bchjs + + // Encapsulate dependencies + this.validationQueue = new PQueue({ concurrency: 1 }) + this.pRetry = pRetry + + this.attempts = 5 + + _this = this + } + + // Add an async function to the queue, and execute it with the input object. + async addToQueue (funcHandle, inputObj) { + try { + console.log('addToQueue inputObj: ', inputObj) + + if (!funcHandle) { + throw new Error('function handler is required') + } + if (!inputObj) { + throw new Error('input object is required') + } + + const returnVal = await _this.validationQueue.add(() => + _this.retryWrapper(funcHandle, inputObj) + ) + return returnVal + } catch (err) { + console.error('Error in addToQueue(): ', err) + throw err + } + } + + // Wrap the p-retry library. + // This function returns a promise that will resolve to the output of the + // function 'funcHandle'. + async retryWrapper (funcHandle, inputObj) { + try { + console.log('retryWrapper inputObj: ', inputObj) + + if (!funcHandle) { + throw new Error('function handler is required') + } + if (!inputObj) { + throw new Error('input object is required') + } + console.log('Entering retryWrapper()') + + // Add artificial delay to prevent 429 errors. + await this.bchjs.Util.sleep(2000) + + return this.pRetry( + async () => { + return await funcHandle(inputObj) + }, + { + onFailedAttempt: _this.handleValidationError, + retries: this.attempts // Retry 5 times + } + ) + } catch (err) { + console.error('Error in retryWrapper: ', err) + throw err + } + } + + // Notifies the user that an error occured and that a retry will be attempted. + // It tracks the number of retries until it fails. + async handleValidationError (error) { + try { + const errorMsg = `Attempt ${error.attemptNumber} to validate entry. There are ${error.retriesLeft} retries left. Waiting before trying again.` + console.log(errorMsg) + const SLEEP_TIME = 30000 + console.log(`Waiting ${SLEEP_TIME} milliseconds before trying again.\n`) + await _this.bchjs.Util.sleep(SLEEP_TIME) // 30 sec + } catch (err) { + console.error('Error in handleValidationError(): ', err) + throw err + } + } +} + +export default RetryQueue + +``` + +`/home/trout/work/psf/code/bch-dex/src/use-cases/usage-use-cases.js`: + +```js +/* + Use Case library for tracking usage. This library contains business logic + for tracking the usage of REST API and JSON RPC calls. This library is used + by admins to keep an eye on how many API calls were made in a 24-hour and + 1-hour time period. +*/ + +// This global variable is used to share data between the REST middleware and +// the Usage Use Case class instance. +let restCalls = [] + +class UsageUseCases { + constructor (localConfig = {}) { + // console.log('User localConfig: ', localConfig) + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of adapters must be passed in when instantiating Usage Use Cases library.' + ) + } + + // Bind 'this' object to all subfunctions + this.cleanUsage = this.cleanUsage.bind(this) + this.getRestSummary = this.getRestSummary.bind(this) + this.getTopIps = this.getTopIps.bind(this) + this.getTopEndpoints = this.getTopEndpoints.bind(this) + + // State + } + + // Clean up the state by removing entries that are older than 24 hours. This + // ensures stats reflect only the last 24 hours. + // This function is called by a Timer Controller. + cleanUsage () { + try { + const now = new Date() + const twentyFourHoursAgo = now.getTime() - (60000 * 60 * 24) + + console.log('cleanUsage() now: ', now) + console.log('cleanUsage() restCalls.length before filtering: ', restCalls.length) + restCalls = restCalls.filter(x => x.timestamp > twentyFourHoursAgo) + console.log('cleanUsage() restCalls.length after filtering: ', restCalls.length) + + return restCalls + } catch (err) { + console.error('Error in usage-use-cases.js/cleanUsage()') + throw err + } + } + + // Track the calls to a REST API + getRestSummary (inObj = {}) { + try { + console.log(`getRestSummary(): There have been ${restCalls.length} REST calls`) + + return restCalls.length + } catch (err) { + console.error('Error in usage-use-cases.js/getRestSummary()') + throw err + } + } + + // Get the top 20 IP addresses from the stats. + getTopIps () { + try { + const ips = restCalls.map(x => x.ip) + // Create a Map to count occurrences of each IP address string + const countMap = new Map() + ips.forEach(ip => { + countMap.set(ip, (countMap.get(ip) || 0) + 1) + }) + + // Convert the Map into an array of objects with `str` and `cnt` properties + const result = Array.from(countMap, ([ip, cnt]) => ({ ip, cnt })) + + // Sort the results by the `cnt` property in descending order + result.sort((a, b) => b.cnt - a.cnt) + + // Ensure the result has at most 20 elements + return result.slice(0, 20) + } catch (err) { + console.error('Error in usage-use-cases.js/getTopIps()') + throw err + } + } + + // Get the top 20 most consumed endpoints. + getTopEndpoints () { + try { + const endpoints = restCalls.map(x => `${x.method} ${x.url}`) + + // Create a Map to count occurrences of each IP address string + const countMap = new Map() + endpoints.forEach(endpoint => { + countMap.set(endpoint, (countMap.get(endpoint) || 0) + 1) + }) + + // Convert the Map into an array of objects with `str` and `cnt` properties + const result = Array.from(countMap, ([endpoint, cnt]) => ({ endpoint, cnt })) + + // Sort the results by the `cnt` property in descending order + result.sort((a, b) => b.cnt - a.cnt) + + // Ensure the result has at most 20 elements + return result.slice(0, 20) + } catch (err) { + console.error('Error in usage-use-cases.js/getTopEndpoints()') + throw err + } + } +} + +// This Koa middleware is called any time there is a REST API. It logs the +// details from the request object. +function usageMiddleware () { + return async (ctx, next) => { + try { + await next() + + // console.log('ctx.request: ', ctx.request) + const now = new Date() + + const reqObj = { + ip: ctx.request.ip, + url: ctx.request.url, + method: ctx.request.method, + timestamp: now.getTime() + } + // console.log('reqObj: ', reqObj) + + restCalls.push(reqObj) + } catch (err) { + ctx.status = err.status || 500 + ctx.body = err.message + ctx.app.emit('error', err, ctx) + } + } +}; + +export { UsageUseCases, usageMiddleware, restCalls } + +``` + +`/home/trout/work/psf/code/bch-dex/src/use-cases/order.js`: + +```js +/* + Order use-case library. +*/ + +// Global npm libraries +import RetryQueue from '@chris.troutner/retry-queue' + +// Local libraries +import wlogger from '../adapters/wlogger.js' +import OrderEntity from '../entities/order.js' +import config from '../../config/index.js' + +const DEFAULT_ENTRIES_PER_PAGE = 20 + +class OrderLib { + constructor (localConfig = {}) { + // console.log('User localConfig: ', localConfig) + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of adapters must be passed in when instantiating Order Use Cases library.' + ) + } + + // Encapsulate dependencies + this.orderEntity = new OrderEntity() + this.OrderModel = this.adapters.localdb.Order + this.UserModel = this.adapters.localdb.Users + this.bch = this.adapters.bch + this.config = config + this.retryQueue = new RetryQueue({ retryPeriod: 1000, attempts: 3 }) + + // Bind subfunctions to the 'this' object. + this.ensureFunds = this.ensureFunds.bind(this) + this.createOrder = this.createOrder.bind(this) + this.findOrderByUtxo = this.findOrderByUtxo.bind(this) + } + + // Create a new order model and add it to the Mongo database. + async createOrder (entryObj) { + try { + // console.log('createOrder(entryObj): ', entryObj) + if (!entryObj) return false + + if (!entryObj.tokenId) throw new Error('entry does not contain required properties') + + const user = await this.UserModel.findById(entryObj.userId) + if (!user) throw new Error('user not found') + + console.log(`Using FullStack.cash: ${this.config.useFullStackCash}`) + const advancedConfig = {} + if (this.config.useFullStackCash) { + advancedConfig.interface = 'rest-api' + advancedConfig.restURL = this.config.apiServer + advancedConfig.apiToken = this.config.apiToken + } else { + advancedConfig.interface = 'consumer-api' + advancedConfig.restURL = this.config.consumerUrl + } + + // Instantiate minimal-slp-wallet with the user's mnemonic. + const BchWallet = this.adapters.wallet.BchWallet + const userWallet = new BchWallet(user.mnemonic, advancedConfig) + + // Wait for wallet to initialize. + await userWallet.walletInfoPromise + await userWallet.initialize() + + // Specify the address to send payment. + console.log('userWallet.walletInfo: ', userWallet.walletInfo) + entryObj.makerAddr = userWallet.walletInfo.cashAddress + console.log('entryObj.makerAddr: ', entryObj.makerAddr) + // console.log('entryObj.makerAddr: ', entryObj.makerAddr) + + // Input Validation + const orderEntity = this.orderEntity.inputValidate(entryObj) + // console.log('orderEntity: ', orderEntity) + + // Optimize the wallet to speed up working with it. + console.log('Optimizing wallet before creating new order.') + // await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.optimize, {}) + await userWallet.optimize() + + // Ensure sufficient tokens exist to create the order. + // await this.ensureFunds(orderEntity) + // await this.retryQueue.addToQueue(this.ensureFunds, orderEntity) + + // Get Ticker for token ID. + // const tokenData = await this.adapters.wallet.bchWallet.getTxData([entryObj.tokenId]) + // const tokenData = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.getTxData, [entryObj.tokenId]) + const tokenData = await userWallet.getTxData([entryObj.tokenId]) + // console.log(`tokenData: ${JSON.stringify(tokenData, null, 2)}`) + orderEntity.ticker = tokenData[0].tokenTicker + + // Move the tokens to holding address. + const moveObj = { + tokenId: orderEntity.tokenId, + qty: orderEntity.numTokens, + wallet: userWallet + } + // const utxoInfo = await this.adapters.wallet.moveTokens(moveObj) + const utxoInfo = await this.retryQueue.addToQueue(this.adapters.wallet.moveTokensFromCustomWallet, moveObj) + // console.log('utxoInfo: ', utxoInfo) + + // Update the UTXO store for the wallet. + await userWallet.bchjs.Util.sleep(3000) + // await this.adapters.wallet.bchWallet.getUtxos() + // await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.initialize, {}) + await userWallet.initialize() + // Update the order with the new UTXO information. + orderEntity.utxoTxid = utxoInfo.txid + orderEntity.utxoVout = utxoInfo.vout + orderEntity.tokenType = utxoInfo.tokenType + + // Add P2WDB specific flag for signaling that this is a new offer. + orderEntity.dataType = 'offer' + + // Post the new Order information to Nostr under the topic set in the + // config file. + const postObj = { + data: orderEntity + } + const postMsg = JSON.stringify(postObj) + const eventId = await this.adapters.nostr.post(postMsg) + // console.log('hash: ', hash) + + // Create a MongoDB model to hold the Order + orderEntity.hdIndex = utxoInfo.hdIndex + orderEntity.nostrEventId = eventId + + console.log(`creating new order model: ${JSON.stringify(orderEntity, null, 2)}`) + const order = new this.OrderModel(orderEntity) + await order.save() + + const noteId = this.adapters.nostr.eventId2note(eventId) + + return { eventId, noteId } + } catch (err) { + // console.log("Error in use-cases/entry.js/createEntry()", err.message) + wlogger.error('Error in use-cases/order.js/createOrder(): ', err) + console.log('error entryObj: ', entryObj) + throw err + } + } + + // Ensure that the wallet has enough BCH and tokens to complete the requested + // trade. + async ensureFunds (orderEntity) { + try { + // console.log('this.adapters.wallet: ', this.adapters.wallet.bchWallet) + // console.log(`walletInfo: ${JSON.stringify(this.adapters.wallet.bchWallet.walletInfo, null, 2)}`) + + // Update the wallet balance + await this.adapters.wallet.bchWallet.getUtxos() + // console.log(`wallet UTXOs: ${JSON.stringify(this.adapters.wallet.bchWallet.utxos.utxoStore, null, 2)}`) + + // Ensure the app wallet has enough funds to write to the P2WDB. + const wif = this.adapters.wallet.bchWallet.walletInfo.privateKey + const canWriteToP2WDB = await this.adapters.p2wdb.checkForSufficientFunds(wif) + if (!canWriteToP2WDB) throw new Error('App wallet does not have funds for writing to the P2WDB.') + + // Get UTXOs. + const utxos = this.adapters.wallet.bchWallet.utxos.utxoStore + // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`) + + if (orderEntity.buyOrSell.includes('sell')) { + // Sell Order + + // Combine Fungible and NFT token UTXOs. + let tokenUtxos = utxos.slpUtxos.type1.tokens.concat(utxos.slpUtxos.nft.tokens) + // Get token UTXOs that match the token in the order. + tokenUtxos = tokenUtxos.filter( + x => x.tokenId === orderEntity.tokenId + ) + + // Get the total amount of tokens in the wallet that match the token + // in the order. + let totalTokenBalance = 0 + tokenUtxos.map(x => (totalTokenBalance += parseFloat(x.qtyStr))) + console.log('totalTokenBalance: ', totalTokenBalance) + + // If there are fewer tokens in the wallet than what's in the order, + // throw an error. + if (totalTokenBalance < orderEntity.numTokens || isNaN(totalTokenBalance)) { + throw new Error( + 'App wallet does not have enough tokens to satisfy the SELL order.' + ) + } + + // + } else { + // Buy Order + throw new Error('Buy orders are not supported yet.') + } + + return true + } catch (err) { + console.error('Error in ensureFunds()') + throw err + } + } + + // Retrieve an Order model from the database. Find it by its event Id. + async findOrderByEvent (nostrEventId) { + try { + if (typeof nostrEventId !== 'string' || !nostrEventId) { + throw new Error('nostrEventId must be a string') + } + + const order = await this.OrderModel.findOne({ nostrEventId }) + + if (!order) { + throw new Error('order not found') + } + + const orderObject = order.toObject() + // return this.offerEntity.validateFromModel(offerObject) + + return orderObject + } catch (err) { + console.error('Error in findOrderByEvent()') + throw err + } + } + + // Retrieve an Order model from the database. Find it by its UTXO (TXID & Vout) + async findOrderByUtxo (offerData = {}) { + try { + // console.log('findOrderByUtxo() offerData: ', offerData) + + // const order = await this.OrderModel.findOne({ nostrEventId }) + const order = await this.OrderModel.findOne({ utxoTxid: offerData.data.utxoTxid, utxoVout: offerData.data.utxoVout }) + // const order = await this.OrderModel.findOne({ utxoTxid: offerData.data.utxoTxid }) + // const order = await this.OrderModel.findOne({ tokenId: offerData.data.tokenId }) + console.log('findOrderByUtxo() order: ', order) + + if (!order) { + throw new Error('order not found') + } + if (!order.nostrEventId) { + throw new Error('order not found') + } + + const orderObject = order.toObject() + // return this.offerEntity.validateFromModel(offerObject) + + return orderObject + } catch (err) { + console.error('Error in findOrderByUtxo(): ', err) + throw err + } + } + + // This function is called by the garbage collection timer controller. It + // checks the UTXO associated with each Order in the database. If the UTXO + // has been spent, the Order is deleted from the database. + async removeStaleOrders () { + try { + const now = new Date() + console.log(`Starting garbage collection for Orders at ${now.toLocaleString()}`) + + // Get all Orders in the database. + const orders = await this.OrderModel.find({}) + // console.log('orders: ', orders) + + // Loop through each Order and ensure the UTXO is still valid. + for (let i = 0; i < orders.length; i++) { + const thisOrder = orders[i] + + let utxoStatus = null + try { + // Get the status of the UTXO associate with this Order. + // utxoStatus = await this.adapters.bchjs.Blockchain.getTxOut( + // thisOrder.utxoTxid, + // thisOrder.utxoVout + // ) + + // Get the status of the UTXO associate with this Order. + const utxo = { + tx_hash: thisOrder.utxoTxid, + tx_pos: thisOrder.utxoVout + } + // utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo) + utxoStatus = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.utxoIsValid, utxo) + // console.log('utxoStatus: ', utxoStatus) + } catch (err) { + // Handle corner case of bad-data in the Order model. + if (err.message && err.message.includes('txid needs to be a proper transaction ID')) { + console.log(`Deleting Order with bad data: ${JSON.stringify(thisOrder, null, 2)}`) + await thisOrder.remove() + continue + } else if (err.isAxiosError) { + console.log('Error trying to contact wallet service: ', err) + continue + } else { + throw err + } + } + + // If the Order UTXO is spent, delete the Order model. + if (utxoStatus === false) { + // console.log('utxoStatus: ', utxoStatus) + console.log(`Spent UTXO detected. Deleting this Order: ${JSON.stringify(thisOrder, null, 2)}`) + await thisOrder.remove() + } + } + } catch (err) { + console.error('Error in removeStaleOrders()') + throw err + } + } + + async listOrders (page = 0) { + try { + const data = await this.OrderModel.find({}) + + // Sort entries so newest entries show first. + .sort('-timestamp') + // Skip to the start of the selected page. + .skip(page * DEFAULT_ENTRIES_PER_PAGE) + // Only return 20 results. + .limit(DEFAULT_ENTRIES_PER_PAGE) + + return data + } catch (error) { + console.error('Error in use-cases/order/listOrders()') + throw error + } + } + + // Delete an Order model by sending the token back to the root address. This + // will allow the garbage collectors to delete the Order and the Offer. + async deleteOrder (nostrEventId) { + try { + // Find the order by the given hash. + const order = await this.findOrderByEvent(nostrEventId) + console.log('order: ', order) + + // Reclaim the tokens + const txid = await this.adapters.wallet.reclaimTokens(order) + + return txid + } catch (err) { + console.error('Error in use-cases/order/deleteOrder()') + throw err + } + } +} + +export default OrderLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/use-cases/user.js`: + +```js +/* + This library contains business-logic for dealing with users. Most of these + functions are called by the /user REST API endpoints. +*/ + +import UserEntity from '../entities/user.js' + +import wlogger from '../adapters/wlogger.js' + +class UserLib { + constructor (localConfig = {}) { + // console.log('User localConfig: ', localConfig) + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of adapters must be passed in when instantiating User Use Cases library.' + ) + } + this.BchWallet = this.adapters.wallet.BchWallet + // Encapsulate dependencies + this.UserEntity = new UserEntity() + this.UserModel = this.adapters.localdb.Users + } + + // Create a new user model and add it to the Mongo database. + async createUser (userObj) { + try { + // Input Validation + + const userEntity = this.UserEntity.validate(userObj) + const user = new this.UserModel(userEntity) + + const wallet = new this.BchWallet() + const walletInfo = await wallet.walletInfoPromise + const mnemonic = walletInfo.mnemonic + user.mnemonic = mnemonic + + // Enforce default value of 'user' + user.type = 'user' + // console.log('user: ', user) + + // Save the new user model to the database. + await user.save() + + // Generate a JWT token for the user. + const token = user.generateToken() + + // Convert the database model to a JSON object. + const userData = user.toJSON() + // console.log('userData: ', userData) + + // Delete the password property. + delete userData.password + + return { userData, token } + } catch (err) { + // console.log('createUser() error: ', err) + wlogger.error('Error in lib/users.js/createUser()') + throw err + } + } + + // Returns an array of all user models in the Mongo database. + async getAllUsers () { + try { + // Get all user models. Delete the password property from each model. + const users = await this.UserModel.find({}, '-password') + + return users + } catch (err) { + wlogger.error('Error in lib/users.js/getAllUsers()') + throw err + } + } + + // Get the model for a specific user. + async getUser (params) { + try { + const { id } = params + + const user = await this.UserModel.findById(id, '-password') + + // Throw a 404 error if the user isn't found. + if (!user) { + const err = new Error('User not found') + err.status = 404 + throw err + } + + return user + } catch (err) { + // console.log('Error in getUser: ', err) + + if (err.status === 404) throw err + + // Return 422 for any other error + err.status = 422 + err.message = 'Unprocessable Entity' + throw err + } + } + + async updateUser (existingUser, newData) { + try { + // console.log('existingUser: ', existingUser) + // console.log('newData: ', newData) + + // Input Validation + // Optional inputs, but they must be strings if included. + + if (newData.email && typeof newData.email !== 'string') { + throw new Error("Property 'email' must be a string!") + } + if (newData.name && typeof newData.name !== 'string') { + throw new Error("Property 'name' must be a string!") + } + if (newData.password && typeof newData.password !== 'string') { + throw new Error("Property 'password' must be a string!") + } + if (newData.mnemonic) { + throw new Error("Property 'mnemonic' cannot be updated!") + } + + // Save a copy of the original user type. + const userType = existingUser.type + // console.log('userType: ', userType) + + // If user 'type' property is sent by the client + if (newData.type) { + if (typeof newData.type !== 'string') { + throw new Error("Property 'type' must be a string!") + } + + // Unless the calling user is an admin, they can not change the user type. + if (userType !== 'admin') { + throw new Error("Property 'type' can only be changed by Admin user") + } + } + + // Overwrite any existing data with the new data. + Object.assign(existingUser, newData) + + // Save the changes to the database. + await existingUser.save() + + // Delete the password property. + delete existingUser.password + + return existingUser + } catch (err) { + wlogger.error('Error in lib/users.js/updateUser()') + throw err + } + } + + async deleteUser (user) { + try { + await user.remove() + } catch (err) { + wlogger.error('Error in lib/users.js/deleteUser()') + throw err + } + } + + // Used to authenticate a user. If the login and password salt match a user in + // the database, then it returns the user model. The Koa REST API uses the + // Passport library for this functionality. This function is used to + // authenticate users who login via the JSON RPC. + async authUser (login, passwd) { + try { + // console.log('login: ', login) + // console.log('passwd: ', passwd) + + const user = await this.UserModel.findOne({ email: login }) + if (!user) { + throw new Error('User not found') + } + + const isMatch = await user.validatePassword(passwd) + + if (!isMatch) { + throw new Error('Login credential do not match') + } + + return user + } catch (err) { + // console.error('Error in users.js/authUser()') + console.log('') + throw err + } + } +} + +export default UserLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/use-cases/entry.js`: + +```js + +// local libraries +import wlogger from '../adapters/wlogger.js' +import EntryEntiy from '../entities/entry.js' + +class EntryLib { + constructor (localConfig = {}) { + // console.log('User localConfig: ', localConfig) + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of adapters must be passed in when instantiating User Use Cases library.' + ) + } + + // Encapsulate dependencies + this.EntryEntity = new EntryEntiy() + this.EntryModel = this.adapters.localdb.Entry + this.bch = this.adapters.bch + } + + // Create a new entry model and add it to the Mongo database. + async createEntry (entryObj) { + try { + // Input Validation + const entryEntity = this.EntryEntity.validate(entryObj) + + // Verify that the entry was signed by a specific BCH address. + const isValidSignature = this.bch._verifySignature(entryEntity) + if (!isValidSignature) { + throw new Error('Invalid signature') + } + + // Verify psf tokens balance + // const psfBalance = await this.bch.getPSFTokenBalance( + // entryEntity.slpAddress + // ) + const psfBalance = 1 + + if (psfBalance < 10) { + throw new Error('Insufficient psf balance') + } + + const merit = await this.bch.getMerit(entryEntity.slpAddress) + + const updatedEntry = { + entry: entryEntity.entry.trim(), + slpAddress: entryEntity.slpAddress.trim(), + description: entryEntity.description.trim(), + signature: entryEntity.signature.trim(), + category: entryEntity.category.trim(), + balance: psfBalance, + merit + } + + const entryModel = new this.EntryModel(updatedEntry) + await entryModel.save() + + return entryModel + } catch (err) { + // console.log("Error in use-cases/entry.js/createEntry()", err.message) + wlogger.error('Error in use-cases/entry.js/createEntry()') + throw err + } + } +} + +export default EntryLib + +``` + +`/home/trout/work/psf/code/bch-dex/src/entities/offer.js`: + +```js +/* + Offer Entity + An ffer is created when a new Signal is detected via the P2WDB webhook. + It's destroyed when the UTXO described in the Signal has been detected as spent. +*/ + +class OfferEntity { + constructor () { + this.offerStatus = ['posted', 'taken', 'dead'] + } + + validate (offerData = {}) { + // Throw an error if input object does not have a data property + if (!offerData.data) { + throw new Error( + 'Input to offer.validate() must be an object with a data property.' + ) + } + + // console.log('offer entity validate() offerData: ', offerData) + + const { + messageType, + messageClass, + tokenId, + buyOrSell, + rateInBaseUnit, + minUnitsToExchange, + numTokens, + utxoTxid, + utxoVout, + offerStatus, + makerAddr, + ticker, + tokenType, + nostrEventId + } = offerData.data + + // Input Validation + if (!messageType || typeof messageType !== 'number') { + throw new Error("Property 'messageType' must be an integer number.") + } + if (!messageClass || typeof messageClass !== 'number') { + throw new Error("Property 'messageClass' must be an integer number.") + } + if (!tokenId || typeof tokenId !== 'string') { + throw new Error("Property 'tokenId' must be a string.") + } + if (!buyOrSell || typeof buyOrSell !== 'string') { + throw new Error("Property 'buyOrSell' must be a string.") + } + if (!rateInBaseUnit || typeof rateInBaseUnit !== 'number') { + throw new Error("Property 'rateInBaseUnit' must be an integer number.") + } + if (!minUnitsToExchange || typeof minUnitsToExchange !== 'number') { + throw new Error("Property 'minUnitsToExchange' must be an integer number.") + } + if (!numTokens || typeof numTokens !== 'number') { + throw new Error("Property 'numTokens' must be a number.") + } + if (!utxoTxid || typeof utxoTxid !== 'string') { + throw new Error("Property 'utxoTxid' must be a string.") + } + if (typeof utxoVout !== 'number') { + throw new Error("Property 'utxoVout' must be an integer number.") + } + if (offerStatus && !this.offerStatus.includes(offerStatus)) { + throw new Error("Property 'offerStatus' must be posted, taken, or dead") + } + if (!makerAddr || typeof makerAddr !== 'string') { + throw new Error("Property 'makerAddr' must be a string.") + } + // if (!ticker || typeof ticker !== 'string') { + // throw new Error("Property 'ticker' must be a string.") + // } + if (!tokenType || typeof tokenType !== 'number') { + throw new Error("Property 'tokenType' must be a number.") + } + if (!nostrEventId || typeof nostrEventId !== 'string') { + throw new Error("Property 'nostrEventId' must be a string.") + } + + // Convert the timestamp to a number. + let timestamp = new Date(offerData.timestamp) + timestamp = timestamp.getTime() + + const validatedOfferData = { + messageType, + messageClass, + tokenId, + buyOrSell, + rateInBaseUnit, + minUnitsToExchange, + numTokens, + utxoTxid, + utxoVout, + timestamp, + globaltimestamp: offerData.timestamp, + localTimestamp: offerData.localTimeStamp, + txid: offerData.txid, + p2wdbHash: offerData.hash, + offerStatus: offerStatus || this.offerStatus[0], + makerAddr, + ticker, + tokenType, + nostrEventId + } + // console.log('offer entity validatedOfferData: ', validatedOfferData) + + return validatedOfferData + } +} + +export default OfferEntity + +``` + +`/home/trout/work/psf/code/bch-dex/src/entities/order.js`: + +```js +/* + Order Entity + An Order Entity is nearly the same as an Offer. But while an Offer is generated + by a webhook from P2WDB, the Order Entity is created internally. It is used + to track an Order generated by this application. + + The Order tracks the hdIndex address used to hold tokens or BCH for sale. +*/ +class Order { + // TODO: Create a fullValidate() function that validates a fully-hydrated + // order model. + + inputValidate (data) { + const { + messageType, + messageClass, + tokenId, + buyOrSell, + rateInBaseUnit, + minUnitsToExchange, + numTokens, + makerAddr + } = data + + // Input Validation + if (!messageType || typeof messageType !== 'number') { + throw new Error("Property 'messageType' must be an integer number.") + } + if (!messageClass || typeof messageClass !== 'number') { + throw new Error("Property 'messageClass' must be an integer number.") + } + if (!tokenId || typeof tokenId !== 'string') { + throw new Error("Property 'tokenId' must be a string.") + } + if (!buyOrSell || typeof buyOrSell !== 'string') { + throw new Error("Property 'buyOrSell' must be a string.") + } + if (!rateInBaseUnit || typeof rateInBaseUnit !== 'number') { + throw new Error("Property 'rateInBaseUnit' must be an integer number.") + } + if (!minUnitsToExchange || typeof minUnitsToExchange !== 'number') { + throw new Error("Property 'minUnitsToExchange' must be an integer number.") + } + if (!numTokens || typeof numTokens !== 'number') { + throw new Error("Property 'numTokens' must be a number.") + } + if (!makerAddr || typeof makerAddr !== 'string') { + throw new Error("Property 'makerAddr' must be a string.") + } + // if (!ticker || typeof ticker !== 'string') { + // throw new Error("Property 'ticker' must be a string.") + // } + + const offerData = { + messageType, + messageClass, + tokenId, + buyOrSell, + rateInBaseUnit, + minUnitsToExchange, + numTokens, + makerAddr + // ticker + } + + return offerData + } +} + +export default Order + +``` + +`/home/trout/work/psf/code/bch-dex/src/entities/user.js`: + +```js +/* + User Entity +*/ + +class User { + validate ({ name, email, password } = {}) { + // Input Validation + if (!email || typeof email !== 'string') { + throw new Error("Property 'email' must be a string!") + } + if (!password || typeof password !== 'string') { + throw new Error("Property 'password' must be a string!") + } + if (!name || typeof name !== 'string') { + throw new Error("Property 'name' must be a string!") + } + + const userData = { name, email, password } + + return userData + } +} + +export default User + +``` + +`/home/trout/work/psf/code/bch-dex/src/entities/entry.js`: + +```js +/* + Entry Entity +*/ +class Entry { + validate ({ + entry, + description, + slpAddress, + signature, + category + } = {}) { + // Input Validation + if (!entry || typeof entry !== 'string') { + throw new Error("Property 'entry' must be a string!") + } + if (!description || typeof description !== 'string') { + throw new Error("Property 'description' must be a string!") + } + if (!slpAddress || typeof slpAddress !== 'string') { + throw new Error("Property 'slpAddress' must be a string!") + } + if (!signature || typeof signature !== 'string') { + throw new Error("Property 'signature' must be a string!") + } + if (!category || typeof category !== 'string') { + throw new Error("Property 'category' must be a string!") + } + + const entryData = { + entry, + description, + slpAddress, + signature, + category + } + + return entryData + } +} + +export default Entry + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/nostr.adapter.unit.js`: + +```js +/* + Unit tests for the Nostr Adapter library. +*/ + +// Public npm libraries. +import { assert } from 'chai' +import sinon from 'sinon' +import NostrAdapter from '../../../src/adapters/nostr.js' +import NostrMock from '../mocks/nostr-mock.js' + +describe('#nostr.js', () => { + let uut + let sandbox + + before(() => {}) + + beforeEach(() => { + uut = new NostrAdapter({ + nostrRelay: 'wss://nostr', + nostrTopic: 'uut-topic' + }) + uut.RelayPool = NostrMock.RelayPoolMock + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + after(() => {}) + + describe('#contructor', () => { + it('should throw an error if nostr relay is not provided', async () => { + try { + const _uut = new NostrAdapter() + // Eslint + console.log(_uut) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include( + err.message, + '"nostrRelay" must be passed when instantiate NostrAdapter' + ) + } + }) + it('should throw an error if nostr topic is not provided', async () => { + try { + const _uut = new NostrAdapter({ nostrRelay: 'wss://' }) + // Eslint + console.log(_uut) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include( + err.message, + '"nostrTopic" must be passed when instantiate NostrAdapter' + ) + } + }) + }) + describe('#start', () => { + it('should throw an error if WIF is not provided', async () => { + try { + await uut.start() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'WIF must be a string!') + } + }) + it('should start adapter', async () => { + // Stub bchNostr + sandbox + .stub(uut.bchNostr.keys, 'createNostrPubKeyFromWif') + .returns({ privKeyBuf: 'privKeyBuf', nostrPubKey: 'nostrPubKey' }) + + const result = await uut.start('WIF') + assert.isTrue(result) + }) + }) + + describe('#post', () => { + it('should throw an error if msg is not provided', async () => { + try { + await uut.post() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'msg must be a string!') + } + }) + it('should post message', async () => { + const evId = 'uut-eventId' // Mock + + sandbox.stub(uut.bchNostr.post, 'uploadToNostr').resolves(evId) + + const result = await uut.post('uut-message') + assert.isString(result) + assert.equal(result, evId) + }) + }) + + describe('#read', () => { + it('should throw an error if provided limit is wrong', async () => { + try { + await uut.read(-5) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'Limit must be greater than 0') + } + }) + + it('should read message', async () => { + const result = await uut.read() + assert.isArray(result) + assert.equal(result.length, 1) + }) + + it('should read message with custom limit', async () => { + const result = await uut.read(1) + assert.isArray(result) + assert.equal(result.length, 1) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/webhook.adapter.unit.js`: + +```js +/* + Unit tests for the webhook adapter. +*/ + +import { assert } from 'chai' +import sinon from 'sinon' + +import WebHook from '../../../src/adapters/webhook.js' + +// Set the environment variable to signal this is a test. +process.env.TORLIST_ENV = 'test' + +describe('#Webhook-Adapter', () => { + let uut + let sandbox + + beforeEach(async () => { + uut = new WebHook() + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#createWebHook', () => { + it('should throw error if input is not provided', async () => { + try { + await uut.createWebhook() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'url must be a string') + } + }) + + it('should throw error if input is not string', async () => { + try { + await uut.createWebhook(1) + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'url must be a string') + } + }) + + it('should handle error', async () => { + try { + sandbox.stub(uut.axios, 'post').throws(new Error('test error')) + await uut.createWebhook('https://test.com/my-webhook') + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should return response', async () => { + sandbox + .stub(uut.axios, 'post') + .resolves({ data: { success: true, id: '61018c8c9a71973a596cdccb' } }) + + const url = 'https://test.com/my-webhook' + const result = await uut.createWebhook(url) + + assert.isObject(result) + assert.property(result, 'success') + assert.property(result, 'id') + assert.isBoolean(result.success) + assert.isString(result.id) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/ipfs.adapter.unit.js`: + +```js +/* + Unit tests for the IPFS Adapter. +*/ + +// Global npm libraries +import { assert } from 'chai' +import sinon from 'sinon' +import cloneDeep from 'lodash.clonedeep' +// import { peerIdFromString } from '@libp2p/peer-id' + +// Local libraries +import IPFSLib from '../../../src/adapters/ipfs/ipfs.js' +// import create from '../mocks/ipfs-mock.js' +import config from '../../../config/index.js' +import createHeliaLib from '../mocks/helia-mock.js' + +// config.isProduction = true; +describe('#IPFS-adapter', () => { + let uut + let sandbox + let ipfs + + beforeEach(() => { + uut = new IPFSLib() + + ipfs = cloneDeep(createHeliaLib) + + sandbox = sinon.createSandbox() + }) + + afterEach(() => { + sandbox.restore() + }) + + describe('#constructor', () => { + it('should instantiate IPFS Lib in dev mode.', async () => { + const _uut = new IPFSLib() + assert.exists(_uut) + assert.isFunction(_uut.start) + assert.isFunction(_uut.stop) + }) + + it('should instantiate dev IPFS Lib in production mode.', async () => { + config.isProduction = true + const _uut = new IPFSLib() + assert.exists(_uut) + assert.isFunction(_uut.start) + assert.isFunction(_uut.stop) + config.isProduction = false + }) + }) + + describe('#start', () => { + it('should return a promise that resolves into an instance of IPFS.', async () => { + // Mock dependencies. + sandbox.stub(uut, 'createNode').resolves(ipfs) + sandbox.stub(uut, 'publicIp').resolves('192.168.2.4') + sandbox.stub(uut, 'multiaddr').returns('/ip4/fake-multiaddr') + + const result = await uut.start() + // console.log('result: ', result) + + // Assert properties of the instance are set. + assert.equal(uut.isReady, true) + assert.property(uut, 'multiaddrs') + assert.property(uut, 'id') + + // Output should be an instance of IPFS + assert.property(result, 'libp2p') + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + sandbox.stub(uut, 'createNode').rejects(new Error('test error')) + + await uut.start() + assert.fail('Unexpected code path.') + } catch (err) { + // console.log(err) + assert.include(err.message, 'test error') + } + }) + }) + + describe('#stop', () => { + it('should stop the IPFS node', async () => { + // Mock dependencies + uut.ipfs = { + stop: () => { + } + } + + const result = await uut.stop() + + assert.equal(result, true) + }) + }) + + describe('#ensureBlocksDir', () => { + it('should create directory if it does not exist', () => { + // Force desired code path + sandbox.stub(uut.fs, 'existsSync').returns(false) + sandbox.stub(uut.fs, 'mkdirSync').returns(true) + + const result = uut.ensureBlocksDir() + + assert.equal(result, true) + }) + + it('should report and throw errors', () => { + // Force an error + sandbox.stub(uut.fs, 'existsSync').throws(new Error('test error')) + + try { + uut.ensureBlocksDir() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) + + describe('#createNode', () => { + it('should report and throw errors', async () => { + // Force an error + sandbox.stub(uut, 'createLibp2p').rejects(new Error('test error')) + + try { + await uut.createNode() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should create an IPFS node from Helia', async () => { + uut.config.isCircuitRelay = false + const result = await uut.createNode() + // console.log('result: ', result) + + // Assert the returned IPFS node has expected properties + assert.property(result, 'libp2p') + assert.property(result, 'blockstore') + + // Stop the IPFS node + await result.stop() + }) + + it('should create a Circuit Relay if configured', async () => { + uut.config.isCircuitRelay = true + const result = await uut.createNode() + + // Assert the returned IPFS node has expected properties + assert.property(result, 'libp2p') + assert.property(result, 'blockstore') + + // Stop the IPFS node + await result.stop() + }) + + it('should create a new private key on first run', async () => { + uut.config.isCircuitRelay = false + + // Mock dependencies and force desired code path. + // const beenCalled = false + // sandbox.stub(uut, 'getKeychain').resolves({ + // exportPeerId: async () => { + // if (!beenCalled) { + // beenCalled = true + // throw new Error('test error') + // } + // return peerIdFromString('12D3KooWSXF1PnEfiA8bCG8SJduCvzdwHtvhVPK4WC6zzDoto2XP') + // }, + // createKey: async () => {} + // }) + sandbox.stub(uut, 'createLibp2p').resolves() + sandbox.stub(uut, 'createHelia').resolves({}) + + const result = await uut.createNode() + // console.log('result: ', result) + + assert.property(result, 'fs') + }) + + it('should not use circuit relay when CONNECT_PREF is set to direct', async () => { + process.env.CONNECT_PREF = 'direct' + + uut.config.isCircuitRelay = false + const result = await uut.createNode() + // console.log('result: ', result) + + delete process.env.CONNECT_PREF + + // Assert the returned IPFS node has expected properties + assert.property(result, 'libp2p') + assert.property(result, 'blockstore') + + // Stop the IPFS node + await result.stop() + }) + }) + + describe('#getSeed', () => { + it('should read the seed from the JSON file', async () => { + // Mock dependencies and force desired code path + sandbox.stub(uut.jsonFiles, 'readJSON').resolves('12345678') + + const result = await uut.getSeed() + // console.log('result: ', result) + + assert.isString(result) + }) + + it('should generate a new seed if the JSON file is not found', async () => { + // Mock dependencies and force desired code path + sandbox.stub(uut.jsonFiles, 'readJSON').rejects(new Error('test error')) + sandbox.stub(uut.jsonFiles, 'writeJSON').resolves() + + const result = await uut.getSeed() + // console.log('result: ', result) + + assert.isString(result) + }) + + it('should catch, report, and throw errors', async () => { + try { + // Force an error + sandbox.stub(uut.jsonFiles, 'readJSON').rejects(new Error('test error')) + sandbox.stub(uut.jsonFiles, 'writeJSON').rejects(new Error('test error')) + + await uut.getSeed() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/ipfs-index.adapter.unit.js`: + +```js +/* + Unit tests for the index.js file for the IPFS and ipfs-coord libraries. +*/ + +import { assert } from 'chai' + +import sinon from 'sinon' +import IPFSLib from '../../../src/adapters/ipfs/index.js' +// import create from '../mocks/ipfs-mock.js' +import IPFSCoordMock from '../mocks/ipfs-coord-mock.js' + +describe('#IPFS-adapter-index', () => { + let uut + let sandbox + + beforeEach(() => { + uut = new IPFSLib() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#start', () => { + it('should return a promise that resolves into an instance of IPFS.', async () => { + // Mock dependencies. + uut.ipfsAdapter = { + start: async () => {} + } + uut.IpfsCoordAdapter = IPFSCoordMock + + const result = await uut.start() + + assert.equal(result, true) + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + sandbox.stub(uut.ipfsAdapter, 'start').rejects(new Error('test error')) + + await uut.start() + + assert.fail('Unexpected code path.') + } catch (err) { + // console.log(err) + assert.include(err.message, 'test error') + } + }) + + it('should handle lock-file errors', async () => { + try { + // Force an error + sandbox + .stub(uut.ipfsAdapter, 'start') + .rejects(new Error('Lock already being held')) + + // Prevent process from exiting + sandbox.stub(uut.process, 'exit').returns() + + await uut.start() + + assert.fail('Unexpected code path.') + } catch (err) { + assert.include(err.message, 'Lock already being held') + } + }) + }) + + describe('#getStatus', () => { + it('should return an object with node metrics', () => { + // Force uut to have the needed properties + uut.ipfsCoordAdapter = { + ipfsCoord: { + thisNode: { + ipfsId: 'fake-id', + ipfsMultiaddrs: [], + bchAddr: 'fake-bch-addr', + slpAddr: 'fake-slp-addr', + pubKey: 'fake-pubkey', + peerList: [], + relayData: [] + } + } + } + + const result = uut.getStatus() + // console.log('result: ', result) + + assert.property(result, 'ipfsId') + assert.property(result, 'multiAddrs') + assert.property(result, 'bchAddr') + assert.property(result, 'slpAddr') + assert.property(result, 'pubKey') + assert.property(result, 'peers') + assert.property(result, 'relays') + }) + + it('should catch, report, and throw errors', () => { + try { + uut.getStatus() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err.message: ', err.message) + assert.include(err.message, 'Cannot read properties') + } + }) + }) + + describe('#_removeDuplicatePeers', () => { + it('should return the same array when there are no duplicates', () => { + const inArray = [ + '12D3KooWPpBXhhAeoCZCGuQ3KR4xwHzzvtP57f6zLmo8P7ZFBJFE', + '12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA', + '12D3KooWGsgHWyDLKuV4ZSfRJfsxQJj77rxx3i8Px3qXKHsLN7a2', + '12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY', + '12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu' + ] + + const result = uut._removeDuplicatePeers(inArray) + // console.log('result: ', result) + + assert.equal(result.length, inArray.length) + }) + + it('should remove duplicates from an array', () => { + const inArray = [ + '12D3KooWPpBXhhAeoCZCGuQ3KR4xwHzzvtP57f6zLmo8P7ZFBJFE', + '12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA', + '12D3KooWGsgHWyDLKuV4ZSfRJfsxQJj77rxx3i8Px3qXKHsLN7a2', + '12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY', + '12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu', + '12D3KooWPpBXhhAeoCZCGuQ3KR4xwHzzvtP57f6zLmo8P7ZFBJFE', + '12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA' + ] + + const result = uut._removeDuplicatePeers(inArray) + // console.log('result: ', result) + + assert.equal(result.length, inArray.length - 2) + }) + }) + + describe('#getPeers', () => { + it('should return an array of current JSON data about each peer when showAll is true', async () => { + // Mock dependencies + uut.ipfsCoordAdapter.ipfsCoord = { + thisNode: { + peerData: [{ from: 'a', data: { jsonLd: { name: 'a', protocol: 'test', version: '1' } } }, { from: 'b' }] + }, + adapters: { + ipfs: { + getPeers: async () => ['a', 'b'] + } + } + } + + const result = await uut.getPeers(true) + + assert.isArray(result) + }) + + it('should catch, report, and throw errors', async () => { + try { + // Force an error + uut.ipfsCoordAdapter.ipfsCoord = { + thisNode: {}, + adapters: { + ipfs: { + getPeers: async () => { throw new Error('test error') } + } + } + } + + await uut.getPeers() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err.message: ', err.message) + assert.include(err.message, 'test error') + } + }) + }) + + describe('#getRelays', () => { + it('should return known relays', () => { + uut.ipfsCoordAdapter.ipfsCoord = { + thisNode: { + peerData: [{ from: 'a', data: { jsonLd: { name: 'a', description: 'test' } } }, { from: 'b' }], + relayData: [{ ipfsId: 'c' }, { ipfsId: 'a' }] + } + } + + const result = uut.getRelays() + // console.log('result: ', result) + + assert.isArray(result.v2Relays) + assert.equal(result.v2Relays.length, 2) + assert.property(result.v2Relays[0], 'name') + assert.property(result.v2Relays[0], 'description') + assert.property(result.v2Relays[1], 'name') + assert.property(result.v2Relays[1], 'description') + }) + + it('should catch, report, and throw errors', () => { + try { + // Force an error + uut.ipfsCoordAdapter.ipfsCoord = { thisNode: {} } + + uut.getRelays() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err.message: ', err.message) + assert.include(err.message, 'Cannot read') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/order-pagination.unit.js`: + +```js +/* + Unit tests for the order-pagination.js library. + + These unit tests will probably be rolled into a larger library in the + the future. +*/ + +// Public npm libraries. +import { assert } from 'chai' + +import sinon from 'sinon' +import mongoose from 'mongoose' + +// Local libraries. +import OrderPagination from '../../../src/adapters/localdb/order-pagination.js' + +import Order from '../../../src/adapters/localdb/models/order.js' +import config from '../../../config/index.js' + +describe('#OrderPagination', () => { + let uut, sandbox + + before(async () => { + // Connect to the Mongo Database. + console.log(`Connecting to database: ${config.database}`) + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + + await mongoose.connect(config.database, { + useUnifiedTopology: true, + useNewUrlParser: true + }) + + const order = new Order({ + lokadId: 'lokadId', + messageType: 1, + messageClass: 1, + tokenId: 'tokenId', + buyOrSell: 'buy', + rateInSats: 'rateInSats', + minSatsToExchange: '100', + signature: 'signature', + sigMsg: 'sigMsg', + utxoTxid: 'utxoTxid', + utxoVout: 1, + numTokens: 1, + timestamp: 'timestamp', + localTimestamp: 'localTimestamp', + txid: 'txid', + p2wdbHash: 'p2wdbHash', + hdIndex: 0, + nostrEventId: 'nostrEventId', + dataType: 'dataType', + makerAddr: 'makerAddr', + rateInBaseUnit: 'rateInBaseUnit', + minUnitsToExchange: 'minUnitsToExchange', + ticker: 'ticker', + tokenType: 1 + }) + await order.save() + }) + + beforeEach(() => { + uut = new OrderPagination() + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + after(() => { + mongoose.connection.close() + }) + + describe('#readAll', () => { + it('should get the first page of Order entries', async () => { + const data = await uut.readAll() + // console.log('data: ', data) + + assert.isArray(data) + }) + + it('should catch and throw an error', async () => { + try { + // Force and error. + sandbox.stub(uut.Order, 'find').rejects(new Error('test error')) + + await uut.readAll() + + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'is not a function') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/users.adapter.unit.js`: + +```js +/* + Unit tests for the users Mongoose model. +*/ + +import { assert } from 'chai' + +import sinon from 'sinon' +import mongoose from 'mongoose' + +import User from '../../../src/adapters/localdb/models/users.js' +import config from '../../../config/index.js' + +// Set the environment variable to signal this is a test. +process.env.TORLIST_ENV = 'test' + +describe('#User-Adapter', () => { + // let uut + let sandbox + let testuser + + before(async () => { + // Connect to the Mongo Database. + console.log(`Connecting to database: ${config.database}`) + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect(config.database, { + useUnifiedTopology: true, + useNewUrlParser: true + }) + + testuser = new User({ + email: 'test983@test.com', + name: 'test983', + password: 'password', + mnemonic: '12 words mnemonic' + }) + }) + + beforeEach(async () => { + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + after(async () => { + await testuser.remove() + + mongoose.connection.close() + }) + + describe('#save', () => { + it('should replace the password with a salt', async () => { + await testuser.save() + // console.log('testuser: ', testuser) + + assert.notEqual(testuser.password, 'password') + }) + }) + + describe('#validatePassword', () => { + it('should return true when password matches', async () => { + const result = await testuser.validatePassword('password') + // console.log('result: ', result) + + assert.equal(result, true) + }) + + it('should return false when password does not match', async () => { + const result = await testuser.validatePassword('wrongpassword') + // console.log('result: ', result) + + assert.equal(result, false) + }) + }) + + describe('#generateToken', () => { + it('should generate a JWT token', () => { + const token = testuser.generateToken() + // console.log('token: ', token) + + assert.include(token, 'eyJ') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/passport.adapter.unit.js`: + +```js +import { assert } from 'chai' +import PassportLib from '../../../src/adapters/passport.js' +import sinon from 'sinon' + +let uut +let sandbox + +describe('#passport.js', () => { + beforeEach(() => { + uut = new PassportLib() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('authUser()', () => { + it('should throw error if ctx is not provided', async () => { + try { + await uut.authUser() + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'ctx is required') + } + }) + + it('Should throw error if the passport library fails', async () => { + try { + const error = new Error('cant auth user') + const user = null + + // Mock calls + // https://sinonjs.org/releases/latest/stubs/ + // About yields + sandbox.stub(uut.passport, 'authenticate').yields(error, user) + + const ctx = {} + await uut.authUser(ctx) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'cant auth user') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/wlogger.adapter.unit.js`: + +```js +import { assert } from 'chai' +import { Wlogger } from '../../../src/adapters/wlogger.js' +import sinon from 'sinon' + +let uut +let sandbox + +describe('#wlogger', () => { + beforeEach(() => { + sandbox = sinon.createSandbox() + }) + + afterEach(() => { + sandbox.restore() + + uut = new Wlogger() + }) + + describe('#constructor', () => { + it('should create a new wlogger instance', () => { + uut = new Wlogger() + // console.log('uut: ', uut) + + assert.property(uut, 'transport') + }) + }) + + describe('#notifyRotation', () => { + it('should notify of a log rotation', () => { + uut.notifyRotation() + }) + }) + + describe('#envronment', () => { + it('should write to console in non-test environment', () => { + uut.outputToConsole() + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/logapi.adapter.unit.js`: + +```js +import { assert } from 'chai' +import sinon from 'sinon' +import util from 'util' + +import LogsApiLib from '../../../src/adapters/logapi.js' +import mockData from '../mocks/log-api-mock.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' +util.inspect.defaultOptions = { depth: 1 } +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +const context = {} +let sandbox +let uut +describe('#LogsApiLib', () => { + beforeEach(() => { + uut = new LogsApiLib() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#getLogs()', () => { + it('should return false if password is not provided', async () => { + try { + const result = await uut.getLogs() + assert.property(result, 'success') + assert.isFalse(result.success) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + + it('should return log', async () => { + // Mock dependencies + sandbox.stub(uut, 'generateFileName').returns(`${__dirname.toString()}/../mocks/adapters/fake-log`) + + const pass = 'test' + const result = await uut.getLogs(pass) + // console.log('result', result) + + assert.isTrue(result.success) + assert.isArray(result.data) + assert.property(result.data[0], 'message') + assert.property(result.data[0], 'level') + assert.property(result.data[0], 'timestamp') + }) + + it('should return false if files are not found!', async () => { + try { + sandbox.stub(uut, 'generateFileName').resolves('bad router') + + const password = 'test' + + const result = await uut.getLogs(password) + // console.log(result) + + assert.isFalse(result.success) + assert.include(result.data, 'file does not exist') + } catch (err) { + console.log('ERRROR', err) + assert.fail('Unexpected result') + } + }) + + it('should catch and handle errors', async () => { + try { + // Force an error + sandbox.stub(uut.fs, 'existsSync').throws(new Error('test error')) + const password = 'test' + + await uut.getLogs(password) + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should throw unhandled error', async () => { + try { + // Force an error + sandbox.stub(uut.fs, 'existsSync').throws(new Error('Unhandled error')) + const password = 'test' + + await uut.getLogs(password) + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'Unhandled error') + } + }) + }) + + describe('#filterLogs()', () => { + it('should throw error if data is not provided', async () => { + try { + await uut.filterLogs() + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'Data must be array') + } + }) + + it('should throw error if data provided is not an array', async () => { + try { + const data = 'data' + await uut.filterLogs(data) + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'Data must be array') + } + }) + + it('should sort the log data', async () => { + try { + const data = mockData.data + const result = await uut.filterLogs(data) + assert.isArray(result) + assert.property(result[1], 'message') + assert.property(result[1], 'level') + assert.property(result[1], 'timestamp') + } catch (err) { + assert.fail('Unexpected result') + } + }) + + it('should sort the log data with a limit', async () => { + try { + const data = mockData.data + const limit = 1 + const result = await uut.filterLogs(data, limit) + assert.isArray(result) + assert.equal(result.length, limit) + assert.property(result[0], 'message') + assert.property(result[0], 'level') + assert.property(result[0], 'timestamp') + } catch (err) { + assert.fail('Unexpected result') + } + }) + }) + + describe('#generateFileName()', () => { + it('should return file name', async () => { + try { + const fileName = await uut.generateFileName() + assert.isString(fileName) + context.fileName = fileName + } catch (err) { + assert.fail('Unexpected result') + } + }) + + it('should throw error if something fails', async () => { + try { + uut.config = null + await uut.generateFileName() + assert.fail('Unexpected result') + } catch (err) { + assert.exists(err) + assert.isString(err.message) + } + }) + }) + + describe('#readLines()', () => { + it('should throw error if fileName is not provided', async () => { + try { + await uut.readLines() + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'filename must be a string') + } + }) + + it('should throw error if fileName provided is not string', async () => { + try { + const fileName = true + await uut.readLines(fileName) + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'filename must be a string') + } + }) + + it('should throw error if the file does not exist', async () => { + try { + const fileName = 'test/logs/' + await uut.readLines(fileName) + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'file does not exist') + } + }) + + it('should ignore fileReader callback errors', async () => { + // https://sinonjs.org/releases/latest/stubs/ + // About yields + sandbox.stub(uut.lineReader, 'eachLine').yieldsRight({}, true) + + const fileName = `${__dirname.toString()}/../mocks/adapters/fake-log` + + const result = await uut.readLines(fileName) + assert.isArray(result) + }) + + it('should return data', async () => { + const fileName = `${__dirname.toString()}/../mocks/adapters/fake-log` + + const result = await uut.readLines(fileName) + + assert.isArray(result) + assert.property(result[1], 'message') + assert.property(result[1], 'level') + assert.property(result[1], 'timestamp') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/contact.adapter.unit.js`: + +```js +import { assert } from 'chai' +import sinon from 'sinon' +import ContactLib from '../../../src/adapters/contact.js' +let uut +let sandbox + +describe('Contact', () => { + beforeEach(() => { + uut = new ContactLib() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('sendEmail()', () => { + it('should throw error if email property is not provided', async () => { + try { + const data = { + formMessage: 'test msg' + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'email' must be a string!") + } + }) + + it('should throw error if formMessage property is not provided', async () => { + try { + const data = { + email: 'test@email.com' + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'formMessage' must be a string!") + } + }) + + it('should throw error if email list provided is not a array', async () => { + try { + sandbox.stub(uut.nodemailer, 'sendEmail').resolves(true) + + const data = { + formMessage: 'test msg', + email: 'test@email.com', + emailList: 'test@email.com' + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include( + err.message, + "Property 'emailList' must be a array of emails!" + ) + } + }) + + it('should throw error if email list provided is a empty array', async () => { + try { + sandbox.stub(uut.nodemailer, 'sendEmail').resolves(true) + + const data = { + formMessage: 'test msg', + email: 'test@email.com', + emailList: [] + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include( + err.message, + "Property 'emailList' must be a array of emails!" + ) + } + }) + + it('should send email to default server email', async () => { + try { + sandbox.stub(uut.nodemailer, 'sendEmail').resolves(true) + + const data = { + formMessage: 'test msg', + email: 'test@email.com' + } + const result = await uut.sendEmail(data) + assert.isTrue(result) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + + it('should catch and throw nodemailer lib error', async () => { + try { + // Force an error with the database. + sandbox + .stub(uut.nodemailer, 'sendEmail') + .throws(new Error('test error')) + + const data = { + formMessage: 'test msg', + email: 'test@email.com' + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should send email to specifics email list', async () => { + try { + sandbox.stub(uut.nodemailer, 'sendEmail').resolves(true) + + const data = { + formMessage: 'test msg', + email: 'test@email.com', + emailList: ['testcontact@email.com'] + } + const result = await uut.sendEmail(data) + assert.isTrue(result) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/bch.adapter.unit.js`: + +```js +import { assert } from 'chai' +import BCHJS from '../../../src/adapters/bch.js' +import sinon from 'sinon' +import util from 'util' +util.inspect.defaultOptions = { depth: 1 } + +// const mockData = require('../mocks/bchjs-mock') + +let sandbox +let uut +describe('bch', () => { + beforeEach(() => { + uut = new BCHJS() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#_verifySignature', () => { + it('should return true for valid signature', () => { + const offerBchAddr = + 'bitcoincash:qphjncqpnv444jq8acqk4dkm3296c50xhqggeatvn8' + const signature = + 'Hz8bi9CsHaYkk5SGtHLU0aaxFspEXz7IdBNn6xV8ejE6OCuIRoZuVE9QJsGSlJ3Rt0ez2LWD0e292NZ84rRwnfk=' + const sigMsg = 'example.com' + const verifyObj = { offerBchAddr, signature, sigMsg } + + const result = uut._verifySignature(verifyObj) + + assert.equal(result, true) + }) + + it('should return false for invalid signature', () => { + const offerBchAddr = + 'bitcoincash:qphjncqpnv444jq8acqk4dkm3296c50xhqggeatvn8' + const signature = + 'Hz8bi9CsHaYkk5SGtHLU0aaxFspEXz7IdBNn6xV8ejE6OCuIRoZuVE9QJsGSlJ3Rt0ez2LWD0e292NZ84rRwnfd=' + const sigMsg = 'example.com' + const verifyObj = { offerBchAddr, signature, sigMsg } + + const result = uut._verifySignature(verifyObj) + + assert.equal(result, false) + }) + + it('should catch and throw errors', () => { + try { + // Force an error + sandbox + .stub(uut.bchjs.BitcoinCash, 'verifyMessage') + .throws(new Error('test error')) + + const offerBchAddr = + 'bitcoincash:qphjncqpnv444jq8acqk4dkm3296c50xhqggeatvn8' + const signature = + 'Hz8bi9CsHaYkk5SGtHLU0aaxFspEXz7IdBNn6xV8ejE6OCuIRoZuVE9QJsGSlJ3Rt0ez2LWD0e292NZ84rRwnfk=' + const sigMsg = 'example.com' + const verifyObj = { offerBchAddr, signature, sigMsg } + uut._verifySignature(verifyObj) + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) + + // describe('#getPSFTokenBalance', () => { + // it('should throw error if slpAddress is not provided', async () => { + // try { + // await uut.getPSFTokenBalance() + // assert.fail('Unexpected result') + // } catch (err) { + // assert.include(err.message, 'slpAddress must be a string') + // } + // }) + // + // it('should return psf tokens balance', async () => { + // // Mock live network calls. + // sandbox + // .stub(uut.bchjs.SLP.Utils, 'balancesForAddress') + // .resolves(mockData.psfBalances) + // + // const slpAddress = + // 'simpleledger:qp49th03gvjn58d6fxzaga6u09w4z56smyuk43lzkd' + // const result = await uut.getPSFTokenBalance(slpAddress) + // + // assert.isNumber(result) + // assert.equal(result, 2) + // }) + // + // it('should return 0 if the slp address does not has Psf tokens', async () => { + // // Mock live network calls. + // sandbox + // .stub(uut.bchjs.SLP.Utils, 'balancesForAddress') + // .resolves(mockData.noPsfBalances) + // + // const slpAddress = + // 'simpleledger:qp49th03gvjn58d6fxzaga6u09w4z56smyuk43lzkd' + // const result = await uut.getPSFTokenBalance(slpAddress) + // + // assert.isNumber(result) + // assert.equal(result, 0) + // }) + // + // it('should return 0 for empty balances', async () => { + // // Mock live network calls. + // sandbox.stub(uut.bchjs.SLP.Utils, 'balancesForAddress').resolves([]) + // + // const slpAddress = + // 'simpleledger:qp49th03gvjn58d6fxzaga6u09w4z56smyuk43lzkd' + // const result = await uut.getPSFTokenBalance(slpAddress) + // + // assert.isNumber(result) + // assert.equal(result, 0) + // }) + // }) + + describe('#getMerit', () => { + it('should throw error if slpAddr is not provided', async () => { + try { + await uut.getMerit() + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'slpAddr must be a string') + } + }) + it('should throw error if slpAddr provided is invalid type', async () => { + try { + await uut.getMerit(1) + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'slpAddr must be a string') + } + }) + + // it('should return the merit ', async () => { + // try { + // // Mock live network calls. + // sandbox.stub(uut.msgLib.merit, 'agMerit').resolves(100) + // + // const slpAddr = + // 'simpleledger:qqgnksc6zr4nzxrye69fq625wu2myxey6uh9kzjy96' + // const merit = await uut.getMerit(slpAddr) + // assert.isNumber(merit) + // } catch (err) { + // assert.fail('Unexpected result') + // } + // }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/nodemailer.adapter.unit.js`: + +```js +/* + Unit tests for the nodemailer.js library. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' +import NodeMailer from '../../../src/adapters/nodemailer.js' + +let sandbox +let uut + +describe('NodeMailer', () => { + beforeEach(() => { + uut = new NodeMailer() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('sendEmail()', () => { + it('should throw error if email property is not provided', async () => { + try { + const data = { + formMessage: 'test msg', + name: 'test name', + subject: 'test subject', + to: ['test2@email.com'] + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'email' must be a string!") + } + }) + + it('should throw error if formMessage property is not provided', async () => { + try { + const data = { + email: 'test@email.com', + name: 'test name', + subject: 'test subject', + to: ['test2@email.com'] + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'formMessage' must be a string!") + } + }) + + it('should throw error if property is not provided', async () => { + try { + const data = { + email: 'test@email.com', + name: 'test name', + subject: 'test subject' + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'to' must be a array!") + } + }) + + it('should throw error if is wrong type', async () => { + try { + const data = { + email: 'test@email.com', + formMessage: 'test msg', + name: 'test name', + subject: 'test subject', + to: 'test' + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'to' must be a array!") + } + }) + + it('should throw error if subject Property is not provided', async () => { + try { + const data = { + email: 'test@email.com', + formMessage: 'test msg', + name: 'test name', + to: ['test2@email.com'] + } + await uut.sendEmail(data) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'subject' must be a string!") + } + }) + + it('should send email with default html data', async () => { + try { + sandbox + .stub(uut.transporter, 'sendMail') + .resolves({ messageId: 'messageId' }) + + const data = { + email: 'test@email.com', + formMessage: 'test msg', + to: ['test2@email.com'], + subject: 'test subject' + } + + const info = await uut.sendEmail(data) + + assert.isObject(info) + assert.isString(info.messageId) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + + it('should send email if htmlData is provided', async () => { + try { + sandbox + .stub(uut.transporter, 'sendMail') + .resolves({ messageId: 'messageId' }) + const data = { + email: 'test@email.com', + formMessage: 'test msg', + name: 'test name', + to: ['test2@email.com'], + subject: 'test subject', + htmlData: '

Unit test

' + } + const info = await uut.sendEmail(data) + assert.isObject(info) + assert.isString(info.messageId) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) + + describe('validateEmailArray()', () => { + it('should throw error if email list is not provided ', async () => { + try { + await uut.validateEmailArray() + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'emailList' must be a array!") + } + }) + + it('should throw error if email list is empty', async () => { + try { + const emailList = [] + await uut.validateEmailArray(emailList) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'emailList' cant be empty!") + } + }) + + it('should return true ', async () => { + try { + const emailList = ['test@email.com', 'simple@email.com'] + const result = await uut.validateEmailArray(emailList) + assert.isTrue(result) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) + + describe('getHtmlFromObject()', () => { + it('should throw error if the input is not provided ', async () => { + try { + await uut.getHtmlFromObject() + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'objectData' must be a object!") + } + }) + + it('should throw error if the object is empty', async () => { + try { + await uut.getHtmlFromObject({}) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'subject' must be a string!") + } + }) + + it('should throw error if "formMessage" property is not provided', async () => { + try { + const obj = { + subject: 'unit' + } + await uut.getHtmlFromObject(obj) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, "Property 'formMessage' must be a string!") + } + }) + + it('should return the html', async () => { + try { + const obj = { + subject: 'unit ', + formMessage: 'test', + value1: 'value1', + value2: 'value2', + value3: 'value3' + } + const result = await uut.getHtmlFromObject(obj) + assert.isString(result) + assert.include(result, '

', 'expect html tag') + assert.include(result, '

', 'expect html tag') + assert.include( + result, + 'value1', + 'Expect value 1 is included in the html' + ) + assert.include(result, 'value2', 'expect is included in the html') + assert.include(result, 'value3', 'expect is included in the html') + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/wallet.unit.js`: + +```js + +/* + Unit tests for the adapter/wallet.js library. +*/ + +// Global npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +import WalletAdapter from '../../../src/adapters/wallet.js' +import { MockBchWallet } from '../mocks/adapters/wallet.js' + +describe('#wallet', () => { + let uut + let sandbox + + beforeEach(() => { + uut = new WalletAdapter() + uut.bchWallet = new MockBchWallet() + uut.bitcoinJs = { + Transaction: { + fromHex: () => { return { } }, + SIGHASH_ALL: () => { return { } } + }, + TransactionBuilder: { + fromTransaction: () => { return { sign: () => { return { } }, build: () => { return { toHex: () => { return 'hex' } } } } } + }, + ECPair: { + fromWIF: () => { return { } } + } + } + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#moveTokensFromCustomWallet', () => { + it('should move tokens from a custom wallet', async () => { + sandbox.stub(uut, 'getKeyPair').resolves({ + cashAddress: 'cashAddress', + wif: 'wif', + hdIndex: 11 + }) + + const customWallet = new MockBchWallet() + customWallet.sendTokens = () => { return 'move token tx id result' } + customWallet.utxos.utxoStore.slpUtxos.type1.tokens = [ + { + tokenId: 'tokenId', + tokenType: 1, + qty: 1 + } + ] + const inObj = { + qty: 1, + wallet: customWallet, + tokenId: 'tokenId' + } + const result = await uut.moveTokensFromCustomWallet(inObj) + assert.equal(result.txid, 'move token tx id result') + assert.equal(result.hdIndex, 11) + assert.equal(result.tokenType, 1) + assert.equal(result.vout, 1) + }) + it('should throw an error if the wallet is not provided', async () => { + try { + const inObj = { + qty: 1, + tokenId: 'tokenId' + } + await uut.moveTokensFromCustomWallet(inObj) + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(error.message, 'wallet is required!') + } + }) + it('should throw an error if the tokenId is not provided', async () => { + try { + const inObj = { + qty: 1, + wallet: new MockBchWallet() + } + await uut.moveTokensFromCustomWallet(inObj) + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(error.message, 'tokenId must be a string!') + } + }) + it('should throw an error if the qty is not provided', async () => { + try { + const inObj = { + tokenId: 'tokenId', + wallet: new MockBchWallet() + } + await uut.moveTokensFromCustomWallet(inObj) + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(error.message, 'qty must be a number!') + } + }) + }) + describe('#completeTx', () => { + it('should complete a transaction', async () => { + sandbox.stub(uut, 'getKeyPair').resolves({ + cashAddress: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00', + wif: 'L5D2UAam8tvo3uii5kpgaGyjvVMimdrXu8nWGQSQjuuAix6ji1YQ', + hdIndex: 11 + }) + sandbox.stub(uut, 'deseralizeTx').resolves({ + txid: 'complete tx id result' + }) + sandbox.stub(uut.retryQueue, 'addToQueue').resolves('complete tx id result') + + const hex = 'hex' + const hdIndex = 11 + const txid = await uut.completeTx(hex, hdIndex) + assert.equal(txid, 'complete tx id result') + }) + it('should throw an error if the hex is not provided', async () => { + try { + const hdIndex = 11 + await uut.completeTx(null, hdIndex) + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(error.message, 'hex must be a string!') + } + }) + it('should throw an error if the hdIndex is not provided', async () => { + try { + const hex = 'hex' + await uut.completeTx(hex, null) + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(error.message, 'hdIndex must be a non-negative number!') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/p2wdb.adapter.unit.js`: + +```js +/* + Unit tests for the p2wdb adapter library. +*/ + +// Public npm libraries. +import { assert } from 'chai' + +import sinon from 'sinon' + +// const BCHJS = require('@psf/bch-js') +import BchWallet from 'minimal-slp-wallet' + +// Local libraries. +import P2wdbAdapter from '../../../src/adapters/p2wdb-adapter.js' + +describe('#P2wdbAdapter', () => { + let uut, sandbox, bchWallet + + beforeEach(async () => { + // const bchjs = new BCHJS() + bchWallet = new BchWallet() + await bchWallet.walletInfoPromise + + uut = new P2wdbAdapter({ bchWallet }) + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw error if bchWallet is not passed in', () => { + try { + uut = new P2wdbAdapter() + + assert.fail('Unexpected coded path') + } catch (err) { + assert.include(err.message, 'Must pass an instance of minimal-slp-wallet as bchWallet when instantiating p2wdb.js adapter.') + } + }) + }) + + describe('#instantiateWriteLib', () => { + it('should instantiate Write library using web 3 interface', async () => { + // Force code path + uut.config.useFullStackCash = false + + // Mock dependencies + uut.Write = + class Write { + constructor () { + this.interface = 'web3' + } + } + + const wif = 'L1tcvcqa5PztqqDH4ZEcUmHA9aSHhTau5E2Zwp1xEK5CrKBrjP3m' + + const result = uut.instantiateWriteLib(wif) + // console.log('result: ', result) + + assert.equal(result.interface, 'web3') + }) + + it('should instantiate Write library using web 2 interface', async () => { + // Force code path + uut.config.useFullStackCash = true + + // Mock dependencies + uut.Write = + class Write { + constructor () { + this.interface = 'fullstack' + } + } + + const wif = 'L1tcvcqa5PztqqDH4ZEcUmHA9aSHhTau5E2Zwp1xEK5CrKBrjP3m' + + const result = uut.instantiateWriteLib(wif) + // console.log('result: ', result) + + assert.equal(result.interface, 'fullstack') + }) + + it('should catch and throw errors', async () => { + try { + await uut.instantiateWriteLib() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'WIF input required when calling instantiateWriteLib()') + } + }) + }) + + describe('#checkForSufficientFunds', () => { + it('should throw error if WIF is not provided', async () => { + try { + await uut.checkForSufficientFunds() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'invalid wif to check for funds') + } + }) + + it('should return status of funds', async () => { + // Mock dependencies + sandbox.stub(uut, 'instantiateWriteLib').returns({ + checkForSufficientFunds: () => true + }) + + const wif = 'L1tcvcqa5PztqqDH4ZEcUmHA9aSHhTau5E2Zwp1xEK5CrKBrjP3m' + + const result = await uut.checkForSufficientFunds(wif) + + assert.equal(result, true) + }) + }) + + describe('#write', async () => { + it('should throw error if WIF is not provided', async () => { + try { + await uut.write() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'wif input must be a private key starting with the letter L or K') + } + }) + + it('should write data to the P2WDB', async () => { + // Mock dependencies + sandbox.stub(uut, 'instantiateWriteLib').returns({ + postEntry: async () => { + return { hash: 'fake-hash' } + } + }) + + const wif = 'L1tcvcqa5PztqqDH4ZEcUmHA9aSHhTau5E2Zwp1xEK5CrKBrjP3m' + const inObj = { wif } + + const result = await uut.write(inObj) + // console.log('result: ', result) + + assert.equal(result, 'fake-hash') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/json-files.adapter.unit.js`: + +```js +/* + Unit tests for the JSON File adapter. +*/ + +import { assert } from 'chai' +import fs from 'fs' +import sinon from 'sinon' +import util from 'util' + +import JsonFiles from '../../../src/adapters/json-files.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' +util.inspect.defaultOptions = { depth: 1 } +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +const JSON_FILE = 'test-json-file.json' +const JSON_PATH = `${__dirname.toString()}/${JSON_FILE}` + +const deleteFile = (filepath) => { + try { + // Delete state if exist + fs.unlinkSync(filepath) + } catch (error) {} +} + +let sandbox +let uut + +describe('JsonFiles', () => { + const obj = { + json: 'file' + } + + beforeEach(() => { + uut = new JsonFiles() + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + after(() => { + deleteFile(JSON_PATH) + }) + + describe('writeJSON()', () => { + it('should throw error if inputs is not provided', async () => { + try { + await uut.writeJSON() + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'obj property is required') + } + }) + + it('should throw error if filename property is not provided', async () => { + try { + await uut.writeJSON(obj) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'fileName property must be a string') + } + }) + it('should throw error if filename property is not string', async () => { + try { + await uut.writeJSON(obj, 1) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'fileName property must be a string') + } + }) + it('should throw error if fs library return an error', async () => { + try { + // https://sinonjs.org/releases/latest/stubs/ + // About yields + sandbox.stub(uut.fs, 'writeFile').yields(new Error('test error')) + + await uut.writeJSON(obj, JSON_PATH) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + it('should write a json file', async () => { + try { + await uut.writeJSON(obj, JSON_PATH) + + assert.isTrue(fs.existsSync(JSON_PATH)) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) + + describe('readJSON()', () => { + it('should throw error if filename property is not provided', async () => { + try { + await uut.readJSON(obj) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'fileName property must be a string') + } + }) + it('should throw error if filename property is not string', async () => { + try { + await uut.readJSON(obj, 1) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'fileName property must be a string') + } + }) + it('should throw error if fs library return an error', async () => { + try { + // https://sinonjs.org/releases/latest/stubs/ + // About yields + sandbox.stub(uut.fs, 'readFile').yields(new Error('test error')) + + await uut.readJSON(JSON_PATH) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + it('should throw error if file not found', async () => { + try { + const testError = new Error('test error') + testError.code = 'ENOENT' + + sandbox.stub(uut.fs, 'readFile').yields(testError) + + await uut.readJSON(JSON_PATH) + assert(false, 'Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should read a json file', async () => { + try { + const result = await uut.readJSON(JSON_PATH) + + const objKeys = Object.keys(obj) + const resultKeys = Object.keys(result) + + assert.isObject(result) + assert.equal(objKeys.length, resultKeys.length) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/wallet.adapter.unit.js`: + +```js +/* + Unit tests for the Wallet Adapter library. +*/ + +// Global npm libraries +import { assert } from 'chai' +import sinon from 'sinon' +import BchWallet from 'minimal-slp-wallet' +import fs from 'fs' + +// Local libraries +import WalletAdapter from '../../../src/adapters/wallet.adapter.js' +import { MockBchWallet } from '../mocks/adapters/wallet.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +// Global constants +const testWalletFile = `${__dirname.toString()}test-wallet.json` + +describe('#wallet', () => { + let uut + let sandbox + + before(() => { + // Delete the test file if it exists. + try { + deleteFile(testWalletFile) + } catch (err) { } + }) + + beforeEach(() => { + uut = new WalletAdapter() + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + after(() => { + // Delete the test file if it exists. + try { + deleteFile(testWalletFile) + } catch (err) { } + }) + + describe('#_instanceWallet', () => { + it('should create a wallet given a mnemonic', async () => { + const mnemonic = 'wagon tray learn flat erase laugh lonely rug check captain jacket morning' + const result = await uut._instanceWallet(mnemonic) + // console.log('result: ', result) + assert.equal(result.walletInfo.mnemonic, mnemonic) + }) + }) + + describe('#openWallet', () => { + it('should create a new wallet when wallet file does not exist', async () => { + // Mock dependencies + uut.BchWallet = MockBchWallet + // Ensure we open the test file, not the production wallet file. + uut.config.walletFile = testWalletFile + const result = await uut.openWallet() + // console.log('result: ', result) + assert.property(result, 'mnemonic') + assert.property(result, 'privateKey') + assert.property(result, 'publicKey') + assert.property(result, 'cashAddress') + assert.property(result, 'address') + assert.property(result, 'slpAddress') + assert.property(result, 'legacyAddress') + assert.property(result, 'hdPath') + }) + + it('should open existing wallet file', async () => { + // This test case uses the file created in the previous test case. + // Ensure we open the test file, not the production wallet file. + uut.config.walletFile = testWalletFile + const result = await uut.openWallet() + // console.log('result: ', result) + assert.property(result, 'mnemonic') + assert.property(result, 'privateKey') + assert.property(result, 'publicKey') + assert.property(result, 'cashAddress') + assert.property(result, 'address') + assert.property(result, 'slpAddress') + assert.property(result, 'legacyAddress') + assert.property(result, 'hdPath') + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + uut.config.walletFile = '' + uut.BchWallet = () => { + } + await uut.openWallet() + // console.log('result: ', result) + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'this.BchWallet is not a constructor') + } + }) + }) + + describe('#instanceWalletWithoutInitialization', () => { + it('should create an instance of BchWallet', async () => { + // Create a mock wallet. + const mockWallet = new BchWallet() + await mockWallet.walletInfoPromise + sandbox.stub(mockWallet, 'initialize').resolves() + + // Mock dependencies + sandbox.stub(uut, '_instanceWallet').resolves(mockWallet) + uut.config.authPass = 'fake-auth-pass' + + // Ensure we open the test file, not the production wallet file. + uut.config.walletFile = testWalletFile + const walletData = await uut.openWallet() + + // console.log('walletData: ', walletData) + const result = await uut.instanceWalletWithoutInitialization(walletData) + // console.log('result: ', result) + + assert.property(result, 'walletInfoPromise') + assert.property(result, 'walletInfo') + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + sandbox.stub(uut, '_instanceWallet').rejects(new Error('test error')) + + await uut.instanceWalletWithoutInitialization() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'test error') + } + }) + + it('should create an instance of BchWallet using web2 infra', async () => { + // Create a mock wallet. + const mockWallet = new BchWallet() + await mockWallet.walletInfoPromise + sandbox.stub(mockWallet, 'initialize').resolves() + + // Mock dependencies + sandbox.stub(uut, '_instanceWallet').resolves(mockWallet) + + // Ensure we open the test file, not the production wallet file. + uut.config.walletFile = testWalletFile + const walletData = await uut.openWallet() + // console.log('walletData: ', walletData) + + // Force desired code path + uut.config.walletInterface = 'web2' + const result = await uut.instanceWalletWithoutInitialization(walletData) + + // console.log('result: ', result) + assert.property(result, 'walletInfoPromise') + assert.property(result, 'walletInfo') + }) + + it('should generate wallet from mnemonic in config', async () => { + // Create a mock wallet. + const mockWallet = new BchWallet() + await mockWallet.walletInfoPromise + sandbox.stub(mockWallet, 'initialize').resolves() + + // Mock dependencies + sandbox.stub(uut, '_instanceWallet').resolves(mockWallet) + + // Ensure we open the test file, not the production wallet file. + uut.config.walletFile = testWalletFile + const walletData = await uut.openWallet() + // console.log('walletData: ', walletData) + + const originalConfig = uut.config.mnemonic + uut.config.mnemonic = walletData.mnemonic + + const result = await uut.instanceWalletWithoutInitialization({}) + // console.log('result: ', result) + + uut.config.mnemonic = originalConfig + + assert.property(result, 'walletInfoPromise') + assert.property(result, 'walletInfo') + }) + }) + + describe('#instanceWallet', () => { + it('should create an instance of BchWallet', async () => { + // Create a mock wallet. + const mockWallet = new BchWallet() + await mockWallet.walletInfoPromise + sandbox.stub(mockWallet, 'initialize').resolves() + + // Mock dependencies + sandbox.stub(uut, '_instanceWallet').resolves(mockWallet) + + // Ensure we open the test file, not the production wallet file. + uut.WALLET_FILE = testWalletFile + const walletData = await uut.openWallet() + // console.log('walletData: ', walletData) + const result = await uut.instanceWallet(walletData) + // console.log('result: ', result) + + assert.property(result, 'walletInfoPromise') + assert.property(result, 'walletInfo') + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + sandbox.stub(uut, 'instanceWalletWithoutInitialization').rejects(new Error('test error')) + + await uut.instanceWallet() + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'test error') + } + }) + + it('should create an instance of BchWallet using web2 infra', async () => { + // Create a mock wallet. + const mockWallet = new BchWallet() + await mockWallet.walletInfoPromise + sandbox.stub(mockWallet, 'initialize').resolves() + + // Mock dependencies + sandbox.stub(uut, '_instanceWallet').resolves(mockWallet) + + // Ensure we open the test file, not the production wallet file. + uut.WALLET_FILE = testWalletFile + const walletData = await uut.openWallet() + // console.log('walletData: ', walletData) + + // Force desired code path + uut.config.useFullStackCash = true + const result = await uut.instanceWallet(walletData) + // console.log('result: ', result) + + assert.property(result, 'walletInfoPromise') + assert.property(result, 'walletInfo') + }) + }) + + describe('#incrementNextAddress', () => { + it('should increment the nextAddress property', async () => { + // Ensure we open the test file, not the production wallet file. + uut.WALLET_FILE = testWalletFile + // mock instance of minimal-slp-wallet + uut.bchWallet = new MockBchWallet() + const result = await uut.incrementNextAddress() + assert.equal(result, 2) + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + sandbox.stub(uut, 'openWallet').rejects(new Error('test error')) + await uut.incrementNextAddress() + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) + + describe('#getKeyPair', () => { + it('should return an object with a key pair', async () => { + // Ensure we open the test file, not the production wallet file. + // uut.WALLET_FILE = testWalletFile + uut.config.walletFile = testWalletFile + + const result = await uut.getKeyPair() + // console.log('result: ', result) + + assert.property(result, 'cashAddress') + assert.property(result, 'wif') + assert.property(result, 'hdIndex') + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + sandbox + .stub(uut, 'incrementNextAddress') + .rejects(new Error('test error')) + await uut.getKeyPair() + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) + + describe('#optimize', () => { + it('should call the wallet optimize function', async () => { + // mock instance of minimal-slp-wallet + uut.bchWallet = new MockBchWallet() + sandbox.stub(uut.bchWallet, 'optimize').resolves({ bchUtxoCnt: 10 }) + const result = await uut.optimize() + assert.equal(result, true) + }) + }) + + describe('#getBalance', () => { + it('should get the balance for the wallet', async () => { + // mock instance of minimal-slp-wallet + uut.bchWallet = new MockBchWallet() + // Mock dependencies and force desired code path + sandbox.stub(uut.bchWallet, 'getBalance').resolves(41012) + sandbox.stub(uut.bchWallet, 'listTokens').resolves([{ + tokenId: '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + ticker: 'PSF', + name: 'Permissionless Software Foundation', + decimals: 8, + tokenType: 1, + url: 'psfoundation.cash', + qty: 2 + }]) + const result = await uut.getBalance() + // console.log('result: ', result) + // Assert the expected properties exist and have the expected values. + assert.equal(result.satBalance, 41012) + assert.equal(result.psfBalance, 2) + assert.equal(result.success, true) + }) + }) +}) + +const deleteFile = (filepath) => { + try { + // Delete state if exist + fs.unlinkSync(filepath) + } catch (err) { + // console.error('Error trying to delete file: ', err) + } +} + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/adapters-index-unit.js`: + +```js +/* + Unit tests for the adapters index.js library +*/ + +// Global npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local libraries +import Adapters from '../../../src/adapters/index.js' + +describe('#adapters', () => { + let uut, sandbox + + beforeEach(() => { + uut = new Adapters() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => { + sandbox.restore() + }) + + describe('#start', () => { + it('should start the async adapters', async () => { + // Mock dependencies + uut.config.getJwtAtStartup = true + uut.config.useIpfs = true + uut.config.env = 'not-a-test' + sandbox.stub(uut.fullStackJwt, 'getJWT').resolves() + sandbox.stub(uut.fullStackJwt, 'instanceBchjs').resolves() + sandbox.stub(uut.ipfs, 'start').resolves() + + const result = await uut.start() + + assert.equal(result, true) + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + uut.config.getJwtAtStartup = false + // uut.config.env = 'dev' + sandbox.stub(uut.wallet, 'openWallet').rejects(new Error('test error')) + + await uut.start() + + assert.fail('Unexpected result') + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'test error') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/fullstack-jwt.adapter.unit.js`: + +```js +/* + Unit tests for the jwt-bch-lib and fullstack-jwt.js adapter library. + +*/ + +import { assert } from 'chai' + +import sinon from 'sinon' +import FullStackJWT from '../../../src/adapters/fullstack-jwt.js' + +describe('#FullStackJWT', () => { + let sandbox + let uut + + beforeEach(() => { + sandbox = sinon.createSandbox() + + const localConfig = { + authServer: 'someserver', + apiServer: 'someserver', + fullstackLogin: 'somelogin', + fullstackPassword: 'somepassword' + } + uut = new FullStackJWT(localConfig) + }) + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if auth server is not specified', () => { + try { + uut = new FullStackJWT() + + assert.fail('Unexpected code path') + console.log(uut) // For linting. + } catch (err) { + assert.include( + err.message, + 'Must pass a url for the AUTH server when instantiating FullStackJWT class.' + ) + } + }) + + it('should throw an error if api server is not specified', () => { + try { + const localConfig = { + authServer: 'someserver' + } + + uut = new FullStackJWT(localConfig) + + assert.fail('Unexpected code path') + console.log(uut) // For linting. + } catch (err) { + assert.include( + err.message, + 'Must pass a url for the API server when instantiating FullStackJWT class.' + ) + } + }) + + it('should throw an error if login is not specified', () => { + try { + const localConfig = { + authServer: 'someserver', + apiServer: 'someserver' + } + uut = new FullStackJWT(localConfig) + + assert.fail('Unexpected code path') + console.log(uut) // For linting. + } catch (err) { + assert.include( + err.message, + 'Must pass a FullStack.cash login (email) instantiating FullStackJWT class.' + ) + } + }) + + it('should throw an error if login is not specified', () => { + try { + const localConfig = { + authServer: 'someserver', + apiServer: 'someserver', + fullstackLogin: 'somelogin' + } + uut = new FullStackJWT(localConfig) + + assert.fail('Unexpected code path') + console.log(uut) // For linting. + } catch (err) { + assert.include( + err.message, + 'Must pass a FullStack.cash account password when instantiating FullStackJWT class.' + ) + } + }) + }) + + describe('#getJWT', () => { + it('should return the JWT token', async () => { + // Mock dependencies to force a code path. + sandbox.stub(uut.jwtLib, 'register').resolves({}) + uut.jwtLib.userData.apiToken = 'abc123' + sandbox.stub(uut.jwtLib, 'validateApiToken').resolves({ isValid: true }) + + const result = await uut.getJWT() + // console.log('result: ', result) + + assert.equal(result, 'abc123') + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + sandbox.stub(uut.jwtLib, 'register').rejects(new Error('test error')) + + await uut.getJWT() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should throw an error if user does not have a JWT', async () => { + try { + // Mock dependencies to force a code path. + sandbox.stub(uut.jwtLib, 'register').resolves({}) + + await uut.getJWT() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err.message: ', err.message) + assert.include(err.message, 'This account does not have a JWT') + } + }) + + it('should retrieve a new JWT token if the old one invalid', async () => { + // Mock dependencies to force a code path. + sandbox.stub(uut.jwtLib, 'register').resolves({}) + uut.jwtLib.userData.apiToken = 'abc123' + uut.jwtLib.userData.apiLevel = 30 + sandbox.stub(uut.jwtLib, 'validateApiToken').resolves({ isValid: false }) + sandbox.stub(uut.jwtLib, 'getApiToken').resolves('xyz789') + + const result = await uut.getJWT() + // console.log('result: ', result) + + assert.equal(result, 'xyz789') + }) + }) + + describe('#instanceBchjs', () => { + it('should return an instance of bch-js', () => { + const result = uut.instanceBchjs() + // console.log('result: ', result) + + assert.property(result, 'restURL') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/adapters/ipfs-coord.adapter.unit.js`: + +```js +/* + Unit tests for the IPFS Adapter. +*/ + +import { assert } from 'chai' + +import sinon from 'sinon' +import IPFSCoordAdapter from '../../../src/adapters/ipfs/ipfs-coord.js' +import create from '../mocks/ipfs-mock.js' +import IPFSCoordMock from '../mocks/ipfs-coord-mock.js' +import config from '../../../config/index.js' + +describe('#IPFS', () => { + let uut + let sandbox + + beforeEach(() => { + const ipfs = create() + uut = new IPFSCoordAdapter({ ipfs }) + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if ipfs instance is not included', () => { + try { + uut = new IPFSCoordAdapter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of IPFS must be passed when instantiating ipfs-coord.' + ) + } + }) + }) + + describe('#start', () => { + it('should return a promise that resolves into an instance of IPFS.', async () => { + // Mock dependencies. + uut.IpfsCoord = IPFSCoordMock + + const result = await uut.start() + // console.log('result: ', result) + + assert.equal(result, true) + }) + + it('should get the public IP address if this node is a Circuit Relay', async () => { + // Mock dependencies. + uut.IpfsCoord = IPFSCoordMock + sandbox.stub(uut, 'publicIp').resolves('123') + + // Force Circuit Relay + uut.config.isCircuitRelay = true + + const result = await uut.start() + // console.log('result: ', result) + + assert.equal(result, true) + }) + + it('should exit quietly if this node is a Circuit Relay and there is an issue getting the IP address', async () => { + // Mock dependencies. + uut.IpfsCoord = IPFSCoordMock + sandbox.stub(uut, 'publicIp').rejects(new Error('test error')) + + // Force Circuit Relay + uut.config.isCircuitRelay = true + + const result = await uut.start() + // console.log('result: ', result) + + assert.equal(result, true) + }) + + it('should return a promise that resolves into an instance of IPFS in production mode', async () => { + uut.config.isProduction = true + // Mock dependencies. + uut.IpfsCoord = IPFSCoordMock + + const result = await uut.start() + // console.log('result: ', result) + assert.equal(result, true) + config.isProduction = false + }) + }) + + describe('#attachRPCRouter', () => { + it('should attached a router output', async () => { + // Mock dependencies + uut.ipfsCoord = { + privateLog: {}, + ipfs: { + orbitdb: { + privateLog: {} + } + }, + adapters: { + pubsub: { + privateLog: () => { + } + } + } + } + + const router = console.log + + uut.attachRPCRouter(router) + }) + + it('should catch and throw an error', () => { + try { + // Force an error + delete uut.ipfsCoord.adapters + + const router = console.log + + uut.attachRPCRouter(router) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'Cannot read') + } + }) + }) + + describe('#subscribeToChat', () => { + it('should subscribe to the chat channel', async () => { + // Mock dependencies + uut.ipfsCoord = { + adapters: { + pubsub: { + subscribeToPubsubChannel: async () => { + } + } + } + } + + await uut.subscribeToChat() + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/README.md`: + +```md +# Unit Tests +Unit tests are defined as testing the smallest possible unit of a function. They also do not make any live network calls. + +Unit tests are broken up by directory: + +- [biz-logic](./biz-logic) tests the business logic libraries. +- [rest-api](./rest-api) tests the REST API specific handling of the router. +- json-rpc (coming soon) tests the JSON-RPC routing using ipfs-coord library. + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/misc/server-unit.js`: + +```js +/* + Unit tests for the bin/server.js file +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import Server from '../../../bin/server.js' + +describe('#server', () => { + let uut, sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new Server() + }) + + afterEach(() => sandbox.restore()) + + describe('#startServer', () => { + it('should start the server', async () => { + // Mock dependencies + sandbox.stub(uut.mongoose, 'connect').resolves() + sandbox.stub(uut.controllers, 'initAdapters').resolves() + sandbox.stub(uut.controllers, 'initUseCases').resolves() + sandbox.stub(uut.controllers, 'attachRESTControllers').resolves() + sandbox.stub(uut.adminLib, 'createSystemUser').resolves(true) + sandbox.stub(uut.controllers, 'attachControllers').resolves() + sandbox.stub(uut, 'sleep').resolves() + uut.config.env = 'dev' + + const result = await uut.startServer() + // console.log('result: ', result) + + assert.property(result, 'env') + + // Turn off the server. + uut.server.close() + + // Restor config env + uut.config.env = 'test' + }) + + it('should exit on failure', async () => { + // Force an error + sandbox.stub(uut.mongoose, 'connect').rejects(new Error('test error')) + + // Prevent default behavior of exiting the program. + sandbox.stub(uut, 'sleep').resolves() + sandbox.stub(uut.process, 'exit').returns() + + await uut.startServer() + + // Not throwing an error is a success + }) + }) + + describe('#sleep', () => { + it('should execute', async () => { + await uut.sleep(1) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/misc/config-unit.js`: + +```js +/* + Unit tests for the config directory +*/ + +import { assert } from 'chai' + +let currentEnv + +describe('#config', () => { + before(() => { + // Backup the current environment setting. + currentEnv = process.env.BCH_DEX + }) + + after(() => { + // Restore the environment setting before starting these tests. + process.env.BCH_DEX = currentEnv + }) + + it('Should return development environment config by default', async () => { + process.env.BCH_DEX = 'dev' + + const importedConfig = await import('../../../config/index.js?foo=bar3') + const config = importedConfig.default + // console.log('config: ', config) + + assert.equal(config.env, 'dev') + }) + + it('Should return test environment config', async () => { + // Hack to dynamically import a library multiple times: + // https://github.com/denoland/deno/issues/6946 + + process.env.BCH_DEX = 'test' + + const importedConfig2 = await import('../../../config/index.js?foo=bar1') + const config = importedConfig2.default + // console.log('config: ', config) + + assert.equal(config.env, 'test') + }) + + it('Should return prod environment config', async () => { + process.env.BCH_DEX = 'prod' + + process.env.WALLET_INTERFACE = 'web2' + process.env.APISERVER = 'https://api.fullstack.cash/v5/' + + await import('../../../config/env/common.js?foo=bar2') + const importedConfig3 = await import('../../../config/index.js?foo=bar2') + const config = importedConfig3.default + // console.log('config: ', config) + + assert.equal(config.env, 'prod') + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/misc/passport.unit.js`: + +```js +/* + Unit tests for the passport library. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' +import passport from 'koa-passport' + +// Local libraries +import User from '../../../src/adapters/localdb/models/users.js' + +import { applyPassportMods, passportCallback } from '../../../config/passport.js' +import adaptersMock from '../mocks/adapters/index.js' + +describe('#passport', () => { + let sandbox + let id + let done + + beforeEach(() => { + sandbox = sinon.createSandbox() + + id = 'abc123' + done = () => {} + }) + + afterEach(() => sandbox.restore()) + + describe('#passportCallback', () => { + it('should return if user is found', () => { + // Mock Users model. + sandbox.stub(User, 'findOne').resolves({ id }) + + passportCallback(id, 'password', done) + }) + + it('should return if password is validated', () => { + // Mock Users model. + sandbox.stub(User, 'findOne').resolves(new adaptersMock.localdb.Users()) + + passportCallback(id, 'password', done) + }) + + it('should catch a high-level error', () => { + // Force an error + sandbox.stub(User, 'findOne').rejects(new Error('test error')) + + passportCallback(id, 'password', done) + }) + }) + + describe('#applyPassportMods', () => { + it('should apply modifications to default passport behavior', () => { + const result = applyPassportMods(passport) + + assert.equal(result, true) + }) + }) + + describe('#serializeUser', () => { + it('should serialize a user', () => { + const user = { + id: 'abc123' + } + const done = () => {} + + applyPassportMods(passport) + + passport.serializeUser(user, done) + }) + }) + + describe('#deserializeUser', () => { + it('should deserialize a user', () => { + // Mock Users model. + sandbox.stub(User, 'findById').resolves({ id }) + + applyPassportMods(passport) + + passport.deserializeUser(id, done) + }) + + it('should catch and handle errors', () => { + // Force an error + sandbox.stub(User, 'findById').rejects(new Error('test error')) + + applyPassportMods(passport) + + passport.deserializeUser(id, done) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/offer/offer.rest.router.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' +import OfferRouter from '../../../../../src/controllers/rest-api/offer/index.js' + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Offer-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new OfferRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new OfferRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /offer REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new OfferRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /offer REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attached REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/offer/offer.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /offer endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' +import OfferRESTController from '../../../../../src/controllers/rest-api/offer/controller.js' + +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' + +let uut +let sandbox +let ctx + +describe('#Offer-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new OfferRESTController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new OfferRESTController() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /offer REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new OfferRESTController({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /offer REST Controller.' + ) + } + }) + }) + + describe('#createOffer', () => { + it('should create a new offer', async () => { + ctx.request.body = { + appId: 'swapTest555', + data: { + messageType: 1, + messageClass: 1, + tokenId: + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + buyOrSell: 'sell', + rateInSats: 1000, + minSatsToExchange: 10, + numTokens: 0.02, + utxoTxid: + '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87', + utxoVout: 0 + }, + timestamp: '2021-09-20T17:54:26.395Z', + localTimeStamp: '9/20/2021, 10:54:26 AM', + txid: '46f50f2a0cf44e3ed70dfb0618ef3ebfee57aabcf229b5d2d17c07322b54a8d7', + hash: 'zdpuB2X25AZCKo3wpr4sSbw44vqPWJRqcxWQRHZccK5BdtoGD' + } + + // Mock dependencies + // sandbox.stub(uut.useCases.offer, 'createOffer').resolves() + + await uut.createOffer(ctx) + + // assert.equal(ctx.body.hash, 'testHash') + }) + + // it('should catch and throw an error', async () => { + // try { + // ctx.request.body = { + // offer: {} + // } + // + // // Force an error + // sandbox + // .stub(uut.useCases.offer, 'createOffer') + // .rejects(new Error('test error')) + // + // await uut.createOffer(ctx) + // + // assert.fail('Unexpected code path') + // } catch (err) { + // // console.log('err: ', err) + // assert.include(err.message, 'test error') + // } + // }) + }) + + describe('#handleError', () => { + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + it('should catch error if message is provided', () => { + try { + const err = { + status: 422, + message: 'Unprocessable Entity' + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Unprocessable Entity') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/contact/contact.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' +import ContactController from '../../../../../src/controllers/rest-api/contact/controller.js' + +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' +let uut +let sandbox +let ctx + +describe('Contact', () => { + before(async () => { + }) + + beforeEach(() => { + uut = new ContactController() + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#POST /contact', () => { + it('should return 422 status on biz logic error', async () => { + try { + await uut.email(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'Cannot read') + } + }) + + it('should return 200 status on success', async () => { + sandbox.stub(uut.contactLib, 'sendEmail').resolves(true) + + ctx.request.body = { + email: 'test02@test.com', + formMessage: 'test' + } + + await uut.email(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'success') + assert.isTrue(ctx.response.body.success) + }) + }) + + describe('#handleError', () => { + it('should pass an error message', () => { + try { + const err = { + status: 422, + message: 'Unprocessable Entity' + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Unprocessable Entity') + } + }) + + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/contact/contact.rest.router.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' + +import UseCasesMock from '../../../mocks/use-cases/index.js' + +// const app = require('../../../mocks/app-mock') + +import ContactRouter from '../../../../../src/controllers/rest-api/contact/index.js' + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Contact-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new ContactRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new ContactRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating Contact REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new ContactRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating Contact REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attaching REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/usage/usage.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /usage endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' +import UsageController from '../../../../../src/controllers/rest-api/usage/controller.js' + +import { context as mockContext } from '../../../mocks/ctx-mock.js' + +let uut +let sandbox +let ctx + +describe('#Usage-REST-Controller', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new UsageController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new UsageController() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /usage REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new UsageController({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /usage REST Controller.' + ) + } + }) + }) + + describe('#Get /usage', () => { + it('should return 422 status on biz logic error', async () => { + try { + sandbox.stub(uut.useCases.usage, 'getRestSummary').throws(new Error('test error')) + await uut.getStatus(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + await uut.getStatus(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'status') + }) + }) + + describe('#Get /ips', () => { + it('should return 422 status on biz logic error', async () => { + try { + sandbox.stub(uut.useCases.usage, 'getTopIps').throws(new Error('test error')) + await uut.getTopIps(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + await uut.getTopIps(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'ips') + }) + }) + + describe('#Get /endpoints', () => { + it('should return 422 status on biz logic error', async () => { + try { + sandbox.stub(uut.useCases.usage, 'getTopEndpoints').throws(new Error('test error')) + await uut.getTopEndpoints(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + await uut.getTopEndpoints(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'endpoints') + }) + }) + + describe('#handleError', () => { + it('should pass an error message', () => { + try { + const err = { + status: 422, + message: 'Unprocessable Entity' + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Unprocessable Entity') + } + }) + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/usage/usage.rest.router.unit.js`: + +```js +/* +Unit tests for the REST API handler for the /usage endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' + +import UseCasesMock from '../../../mocks/use-cases/index.js' + +import UsageRouter from '../../../../../src/controllers/rest-api/usage/index.js' + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Usage-REST-Router', () => { + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new UsageRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new UsageRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating IPFS REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new UsageRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating IPFS REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attaching REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/logs/logs.rest.router.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' + +import UseCasesMock from '../../../mocks/use-cases/index.js' + +// const app = require('../../../mocks/app-mock') + +import LogsRouter from '../../../../../src/controllers/rest-api/logs/index.js' + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Contact-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new LogsRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new LogsRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating Logs REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new LogsRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating Logs REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attaching REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/logs/logs.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' +import LogsApiController from '../../../../../src/controllers/rest-api/logs/controller.js' + +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' +let uut +let sandbox +let ctx + +describe('Logapi', () => { + before(async () => { + }) + + beforeEach(() => { + uut = new LogsApiController() + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#POST /logapi', () => { + it('should return 422 status on biz logic error', async () => { + try { + await uut.getLogs(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'Cannot read') + } + }) + + it('should return 500 status on biz logic Unhandled error', async () => { + try { + // eslint-disable + sandbox + .stub(uut.logsApiLib, 'getLogs') + .returns(Promise.reject(new Error())) + + ctx.request.body = { + password: 'test' + } + + await uut.getLogs(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 500) + assert.include(err.message, 'Unhandled error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.logsApiLib, 'getLogs').resolves({}) + + ctx.request.body = { + password: 'test' + } + + await uut.getLogs(ctx) + + assert.isOk(ctx.body) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/order/order.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /order endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' +import OrderRESTController from '../../../../../src/controllers/rest-api/order/controller.js' + +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' + +let uut +let sandbox +let ctx + +describe('#Order-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new OrderRESTController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new OrderRESTController() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /order REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new OrderRESTController({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /order REST Controller.' + ) + } + }) + }) + + describe('#createOrder', () => { + it('should create a new order', async () => { + ctx.request.body = { + order: {} + } + ctx.state.user = { + id: 'testUserId' + } + + // Mock dependencies + sandbox.stub(uut.useCases.order, 'createOrder').resolves({ eventId: 'testEventId', noteId: 'testNoteId' }) + + await uut.createOrder(ctx) + + assert.equal(ctx.body.eventId, 'testEventId') + assert.equal(ctx.body.noteId, 'testNoteId') + }) + + it('should catch and throw an error', async () => { + try { + ctx.request.body = { + order: {} + } + ctx.state.user = { + id: 'testUserId' + } + + // Force an error + sandbox + .stub(uut.useCases.order, 'createOrder') + .rejects(new Error('test error')) + + await uut.createOrder(ctx) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'test error') + } + }) + }) + + describe('#handleError', () => { + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + it('should catch error if message is provided', () => { + try { + const err = { + status: 422, + message: 'Unprocessable Entity' + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Unprocessable Entity') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/order/order.rest.router.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' +import OrderRouter from '../../../../../src/controllers/rest-api/order/index.js' + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Order-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new OrderRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new OrderRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /order REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new OrderRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /order REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attached REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/middleware/error-unit.js`: + +```js +/* +Unit tests for the REST API middleware that handle response errors. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import errorMiddleware from '../../../../../src/controllers/rest-api/middleware/error.js' +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' + +describe('#Validators', () => { + let ctx + let sandbox + + beforeEach(() => { + // Mock the context object. + ctx = mockContext() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#errorMiddleware', () => { + it('should run next function', async () => { + // Spy on next + const next = sinon.spy(() => { }) + errorMiddleware()(ctx, next) + + assert.isTrue(next.calledOnce) + }) + + it('should handle unknown status error', async () => { + try { + const next = async () => { + const e = new Error('test error') + e.status = null + throw e + } + + await errorMiddleware()(ctx, next) + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(ctx.status, 500) + assert.equal(ctx.body, 'test error') + } + }) + it('should handle known status error', async () => { + try { + const next = async () => { + const e = new Error('test error') + e.status = 422 + throw e + } + + await errorMiddleware()(ctx, next) + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(ctx.status, 422) + assert.equal(ctx.body, 'test error') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/middleware/validators-unit.js`: + +```js +/* + Unit tests for the REST API middleware that validates users. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import Validators from '../../../../../src/controllers/rest-api/middleware/validators.js' +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' + +describe('#Validators', () => { + let uut + let ctx + let sandbox + + beforeEach(() => { + uut = new Validators() + + // Mock the context object. + ctx = mockContext() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#getToken', () => { + it('should return null if no header is provided', () => { + const result = uut.getToken(ctx) + + assert.equal(result, null) + }) + + it('should return null if header is not in two parts', () => { + ctx.request.header.authorization = 'Bearer' + + const result = uut.getToken(ctx) + + assert.equal(result, null) + }) + + it('should return null if first part of header does not container the word bearer', () => { + ctx.request.header.authorization = 'some thing' + + const result = uut.getToken(ctx) + + assert.equal(result, null) + }) + + it('should return the JWT token from the header', () => { + const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzMjNiNTUwNzgxYWYzNTc4YzI0ZmU5YiIsImlhdCI6MTY2MzQ0NDczNCwiZXhwIjoxNjYzNTMxMTM0fQ.BY5sOfXc4z5axS98CdTfyqnO9y2wijOlwnv52rcvxHA' + ctx.request.header.authorization = `Bearer ${jwt}` + + const result = uut.getToken(ctx) + + assert.equal(result, jwt) + }) + }) + + describe('#ensureUser', () => { + it('should throw error if token is not provided', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns() + + await uut.ensureUser(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error if token can not be verified', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').throws(new Error('test error')) + + await uut.ensureUser(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error if user can not be found in database', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves(false) + + await uut.ensureUser(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should return true if the user is verified', async () => { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves({ user: 'alice' }) + + const result = await uut.ensureUser(ctx) + + assert.equal(result, true) + }) + }) + + describe('#ensureUser', () => { + it('should throw error if token is not provided', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns() + + await uut.ensureAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error if token can not be verified', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').throws(new Error('test error')) + + await uut.ensureAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error if user can not be found in database', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves(false) + + await uut.ensureAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error if user is not an admin', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves({ type: 'user' }) + + await uut.ensureAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should return true if the user is an admin', async () => { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves({ type: 'admin' }) + + const result = await uut.ensureAdmin(ctx) + + assert.equal(result, true) + }) + }) + + describe('#ensureTargetUserOrAdmin', () => { + it('should throw error if token is not provided', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns() + + await uut.ensureTargetUserOrAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error if token can not be verified', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').throws(new Error('test error')) + + ctx.params = { + id: '456' + } + + await uut.ensureTargetUserOrAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error if user can not be found in database', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves(false) + + ctx.params = { + id: '456' + } + + await uut.ensureTargetUserOrAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error if user is not an admin', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves({ type: 'user' }) + + ctx.params = { + id: '456' + } + + await uut.ensureTargetUserOrAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should throw error is user is not admin or target user', async () => { + try { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves({ type: 'user', _id: '123' }) + + ctx.params = { + id: '456' + } + + await uut.ensureTargetUserOrAdmin(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(ctx.status, 401) + } + }) + + it('should return true if the user is an admin', async () => { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves({ type: 'admin', _id: '123' }) + + ctx.params = { + id: '456' + } + + const result = await uut.ensureTargetUserOrAdmin(ctx) + + assert.equal(result, true) + }) + + it('should return true if the user is the target user', async () => { + // Mock dependencies and force desired code path + sandbox.stub(uut, 'getToken').returns('fake-jwt') + sandbox.stub(uut.jwt, 'verify').returns({}) + sandbox.stub(uut.User, 'findById').resolves({ type: 'user', _id: '123' }) + + ctx.params = { + id: '123' + } + + const result = await uut.ensureTargetUserOrAdmin(ctx) + + assert.equal(result, true) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/auth/auth.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' + +import UseCasesMock from '../../../mocks/use-cases/index.js' + +// const app = require('../../../mocks/app-mock') + +import AuthRESTController from '../../../../../src/controllers/rest-api/auth/controller.js' + +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' + +let uut +let sandbox +let ctx + +describe('#Auth-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new AuthRESTController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new AuthRESTController() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating Auth REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new AuthRESTController({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating Auth REST Controller.' + ) + } + }) + }) + + describe('#authUser', () => { + it('should authorize a user', async () => { + // Mock dependencies + const user = { + toJSON: () => { + return { password: 'password' } + }, + generateToken: () => {} + } + sandbox.stub(uut.passport, 'authUser').resolves(user) + + await uut.authUser(ctx) + }) + + it('should catch and throw an error', async () => { + try { + // Force an error + sandbox.stub(uut.passport, 'authUser').rejects('test error') + + await uut.authUser(ctx) + } catch (err) { + // console.log('err: ', err) + assert.include(err.message, 'Unauthorized') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/auth/auth.rest.router.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' + +import UseCasesMock from '../../../mocks/use-cases/index.js' + +// const app = require('../../../mocks/app-mock') + +import AuthRouter from '../../../../../src/controllers/rest-api/auth/index.js' + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Auth-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new AuthRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new AuthRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating PostEntry REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new AuthRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating PostEntry REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attached REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/users/users.rest.router.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' + +import UseCasesMock from '../../../mocks/use-cases/index.js' + +// const app = require('../../../mocks/app-mock') + +import UserRouter from '../../../../../src/controllers/rest-api/users/index.js' + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Users-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new UserRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new UserRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating PostEntry REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new UserRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating PostEntry REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attaching REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/users/users.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' +import UserController from '../../../../../src/controllers/rest-api/users/controller.js' + +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' +let uut +let sandbox +let ctx + +describe('#Users-REST-Controller', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new UserController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new UserController() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /users REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new UserController({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /users REST Controller.' + ) + } + }) + }) + + describe('#POST /users', () => { + it('should return 422 status on biz logic error', async () => { + try { + await uut.createUser(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'Cannot read') + } + }) + + it('should return 200 status on success', async () => { + ctx.request.body = { + user: { + email: 'test02@test.com', + password: 'test', + name: 'test02' + } + } + + await uut.createUser(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'user') + assert.property(ctx.response.body, 'token') + + // Used by downstream tests. + // testUser = ctx.response.body.user + // console.log('testUser: ', testUser) + }) + }) + + describe('GET /users', () => { + it('should return 422 status on arbitrary biz logic error', async () => { + try { + // Force an error + sandbox + .stub(uut.useCases.user, 'getAllUsers') + .rejects(new Error('test error')) + + await uut.getUsers(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + await uut.getUsers(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'users') + }) + }) + + describe('GET /users/:id', () => { + it('should return 422 status on arbitrary biz logic error', async () => { + try { + // Force an error + sandbox + .stub(uut.useCases.user, 'getUser') + .rejects(new Error('test error')) + + await uut.getUser(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.useCases.user, 'getUser').resolves({ _id: '123' }) + + await uut.getUser(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'user') + }) + + it('should return other error status passed by biz logic', async () => { + try { + // Mock dependencies + const testErr = new Error('test error') + testErr.status = 404 + sandbox.stub(uut.useCases.user, 'getUser').rejects(testErr) + + await uut.getUser(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 404) + assert.include(err.message, 'test error') + } + }) + }) + + describe('PUT /users/:id', () => { + it('should return 422 if no input data given', async () => { + try { + await uut.updateUser(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'Cannot read') + } + }) + + it('should return 200 on success', async () => { + // Prep the testUser data. + // console.log('testUser: ', testUser) + // testUser.password = 'password' + // delete testUser.type + + // Replace the testUser variable with an actual model from the DB. + // const existingUser = await User.findById(testUser._id) + + ctx.body = { + user: {} + } + ctx.request.body = { + user: {} + } + + // Mock dependencies + sandbox.stub(uut.useCases.user, 'updateUser').resolves({}) + + await uut.updateUser(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'user') + }) + }) + + describe('DELETE /users/:id', () => { + it('should return 422 if no input data given', async () => { + try { + await uut.deleteUser(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'Cannot read') + } + }) + + it('should return 200 status on success', async () => { + // Replace the testUser variable with an actual model from the DB. + const existingUser = {} + + ctx.body = { + user: existingUser + } + + await uut.deleteUser(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + }) + }) + + describe('#handleError', () => { + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API controllers/rest-api/index.js library. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local libraries +import RESTControllers from '../../../../src/controllers/rest-api/index.js' + +// const mockContext = require('../../../unit/mocks/ctx-mock').context +import adapters from '../../mocks/adapters/index.js' + +import UseCasesMock from '../../mocks/use-cases/index.js' + +describe('#RESTControllers', () => { + let uut + let sandbox + // let ctx + + before(async () => {}) + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new RESTControllers({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new RESTControllers() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating REST Controller libraries.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new RESTControllers({ adapters }) + + assert.fail('Unexpected code path') + + // use to prevent complaints from linter. + console.log('uut: ', uut) + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating REST Controller libraries.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/entry/entry.rest.router.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' + +// const app = require('../../../mocks/app-mock') + +import EntryRouter from '../../../../../src/controllers/rest-api/entry/index.js' + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Entry-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new EntryRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new EntryRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /entry REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new EntryRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /entry REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attaching REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/entry/entry.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' + +import UseCasesMock from '../../../mocks/use-cases/index.js' +import EntryController from '../../../../../src/controllers/rest-api/entry/controller.js' + +import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js' +let uut +let sandbox +let ctx + +describe('#Entry-REST-Controller', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new EntryController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new EntryController() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /entry REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new EntryController({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /entry REST Controller.' + ) + } + }) + }) + + describe('#POST /entry', () => { + it('should return 422 status on biz logic error', async () => { + try { + await uut.createEntry(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'Cannot read') + } + }) + + it('should return 200 status on success', async () => { + ctx.request.body = { + entry: { + entry: 'entry', + description: 'test', + slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg', + signature: 'IFytRg6KpvTHCzcW0ZwVhPqdKtRGpoRDcuEb958yIgJFUJlb1F5qPzt/JnlYE7r012BSFj+UT67DZVTU8oNB5vw=', + category: 'test' + } + } + + await uut.createEntry(ctx) + + // Assert the expected HTTP response + assert.equal(ctx.status, 200) + + // Assert that expected properties exist in the returned data. + assert.property(ctx.response.body, 'entry') + }) + }) + + describe('#handleError', () => { + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + it('should catch error if message is provided', () => { + try { + const err = { + status: 422, + message: 'Unprocessable Entity' + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Unprocessable Entity') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/README.md`: + +```md +# REST API Unit Tests + +The tests in this directory are unit tests of REST API. These tests are not +concerned with the business logic behind the endpoints. They are only concerned +with the handling of the REST API endpoint. These tests answer questions like: + +- Is the endpoint responding properly when the business logic throws an error? +- When returning an error, is it returning the proper HTTP response? +- When returning success, is it returning the correct payload? + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/ipfs/ipfs.rest.controller.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /ipfs endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import IpfsApiController from '../../../../../src/controllers/rest-api/ipfs/controller.js' +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' + +import { context as mockContext } from '../../../mocks/ctx-mock.js' +let uut +let sandbox +let ctx + +describe('#IPFS REST API', () => { + before(async () => { + }) + + beforeEach(() => { + const useCases = new UseCasesMock() + + uut = new IpfsApiController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new IpfsApiController() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating /ipfs REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new IpfsApiController({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating /ipfs REST Controller.' + ) + } + }) + }) + + describe('#GET /status', () => { + it('should return 422 status on biz logic error', async () => { + try { + // Force an error + sandbox.stub(uut.adapters.ipfs, 'getStatus').rejects(new Error('test error')) + + await uut.getStatus(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.ipfs, 'getStatus').resolves({ a: 'b' }) + + await uut.getStatus(ctx) + // console.log('ctx.body: ', ctx.body) + + assert.property(ctx.body, 'status') + assert.equal(ctx.body.status.a, 'b') + }) + }) + + describe('#POST /peers', () => { + it('should return 422 status on biz logic error', async () => { + try { + // Force an error + sandbox.stub(uut.adapters.ipfs, 'getPeers').rejects(new Error('test error')) + + ctx.request.body = { + showAll: true + } + + await uut.getPeers(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves({ a: 'b' }) + + ctx.request.body = { + showAll: true + } + + await uut.getPeers(ctx) + // console.log('ctx.body: ', ctx.body) + + assert.property(ctx.body, 'peers') + assert.equal(ctx.body.peers.a, 'b') + }) + }) + + describe('#POST /relays', () => { + it('should return 422 status on biz logic error', async () => { + try { + // Force an error + sandbox.stub(uut.adapters.ipfs, 'getRelays').rejects(new Error('test error')) + + await uut.getRelays(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.ipfs, 'getRelays').resolves({ a: 'b' }) + + await uut.getRelays(ctx) + // console.log('ctx.body: ', ctx.body) + + assert.property(ctx.body, 'relays') + assert.equal(ctx.body.relays.a, 'b') + }) + }) + + describe('#POST /connect', () => { + it('should return 422 status on biz logic error', async () => { + try { + // Force an error + sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs, 'connectToPeer').rejects(new Error('test error')) + + ctx.request.body = { + multiaddr: '/ip4/161.35.99.207/tcp/4001/p2p/12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu' + } + + await uut.connect(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.equal(err.status, 422) + assert.include(err.message, 'test error') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs, 'connectToPeer').resolves({ success: true }) + + ctx.request.body = { + multiaddr: '/ip4/161.35.99.207/tcp/4001/p2p/12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu' + } + + await uut.connect(ctx) + // console.log('ctx.body: ', ctx.body) + + assert.property(ctx.body, 'success') + assert.equal(ctx.body.success, true) + }) + }) + + describe('#handleError', () => { + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + + it('should throw error with message', () => { + try { + const err = { + status: 422, + message: 'test error' + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) + + describe('#getThisNode', () => { + it('should return 422 status on biz logic error', async () => { + try { + // Force an error + // sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter.ipfsCoord, 'thisNode').rejects(new Error('test error')) + uut.adapters.ipfs.ipfsCoordAdapter = {} + + ctx.request.body = {} + + await uut.getThisNode(ctx) + + assert.fail('Unexpected result') + } catch (err) { + // console.log('err: ', err) + assert.equal(err.status, 422) + assert.include(err.message, 'Cannot read') + } + }) + + it('should return 200 status on success', async () => { + // Mock dependencies + // sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs, 'connectToPeer').resolves({ success: true }) + + uut.adapters.ipfs.ipfsCoordAdapter = { + ipfsCoord: { + thisNode: {} + } + } + + ctx.request.body = {} + + await uut.getThisNode(ctx) + + assert.property(ctx.body, 'thisNode') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/rest-api/ipfs/ipfs.rest.router.unit.js`: + +```js +/* + Unit tests for the REST API handler for the /ipfs endpoints. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../../../mocks/adapters/index.js' +import UseCasesMock from '../../../mocks/use-cases/index.js' +import IpfsRouter from '../../../../../src/controllers/rest-api/ipfs/index.js' +// const app = require('../../../mocks/app-mock') + +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#IPFS-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new IpfsRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new IpfsRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating IPFS REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new IpfsRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating IPFS REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attaching REST API controllers.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/controllers.unit.js`: + +```js +/* + Unit tests for controllers index.js file. +*/ + +// Public npm libraries +// const assert = require('chai').assert +import sinon from 'sinon' + +import Controllers from '../../../src/controllers/index.js' + +describe('#Controllers', () => { + let uut + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new Controllers() + }) + + afterEach(() => sandbox.restore()) + + describe('#attachControllers', () => { + it('should attach the controllers', async () => { + // mock IPFS + sandbox.stub(uut.adapters, 'start').resolves({}) + uut.adapters.ipfs.ipfsCoordAdapter = { + attachRPCRouter: () => {} + } + + // Mock the timer controllers + sandbox.stub(uut.timerControllers, 'startTimers').returns() + + const app = { + use: () => {} + } + + await uut.attachControllers(app) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/json-rpc/auth.json-rpc.controller.unit.js`: + +```js +/* + Unit tests for the json-rpc/auth/index.js file. +*/ + +// Public npm libraries +import jsonrpc from 'jsonrpc-lite' + +import sinon from 'sinon' +import { assert } from 'chai' +import { v4 as uid } from 'uuid' + +// Local libraries +import AuthRPC from '../../../../src/controllers/json-rpc/auth/index.js' + +import RateLimit from '../../../../src/controllers/json-rpc/rate-limit.js' +import adapters from '../../mocks/adapters/index.js' +import UseCasesMock from '../../mocks/use-cases/index.js' + +// Set the environment variable to signal this is a test. +process.env.TORLIST_ENV = 'test' + +describe('#AuthRPC', () => { + let uut + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + const useCases = new UseCasesMock() + + uut = new AuthRPC({ adapters, useCases }) + uut.rateLimit = new RateLimit({ max: 100 }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new AuthRPC() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating Auth JSON RPC Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new AuthRPC({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating Auth JSON RPC Controller.' + ) + } + }) + }) + + describe('#authRouter', () => { + it('should route to the authUser method', async () => { + // Mock dependencies + sandbox.stub(uut, 'authUser').resolves(true) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const authCall = jsonrpc.request(id, 'auth', { endpoint: 'authUser' }) + const jsonStr = JSON.stringify(authCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + rpcData.from = 'Origin request' + + const result = await uut.authRouter(rpcData) + + assert.equal(result, true) + }) + + it('should return 500 status on routing issue', async () => { + // Mock dependencies + sandbox.stub(uut, 'authUser').rejects(new Error('test error')) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const authCall = jsonrpc.request(id, 'auth', { endpoint: 'authUser' }) + const jsonStr = JSON.stringify(authCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + rpcData.from = 'Origin request' + + const result = await uut.authRouter(rpcData) + + assert.equal(result.success, false) + assert.equal(result.status, 500) + assert.equal(result.message, 'test error') + assert.equal(result.endpoint, 'authUser') + }) + }) + + describe('#authUser', () => { + it('should return a JWT token if user successfully authenticates', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const authCall = jsonrpc.request(id, 'auth', { + endpoint: 'authUser', + login: 'test543@test.com', + password: 'password' + }) + const jsonStr = JSON.stringify(authCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + const response = await uut.authUser(rpcData) + // console.log('response: ', response) + + assert.equal(response.endpoint, 'authUser') + assert.property(response, 'userId') + // assert.equal(response.userType, 'user') + assert.property(response, 'userName') + assert.property(response, 'userEmail') + assert.property(response, 'apiToken') + assert.equal(response.status, 200) + assert.equal(response.success, true) + assert.property(response, 'message') + }) + + it('should return an error for invalid credentials', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const authCall = jsonrpc.request(id, 'auth', { + endpoint: 'authUser', + login: 'test543@test.com', + password: 'badpassword' + }) + const jsonStr = JSON.stringify(authCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + // Force an error. + sandbox + .stub(uut.userLib, 'authUser') + .rejects(new Error('Login credential do not match')) + + const response = await uut.authUser(rpcData) + // console.log('response: ', response) + + assert.equal(response.success, false) + assert.equal(response.status, 422) + assert.equal(response.message, 'Login credential do not match') + assert.equal(response.endpoint, 'authUser') + }) + + it('should throw an error if login is not provided', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const authCall = jsonrpc.request(id, 'auth', { + endpoint: 'authUser' + }) + const jsonStr = JSON.stringify(authCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + const response = await uut.authUser(rpcData) + // console.log('response: ', response) + + assert.equal(response.success, false) + assert.equal(response.status, 422) + assert.equal(response.message, 'login must be specified') + assert.equal(response.endpoint, 'authUser') + }) + + it('should throw an error if password is not provided', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const authCall = jsonrpc.request(id, 'auth', { + endpoint: 'authUser', + login: 'test543@test.com' + }) + const jsonStr = JSON.stringify(authCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + const response = await uut.authUser(rpcData) + // console.log('response: ', response) + + assert.equal(response.success, false) + assert.equal(response.status, 422) + assert.equal(response.message, 'password must be specified') + assert.equal(response.endpoint, 'authUser') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/json-rpc/a14-rate-limits.js`: + +```js +/* + Unit tests for the JSON RPC validator middleware. + + TODO: ensureTargetUserOrAdmin: it should exit quietly if user is an admin. +*/ + +// Public npm libraries +import sinon from 'sinon' + +import { assert } from 'chai' + +// Local libraries +import RateLimit from '../../../../src/controllers/json-rpc/rate-limit.js' + +// Set the environment variable to signal this is a test. +process.env.TORLIST_ENV = 'test' + +describe('#rate-limit', () => { + let uut + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new RateLimit() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should use the options provided', async () => { + try { + const options = { + interval: { min: 10 }, + delayAfter: 1, + timeWait: { sec: 5 }, + max: 2, + onLimitReached: () => { + throw new Error('custom message error') + } + } + const _uut = new RateLimit(options) + + // Assert options + assert.equal(_uut.rateLimitOptions.interval.min, options.interval.min) + assert.equal(_uut.rateLimitOptions.delayAfter, options.delayAfter) + assert.equal(_uut.rateLimitOptions.timeWait.sec, options.timeWait.sec) + + const from = 'constructor test' + const firstRequest = await _uut.limiter(from) + assert.isTrue(firstRequest) + + const secondRequest = await _uut.limiter(from) + assert.isTrue(secondRequest) + + await _uut.limiter(from) + assert.fail('unexpected error') + } catch (error) { + assert.include(error.message, 'custom message error') + } + }) + }) + + describe('#onLimitReached', () => { + it('should throw error', async () => { + try { + uut.onLimitReached() + assert.fail('unexpected error') + } catch (error) { + assert.equal(error.status, 429) + assert.include( + error.message, + 'Too many requests, please try again later.' + ) + } + }) + }) + + describe('#limiter', () => { + it('should throw error if "from" input is not provider', async () => { + try { + await uut.limiter() + assert.fail('unexpected error') + } catch (error) { + assert.include(error.message, 'from must be a string') + } + }) + + it('should throw error 429', async () => { + try { + const _uut = new RateLimit({ max: 1 }) + const from = 'Origin request' + + const firstRequest = await _uut.limiter(from) + assert.isTrue(firstRequest) + + const secondRequest = await _uut.limiter(from) + assert.isTrue(secondRequest) + + await _uut.limiter(from) + assert.fail('unexpected error') + } catch (error) { + assert.include( + error.message, + 'Too many requests, please try again later.' + ) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/json-rpc/a12-validators.unit.js`: + +```js +/* + Unit tests for the JSON RPC validator middleware. + + TODO: ensureTargetUserOrAdmin: it should exit quietly if user is an admin. +*/ + +// Public npm libraries +import jsonrpc from 'jsonrpc-lite' + +import sinon from 'sinon' +import { assert } from 'chai' +import { v4 as uid } from 'uuid' + +// Local libraries +import Validators from '../../../../src/controllers/json-rpc/validators.js' + +import adapters from '../../mocks/adapters/index.js' + +// Set the environment variable to signal this is a test. +process.env.TORLIST_ENV = 'test' + +describe('#validators', () => { + let uut + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new Validators({ adapters }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters is not passed in.', () => { + try { + uut = new Validators() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating JSON RPC Validators library.' + ) + } + }) + }) + + describe('#ensureUser', () => { + it('should return user model for valid JWT token', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'getAll', + apiToken: 'fakeJWTToken' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + // Mock external dependencies. + sandbox.stub(uut.jwt, 'verify').returns(true) + sandbox.stub(uut.UserModel, 'findById').resolves(true) + + const user = await uut.ensureUser(rpcData) + // console.log('user: ', user) + + // For this test, we return a value of 'true' instead of actual user data. + assert.equal(user, true) + }) + + it('should throw an error if JWT token is not included', async () => { + try { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'getAll' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + await uut.ensureUser(rpcData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'apiToken JWT required as a parameter') + } + }) + + it('should throw an error if JWT token can not be decoded', async () => { + try { + const token = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYwNmQxYTlkNTgxNTVjMjIzNWFmMTNhMSIsImlhdCI6MTYxNzc2Mjk3M30.6JkM1v0n71Mzsd3qzClzlMKtq6HlD0umoauG23N9FFF' + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'getAll', + apiToken: token + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + await uut.ensureUser(rpcData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'invalid signature') + } + }) + + it('should throw an error if the user can not be found', async () => { + try { + // Force 'error not found' error + sandbox.stub(uut.UserModel, 'findById').resolves(null) + sandbox.stub(uut.jwt, 'verify').returns(true) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'getAll', + apiToken: 'fakeJWTToken' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + await uut.ensureUser(rpcData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'User not found!') + } + }) + }) + + describe('#ensureTargetUserOrAdmin', () => { + it('should return user model for valid JWT token', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'deleteUser', + apiToken: 'fakeJWTToken', + userId: 'abc123' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + // Mock external dependencies. + sandbox.stub(uut.jwt, 'verify').returns(true) + sandbox.stub(uut.UserModel, 'findById').resolves({ _id: 'abc123' }) + + const user = await uut.ensureTargetUserOrAdmin(rpcData) + // console.log('user: ', user) + + // Assert that the mocked data expected is returned. + assert.equal(user._id, 'abc123') + }) + + it('should throw error if JWT token is not provided', async () => { + try { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'deleteUser' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + await uut.ensureTargetUserOrAdmin(rpcData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'apiToken JWT required as a parameter') + } + }) + + it('should throw error if user ID is not specified', async () => { + try { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'deleteUser', + apiToken: 'fakeJWTToken' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + await uut.ensureTargetUserOrAdmin(rpcData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'userId must be specified') + } + }) + + it('should throw error if JWT token can not be decoded', async () => { + try { + const token = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYwNmU0YzkxYzdlYWNjN2Q4NWJjOGI0NCIsImlhdCI6MTYxNzg0MTI5N30.n1sas7YlqtmhBlNDBY_IXxQCrIQTiE8UITqy0PJAFFF' + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'deleteUser', + apiToken: token, + userId: 'abc123' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + await uut.ensureTargetUserOrAdmin(rpcData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'invalid signature') + } + }) + + it('should throw an error if user can not be found', async () => { + try { + // Mock external dependencies. + sandbox.stub(uut.jwt, 'verify').returns(true) + sandbox.stub(uut.UserModel, 'findById').resolves(null) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'deleteUser', + apiToken: 'fakeJWTToken', + userId: 'abc123' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + await uut.ensureTargetUserOrAdmin(rpcData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'User not found!') + } + }) + + it('should throw an error if JWT is from a different user', async () => { + try { + // Mock external dependencies. + sandbox.stub(uut.jwt, 'verify').returns(true) + sandbox.stub(uut.UserModel, 'findById').resolves({ _id: 'badId' }) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'deleteUser', + apiToken: 'fakeJWTToken', + userId: 'abc123' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + await uut.ensureTargetUserOrAdmin(rpcData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'User is neither admin nor target user.') + } + }) + + it('should return true if user is an admin', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'deleteUser', + apiToken: 'fakeJWTToken', + userId: 'abc123' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + // Mock external dependencies. + sandbox.stub(uut.jwt, 'verify').returns(true) + sandbox + .stub(uut.UserModel, 'findById') + .resolves({ _id: 'abc123', type: 'admin' }) + + const user = await uut.ensureTargetUserOrAdmin(rpcData) + // console.log('user: ', user) + + // Assert that the mocked data expected is returned. + assert.equal(user, true) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/json-rpc/a10-rpc.unit.js`: + +```js +/* + Unit tests for the rpc/index.js library. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import jsonrpc from 'jsonrpc-lite' +import sinon from 'sinon' +import { v4 as uid } from 'uuid' + +// Local libraries. +import JSONRPC from '../../../../src/controllers/json-rpc/index.js' + +import adapters from '../../mocks/adapters/index.js' +import UseCasesMock from '../../mocks/use-cases/index.js' + +// Set the environment variable to signal this is a test. +process.env.TORLIST_ENV = 'test' + +describe('#JSON RPC', () => { + let uut + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + const useCases = new UseCasesMock() + uut = new JSONRPC({ adapters, useCases }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new JSONRPC() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating JSON RPC Controllers.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new JSONRPC({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating JSON RPC Controllers.' + ) + } + }) + }) + + describe('#router', () => { + it('should exit quietly if given a random string', async () => { + const str = 'random string message' + await uut.router(str) + + assert.isOk('Not throwing an error is a pass.') + }) + + it('should exit quietly if invalid JSON RPC message received', async () => { + const malformedRpc = '{"jsonrpc":"2.0"}' + + await uut.router(malformedRpc, 'peerA') + + assert.isOk('Not throwing an error is a pass.') + }) + + it('should return default response if routing is not possible', async () => { + const id = uid() + const json = jsonrpc.request(id, 'unknownMethod', {}) + + const str = JSON.stringify(json) + + const result = await uut.router(str, 'peerA') + // console.log('result: ', result) + + const jsonObj = jsonrpc.parse(result.retStr) + // console.log(`jsonObj: ${JSON.stringify(jsonObj, null, 2)}`) + + // Assert the expected properties exist on the returned object. + assert.property(jsonObj, 'payload') + assert.property(jsonObj, 'type') + assert.property(jsonObj.payload, 'jsonrpc') + assert.property(jsonObj.payload, 'id') + assert.property(jsonObj.payload, 'result') + assert.property(jsonObj.payload.result, 'reciever') + assert.property(jsonObj.payload.result.value, 'success') + assert.property(jsonObj.payload.result.value, 'message') + + // Assert the expected values exist. + assert.equal(jsonObj.payload.id, id) + assert.equal(jsonObj.payload.result.value.success, false) + assert.equal(jsonObj.payload.result.value.status, 422) + assert.equal( + jsonObj.payload.result.value.message, + 'Input does not match routing rules.' + ) + }) + + it('should catch and handle errors', async () => { + // Force an error + sandbox.stub(uut.jsonrpc, 'parse').throws(new Error('test error')) + + const malformedRpc = '{"jsonrpc":"2.0"}' + + await uut.router(malformedRpc, 'peerA') + + assert.isOk('Not throwing an error is a pass.') + }) + + it('should route to users handler', async () => { + const id = uid() + const userCall = jsonrpc.request(id, 'users', { endpoint: 'getAll' }) + const jsonStr = JSON.stringify(userCall, null, 2) + + // Mock the users controller. + sandbox.stub(uut.userController, 'userRouter').resolves('true') + + const result = await uut.router(jsonStr, 'peerA') + // console.log(result) + + const obj = JSON.parse(result.retStr) + // console.log('obj: ', obj) + + assert.equal(obj.result.value, 'true') + assert.equal(obj.result.method, 'users') + assert.equal(obj.id, id) + }) + + it('should route to auth handler', async () => { + const id = uid() + const userCall = jsonrpc.request(id, 'auth', { endpoint: 'getAll' }) + const jsonStr = JSON.stringify(userCall, null, 2) + + // Mock the controller. + sandbox.stub(uut.authController, 'authRouter').resolves('true') + + const result = await uut.router(jsonStr, 'peerA') + // console.log(result) + + const obj = JSON.parse(result.retStr) + // console.log('obj: ', obj) + + assert.equal(obj.result.value, 'true') + assert.equal(obj.result.method, 'auth') + assert.equal(obj.id, id) + }) + + it('should route to about handler', async () => { + const id = uid() + const userCall = jsonrpc.request(id, 'about', { endpoint: 'getAll' }) + const jsonStr = JSON.stringify(userCall, null, 2) + + // Mock the controller. + sandbox.stub(uut.aboutController, 'aboutRouter').resolves('true') + + // Force ipfs-coord communication. + uut.ipfsCoord.ipfs = { + orbitdb: { + sendToDb: () => {} + } + } + + const result = await uut.router(jsonStr, 'peerA') + // console.log(result) + + const obj = JSON.parse(result.retStr) + // console.log('obj: ', obj) + + assert.equal(obj.result.value, 'true') + assert.equal(obj.result.method, 'about') + assert.equal(obj.id, id) + }) + + it('should exit quietly for duplicate RPC message', async () => { + const id = uid() + const json = jsonrpc.request(id, 'unknownMethod', {}) + + const str = JSON.stringify(json) + + // Call router once. + await uut.router(str, 'peerA') + + // Call the router again with the same input. + const result = await uut.router(str, 'peerA') + + assert.equal(result, false) + }) + + it('should ignore metric queries from ipfs-coord', async () => { + const id = uid() + const json = jsonrpc.request(id, 'unknownMethod', {}) + + const str = JSON.stringify(json) + + // Force the RPC type to be 'success', to indicate an RPC that was + // processed internal to ipfs-coord. + sandbox.stub(uut.jsonrpc, 'parse').returns({ + payload: {}, + type: 'success' + }) + + // Call the router again with the same input. + const result = await uut.router(str, 'peerA') + + assert.equal(result, false) + }) + + it('should report errors when trying to send messages to peers', async () => { + const id = uid() + const json = jsonrpc.request(id, 'unknownMethod', {}) + + const str = JSON.stringify(json) + + // Force issue with sendPrivateMessage() + sandbox + .stub(uut.ipfsCoord.useCases.peer, 'sendPrivateMessage') + .rejects('test error') + + // Call the router again with the same input. + const result = await uut.router(str, 'peerA') + // console.log('result: ', result) + + assert.property(result, 'from') + assert.property(result, 'retStr') + }) + }) + + describe('#_checkIfAlreadyProcessed', () => { + it('should return false the first time an RPC command is seen', () => { + const data = { + payload: { + jsonrpc: '2.0', + id: '6c515f3c-cf8a-42ec-870e-e416edd4923f', + method: 'unknownMethod', + params: {} + }, + type: 'request' + } + + const result = uut._checkIfAlreadyProcessed(data) + + assert.equal(result, false) + }) + + it('should return true the second time an RPC command is seen', () => { + const data = { + payload: { + jsonrpc: '2.0', + id: '6c515f3c-cf8a-42ec-870e-e416edd4923f', + method: 'unknownMethod', + params: {} + }, + type: 'request' + } + + // First call. + uut._checkIfAlreadyProcessed(data) + + // Second call. + const result = uut._checkIfAlreadyProcessed(data) + + assert.equal(result, true) + }) + + it('should push out old data from the cache for new data', () => { + const data = { + payload: { + jsonrpc: '2.0', + id: '6c515f3c-cf8a-42ec-870e-e416edd4923f', + method: 'unknownMethod', + params: {} + }, + type: 'request' + } + + uut.MSG_CACHE_SIZE = 0 + + const result = uut._checkIfAlreadyProcessed(data) + + assert.equal(result, false) + }) + + it('should return true on error', () => { + const result = uut._checkIfAlreadyProcessed() + + assert.equal(result, true) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/json-rpc/users.json-rpc-controller.unit.js`: + +```js +/* + Unit tests for the rpc/users/index.js file. +*/ + +// Public npm libraries +import jsonrpc from 'jsonrpc-lite' + +import sinon from 'sinon' +import { assert } from 'chai' +import { v4 as uid } from 'uuid' + +// Local libraries +import UserRPC from '../../../../src/controllers/json-rpc/users/index.js' + +import adapters from '../../mocks/adapters/index.js' +import UseCasesMock from '../../mocks/use-cases/index.js' + +// Set the environment variable to signal this is a test. +process.env.TORLIST_ENV = 'test' + +describe('#UserRPC', () => { + let uut + let sandbox + let testUser + + beforeEach(() => { + sandbox = sinon.createSandbox() + + const useCases = new UseCasesMock() + + uut = new UserRPC({ adapters, useCases }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new UserRPC() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating User JSON RPC Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new UserRPC({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating User JSON RPC Controller.' + ) + } + }) + }) + + describe('#createUser', () => { + it('should create a new user', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'createUser', + email: 'test973@test.com', + name: 'test973', + password: 'password' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + const result = await uut.createUser(rpcData) + // console.log('result: ', result) + + // CreateUser() specific return values. + // assert.equal(result.userData.type, 'user') + // assert.equal(result.userData.email, 'test973@test.com') + // assert.equal(result.userData.name, 'test973') + // assert.property(result.userData, '_id') + // assert.property(result, 'token') + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'createUser') + assert.equal(result.success, true) + assert.equal(result.status, 200) + assert.equal(result.message, '') + + // Save the user ID for future tests. + testUser = result + }) + + it('should return error data if biz logic throws an error', async () => { + // Force an error + sandbox.stub(uut.userLib, 'createUser').rejects(new Error('test error')) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'createUser', + email: 'test973@test.com', + name: 'test973', + password: 'password' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + const result = await uut.createUser(rpcData) + // console.log('result: ', result) + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'createUser') + assert.equal(result.success, false) + assert.equal(result.status, 422) + assert.equal(result.message, 'test error') + }) + }) + + describe('#userRouter', () => { + it('should route to the createUser method', async () => { + // Mock dependencies + sandbox.stub(uut, 'createUser').resolves(true) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { endpoint: 'createUser' }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + rpcData.from = 'Origin request' + + const result = await uut.userRouter(rpcData) + + assert.equal(result, true) + }) + + it('should route to the getAllUsers method', async () => { + // Mock dependencies + sandbox.stub(uut, 'getAll').resolves(true) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'getAllUsers', + apiToken: testUser.token + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + rpcData.from = 'Origin request' + + // Force middleware to pass. + sandbox.stub(uut.validators, 'ensureUser').resolves(true) + + const result = await uut.userRouter(rpcData) + // console.log('result', result) + assert.equal(result, true) + }) + + it('should route to the updateUser method', async () => { + // Mock dependencies + sandbox.stub(uut, 'updateUser').resolves(true) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'updateUser', + apiToken: 'fakeJWTToken', + userId: 'abc123' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + rpcData.from = 'Origin request' + + // Force middleware to pass. + sandbox.stub(uut.validators, 'ensureTargetUserOrAdmin').resolves(true) + + const result = await uut.userRouter(rpcData) + // console.log('result: ', result) + + assert.equal(result, true) + }) + + it('should route to the getUser method', async () => { + // Mock dependencies + sandbox.stub(uut, 'getUser').resolves(true) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'getUser', + apiToken: testUser.token + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + rpcData.from = 'Origin request' + + // Force middleware to pass. + sandbox.stub(uut.validators, 'ensureUser').resolves(true) + + const result = await uut.userRouter(rpcData) + // console.log('result: ', result) + + assert.equal(result, true) + }) + + it('should route to the deleteUsers method', async () => { + // Mock dependencies + sandbox.stub(uut, 'deleteUser').resolves(true) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'deleteUser', + apiToken: 'fakeJWTToken', + userId: 'abc123' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + rpcData.from = 'Origin request' + + // Force middleware to pass. + sandbox.stub(uut.validators, 'ensureTargetUserOrAdmin').resolves(true) + + const result = await uut.userRouter(rpcData) + // console.log('result: ', result) + + assert.equal(result, true) + }) + + it('should return 500 status on routing issue', async () => { + // Force an error + sandbox.stub(uut, 'createUser').rejects(new Error('test error')) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { endpoint: 'createUser' }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + rpcData.from = 'Origin request' + + const result = await uut.userRouter(rpcData) + // console.log('result: ', result) + + assert.equal(result.success, false) + assert.equal(result.status, 500) + assert.equal(result.message, 'test error') + assert.equal(result.endpoint, 'createUser') + }) + }) + + describe('#getAllUsers', () => { + it('should return all users', async () => { + const result = await uut.getAll() + // console.log('getAll result: ', result) + + // Endpoint specific properties + assert.property(result, 'users') + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'getAllUsers') + assert.equal(result.success, true) + assert.equal(result.status, 200) + assert.equal(result.message, '') + }) + + it('should return error data if biz logic throws an error', async () => { + // Force an error + sandbox.stub(uut.userLib, 'getAllUsers').rejects(new Error('test error')) + + const result = await uut.getAll() + // console.log('result: ', result) + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'getAllUsers') + assert.equal(result.success, false) + assert.equal(result.status, 422) + assert.equal(result.message, 'test error') + }) + }) + + describe('#updateUser', () => { + it('should update a user', async () => { + // Get the user model for the test user. + // const testUserModel = await UserModel.findById( + // testUser.userData._id, + // '-password' + // ) + + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'updateUser', + // userId: testUser.userData._id.toString(), + userId: 'abc123', + name: 'test777' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + const result = await uut.updateUser(rpcData, {}) + // console.log('updateUser result: ', result) + + // Endpoint specific properties + assert.property(result, 'user') + // assert.property(result.user, 'type') + // assert.property(result.user, '_id') + // assert.property(result.user, 'email') + // assert.property(result.user, 'name') + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'updateUser') + assert.equal(result.success, true) + assert.equal(result.status, 200) + assert.equal(result.message, '') + }) + + it('should return error data if biz logic throws an error', async () => { + // Force an error by not specifying an user ID. + const result = await uut.updateUser() + // console.log('result: ', result) + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'updateUser') + assert.equal(result.success, false) + assert.equal(result.status, 422) + assert.include(result.message, 'Cannot read') + }) + }) + + describe('#getUser', () => { + it('should return a specific user', async () => { + // Generate the parsed data that the main router would pass to this + // endpoint. + const id = uid() + const userCall = jsonrpc.request(id, 'users', { + endpoint: 'getUser', + userId: 'abc123' + }) + const jsonStr = JSON.stringify(userCall, null, 2) + const rpcData = jsonrpc.parse(jsonStr) + + const result = await uut.getUser(rpcData) + // console.log('getUser result: ', result) + + // Endpoint specific properties + assert.property(result, 'user') + // assert.property(result.user, 'type') + // assert.property(result.user, '_id') + // assert.property(result.user, 'email') + // assert.property(result.user, 'name') + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'getUser') + assert.equal(result.success, true) + assert.equal(result.status, 200) + assert.equal(result.message, '') + }) + + it('should return error data if biz logic throws an error', async () => { + // Force an error by not specifying an user ID. + const result = await uut.getUser() + // console.log('result: ', result) + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'getUser') + assert.equal(result.success, false) + assert.equal(result.status, 422) + assert.include(result.message, 'Cannot read') + }) + }) + + describe('#deleteUser', () => { + it('should delete a user', async () => { + // Get the user model for the test user. + // const testUserModel = await UserModel.findById( + // testUser.userData._id, + // '-password' + // ) + + await uut.deleteUser({}, {}) + // console.log(result) + + assert.isOk('Not throwing an error is a success') + }) + + it('should return error data if biz logic throws an error', async () => { + // Force an error: + sandbox + .stub(uut.userLib, 'deleteUser') + .rejects(new Error('Cannot read property')) + + const result = await uut.deleteUser() + // console.log('result: ', result) + + // Generic JSON RPC return values + assert.equal(result.endpoint, 'deleteUser') + assert.equal(result.success, false) + assert.equal(result.status, 422) + assert.include(result.message, 'Cannot read property') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/json-rpc/about.json-rpc.controller.unit.js`: + +```js +/* + Unit tests for the json-rpc/about/index.js file. +*/ + +// Public npm libraries +import sinon from 'sinon' + +import { assert } from 'chai' + +// Local libraries +import AboutRPC from '../../../../src/controllers/json-rpc/about/index.js' + +describe('#AboutRPC', () => { + let uut + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new AboutRPC() + }) + + afterEach(() => sandbox.restore()) + + describe('#aboutRouter', () => { + it('should return information about the service', async () => { + const result = await uut.aboutRouter() + // console.log('result: ', result) + + assert.property(result, 'success') + assert.equal(result.success, true) + assert.property(result, 'status') + assert.equal(result.status, 200) + assert.property(result, 'message') + assert.property(result, 'endpoint') + assert.equal(result.endpoint, 'about') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/controllers/timer-controllers.unit.js`: + +```js +/* + Unit tests for the timer-controller.js Controller library +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import TimerControllers from '../../../src/controllers/timer-controllers.js' +import adapters from '../mocks/adapters/index.js' +import UseCasesMock from '../mocks/use-cases/index.js' + +describe('#Timer-Controllers', () => { + let uut + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + const useCases = new UseCasesMock() + uut = new TimerControllers({ adapters, useCases }) + }) + + afterEach(() => { + sandbox.restore() + + uut.stopTimers() + }) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new TimerControllers() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating Timer Controller libraries.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new TimerControllers({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating Timer Controller libraries.' + ) + } + }) + }) + + describe('#startTimers', () => { + it('should start the timers', () => { + const result = uut.startTimers() + + // uut.stopTimers() + + assert.equal(result, true) + }) + }) + + describe('#gcOrders', () => { + it('should kick off the Use Case', async () => { + const result = await uut.gcOrders() + + assert.equal(result, true) + }) + + it('should return false on error', async () => { + sandbox.stub(uut.useCases.order, 'removeStaleOrders').throws(new Error('test error')) + const result = await uut.gcOrders() + + assert.equal(result, false) + }) + }) + describe('#gcOffers', () => { + it('should kick off the Use Case', async () => { + const result = await uut.gcOffers() + + assert.equal(result, true) + }) + + it('should return false on error', async () => { + sandbox.stub(uut.useCases.offer, 'removeStaleOffers').throws(new Error('test error')) + const result = await uut.gcOffers() + + assert.equal(result, false) + }) + }) + describe('#checkDupOffers', () => { + it('should kick off the Use Case', async () => { + const result = await uut.checkDupOffers() + + assert.equal(result, true) + }) + + it('should return false on error', async () => { + sandbox.stub(uut.useCases.offer, 'removeDuplicateOffers').throws(new Error('test error')) + const result = await uut.checkDupOffers() + + assert.equal(result, false) + }) + }) + describe('#loadOffers', () => { + it('should kick off the Use Case', async () => { + const result = await uut.loadOffers() + + assert.equal(result, true) + }) + + it('should return false on error', async () => { + sandbox.stub(uut.useCases.offer, 'loadOffers').throws(new Error('test error')) + const result = await uut.loadOffers() + + assert.equal(result, false) + }) + }) + + describe('#cleanUsage', () => { + it('should kick off the Use Case', async () => { + const result = await uut.cleanUsage() + + assert.equal(result, true) + }) + + it('should return false on error', async () => { + sandbox.stub(uut.useCases.usage, 'cleanUsage').throws(new Error('test error')) + const result = await uut.cleanUsage() + + assert.equal(result, false) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/use-cases/offer.use-case.unit.js`: + +```js +/* + Unit tests for the Offer Use Case library. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +// const testUtils = require('../../utils/test-utils') + +// Unit under test (uut) +import OfferLib from '../../../src/use-cases/offer/index.js' + +import OrderUseCase from '../../../src/use-cases/order.js' +import adapters from '../mocks/adapters/index.js' +import mockData from '../mocks/use-cases/offer-mock-data.js' + +describe('#offer-use-case', () => { + let uut + let sandbox + + before(async () => { + // Delete all previous users in the database. + // await testUtils.deleteAllUsers() + }) + + beforeEach(() => { + sandbox = sinon.createSandbox() + + const order = new OrderUseCase({ adapters }) + uut = new OfferLib({ adapters, order }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new OfferLib() + + assert.fail('Unexpected code path') + console.log(uut) // linter + } catch (err) { + assert.include( + err.message, + 'Instance of adapters must be passed in when instantiating Offer Use Cases library.' + ) + } + }) + + it('should throw an error if order use cases are not passed in', () => { + try { + uut = new OfferLib({ adapters }) + + assert.fail('Unexpected code path') + console.log(uut) // linter + } catch (err) { + assert.include( + err.message, + 'Instance of Order Use Cases must be passed in when instantiating Offer Use Cases library.' + ) + } + }) + }) + + describe('#createOffer', () => { + it('should handle error', async () => { + try { + await uut.createOffer() + assert.fail('unexpected code path') + } catch (error) { + assert.include(error.message, 'Cannot read properties of undefined') + } + }) + + it('should return false if offer already exist', async () => { + const offerObj = mockData.offerMockData + + // Mock dependencies + // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(false) + sandbox.stub(uut, 'findOfferByTxid').resolves({}) + + const result = await uut.createOffer(offerObj) + assert.isFalse(result) + }) + + it('should return false for invalid utxo', async () => { + const offerObj = mockData.offerMockData + + // Mock dependencies + // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(false) + sandbox.stub(uut, 'findOfferByTxid').throws(new Error('offer not found')) + sandbox.stub(uut.retryQueue, 'addToQueue').resolves(null) + + const result = await uut.createOffer(offerObj) + assert.isFalse(result) + }) + + it('should create offer', async () => { + const tokenDataMock = mockData.simpleNftTokenData01 + const offerObj = mockData.offerMockData + + // Mock dependencies + // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(false) + sandbox.stub(uut, 'findOfferByTxid').throws(new Error('offer not found')) + sandbox.stub(uut.retryQueue, 'addToQueue') + .onCall(0).resolves({}) // Utxo Status call + .onCall(1).resolves(tokenDataMock) // Token Data call + .onCall(2).resolves(false) // detectNsfw call + + const result = await uut.createOffer(offerObj) + assert.isTrue(result) + }) + }) + + describe('#categorizeToken', () => { + it('should categorize an NFT', async () => { + // Mock dependencies + // sandbox.stub(uut.adapters.wallet.bchWallet, 'getTokenData').resolves(mockData.nftTokenData01) + + const offerData = mockData.nftOffer01 + const tokenData = mockData.nftTokenData01 + + const result = await uut.categorizeToken(offerData, tokenData) + + assert.equal(result, 'nft') + }) + + it('should categorize a simple NFT', async () => { + // Mock dependencies + // sandbox.stub(uut.adapters.wallet.bchWallet, 'getTokenData').resolves(mockData.simpleNftTokenData01) + + const offerData = mockData.simpleNftOffer01 + const tokenData = mockData.simpleNftTokenData01 + + const result = await uut.categorizeToken(offerData, tokenData) + + assert.equal(result, 'simple-nft') + }) + + it('should categorize a fungible token', async () => { + // Mock dependencies + // sandbox.stub(uut.adapters.wallet.bchWallet, 'getTokenData').resolves(mockData.fungibleTokenData01) + + const offerData = mockData.fungibleOffer01 + const tokenData = mockData.fungibleTokenData01 + + const result = await uut.categorizeToken(offerData, tokenData) + + assert.equal(result, 'fungible') + }) + + it('should unknow type', async () => { + try { + // Mock dependencies + const offerData = mockData.fungibleOffer01 + const tokenData = { genesisData: {} } + + await uut.categorizeToken(offerData, tokenData) + + assert.fail('unexpected code path') + } catch (error) { + assert.include(error.message, 'Unknown token type:') + } + }) + }) + + describe('#removeDuplicateOffers', () => { + it('should remove duplicate entries and return true', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'find').resolves([ + { p2wdbHash: 'a', remove: async () => { } }, + { p2wdbHash: 'a', remove: async () => { } }, + { p2wdbHash: 'b', remove: async () => { } } + ]) + // sandbox.stub(uut.OfferModel, 'remove').resolves() + + const result = await uut.removeDuplicateOffers() + console.log('result: ', result) + + assert.equal(result, true) + }) + + it('should return false if there are no duplicate entries', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'find').resolves([ + { p2wdbHash: 'a', remove: async () => { } }, + { p2wdbHash: 'b', remove: async () => { } } + ]) + // sandbox.stub(uut.OfferModel, 'remove').resolves() + + const result = await uut.removeDuplicateOffers() + console.log('result: ', result) + + assert.equal(result, false) + }) + + it('should handle error', async () => { + try { + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'find').throws(new Error('test error')) + // sandbox.stub(uut.OfferModel, 'remove').resolves() + + await uut.removeDuplicateOffers() + assert.fail('unexpected code path') + } catch (error) { + assert.equal(error.message, 'test error') + } + }) + }) + + describe('#removeStaleOffers', () => { + it('remove offer with wrong utxoState', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'find').resolves([{ remove: async () => { } }]) + sandbox.stub(uut.retryQueue, 'addToQueue').resolves(false) + + await uut.removeStaleOffers() + }) + + it('remove offer with wrong txid', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'find').resolves([{ remove: async () => { } }]) + sandbox.stub(uut.retryQueue, 'addToQueue').throws(new Error('txid needs to be a proper transaction ID')) + + await uut.removeStaleOffers() + }) + + it('remove expired offer ', async () => { + const tsMock = new Date() + tsMock.setMonth(tsMock.getMonth() - 3) + + const timestamp = tsMock.getTime() + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'find').resolves([{ timestamp, remove: async () => { } }]) + sandbox.stub(uut.retryQueue, 'addToQueue').resolves(true) + + await uut.removeStaleOffers() + }) + + it('should handle axios error ', async () => { + const testErr = new Error() + testErr.isAxiosError = true + + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'find').resolves([{ remove: async () => { } }]) + sandbox.stub(uut.retryQueue, 'addToQueue').throws(testErr) + + await uut.removeStaleOffers() + }) + + it('should handle error ', async () => { + try { + const testErr = new Error('unknow error') + + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'find').resolves([{ remove: async () => { } }]) + sandbox.stub(uut.retryQueue, 'addToQueue').throws(testErr) + + await uut.removeStaleOffers() + assert.fail('unexpected code path') + } catch (error) { + assert.equal(error.message, 'unknow error') + } + }) + }) + + describe('#findOfferByTxid', () => { + it('should throw an error if input is not provided', async () => { + try { + await uut.findOfferByTxid() + assert.fail('unexpected code path') + } catch (error) { + assert.equal(error.message, 'utxoTxid must be a string') + } + }) + + it('should throw an error if offer is not found', async () => { + try { + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'findOne').resolves(null) + + await uut.findOfferByTxid('241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87') + assert.fail('unexpected code path') + } catch (error) { + assert.equal(error.message, 'offer not found') + } + }) + + it('should return offer', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.OfferModel, 'findOne').resolves(mockData.nftOffer01) + + const result = await uut.findOfferByTxid('241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87') + assert.isObject(result) + }) + }) + + describe('#detectNsfw', () => { + it('should return false for wrong cid format', async () => { + const result = await uut.detectNsfw({ mutableData: '' }) + assert.isFalse(result) + }) + + it('should return true if nft boolean detected', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.axios, 'get').resolves({ data: { nsfw: true } }) + + const result = await uut.detectNsfw({ mutableData: 'ipfs://bafybeibqnsmmh6bkf2wwextetki4tly65z4r4qkrrpl5xwgvzdzjley6wm' }) + assert.isTrue(result) + }) + + it('should return true if nft string detected', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.axios, 'get').resolves({ data: { nsfw: 'true' } }) + + const result = await uut.detectNsfw({ mutableData: 'ipfs://bafybeibqnsmmh6bkf2wwextetki4tly65z4r4qkrrpl5xwgvzdzjley6wm' }) + assert.isTrue(result) + }) + + it('should return false if nfsw property does not exist', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.axios, 'get').resolves({ data: {} }) + + const result = await uut.detectNsfw({ mutableData: 'ipfs://bafybeibqnsmmh6bkf2wwextetki4tly65z4r4qkrrpl5xwgvzdzjley6wm' }) + assert.isFalse(result) + }) + + it('should return false on error', async () => { + // Mock dependencies and force desired code path. + sandbox.stub(uut.axios, 'get').throws(new Error('test error')) + + const result = await uut.detectNsfw({ mutableData: 'ipfs://bafybeibqnsmmh6bkf2wwextetki4tly65z4r4qkrrpl5xwgvzdzjley6wm' }) + assert.isFalse(result) + }) + }) + + describe('#listOffers', () => { + it('should handle error', async () => { + try { + // Mock dependencies + sandbox.stub(uut.OfferModel, 'find').throws(new Error('test error')) + + await uut.listOffers() + + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should list orders', async () => { + const queryMock = { + sort () { + return this + }, + skip () { + return this + }, + limit () { return [] } + } + // Mock dependencies + sandbox.stub(uut.OfferModel, 'find').returns(queryMock) + + const result = await uut.listOffers() + assert.isArray(result) + }) + }) + + describe('#listNftOffers', () => { + it('should handle error', async () => { + try { + // Mock dependencies + sandbox.stub(uut.OfferModel, 'find').throws(new Error('test error')) + + await uut.listNftOffers() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should list orders', async () => { + const queryMock = { + sort () { + return this + }, + skip () { + return this + }, + limit () { return [] } + } + // Mock dependencies + sandbox.stub(uut.OfferModel, 'find').returns(queryMock) + + const result = await uut.listNftOffers(1, true) + assert.isArray(result) + }) + }) + + describe('#listFungibleOffers', () => { + it('should handle error', async () => { + try { + // Mock dependencies + sandbox.stub(uut.OfferModel, 'find').throws(new Error('test error')) + + await uut.listFungibleOffers() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should list orders', async () => { + const queryMock = { + sort () { + return this + }, + skip () { + return this + }, + limit () { return [] } + } + + // Mock dependencies + sandbox.stub(uut.OfferModel, 'find').returns(queryMock) + + const result = await uut.listFungibleOffers() + assert.isArray(result) + }) + }) + + describe('#takeOffer', () => { + it('should handle error if input is not provided', async () => { + try { + await uut.takeOffer() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'eventId must be a string') + } + }) + + it('should handle error for wrong offer status', async () => { + try { + // Mock dependencies + sandbox.stub(uut, 'findOfferByEvent').returns({ offerStatus: 'completed' }) + + await uut.takeOffer('eventId') + + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'offer status is not "posted", so offer is dead and can not be countered.') + } + }) + + it('should handle error for invalid utxo', async () => { + try { + // Mock dependencies + sandbox.stub(uut, 'findOfferByEvent').returns({ offerStatus: 'posted' }) + sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').returns(false) + + await uut.takeOffer('eventId') + + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'UTXO does not exist. Aborting.') + } + }) + + it('should handle insufficient funds', async () => { + try { + // Mock dependencies + sandbox.stub(uut, 'findOfferByEvent').returns({ offerStatus: 'posted' }) + sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').returns(true) + sandbox.stub(uut, 'ensureFunds').throws(new Error('test error')) + + await uut.takeOffer('eventId') + + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should handle error if counter offer cant be calculated', async () => { + try { + // Mock dependencies + sandbox.stub(uut, 'findOfferByEvent').returns({ offerStatus: 'posted' }) + sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').returns(true) + sandbox.stub(uut, 'ensureFunds').resolves(true) + + await uut.takeOffer('eventId') + + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'Could not calculate the amount of BCH to generate counter offer') + } + }) + + it('should handle error if counter offer cant be calculated', async () => { + try { + // Mock dependencies + sandbox.stub(uut, 'findOfferByEvent').returns({ offerStatus: 'posted' }) + sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').returns(true) + sandbox.stub(uut, 'ensureFunds').resolves(true) + + await uut.takeOffer('eventId') + + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'Could not calculate the amount of BCH to generate counter offer') + } + }) + + it('should take offer', async () => { + // Mock data + const offerMock = Object.assign({}, mockData.offerMockData.data) + offerMock.remove = async () => { } + offerMock.offerStatus = 'posted' + + // Mock dependencies + sandbox.stub(uut, 'findOfferByEvent').returns(offerMock) + sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').returns(true) + sandbox.stub(uut, 'ensureFunds').resolves(true) + sandbox.stub(uut.adapters.wallet, 'moveBch').resolves({ sats: 1 }) + + await uut.takeOffer('eventId') + }) + }) + + describe('#ensureFunds', () => { + // it('should handle insufficient funds to use p2wdb', async () => { + // try { + // // Mock dependencies + // sandbox.stub(uut.adapters.p2wdb, 'checkForSufficientFunds').resolves(false) + // + // await uut.ensureFunds(mockData.offerMockData.data) + // + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, 'App wallet does not have funds for writing to the P2WDB') + // } + // }) + + it('should throw error if sats needed could no be able to calculated', async () => { + try { + // Mock dependencies + sandbox.stub(uut.adapters.p2wdb, 'checkForSufficientFunds').resolves(true) + + // Mock Input + const mock = Object.assign({}, mockData.offerMockData.data) + mock.rateInBaseUnit = null + + await uut.ensureFunds(mock) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'Could not calculate sats needed!') + } + }) + + it('should throw error if app wallet does not have enough bch', async () => { + try { + // Mock dependencies + sandbox.stub(uut.adapters.p2wdb, 'checkForSufficientFunds').resolves(true) + sandbox.stub(uut.adapters.wallet.bchWallet, 'getBalance').resolves(0) + + await uut.ensureFunds(mockData.offerMockData.data) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'App wallet does not control enough BCH to purchase the tokens.') + } + }) + + it('should handle BUY offer', async () => { + try { + const mock = Object.assign({}, mockData.offerMockData.data) + mock.buyOrSell = 'buy' + + await uut.ensureFunds(mock) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'Buy offers are not supported yet.') + } + }) + + it('should return true', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.p2wdb, 'checkForSufficientFunds').resolves(true) + sandbox.stub(uut.adapters.wallet.bchWallet, 'getBalance').resolves(10 * 10 ** 6) + + const result = await uut.ensureFunds(mockData.offerMockData.data) + assert.isTrue(result) + }) + }) + + describe('#findOrderByEvent', () => { + it('should throw an error if hash is not provided', async () => { + try { + await uut.findOfferByEvent() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'nostrEventId must be a string') + } + }) + + it('should throw an error if order is not found!', async () => { + try { + // Mock dependencies + sandbox.stub(uut.OfferModel, 'findOne').resolves(null) + + await uut.findOfferByEvent('eventId') + + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'offer not found') + } + }) + + it('should return offer by eventId', async () => { + // Mock dependencies + sandbox.stub(uut.OfferModel, 'findOne').resolves({ toObject: () => { return { hash: 'hash' } } }) + + const result = await uut.findOfferByEvent('eventId') + assert.isObject(result) + }) + }) + + describe('#flagOffer', () => { + it('should throw an error if input is not provided', async () => { + try { + await uut.flagOffer() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, '"data" property is required') + } + }) + + it('should throw an error if offer is not found!', async () => { + try { + // Mock dependencies + sandbox.stub(uut, 'findOfferByEvent').resolves(null) + + const input = { + data: + { + nostrEventId: 'eventId' + } + } + await uut.flagOffer(input) + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'not found in the database') + } + }) + + it('should flag offer', async () => { + // Mock dependencies + sandbox.stub(uut, 'findOfferByEvent').resolves({ flags: ['a', 'b', 'c'], save: () => { } }) + + const input = { + data: + { + nostrEventId: 'eventId' + } + } + const result = await uut.flagOffer(input) + assert.isTrue(result) + }) + }) + + describe('#loadOffers', () => { + it('should handle nostr error', async () => { + try { + // Mock dependencies + sandbox.stub(uut.adapters.nostr, 'read').throws(new Error('test error')) + + await uut.loadOffers() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should skip internal function errors ', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.nostr, 'read').resolves([mockData.offerMockData]) + + await uut.loadOffers() + }) + + it('should review and load offers', async () => { + // Mock dependencies + sandbox.stub(uut.adapters.nostr, 'read').resolves([JSON.stringify(mockData.offerMockData)]) + + await uut.loadOffers() + }) + }) + + describe('#acceptCounterOffer', () => { + it('should return if order is not found!', async () => { + // Mock dependencies + sandbox.stub(uut.orderUseCase, 'findOrderByEvent').throws(new Error('test error')) + + const result = await uut.acceptCounterOffer({ data: { /** .... */ } }) + assert.equal(result, 'N/A') + }) + + it('should handle error if counter offer cant be calculated', async () => { + try { + // Mock Data + const mock = Object.assign({}, mockData.offerMockData.data) + mock.rateInBaseUnit = null + + // Mock dependencies + sandbox.stub(uut.orderUseCase, 'findOrderByEvent').resolves(mock) + sandbox.stub(uut.orderUseCase, 'findOrderByUtxo').resolves(mock) + + const result = await uut.acceptCounterOffer({ data: { /** .... */ } }) + console.log('result: ', result) + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'Could not calculate the amount of BCH offered in the Counter Offer') + } + }) + + it('should handle error for wrong transaction output', async () => { + try { + // Mock Data + const mock = Object.assign({}, mockData.offerMockData.data) + + // Mock dependencies + sandbox.stub(uut.orderUseCase, 'findOrderByUtxo').resolves(mock) + sandbox.stub(uut.orderUseCase, 'findOrderByEvent').resolves(mockData.offerMockData.data) + sandbox.stub(uut.adapters.wallet.bchWallet.bchjs.BitcoinCash, 'toSatoshi').returns(0) + sandbox.stub(uut.adapters.wallet, 'deseralizeTx').resolves(mockData.deserealizeTxMock) + + await uut.acceptCounterOffer({ data: mock }) + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'The Counter Offer has an output of ') + assert.include(err.message, 'which does not match the required') + } + }) + + it('should handle error for wrong transaction output address', async () => { + try { + // Mock data + const mock = Object.assign({}, mockData.offerMockData.data) + mock.makerAddr = 'bitcoincash:qzy97glp47ut7tstm5g0tlrmkhk742795gkmyc7477' // Unknow Adress + mock.rateInBaseUnit = 0 + mock.numTokens = 0 + + // Mock dependencies + sandbox.stub(uut.orderUseCase, 'findOrderByEvent').resolves(mock) + sandbox.stub(uut.orderUseCase, 'findOrderByUtxo').resolves(mock) + sandbox.stub(uut.adapters.wallet.bchWallet.bchjs.BitcoinCash, 'toSatoshi').returns(0) + + sandbox.stub(uut.adapters.wallet, 'deseralizeTx').resolves(mockData.deserealizeTxMock) + + await uut.acceptCounterOffer({ data: { /** .... */ } }) + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'The Counter Offer has an output address of') + assert.include(err.message, 'which does not match the Maker address') + } + }) + + it('should return tx id', async () => { + // Mock data + const mock = Object.assign({}, mockData.offerMockData.data) + mock.makerAddr = mockData.deserealizeTxMock.vout[2].scriptPubKey.addresses[0] // Maker Address + mock.rateInBaseUnit = 0 + mock.numTokens = 0 + + // Mock dependencies + sandbox.stub(uut.orderUseCase, 'findOrderByEvent').resolves(mock) + sandbox.stub(uut.adapters.wallet.bchWallet.bchjs.BitcoinCash, 'toSatoshi').returns(0) + sandbox.stub(uut.adapters.wallet, 'deseralizeTx').resolves(mockData.deserealizeTxMock) + + // + const result = await uut.acceptCounterOffer({ data: { /** .... */ } }) + assert.isString(result) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/use-cases/users.use-case.unit.js`: + +```js +/* + Unit tests for the src/lib/users.js business logic library. + + TODO: verify that an admin can change the type of a user +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Unit under test (uut) +import UserLib from '../../../src/use-cases/user.js' + +// Local support libraries +import adapters from '../mocks/adapters/index.js' + +describe('#users-use-case', () => { + let uut + let sandbox + let testUser = {} + + before(async () => { + // Delete all previous users in the database. + // await testUtils.deleteAllUsers() + }) + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new UserLib({ adapters }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new UserLib() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of adapters must be passed in when instantiating User Use Cases library.' + ) + } + }) + }) + + describe('#createUser', () => { + it('should throw an error if no input is given', async () => { + try { + await uut.createUser() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + // assert.equal(err.status, 422) + assert.include(err.message, "Property 'email' must be a string!") + } + }) + + it('should throw an error if email is not provided', async () => { + try { + await uut.createUser({}) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, "Property 'email' must be a string!") + } + }) + + it('should throw an error if password is not provided', async () => { + try { + const usrObj = { + email: 'test@test.com' + } + + await uut.createUser(usrObj) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, "Property 'password' must be a string!") + } + }) + + it('should throw an error if name is not provided', async () => { + try { + const usrObj = { + email: 'test@test.com', + password: 'password' + } + + await uut.createUser(usrObj) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, "Property 'name' must be a string!") + } + }) + + it('should catch and throw DB errors', async () => { + try { + // Force an error with the database. + sandbox.stub(uut, 'UserModel').throws(new Error('test error')) + + const usrObj = { + email: 'test@test.com', + password: 'password', + name: 'test' + } + + await uut.createUser(usrObj) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + it('should handle wallet errors', async () => { + try { + // Force an error with the database. + class MockErrorBchWallet { + constructor () { + this.walletInfoPromise = Promise.reject(new Error('test error')) + } + } + uut.BchWallet = MockErrorBchWallet + + const usrObj = { + email: 'test@test.com', + password: 'password', + name: 'test' + } + + await uut.createUser(usrObj) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should create a new user in the DB', async () => { + // Note: The user created in this test is used by the getUser, update, + // and delete tests. + + const usrObj = { + email: 'test01@test.com', + password: 'test', + name: 'test01' + } + + const { userData, token } = await uut.createUser(usrObj) + testUser = userData + + // Commented out because there is some sophisticated mocking required that + // I didn't have time to figure out. -CT 6/11/21 + // Assert that the user model has the expected properties with expected values. + // assert.property(userData, 'type') + // assert.equal(userData.type, 'user') + // assert.property(userData, '_id') + // assert.property(userData, 'email') + // assert.property(userData, 'name') + + // Assert that the JWT token was generated for this user. + assert.isString(token) + assert.include(token, '123') + }) + }) + + describe('#getAllUsers', () => { + it('should return all users from the database', async () => { + await uut.getAllUsers() + // console.log(`users: ${JSON.stringify(users, null, 2)}`) + + // assert.isArray(users) + }) + + it('should catch and throw an error', async () => { + try { + // Force an error. + sandbox.stub(uut.UserModel, 'find').rejects(new Error('test error')) + + await uut.getAllUsers() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) + + describe('#getUser', () => { + it('should throw 422 if no id given.', async () => { + try { + await uut.getUser() + + assert.fail('Unexpected code path.') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'Unprocessable Entity') + } + }) + + it('should throw 422 for malformed id', async () => { + try { + // Force an error. + sandbox + .stub(uut.UserModel, 'findById') + .rejects(new Error('Unprocessable Entity')) + + const params = { id: 1 } + await uut.getUser(params) + + assert.fail('Unexpected code path.') + } catch (err) { + // console.log(err) + assert.equal(err.status, 422) + assert.include(err.message, 'Unprocessable Entity') + } + }) + + it('should throw 404 if user is not found', async () => { + try { + const params = { id: '5fa4bd7ee1828f5f4d3ed004' } + await uut.getUser(params) + + assert.fail('Unexpected code path.') + } catch (err) { + // console.log(err) + assert.equal(err.status, 404) + assert.include(err.message, 'User not found') + } + }) + + it('should return the user model', async () => { + sandbox.stub(uut.UserModel, 'findById').resolves({ _id: 'abc123' }) + + const params = { id: testUser._id } + const result = await uut.getUser(params) + // console.log('result: ', result) + + // Replace the JSON model with an actual Mongoos model. Used by later + // test cases. + testUser = result + + // Assert that the expected properties for the user model exist. + // assert.property(result, 'type') + assert.property(result, '_id') + // assert.property(result, 'email') + // assert.property(result, 'name') + }) + }) + + describe('#updateUser', () => { + it('should throw an error if no input is given', async () => { + try { + await uut.updateUser() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, 'Cannot read') + } + }) + + it('should throw an error if email is not a string', async () => { + try { + await uut.updateUser(testUser, { + email: 1234 + }) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'email' must be a string!") + } + }) + + it('should throw an error if name is not a string', async () => { + try { + const newData = { + name: 1234 + } + + await uut.updateUser(testUser, newData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'name' must be a string!") + } + }) + + it('should throw an error if non-string password given', async () => { + try { + const newData = { + email: 'test@test.com', + name: 'test', + password: 1234 + } + + await uut.updateUser(testUser, newData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'password' must be a string!") + } + }) + + it('should throw an error for malformed type given', async () => { + try { + const newData = { + email: 'test@test.com', + password: 'password', + name: 'test', + type: 1234 + } + + await uut.updateUser(testUser, newData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'type' must be a string!") + } + }) + + it('should throw an error if normal user tries to change themselves into an admin', async () => { + try { + const newData = { + email: 'test@test.com', + password: 'password', + name: 'test', + type: 'admin' + } + + await uut.updateUser(testUser, newData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'type' can only be changed by Admin user" + ) + } + }) + it('should throw an error if mnemonic is provided', async () => { + try { + const newData = { + email: 'test@test.com', + password: 'password', + name: 'test', + mnemonic: 'test' + } + + await uut.updateUser(testUser, newData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'mnemonic' cannot be updated!" + ) + } + }) + + it('should update the user model', async () => { + const newData = { + email: 'test@test.com', + password: 'password', + name: 'testy tester' + } + testUser.save = async () => {} + + const result = await uut.updateUser(testUser, newData) + + // Assert that expected properties and values exist. + assert.property(result, '_id') + assert.property(result, 'email') + assert.equal(result.email, 'test@test.com') + assert.property(result, 'name') + assert.equal(result.name, 'testy tester') + }) + + // TODO: verify that an admin can change the type of a user + }) + + describe('#authUser', () => { + it('should return a user db model after successful authentication', async () => { + // sandbox.stub(uut.UserModel, 'findOne').resolves(true) + + await uut.authUser('test@test.com', 'password') + // console.log('user: ', user) + + // assert.property(user, '_id') + // assert.property(user, 'email') + // assert.property(user, 'name') + }) + + it('should throw an error if no user matches the login', async () => { + try { + sandbox.stub(uut.UserModel, 'findOne').resolves(false) + + await uut.authUser('noone@nowhere.com', 'password') + // console.log('user: ', user) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'User not found') + } + }) + + it('should throw an error if password does not match', async () => { + try { + // Force authentication to fial. + adapters.localdb.validatePassword = () => { + return false + } + + await uut.authUser('test@test.com', 'badpassword') + // console.log('user: ', user) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'Login credential do not match') + } + }) + }) + + describe('#deleteUser', () => { + it('should throw error if no user provided', async () => { + try { + await uut.deleteUser() + + assert.fail('Unexpected code path.') + } catch (err) { + // console.log(err) + assert.include(err.message, 'Cannot read') + } + }) + + it('should delete the user from the database', async () => { + testUser = new adapters.localdb.Users() + + await uut.deleteUser(testUser) + + assert.isOk('Not throwing an error is a pass!') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/use-cases/order.use-case.unit.js`: + +```js +/* + Unit tests for the Order Use Case library. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Unit under test (uut) +import OrderLib from '../../../src/use-cases/order.js' + +// Local support libraries +import adapters from '../mocks/adapters/index.js' + +describe('#order-use-case', () => { + let uut + let sandbox + + before(async () => { + // Delete all previous users in the database. + // await testUtils.deleteAllUsers() + }) + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new OrderLib({ adapters }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new OrderLib() + + assert.fail('Unexpected code path') + console.log(uut) // linter + } catch (err) { + assert.include( + err.message, + 'Instance of adapters must be passed in when instantiating Order Use Cases library.' + ) + } + }) + }) + + describe('#ensureFunds', () => { + it('should return true if wallet has enough funds for a sell order', async () => { + const orderEntity = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + buyOrSell: 'sell', + rateInSats: 1000, + minSatsToExchange: 0, + numTokens: 1 + } + + const result = await uut.ensureFunds(orderEntity) + + assert.equal(result, true) + }) + it('should handle insufficient funds', async () => { + try { + sandbox.stub(uut.adapters.p2wdb, 'checkForSufficientFunds').resolves(false) + const orderEntity = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + buyOrSell: 'sell', + rateInSats: 1000, + minSatsToExchange: 0, + numTokens: 1 + } + + await uut.ensureFunds(orderEntity) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'App wallet does not have funds for writing to the P2WDB') + } + }) + + it('should handle insufficient tokens to satisfy the order', async () => { + try { + const orderEntity = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + buyOrSell: 'sell', + rateInSats: 1000, + minSatsToExchange: 0, + numTokens: 1000 + } + + await uut.ensureFunds(orderEntity) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'App wallet does not have enough tokens to satisfy the SELL order.') + } + }) + + it('should handle BUY order', async () => { + try { + const orderEntity = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + buyOrSell: 'buy', + rateInSats: 1000, + minSatsToExchange: 0, + numTokens: 1 + } + + await uut.ensureFunds(orderEntity) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'Buy orders are not supported yet') + } + }) + }) + + // describe('#moveTokens', () => { + // it('should move tokens to the holding address', async () => { + // // Mock dependencies + // // sandbox + // // .stub(uut.adapters.wallet.bchWallet, 'sendTokens') + // // .resolves('fakeTxid') + // + // const orderEntity = { + // lokadId: 'SWP', + // messageType: 1, + // messageClass: 1, + // tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + // buyOrSell: 'sell', + // rateInBaseUnit: 1000, + // minUnitsToExchange: 0, + // numTokens: 1 + // } + // + // const result = await uut.moveTokens(orderEntity) + // // console.log('result: ', result) + // + // assert.property(result, 'txid') + // assert.property(result, 'vout') + // + // assert.equal(result.txid, 'fakeTxid') + // assert.equal(result.vout, 1) + // }) + // }) + + describe('#createOrder', () => { + it('should create an order and return the hash', async () => { + const entryObj = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: 'token-id', + buyOrSell: 'sell', + rateInBaseUnit: 1000, + minUnitsToExchange: 1250, + numTokens: 1, + ticker: 'TEST' + } + + // Mock dependencies and force expected code path + sandbox.stub(uut.orderEntity, 'inputValidate').returns(entryObj) + sandbox.stub(uut, 'ensureFunds').resolves() + sandbox.stub(uut.UserModel, 'findById').resolves({ mnemonic: 'testMnemonic' }) + sandbox.stub(uut.adapters.wallet.bchWallet.bchjs.Util, 'sleep').resolves() + sandbox.stub(uut.adapters.wallet, 'moveTokensFromCustomWallet').resolves({ txid: 'fakeTxid', vout: 0, hdIndex: 1 }) + sandbox.stub(uut.adapters.wallet.bchWallet, 'initialize').resolves() + sandbox.stub(uut.adapters.nostr, 'post').resolves('fakeEvenetId') + + const result = await uut.createOrder(entryObj) + console.log('result: ', result) + + assert.property(result, 'eventId') + assert.property(result, 'noteId') + }) + it('should create an order with consumer-api', async () => { + uut.config.useFullStackCash = false + const entryObj = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: 'token-id', + buyOrSell: 'sell', + rateInBaseUnit: 1000, + minUnitsToExchange: 1250, + numTokens: 1, + ticker: 'TEST' + } + + // Mock dependencies and force expected code path + sandbox.stub(uut.orderEntity, 'inputValidate').returns(entryObj) + sandbox.stub(uut, 'ensureFunds').resolves() + sandbox.stub(uut.UserModel, 'findById').resolves({ mnemonic: 'testMnemonic' }) + sandbox.stub(uut.adapters.wallet.bchWallet.bchjs.Util, 'sleep').resolves() + sandbox.stub(uut.adapters.wallet, 'moveTokensFromCustomWallet').resolves({ txid: 'fakeTxid', vout: 0, hdIndex: 1 }) + sandbox.stub(uut.adapters.wallet.bchWallet, 'initialize').resolves() + sandbox.stub(uut.adapters.nostr, 'post').resolves('fakeEvenetId') + + const result = await uut.createOrder(entryObj) + console.log('result: ', result) + + assert.property(result, 'eventId') + assert.property(result, 'noteId') + }) + it('should throw error if user is not found', async () => { + try { + const entryObj = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: 'token-id', + buyOrSell: 'sell', + rateInBaseUnit: 1000, + minUnitsToExchange: 1250, + numTokens: 1, + ticker: 'TEST' + } + await uut.createOrder(entryObj) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'user not found') + } + }) + + it('should catch and throw an error', async () => { + try { + await uut.createOrder({ a: 'b' }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include(err.message, 'entry does not contain required properties') + } + }) + + it('should exit quietly if the entry is empty', async () => { + const result = await uut.createOrder() + + assert.equal(result, false) + }) + }) + + describe('#findOrderByEvent', () => { + it('should throw an error if hash is not provided', async () => { + try { + await uut.findOrderByEvent() + } catch (err) { + assert.include(err.message, 'nostrEventId must be a string') + } + }) + it('should throw an error if order is not found!', async () => { + try { + sandbox.stub(uut.OrderModel, 'findOne').resolves(null) + await uut.findOrderByEvent('hash') + } catch (err) { + assert.include(err.message, 'order not found') + } + }) + it('should return order by hash', async () => { + sandbox.stub(uut.OrderModel, 'findOne').resolves({ toObject: () => { return { hash: 'hash' } } }) + const result = await uut.findOrderByEvent('hash') + assert.isObject(result) + }) + }) + + describe('#removeStaleOrders', () => { + it('should remove stale orders', async () => { + const spy = sinon.spy() // Spy the function + + // Create 2 orders mock . + const ordersMock = new Array(2) + ordersMock.fill({ remove: () => { spy.call() } }) + + sandbox.stub(uut.OrderModel, 'find').resolves(ordersMock) + sandbox.stub(uut.retryQueue, 'addToQueue').resolves(false) + + await uut.removeStaleOrders() + + assert.equal(spy.callCount, 2, 'Expected to be called twice.') + }) + it('should handle wrong txid', async () => { + const spy = sinon.spy() // Spy the function + + // Create 2 orders mock . + const ordersMock = new Array(2) + ordersMock.fill({ remove: () => { spy.call() } }) + + sandbox.stub(uut.OrderModel, 'find').resolves(ordersMock) + sandbox.stub(uut.retryQueue, 'addToQueue').throws(new Error('txid needs to be a proper transaction ID')) + + await uut.removeStaleOrders() + + assert.equal(spy.callCount, 2, 'Expected to be called twice.') + }) + it('should skip order on axios error', async () => { + const spy = sinon.spy() // Spy the function + + // Create 2 orders mock . + const ordersMock = new Array(2) + ordersMock.fill({ remove: () => { spy.call() } }) + + const axiosError = new Error() + axiosError.isAxiosError = true + + sandbox.stub(uut.OrderModel, 'find').resolves(ordersMock) + sandbox.stub(uut.retryQueue, 'addToQueue').throws(axiosError) + + await uut.removeStaleOrders() + + assert.equal(spy.callCount, 0, 'Expected to no be called.') + }) + it('should handle unknow error', async () => { + try { + // Create 2 orders mock . + const ordersMock = new Array(2) + ordersMock.fill({ remove: () => { } }) + + sandbox.stub(uut.OrderModel, 'find').resolves(ordersMock) + sandbox.stub(uut.retryQueue, 'addToQueue').throws(new Error('test error')) + + await uut.removeStaleOrders() + assert.fail('unexpected code path') + } catch (error) { + assert.include(error.message, 'test error') + } + }) + }) + + describe('#listOrders', () => { + it('should handle error', async () => { + try { + sandbox.stub(uut.OrderModel, 'find').throws(new Error('test error')) + await uut.listOrders() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should list orders', async () => { + const queryMock = { + sort () { + return this + }, + skip () { + return this + }, + limit () { return [] } + } + + sandbox.stub(uut.OrderModel, 'find').returns(queryMock) + const result = await uut.listOrders() + assert.isArray(result) + }) + }) + + describe('#deleteOrder', () => { + it('should handle error', async () => { + try { + sandbox.stub(uut, 'findOrderByEvent').throws(new Error('test error')) + await uut.deleteOrder() + assert.fail('unexpected code path') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should delete orders', async () => { + sandbox.stub(uut, 'findOrderByEvent').resolves([]) + sandbox.stub(uut.adapters.wallet, 'reclaimTokens').resolves('txid') + const result = await uut.deleteOrder() + assert.isString(result) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/use-cases/usage.use-case.unit.js`: + +```js +/* + Unit tests for the use-cases/usage-use-cases.js business logic library. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local support libraries +import adapters from '../mocks/adapters/index.js' + +// Mock +import { context as mockContext } from '../mocks/ctx-mock.js' + +// Unit under test (uut) +import { UsageUseCases, restCalls, usageMiddleware } from '../../../src/use-cases/usage-use-cases.js' + +describe('#usage-use-case', () => { + let uut + let sandbox + let ctx + + before(async () => { + + }) + + beforeEach(() => { + sandbox = sinon.createSandbox() + uut = new UsageUseCases({ adapters }) + + // Set as empty array + restCalls.splice(0, restCalls.length) + + ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new UsageUseCases() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of adapters must be passed in when instantiating Usage Use Cases library.' + ) + } + }) + }) + + describe('#cleanUsage', () => { + it('should delete older data than 24 hours', () => { + const now = new Date() // Mock date + + // set older mock data + restCalls.push({ + timestamp: now.getTime() - (60000 * 60 * 48), // 48 hours ago + ip: '127.0.0.1' + }) + + // Set recently mock data + restCalls.push({ + timestamp: now.getTime(), + ip: 'localhost' + }) + + const result = uut.cleanUsage() + + assert.isArray(result) + assert.equal(result.length, 1) + assert.equal(result[0].ip, 'localhost') + }) + + it('should handle error', () => { + try { + // Force an error + sandbox.stub(restCalls, 'filter').throws(new Error('uut error')) + + uut.cleanUsage() + + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(error.message, 'uut error') + } + }) + }) + + describe('#getRestSummary', () => { + it('should get the number of rest calls', () => { + // Set mock data + restCalls.push({ + ip: 'localhost' + }) + + const result = uut.getRestSummary() + + assert.isNumber(result) + assert.equal(result, 1) + }) + + it('should handle error', () => { + try { + // Force an error + sandbox.stub(console, 'log').throws(new Error('uut error')) + + uut.getRestSummary() + + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(error.message, 'uut error') + } + }) + }) + + describe('#getTopIps', () => { + it('should get top IPs', () => { + // Set mock data + restCalls.push({ + ip: 'localhost' + }) + + // Set mock data + restCalls.push({ + ip: 'localhost' + }) + + const result = uut.getTopIps() + + assert.isArray(result) + + assert.property(result[0], 'ip') + assert.property(result[0], 'cnt') + + assert.equal(result[0].ip, 'localhost') + assert.equal(result[0].cnt, '2') + }) + + it('should return a maximum of 20 values', () => { + // Fill Array with 21 values + for (let i = 0; i < 21; i++) { + restCalls.push({ + ip: `localhost-${i}` + }) + } + + const result = uut.getTopIps() + + assert.isArray(result) + + assert.property(result[0], 'ip') + assert.property(result[0], 'cnt') + + assert.equal(result.length, 20) + }) + + it('should handle error', () => { + try { + // Set mock data + restCalls.push(null) + + uut.getTopIps() + + assert.fail('Unexpected code path') + } catch (error) { + assert.include(error.message, 'Cannot read properties') + } + }) + }) + + describe('#getTopEndpoints', () => { + it('should get top Endpoints', () => { + // Set mock data + restCalls.push({ + ip: 'localhost', + url: '/api/v1/users', + method: 'GET' + }) + + // Set mock data + restCalls.push({ + ip: 'localhost', + url: '/api/v1/users', + method: 'GET' + }) + + const result = uut.getTopEndpoints() + + assert.isArray(result) + + assert.property(result[0], 'endpoint') + assert.property(result[0], 'cnt') + + assert.equal(result[0].endpoint, 'GET /api/v1/users') + assert.equal(result[0].cnt, '2') + }) + + it('should return a maximum of 20 values', () => { + // Fill Array with 21 values + for (let i = 0; i < 21; i++) { + restCalls.push({ + ip: 'localhost', + url: `/api/v1/users-${i}`, + method: 'GET' + }) + } + + const result = uut.getTopEndpoints() + + assert.isArray(result) + + assert.property(result[0], 'endpoint') + assert.property(result[0], 'cnt') + + assert.equal(result.length, 20) + }) + + it('should handle error', () => { + try { + // Set mock data + restCalls.push(null) + + uut.getTopEndpoints() + + assert.fail('Unexpected code path') + } catch (error) { + assert.include(error.message, 'Cannot read properties') + } + }) + }) + + describe('#usageMiddleware', () => { + it('should update restCalls state', async () => { + // Spy on next + const next = sinon.spy(() => { }) + + await usageMiddleware()(ctx, next) + + assert.equal(restCalls.length, 1) + assert.isTrue(next.called) + }) + + it('should handle error', async () => { + try { + const next = () => { throw new Error('uut error') } + + await usageMiddleware()(ctx, next) + assert.fail('Unexpected code path') + } catch (error) { + assert.equal(error.message, 'uut error') + assert.equal(ctx.status, 500) + assert.equal(restCalls.length, 0) + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/use-cases/entry.use-case.unit.js`: + +```js +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import adapters from '../mocks/adapters/index.js' + +// Unit under test (uut) +import EntryLib from '../../../src/use-cases/entry.js' + +describe('#entry-use-case', () => { + let uut + let sandbox + + before(async () => { + // Delete all previous users in the database. + // await testUtils.deleteAllUsers() + }) + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new EntryLib({ adapters }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new EntryLib() + + assert.fail('Unexpected code path') + console.log(uut) + } catch (err) { + assert.include( + err.message, + 'Instance of adapters must be passed in when instantiating User Use Cases library.' + ) + } + }) + }) + + // describe('#createEntry', () => { + // it('should throw an error if entry is not provided', async () => { + // try { + // await uut.createEntry({}) + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, "Property 'entry' must be a string!") + // } + // }) + // + // it('should throw an error if description is not provided', async () => { + // try { + // const inputData = { + // entry: 'entry' + // } + // await uut.createEntry(inputData) + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, "Property 'description' must be a string!") + // } + // }) + // + // it('should throw an error if slpAddress is not provided', async () => { + // try { + // const inputData = { + // entry: 'entry', + // description: 'test' + // } + // await uut.createEntry(inputData) + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, "Property 'slpAddress' must be a string!") + // } + // }) + // + // it('should throw an error if signature is not provided', async () => { + // try { + // const inputData = { + // entry: 'entry', + // description: 'test', + // slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg' + // } + // await uut.createEntry(inputData) + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, "Property 'signature' must be a string!") + // } + // }) + // + // it('should throw an error if category is not provided', async () => { + // try { + // const inputData = { + // entry: 'entry', + // description: 'test', + // slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg', + // signature: + // 'IFytRg6KpvTHCzcW0ZwVhPqdKtRGpoRDcuEb958yIgJFUJlb1F5qPzt/JnlYE7r012BSFj+UT67DZVTU8oNB5vw=' + // } + // await uut.createEntry(inputData) + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, "Property 'category' must be a string!") + // } + // }) + // + // it('should catch and throw DB errors', async () => { + // try { + // // Force an error with the database. + // sandbox.stub(uut, 'EntryModel').throws(new Error('test error')) + // + // const inputData = { + // entry: 'entry', + // description: 'test', + // slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg', + // signature: + // 'IFytRg6KpvTHCzcW0ZwVhPqdKtRGpoRDcuEb958yIgJFUJlb1F5qPzt/JnlYE7r012BSFj+UT67DZVTU8oNB5vw=', + // category: 'test' + // } + // + // await uut.createEntry(inputData) + // + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, 'test error') + // } + // }) + // + // it('should throw error if signature is invalid', async () => { + // try { + // // Mocking bchjs functions + // sandbox.stub(uut.bch, '_verifySignature').callsFake(() => { + // return false + // }) + // + // const inputData = { + // entry: 'entry', + // description: 'test', + // slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg', + // signature: + // 'IFytRg6KpvTHCzcW0ZwVhPqdKtRGpoRDcuEb958yIgJFUJlb1F5qPzt/JnlYE7r012BSFj+UT67DZVTU8oNB5vw=', + // category: 'test' + // } + // + // await uut.createEntry(inputData) + // + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, 'Invalid signature') + // } + // }) + // it('should throw error for insufficient psf balance', async () => { + // try { + // // Mocking bchjs functions + // sandbox.stub(uut.bch, 'getPSFTokenBalance').resolves(0) + // + // const inputData = { + // entry: 'entry', + // description: 'test', + // slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg', + // signature: + // 'IFytRg6KpvTHCzcW0ZwVhPqdKtRGpoRDcuEb958yIgJFUJlb1F5qPzt/JnlYE7r012BSFj+UT67DZVTU8oNB5vw=', + // category: 'test' + // } + // + // await uut.createEntry(inputData) + // + // assert.fail('Unexpected code path') + // } catch (err) { + // assert.include(err.message, 'Insufficient psf balance') + // } + // }) + // + // it('should create a new entry in the DB', async () => { + // // Mocking bchjs functions + // // sandbox.stub(uut.bchjs, '_verifySignature').resolves(true) + // // sandbox.stub(uut.bchjs, 'getPSFTokenBalance').resolves(100) + // // sandbox.stub(uut.bchjs, 'getMerit').resolves(100) + // + // const inputData = { + // entry: 'entry', + // description: 'test', + // slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg', + // signature: + // 'IFytRg6KpvTHCzcW0ZwVhPqdKtRGpoRDcuEb958yIgJFUJlb1F5qPzt/JnlYE7r012BSFj+UT67DZVTU8oNB5vw=', + // category: 'test' + // } + // + // const result = await uut.createEntry(inputData) + // + // assert.property(result, 'entry') + // assert.isString(result.entry) + // + // assert.property(result, 'slpAddress') + // assert.isString(result.slpAddress) + // + // assert.property(result, 'description') + // assert.isString(result.description) + // + // assert.property(result, 'signature') + // assert.isString(result.signature) + // + // assert.property(result, 'category') + // assert.isString(result.category) + // + // assert.property(result, 'balance') + // assert.isNumber(result.balance) + // + // assert.property(result, 'merit') + // assert.isNumber(result.merit) + // }) + // }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/use-cases/index.use-case.unit.js`: + +```js +/* + Unit tests for the index.js file that aggregates all use-cases. +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import adapters from '../mocks/adapters/index.js' + +// Unit under test (uut) +import UseCases from '../../../src/use-cases/index.js' + +describe('#use-cases', () => { + let uut + let sandbox + + before(async () => { + // Delete all previous users in the database. + // await testUtils.deleteAllUsers() + }) + + beforeEach(() => { + sandbox = sinon.createSandbox() + + uut = new UseCases({ adapters }) + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new UseCases() + + assert.fail('Unexpected code path') + + // This is here to prevent the linter from complaining. + assert.isOk(uut) + } catch (err) { + assert.include( + err.message, + 'Instance of adapters must be passed in when instantiating Use Cases library.' + ) + } + }) + }) + + describe('#start', () => { + it('should initialize async use cases', async () => { + const result = await uut.start() + + assert.equal(result, true) + }) + + // it('should catch and throw errors', async () => { + // // Force an error + // sandbox.stub() + // }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/entities/order.entity.unit.js`: + +```js +/* + Unit tests for the User entity library. +*/ + +import { assert } from 'chai' +import sinon from 'sinon' + +import Order from '../../../src/entities/order.js' + +let sandbox +let uut + +describe('#Order-Entity', () => { + before(async () => {}) + + beforeEach(() => { + uut = new Order() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#inputValidate', () => { + it('should throw an error if data is not provided', () => { + try { + uut.inputValidate() + } catch (err) { + // console.log(err) + assert.include(err.message, 'Cannot destructure property') + } + }) + + it('should throw an error if messageType is not included', () => { + try { + const data = {} + uut.inputValidate(data) + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'messageType' must be an integer number" + ) + } + }) + + it('should throw an error if messageClass is not included', () => { + try { + const data = { messageType: 1 } + uut.inputValidate(data) + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'messageClass' must be an integer number" + ) + } + }) + + it('should throw an error if tokenId is not included', () => { + try { + const data = { messageType: 1, messageClass: 1 } + uut.inputValidate(data) + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'tokenId' must be a string.") + } + }) + + it('should throw an error if buyOrSell is not included', () => { + try { + const data = { messageType: 1, messageClass: 1, tokenId: 'fakeId' } + uut.inputValidate(data) + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'buyOrSell' must be a string.") + } + }) + + it('should throw an error if rateInBaseUnit is not included', () => { + try { + const data = { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy' + } + uut.inputValidate(data) + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'rateInBaseUnit' must be an integer number." + ) + } + }) + + it('should throw an error if minUnitsToExchange is not included', () => { + try { + const data = { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy', + rateInBaseUnit: 1000 + } + uut.inputValidate(data) + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'minUnitsToExchange' must be an integer number." + ) + } + }) + + it('should throw an error if numTokens is not included', () => { + try { + const data = { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy', + rateInBaseUnit: 1000, + minUnitsToExchange: 350 + } + uut.inputValidate(data) + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'numTokens' must be a number.") + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/entities/entry.entity.unit.js`: + +```js +/* + Unit tests for the User entity library. +*/ + +import { assert } from 'chai' +import sinon from 'sinon' + +import Entry from '../../../src/entities/entry.js' + +let sandbox +let uut + +describe('#User-Entity', () => { + before(async () => { }) + + beforeEach(() => { + uut = new Entry() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#validate', () => { + it('should throw an error if entry is not provided', () => { + try { + uut.validate() + } catch (err) { + assert.include(err.message, "Property 'entry' must be a string!") + } + }) + + it('should throw an error if description is not provided', () => { + try { + const inputData = { + entry: 'entry' + } + uut.validate(inputData) + } catch (err) { + assert.include(err.message, "Property 'description' must be a string!") + } + }) + + it('should throw an error if slpAddress is not provided', () => { + try { + const inputData = { + entry: 'entry', + description: 'test' + } + uut.validate(inputData) + } catch (err) { + assert.include(err.message, "Property 'slpAddress' must be a string!") + } + }) + + it('should throw an error if signature is not provided', () => { + try { + const inputData = { + entry: 'entry', + description: 'test', + slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg' + } + uut.validate(inputData) + } catch (err) { + assert.include(err.message, "Property 'signature' must be a string!") + } + }) + it('should throw an error if category is not provided', () => { + try { + const inputData = { + entry: 'entry', + description: 'test', + slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg', + signature: 'IFytRg6KpvTHCzcW0ZwVhPqdKtRGpoRDcuEb958yIgJFUJlb1F5qPzt/JnlYE7r012BSFj+UT67DZVTU8oNB5vw=' + } + uut.validate(inputData) + } catch (err) { + assert.include(err.message, "Property 'category' must be a string!") + } + }) + + it('should return a Entry object', () => { + const inputData = { + entry: 'entry', + description: 'test', + slpAddress: 'simpleledger:qpnty9t0w93fez04h7yzevujpv8pun204qqp0jfafg', + signature: 'IFytRg6KpvTHCzcW0ZwVhPqdKtRGpoRDcuEb958yIgJFUJlb1F5qPzt/JnlYE7r012BSFj+UT67DZVTU8oNB5vw=', + category: 'test' + } + + const entry = uut.validate(inputData) + // console.log('entry: ', entry) + + assert.property(entry, 'entry') + assert.equal(entry.entry, inputData.entry) + + assert.property(entry, 'description') + assert.equal(entry.description, inputData.description) + + assert.property(entry, 'slpAddress') + assert.equal(entry.slpAddress, inputData.slpAddress) + + assert.property(entry, 'signature') + assert.equal(entry.signature, inputData.signature) + + assert.property(entry, 'slpAddress') + assert.equal(entry.category, inputData.category) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/entities/user.entity.unit.js`: + +```js +/* + Unit tests for the User entity library. +*/ + +import { assert } from 'chai' +import sinon from 'sinon' + +import User from '../../../src/entities/user.js' + +let sandbox +let uut + +describe('#User-Entity', () => { + before(async () => {}) + + beforeEach(() => { + uut = new User() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#validate', () => { + it('should throw an error if email is not provided', () => { + try { + uut.validate() + } catch (err) { + assert.include(err.message, "Property 'email' must be a string!") + } + }) + + it('should throw an error if password is not provided', () => { + try { + uut.validate({ email: 'test@test.com' }) + } catch (err) { + assert.include(err.message, "Property 'password' must be a string!") + } + }) + + it('should throw an error if name is not provided', () => { + try { + uut.validate({ email: 'test@test.com', password: 'test' }) + } catch (err) { + assert.include(err.message, "Property 'name' must be a string!") + } + }) + + it('should return a User object', () => { + const inputData = { + email: 'test@test.com', + password: 'test', + name: 'test' + } + + const entry = uut.validate(inputData) + // console.log('entry: ', entry) + + assert.property(entry, 'email') + assert.equal(entry.email, inputData.email) + + assert.property(entry, 'password') + assert.equal(entry.password, inputData.password) + + assert.property(entry, 'name') + assert.equal(entry.name, inputData.name) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/entities/offer.entity.unit.js`: + +```js +/* + Unit tests for the Offer entity library. +*/ + +import { assert } from 'chai' +import sinon from 'sinon' + +import Offer from '../../../src/entities/offer.js' + +let sandbox +let uut + +describe('#Offer-Entity', () => { + before(async () => {}) + + beforeEach(() => { + uut = new Offer() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('#validate', () => { + it('should throw an error if data is not provided', () => { + try { + uut.validate() + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + 'Input to offer.validate() must be an object with a data property.' + ) + } + }) + + it('should throw an error if messageType is not included', () => { + try { + const offerData = { data: {} } + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'messageType' must be an integer number" + ) + } + }) + + it('should throw an error if messageClass is not included', () => { + try { + const offerData = { data: { messageType: 1 } } + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'messageClass' must be an integer number" + ) + } + }) + + it('should throw an error if tokenId is not included', () => { + try { + const offerData = { data: { messageType: 1, messageClass: 1 } } + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'tokenId' must be a string.") + } + }) + + it('should throw an error if buyOrSell is not included', () => { + try { + const offerData = { + data: { messageType: 1, messageClass: 1, tokenId: 'fakeId' } + } + + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'buyOrSell' must be a string.") + } + }) + + it('should throw an error if rateInBaseUnit is not included', () => { + try { + const offerData = { + data: { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy' + } + } + + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'rateInBaseUnit' must be an integer number." + ) + } + }) + + it('should throw an error if minUnitsToExchange is not included', () => { + try { + const offerData = { + data: { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy', + rateInBaseUnit: 1000 + } + } + + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'minUnitsToExchange' must be an integer number." + ) + } + }) + + it('should throw an error if numTokens is not included', () => { + try { + const offerData = { + data: { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy', + rateInBaseUnit: 1000, + minUnitsToExchange: 350 + } + } + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'numTokens' must be a number.") + } + }) + + it('should throw an error if utxoTxid is not included', () => { + try { + const offerData = { + data: { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy', + rateInBaseUnit: 1000, + minUnitsToExchange: 350, + numTokens: 1 + } + } + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include(err.message, "Property 'utxoTxid' must be a string.") + } + }) + + it('should throw an error if utxoVout is not included', () => { + try { + const offerData = { + data: { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy', + rateInBaseUnit: 1000, + minUnitsToExchange: 350, + numTokens: 1, + utxoTxid: 'fakeTxid' + } + } + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'utxoVout' must be an integer number." + ) + } + }) + + it('should throw an error if proper status is not applied', () => { + try { + const offerData = { + data: { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy', + rateInBaseUnit: 1000, + minUnitsToExchange: 350, + numTokens: 1, + utxoTxid: 'fakeTxid', + utxoVout: 0, + offerStatus: 'badStatus' + } + } + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'offerStatus' must be posted, taken, or dead" + ) + } + }) + + it('should throw an error if nostrEventId is not included', () => { + try { + const offerData = { + data: { + messageType: 1, + messageClass: 1, + tokenId: 'fakeId', + buyOrSell: 'buy', + rateInBaseUnit: 1000, + minUnitsToExchange: 350, + numTokens: 1, + utxoTxid: 'fakeTxid', + utxoVout: 0, + offerStatus: 'posted', + makerAddr: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00', + tokenType: 1 + } + } + uut.validate(offerData) + + assert.fail('Unexpected code path') + } catch (err) { + // console.log(err) + assert.include( + err.message, + "Property 'nostrEventId' must be a string." + ) + } + }) + + it('should validate a new offer', () => { + const offerObj = { + appId: 'swapTest555', + data: { + messageType: 1, + messageClass: 1, + tokenId: + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + buyOrSell: 'sell', + rateInBaseUnit: 1000, + minUnitsToExchange: 10, + numTokens: 0.02, + utxoTxid: + '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87', + utxoVout: 0, + offerStatus: 'posted', + makerAddr: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00', + ticker: 'TROUT', + tokenType: 1, + nostrEventId: 'test' + }, + timestamp: '2021-09-20T17:54:26.395Z', + localTimeStamp: '9/20/2021, 10:54:26 AM', + txid: '46f50f2a0cf44e3ed70dfb0618ef3ebfee57aabcf229b5d2d17c07322b54a8d7', + hash: 'zdpuB2X25AZCKo3wpr4sSbw44vqPWJRqcxWQRHZccK5BdtoGD' + + } + + const result = uut.validate(offerObj) + // console.log('result: ', result) + + assert.property(result, 'messageType') + assert.property(result, 'messageClass') + assert.property(result, 'tokenId') + assert.property(result, 'buyOrSell') + assert.property(result, 'rateInBaseUnit') + assert.property(result, 'minUnitsToExchange') + assert.property(result, 'numTokens') + assert.property(result, 'utxoTxid') + assert.property(result, 'utxoVout') + assert.property(result, 'timestamp') + assert.property(result, 'localTimestamp') + assert.property(result, 'txid') + assert.property(result, 'p2wdbHash') + assert.property(result, 'tokenType') + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/ipfs-mock.js`: + +```js +/* + Mocks for the js-ipfs +*/ + +// class IPFS { +// constructor () { +// this.ipfs = {} +// } +// +// static create () { +// const mockIpfs = new MockIpfsInstance() +// +// return mockIpfs +// } +// +// async start () {} +// } + +function create () { + const mockIpfs = new MockIpfsInstance() + + return mockIpfs +} + +class MockIpfsInstance { + constructor () { + this.config = { + profiles: { + apply: () => {} + } + } + } + + stop () {} +} + +export default create; + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/adapters/index.js`: + +```js +/* + Mocks for the Adapter library. +*/ +import BCHJS from '@psf/bch-js'; + +const bchjs = new BCHJS() + +class IpfsAdapter { + constructor () { + this.ipfs = { + files: { + stat: () => {} + } + } + } +} + +class IpfsCoordAdapter { + constructor () { + this.ipfsCoord = { + adapters: { + ipfs: { + connectToPeer: async () => {} + } + }, + useCases: { + peer: { + sendPrivateMessage: () => { + } + } + }, + thisNode: {} + } + } +} + +const ipfs = { + ipfsAdapter: new IpfsAdapter(), + ipfsCoordAdapter: new IpfsCoordAdapter(), + getStatus: async () => {}, + getPeers: async () => {}, + getRelays: async () => {} +} +ipfs.ipfs = ipfs.ipfsAdapter.ipfs + +const localdb = { + Users: class Users { + static findById () {} + static find () {} + static findOne () { + return { + validatePassword: localdb.validatePassword + } + } + + async save () { + return {} + } + + generateToken () { + return '123' + } + + toJSON () { + return {} + } + + async remove () { + return true + } + + async validatePassword () { + return true + } + }, + + validatePassword: () => { + return true + }, + + Entry: class Entry { + constructor (obj) { + ;(this._id = 'id'), (this.entry = obj.entry) + this.slpAddress = obj.slpAddress + this.description = obj.description + this.signature = obj.signature + this.category = obj.category + this.balance = obj.balance + this.merit = obj.merit + } + + static findById () {} + static find () {} + static findOne () {} + + async save () { + return {} + } + }, + + Order: class Order { + constructor (obj) {} + + static findById () {} + static find () {} + static findOne () {} + + async save () { + return {} + } + }, + + Offer: class Offer { + constructor (obj) {} + + static findById () {} + static find () {} + static findOne () {} + + async save () { + return {} + } + } +} + +const bch = { + getMerit: async () => { + return 100 + }, + getPSFTokenBalance: async () => { + return 100 + }, + _verifySignature: () => { + return true + } +} + +// const wallet = { +// burnPsf: async () => {}, +// generateSignature: async () => {} +// } +import { MockBchWallet } from './wallet.js'; + +const wallet = { + burnPsf: async () => { + }, + generateSignature: async () => { + }, + getKeyPair: async () => { + return { cashAddress: 'fakeAddr', wif: 'fakeWif', hdIndex: 1 } + }, + bchWallet: new MockBchWallet(), + BchWallet: MockBchWallet, + moveTokens: async () => {}, + moveTokensFromCustomWallet: async () => {}, + moveBch: async () => {}, + reclaimTokens: async ()=>{}, + generatePartialTx: async ()=>{}, + deseralizeTx:async ()=>{}, + completeTx:async ()=>{ return ''}, +} + +const p2wdb = { + write: async () => { + }, + checkForSufficientFunds: async () => true +} + +const nostr = { + post: async () => {return true }, + read: async () => { return true }, + eventId2note: () => { return 'testNoteId' } +} + +export default { ipfs, localdb, bch, wallet, p2wdb, bchjs, nostr} + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/adapters/fake-log`: + +``` +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.907Z"} +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.909Z"} +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.910Z"} +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.912Z"} +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.915Z"} +{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.979Z"} +{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.980Z"} +{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.981Z"} +{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.982Z"} +{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.983Z"} +{"level":"error","message":"Error in lib/nodemailer.js/validateEmailArray()","timestamp":"2022-06-27T17:36:59.002Z"} +{"level":"error","message":"Error in lib/nodemailer.js/validateEmailArray()","timestamp":"2022-06-27T17:36:59.003Z"} +{"level":"error","message":"Error in lib/nodemailer.js/getHtmlFromObject()","timestamp":"2022-06-27T17:36:59.005Z"} +{"level":"error","message":"Error in lib/nodemailer.js/getHtmlFromObject()","timestamp":"2022-06-27T17:36:59.006Z"} +{"level":"error","message":"Error in lib/nodemailer.js/getHtmlFromObject()","timestamp":"2022-06-27T17:36:59.008Z"} +{"level":"info","message":"Warning: Can not send JSON RPC response. Can not determine which peer this message came from.","timestamp":"2022-06-27T17:36:59.353Z"} +{"level":"info","message":"Rejecting invalid JSON RPC command.","timestamp":"2022-06-27T17:36:59.354Z"} +{"level":"info","message":"JSON RPC received from peerA, ID: ea442e78-2297-466a-823b-9cbb12c8ddd9, type: request, method: unknownMethod","timestamp":"2022-06-27T17:36:59.355Z"} +{"level":"error","message":"Error in rpc router(): test error","stack":"Error: test error\n at Context. (/home/trout/work/psf/code/ipfs-service-provider/test/unit/controllers/json-rpc/a10-rpc.unit.js:110:49)\n at callFn (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:366:21)\n at Test.Runnable.run (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:354:5)\n at Runner.runTest (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:666:10)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:789:12\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:581:14)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:591:7\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:474:14)\n at Immediate._onImmediate (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:559:5)\n at processImmediate (node:internal/timers:466:21)","timestamp":"2022-06-27T17:36:59.357Z"} +{"level":"info","message":"JSON RPC received from peerA, ID: 9ef6ad90-7fc3-4cb3-8769-4498e5512b3d, type: request, method: users","timestamp":"2022-06-27T17:36:59.358Z"} +{"level":"info","message":"JSON RPC received from peerA, ID: bd57a1cf-7f2f-4ff2-93d4-6727eec4d778, type: request, method: auth","timestamp":"2022-06-27T17:36:59.359Z"} +{"level":"info","message":"JSON RPC received from peerA, ID: 8fd9edc8-6a45-4042-ac06-9ace60567cbf, type: request, method: about","timestamp":"2022-06-27T17:36:59.361Z"} +{"level":"info","message":"JSON RPC received from peerA, ID: 1b27624a-e698-4bbe-9183-b860a1a0d78d, type: request, method: unknownMethod","timestamp":"2022-06-27T17:36:59.363Z"} +{"level":"info","message":"JSON RPC received from peerA, ID: 40fabddf-59c6-4910-a22c-63da7387f99a, type: request, method: unknownMethod","timestamp":"2022-06-27T17:36:59.365Z"} +{"level":"error","message":"Error in authUser(): Login credential do not match","stack":"Error: Login credential do not match\n at Context. (/home/trout/work/psf/code/ipfs-service-provider/test/unit/controllers/json-rpc/auth.json-rpc.controller.unit.js:144:18)\n at callFn (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:366:21)\n at Test.Runnable.run (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:354:5)\n at Runner.runTest (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:666:10)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:789:12\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:581:14)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:591:7\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:474:14)\n at Immediate. (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:559:5)\n at processImmediate (node:internal/timers:466:21)","timestamp":"2022-06-27T17:37:04.421Z"} +{"level":"error","message":"Error in authUser(): login must be specified","stack":"Error: login must be specified\n at AuthRPC.authUser (/home/trout/work/psf/code/ipfs-service-provider/src/controllers/json-rpc/auth/index.js:78:93)\n at Context. (/home/trout/work/psf/code/ipfs-service-provider/test/unit/controllers/json-rpc/auth.json-rpc.controller.unit.js:165:34)\n at callFn (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:366:21)\n at Test.Runnable.run (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:354:5)\n at Runner.runTest (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:666:10)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:789:12\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:581:14)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:591:7\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:474:14)\n at Immediate._onImmediate (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:559:5)\n at processImmediate (node:internal/timers:466:21)","timestamp":"2022-06-27T17:37:04.423Z"} +{"level":"error","message":"Error in authUser(): password must be specified","stack":"Error: password must be specified\n at AuthRPC.authUser (/home/trout/work/psf/code/ipfs-service-provider/src/controllers/json-rpc/auth/index.js:78:284)\n at Context. (/home/trout/work/psf/code/ipfs-service-provider/test/unit/controllers/json-rpc/auth.json-rpc.controller.unit.js:185:34)\n at callFn (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:366:21)\n at Test.Runnable.run (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:354:5)\n at Runner.runTest (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:666:10)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:789:12\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:581:14)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:591:7\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:474:14)\n at Immediate._onImmediate (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:559:5)\n at processImmediate (node:internal/timers:466:21)","timestamp":"2022-06-27T17:37:04.425Z"} +{"level":"error","timestamp":"2022-06-27T17:37:04.466Z"} +{"level":"info","message":"Running server in environment: dev","timestamp":"2022-06-27T17:37:04.487Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.495Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.495Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.496Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.497Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.497Z"} +{"level":"error","message":"Error in lib/users.js/getAllUsers()","timestamp":"2022-06-27T17:37:04.499Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.502Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.503Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.503Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.504Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.505Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.506Z"} +{"level":"error","message":"Error in lib/users.js/deleteUser()","timestamp":"2022-06-27T17:37:04.508Z"} +{"level":"info","message":"Running server in environment: test","timestamp":"2022-06-27T17:37:04.514Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.638Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:05.273Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:05.277Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:05.280Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:05.286Z"} +{"level":"error","timestamp":"2022-06-27T17:37:05.412Z"} +{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d27f, Target user: 1","timestamp":"2022-06-27T17:37:05.441Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.448Z"} +{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d27f, Target user: 62b9eac1b4f08950b955d27d","timestamp":"2022-06-27T17:37:05.452Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.457Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.463Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.467Z"} +{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.473Z"} +{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac0b4f08950b955d274, Target user: 62b9eac1b4f08950b955d27d","timestamp":"2022-06-27T17:37:05.478Z"} +{"level":"verbose","message":"It's ok. The user is an admin.","timestamp":"2022-06-27T17:37:05.478Z"} +{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d27f, Target user: 1","timestamp":"2022-06-27T17:37:05.600Z"} +{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d27f, Target user: 62b9eac1b4f08950b955d27d","timestamp":"2022-06-27T17:37:05.603Z"} +{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac0b4f08950b955d274, Target user: 62b9eac1b4f08950b955d27d","timestamp":"2022-06-27T17:37:05.615Z"} +{"level":"verbose","message":"It's ok. The user is an admin.","timestamp":"2022-06-27T17:37:05.615Z"} +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:37:05.619Z"} +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:37:05.622Z"} +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:37:05.624Z"} +{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:37:05.627Z"} +{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d2a6, Target user: Target Id","timestamp":"2022-06-27T17:37:05.754Z"} +{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac0b4f08950b955d274, Target user: 62b9eac1b4f08950b955d2a6","timestamp":"2022-06-27T17:37:05.756Z"} +{"level":"verbose","message":"It's ok. The user is an admin.","timestamp":"2022-06-27T17:37:05.756Z"} +{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:06.060Z"} + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/adapters/wallet.js`: + +```js +import BCHJS from "@psf/bch-js"; + +const mockWallet = { + mnemonic: 'course abstract aerobic deer try switch turtle diet fence affair butter top', + privateKey: 'L5D2UAam8tvo3uii5kpgaGyjvVMimdrXu8nWGQSQjuuAix6ji1YQ', + publicKey: '0379433ffc401483ade310469953c1cba77c71af904f07c15bde330d7198b4d6dc', + cashAddress: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00', + address: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00', + slpAddress: 'simpleledger:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acq9zm7d33', + legacyAddress: '1JQj1KcQL7GPKzc1D2PvdUSgw3MbDtrHzi', + hdPath: "m/44'/245'/0'/0/0", + nextAddress: 1 +}; + +class MockBchWallet { + constructor() { + this.walletInfoPromise = true; + this.walletInfo = mockWallet; + this.initialize = async () => {} + this.bchjs = new BCHJS(); + this.burnTokens = async () => { + return { success: true, txid: 'txid' }; + }; + this.sendTokens = async () => { + return 'fakeTxid'; + }; + this.utxoIsValid =async ()=>{} + this.getUtxos = async () => { }; + this.getBalance = async () => { }; + this.listTokens = async () => { }; + this.getTxData = async () => { + return [{ + tokenTicker: 'TROUT' + }]; + }; + this.optimize = async () => { }; + // Environment variable is used by wallet-balance.unit.js to force an error. + if (process.env.NO_UTXO) { + this.utxos = {}; + } + else { + this.utxos = { + utxoStore: { + address: 'bitcoincash:qqetvdnlt0p8g27dr44cx7h057kpzly9xse9huc97z', + bchUtxos: [ + { + height: 700685, + tx_hash: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654', + tx_pos: 0, + value: 1000, + txid: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654', + vout: 0, + isValid: false + }, + { + height: 700685, + tx_hash: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654', + tx_pos: 2, + value: 19406, + txid: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654', + vout: 2, + isValid: false + } + ], + nullUtxos: [], + slpUtxos: { + type1: { + mintBatons: [], + tokens: [ + { + 'height': 717331, + 'tx_hash': '74889580bb1a5f8c026aa2f55118ac9917df3332f7abae72a70343daa1c29621', + 'tx_pos': 1, + 'value': 546, + 'txid': '74889580bb1a5f8c026aa2f55118ac9917df3332f7abae72a70343daa1c29621', + 'vout': 1, + 'isSlp': true, + 'type': 'token', + 'qty': '10', + 'tokenId': '600ee24d0f208aebc2bdd2c4ee1b9acb6d57343561442e8676b5bbea311d5a0f', + 'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5', + 'ticker': 'FLIPS', + 'name': 'FLIPS', + 'documentUri': '', + 'documentHash': '', + 'decimals': 1, + 'qtyStr': '1' + }, + { + 'height': 730597, + 'tx_hash': '52520faddfafc46b8f8c9548b097f3a3b82a5bf363b5095047b9c5f83247fe36', + 'tx_pos': 1, + 'value': 546, + 'txid': '52520faddfafc46b8f8c9548b097f3a3b82a5bf363b5095047b9c5f83247fe36', + 'vout': 1, + 'isSlp': true, + 'type': 'token', + 'qty': '34999991', + 'tokenId': '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + 'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5', + 'ticker': 'PSF', + 'name': 'Permissionless Software Foundation', + 'documentUri': 'psfoundation.cash', + 'documentHash': '', + 'decimals': 8, + 'qtyStr': '0.34999991' + }, + { + 'height': 730597, + 'tx_hash': '5dc7e7c91382aed1666a51212dfb74050261e12c3c4f62b6b1e57f42d6c51ee1', + 'tx_pos': 2, + 'value': 546, + 'txid': '5dc7e7c91382aed1666a51212dfb74050261e12c3c4f62b6b1e57f42d6c51ee1', + 'vout': 2, + 'isSlp': true, + 'type': 'token', + 'qty': '18898', + 'tokenId': 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + 'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5', + 'ticker': 'TROUT', + 'name': "Trout's test token", + 'documentUri': 'troutsblog.com', + 'documentHash': '', + 'decimals': 2, + 'qtyStr': '188.98' + } + ] + }, + nft: { + tokens: [] + }, + group: { + tokens: [], + mintBatons: [] + } + } + } + }; + } + } +} + +export { MockBchWallet }; + +export { mockWallet }; + +export default { + MockBchWallet, + mockWallet +}; + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/ctx-mock.js`: + +```js +// Ripped from https://github.com/koajs/koa/blob/master/test/helpers/context.js +// Solution courtesy of user @fl0w. See: https://github.com/koajs/koa/issues/999#issuecomment-309270599 +// Take from this gist: https://gist.github.com/emmanuelnk/f1254eed8f947a81e8d715476d9cc92c + +// if you want more comprehensive Koa Context object to test stuff like Cookies etc +// then use https://www.npmjs.com/package/@shopify/jest-koa-mocks (requires Jest) + +// INSTRUCTIONS: +// Import in test file as below: +// +// const mockContext = require('./mocks/ctx-mock').context +// const ctx = mockContext() +// ... + +import Stream from 'stream'; + +import Koa from 'koa'; + +const context = (req, res, app) => { + const socket = new Stream.Duplex() + + req = Object.assign( + { headers: {}, socket }, + Stream.Readable.prototype, + req || {} + ) + res = Object.assign( + { _headers: {}, socket }, + Stream.Writable.prototype, + res || {} + ) + req.socket.remoteAddress = req.socket.remoteAddress || '127.0.0.1' + app = app || new Koa() + res.getHeader = k => res._headers[k.toLowerCase()] + res.setHeader = (k, v) => (res._headers[k.toLowerCase()] = v) + res.removeHeader = (k, v) => delete res._headers[k.toLowerCase()] + + const retApp = app.createContext(req, res) + + return retApp +} + +const request = (req, res, app) => context(req, res, app).request + +const response = (req, res, app) => context(req, res, app).response + +export { + context, + request, + response +}; + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/log-api-mock.js`: + +```js +// Mocks representing an array of logs for the +// Unit tests of logapi + +const data = [ + { + message: 'Error in lib/nodemailer.js/validateEmailArray()', + level: 'error', + timestamp: '2020-11-14T12:15:55.230Z' + }, + { + message: 'Error in lib/nodemailer.js/validateEmailArray()', + level: 'error', + timestamp: '2020-11-14T12:15:55.231Z' + }, + { + message: 'Error in lib/nodemailer.js/validateEmailArray()', + level: 'error', + timestamp: '2020-11-14T12:15:55.230Z' + }, + { + message: 'Error in lib/nodemailer.js/validateEmailArray()', + level: 'error', + timestamp: '2020-11-14T12:15:55.231Z' + } +] + +export default { + data +}; + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/helia-mock.js`: + +```js +/* + Mocking library for helia. + This is used to replace the helia library when running unit tests. +*/ + +const ipfs = { + libp2p: { + getMultiaddrs: () => [], + peerId: 'fake-id' + } +} + +export default ipfs + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/use-cases/index.js`: + +```js +/* + Mocks for the use cases. +*/ +/* eslint-disable */ + +class UserUseCaseMock { + async createUser(userObj) { + return {} + } + + async getAllUsers() { + return true + } + + async getUser(params) { + return true + } + + async updateUser(existingUser, newData) { + return true + } + + async deleteUser(user) { + return true + } + + async authUser(login, passwd) { + return { + generateToken: () => {} + } + } +} + +class EntryUseCaseMock { + async createEntry(userObj) { + return {} + } +} + +class Offer { + async createOffer() { + return {} + } + async removeStaleOffers(){ + + } + async removeDuplicateOffers(){ + + } + async loadOffers(){ + + } +} + +class Order { + async createOrder() { + return {} + } + async removeStaleOrders(){ + return {} + } +} + +class UsageUseCaseMock { + async cleanUsage() { + return {} + } + + async getRestSummary() { + return true + } + + async getTopIps(params) { + return true + } + + async getTopEndpoints(existingUser, newData) { + return true + } +} + +class UseCasesMock { + constuctor(localConfig = {}) { + // this.user = new UserUseCaseMock(localConfig) + } + + user = new UserUseCaseMock() + entry = new EntryUseCaseMock() + offer = new Offer() + order = new Order() + usage = new UsageUseCaseMock() +} + +export default UseCasesMock; + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/use-cases/offer-mock-data.js`: + +```js +/* + Mocking data for Offer Use Case unit tests. +*/ + +const nftOffer01 = { + "messageType": 1, + "messageClass": 1, + "tokenId": "eb93f05553ff088bffb0ec687519e83c59e5108c160f7c25a4b6c45109d7e40b", + "buyOrSell": "sell", + "rateInBaseUnit": 7672536, + "minUnitsToExchange": 7672536, + "numTokens": 1, + "utxoTxid": "c736d73e274df20e9b069b4990d1a264fb80aa98d67cc6c7a39e42bff48e7c04", + "utxoVout": 1, + "timestamp": 1662930309998, + "globaltimestamp": "2022-09-11T21:05:09.998Z", + "localTimestamp": "9/11/2022, 9:05:09 PM", + "txid": "4266862b8358664996038d8c29d49dc0f3d3058fd1ef3d567b084e6b16ceb5b2", + "p2wdbHash": "zdpuArq7rCuVCGPyTnWpLjy9AYsh8yrbwjGdKwg2GDDALkM8t", + "offerStatus": "posted", + "makerAddr": "bitcoincash:qrqlz63cwmu0hcmsrfnd8jemn3atkpaqds6tf4ksrr", + "ticker": "TV001", + "tokenType": 65 +} + +const nftTokenData01 = { + "genesisData": { + "type": 65, + "ticker": "TV001", + "name": "Introduction to NFTs on BCH", + "tokenId": "eb93f05553ff088bffb0ec687519e83c59e5108c160f7c25a4b6c45109d7e40b", + "documentUri": "ipfs://bafybeibmgilu4lk3uivwyzhtm7jorl5zbsluewqmcsxs6otzrphh33okk4", + "documentHash": "c1731268f4873f1928438abdaf6ffc546d86a1817dc6f3c6bc73fbdfb4664f10", + "decimals": 0, + "mintBatonIsActive": false, + "tokensInCirculationBN": "1", + "tokensInCirculationStr": "1", + "blockCreated": 740395, + "totalBurned": "0", + "totalMinted": "1", + "parentGroupId": "030563ddd65772d8e9b79b825529ed53c7d27037507b57c528788612b4911107" + }, + "immutableData": "ipfs://bafybeibmgilu4lk3uivwyzhtm7jorl5zbsluewqmcsxs6otzrphh33okk4", + "mutableData": "ipfs://bafybeifzhunfpodsztsj5x4ypopngkxuapbxwaxaxkahaybdktk6joqtlq" +} + +const simpleNftOffer01 = { + "messageType": 1, + "messageClass": 1, + "tokenId": "a80c89d2f9f7ad7584743587c4950a0f28514ba8054e8cec4e871747cf9c162c", + "buyOrSell": "sell", + "rateInBaseUnit": 76725, + "minUnitsToExchange": 76725, + "numTokens": 1, + "utxoTxid": "dd51a8bf96c8ab16a2935b09e51650e1769a1fa75cce9f0455abdbf72071d3c2", + "utxoVout": 1, + "timestamp": 1662930102814, + "globaltimestamp": "2022-09-11T21:01:42.814Z", + "localTimestamp": "9/11/2022, 9:01:42 PM", + "txid": "4013177602ee75bbc5c4a67ea8d6d80e4f3d12b9c46ae2a6643911f48257b578", + "p2wdbHash": "zdpuAzyLPFBwFWbNi8XQuxgAx9aBNGWZEGqib7KE6Hp3AEEhq", + "offerStatus": "posted", + "makerAddr": "bitcoincash:qrqlz63cwmu0hcmsrfnd8jemn3atkpaqds6tf4ksrr", + "ticker": "BAA", + "tokenType": 1 +} + +const simpleNftTokenData01 = { + "genesisData": { + "type": 1, + "ticker": "BAA", + "name": "Bitcoin AI Art 001", + "tokenId": "a80c89d2f9f7ad7584743587c4950a0f28514ba8054e8cec4e871747cf9c162c", + "documentUri": "ipfs://bafybeifevvtnap3m3fsjbwnvpknvzhqihl2ouuypio33f2vtwqejipgpkq", + "documentHash": "d6213e5629d01fd2cd714cde709e11b888c0ba441e05bb1cc649f8b784df5a6c", + "decimals": 0, + "mintBatonIsActive": false, + "tokensInCirculationBN": "1", + "tokensInCirculationStr": "1", + "blockCreated": 757238, + "totalBurned": "0", + "totalMinted": "1" + }, + "immutableData": "ipfs://bafybeifevvtnap3m3fsjbwnvpknvzhqihl2ouuypio33f2vtwqejipgpkq", + "mutableData": "ipfs://bafybeibqnsmmh6bkf2wwextetki4tly65z4r4qkrrpl5xwgvzdzjley6wm" +} + +const fungibleOffer01 = { + "messageType": 1, + "messageClass": 1, + "tokenId": "a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2", + "buyOrSell": "sell", + "rateInBaseUnit": 7672, + "minUnitsToExchange": 7672, + "numTokens": 1, + "utxoTxid": "822dc4c765cc68314479c7707bba28028eacab6013bb683b1680dbcc9c95b286", + "utxoVout": 1, + "timestamp": 1662930501091, + "globaltimestamp": "2022-09-11T21:08:21.091Z", + "localTimestamp": "9/11/2022, 9:08:21 PM", + "txid": "7ee0ec32e116b068ff43c5516fa500058d14f53037ba5cc729e78eb51d1f1ffd", + "p2wdbHash": "zdpuB2gHDvmByfvPFLJgEAaRyUi1cwnD45Qt66y4f5tnMXFo7", + "offerStatus": "posted", + "makerAddr": "bitcoincash:qrqlz63cwmu0hcmsrfnd8jemn3atkpaqds6tf4ksrr", + "ticker": "TROUT", + "tokenType": 1 +} + +const fungibleTokenData01 = { + "genesisData": { + "type": 1, + "ticker": "TROUT", + "name": "Trout's test token", + "tokenId": "a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2", + "documentUri": "troutsblog.com", + "documentHash": "", + "decimals": 2, + "mintBatonIsActive": true, + "tokensInCirculationBN": "100097954686", + "tokensInCirculationStr": "100097954686", + "blockCreated": 622414, + "totalBurned": "2045314", + "totalMinted": "100100000000" + }, + "immutableData": "troutsblog.com", + "mutableData": "" +} + +const offerMockData = { + data: { + messageType: 1, + messageClass: 1, + tokenId: + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + buyOrSell: 'sell', + rateInBaseUnit: 1000, + minUnitsToExchange: 10, + numTokens: 0.02, + utxoTxid: + '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87', + utxoVout: 0, + makerAddr: 'address', + tokenType: 1, + nostrEventId: 'test' + } +} + +const deserealizeTxMock = { + //... + vout: [ + { + value: 0, + scriptPubKey: { + addresses: ['bitcoincash:qzy97glp47ut7tstm5g0tlrmkhk742795gkmyc7478'] + } + }, + { + value: 0, + scriptPubKey: { + addresses: ['bitcoincash:qzy97glp47ut7tstm5g0tlrmkhk742795gkmyc7478'] + } + }, + { + value: 0, + scriptPubKey: { + addresses: ['bitcoincash:qzy97glp47ut7tstm5g0tlrmkhk742795gkmyc7478'] + } + }, + //... + ] +} + +export default { + nftOffer01, + nftTokenData01, + simpleNftOffer01, + simpleNftTokenData01, + fungibleOffer01, + fungibleTokenData01, + offerMockData, + deserealizeTxMock +}; + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/bchjs-mock.js`: + +```js +// Mocks for bch unit test + +// Tokens array containing some psf tokens +const psfBalances = [ + { + tokenId: + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + balance: 1, + slpAddress: 'simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk', + decimalCount: 9 + }, + { + tokenId: + 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb', + balance: 617, + slpAddress: 'simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk', + decimalCount: 8 + }, + { + tokenId: + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + balance: 1, + slpAddress: 'simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk', + decimalCount: 0 + }, + { + tokenId: + 'a436c8e1b6bee3d701c6044d190f76f774be83c36de8d34a988af4489e86dd37', + balance: 776, + slpAddress: 'simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk', + decimalCount: 7 + } + ] + +// Token array without psf tokens +const noPsfBalances = [ + { + tokenId: + 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb', + balance: 617, + slpAddress: 'simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk', + decimalCount: 8 + }, + { + tokenId: + 'a436c8e1b6bee3d701c6044d190f76f774be83c36de8d34a988af4489e86dd37', + balance: 776, + slpAddress: 'simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk', + decimalCount: 7 + }, + { + tokenId: + 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb', + balance: 617, + slpAddress: 'simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk', + decimalCount: 8 + } +] + +export default { + psfBalances, + noPsfBalances +}; +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/nostr-mock.js`: + +```js +class RelayPoolClassMock { + constructor() { + this.relay = { close: () => { } , subscribe: () => { } } + this.event = { content: 'content' } + } + on(ev, callback) { + callback(this.relay, null, this.event) + } +} + +const RelayPoolMock =()=>{ + return new RelayPoolClassMock() +} + +export default { RelayPoolMock } +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/app-mock.js`: + +```js +/* + Mocks for Koa 'app' object. +*/ + +const app = { + use: () => {} +} + +export default app; + +``` + +`/home/trout/work/psf/code/bch-dex/test/unit/mocks/ipfs-coord-mock.js`: + +```js +/* + Mocks for the ipfs-coord library +*/ + +class IPFSCoord { + async isReady () { + return true + } + + async start () {} + + async subscribeToChat() {} +} + +export default IPFSCoord; + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/a10-offer.rest-e2e.js`: + +```js +/* + Automated E2E tests for the /offer endpoint. +*/ + +// const config = require('../../../config') +// const assert = require('chai').assert + +// const axios = require('axios').default +import sinon from 'sinon' + +// const LOCALHOST = `http://localhost:${config.port}` + +// const OfferController = require('../../../src/controllers/rest-api/offer/controller') +// const mockContext = require('../../unit/mocks/ctx-mock').context + +let sandbox +// let uut +describe('OfferApi', () => { + beforeEach(() => { + // uut = new OfferController() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('POST /offer', () => { + // it('should pass data to the handlers', async () => { + // try { + // const mockOffer = { + // lokadId: 'SWP', + // messageType: 1, + // messageClass: 1, + // tokenId: 'token-id', + // buyOrSell: 'sell', + // rateInSats: 1000, + // minSatsToExchange: 1250, + // signature: + // 'H4cRPaAtyNyzG+4Qz+Tp2O7TtFZ7QRsWKKxG71dUZG5xfX0EWRMrBmqM6rH7jToOAT2s9Dm759HMxwP/WTMPzyA=', + // sigMsg: 'test', + // utxoTxid: 'txid-goes-here', + // utxoVout: 1, + // offerIpfsId: 'Qmblah', + // offerBchAddr: + // 'bitcoincash:qzxj37k35z6whp4mj4hrdw2vprx4klcydc6ete5xft', + // offerPubKey: 'pubkeyInHex' + // } + // + // const options = { + // method: 'post', + // url: `${LOCALHOST}/offer`, + // data: { offer: mockOffer } + // } + // + // const result = await axios(options) + // console.log('result.data: ', result.data) + // + // // assert.isFalse(result.data.success) + // } catch (err) { + // assert(false, 'Unexpected result') + // } + // }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/a01-auth.rest-e2e.js`: + +```js +/* + End-to-end tests for /auth endpoints. + + This test sets up the environment for other e2e tests. +*/ + +// Public npm libraries +import { assert } from 'chai' + +import axios from 'axios' + +// const sinon = require('sinon') + +// Local support libraries +import config from '../../../config/index.js' +import Server from '../../../bin/server.js' +import testUtils from '../../utils/test-utils.js' +import AdminLib from '../../../src/adapters/admin.js' +const adminLib = new AdminLib() + +// const request = supertest.agent(app.listen()) +const context = {} + +const LOCALHOST = `http://localhost:${config.port}` + +if (!config.noMongo) { + describe('Auth', () => { + before(async () => { + const app = new Server() + + // This should be the first instruction. It starts the REST API server. + await app.startServer() + + // Stop the IPFS node for the rest of the e2e tests. + // await app.controllers.adapters.ipfs.stop() + + // Delete all previous users in the database. + await testUtils.deleteAllUsers() + + // Create a new admin user. + await adminLib.createSystemUser() + + const userObj = { + email: 'test@test.com', + password: 'pass', + name: 'test' + } + const testUser = await testUtils.createUser(userObj) + // console.log('TestUser: ', testUser) + + context.user = testUser.user + context.token = testUser.token + }) + + describe('POST /auth', () => { + it('should throw 401 if credentials are incorrect', async () => { + try { + const options = { + method: 'post', + url: `${LOCALHOST}/auth`, + data: { + email: 'test@test.com', + password: 'wrongpassword' + } + } + + const result = await axios(options) + + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + console.log( + `result stringified: ${JSON.stringify(result.data, null, 2)}` + ) + assert(false, 'Unexpected result') + } catch (err) { + assert(err.response.status === 401, 'Error code 401 expected.') + } + }) + + it('should throw 401 if email is wrong format', async () => { + try { + const options = { + method: 'post', + url: `${LOCALHOST}/auth`, + data: { + email: 'wrongEmail', + password: 'wrongpassword' + } + } + + await axios(options) + assert(false, 'Unexpected result') + } catch (err) { + assert(err.response.status === 401, 'Error code 401 expected.') + } + }) + + it('should auth user', async () => { + try { + const options = { + method: 'post', + url: `${LOCALHOST}/auth`, + data: { + email: 'test@test.com', + password: 'pass' + } + } + const result = await axios(options) + // console.log(`result: ${JSON.stringify(result.data, null, 2)}`) + + assert(result.status === 200, 'Status Code 200 expected.') + assert( + result.data.user.email === 'test@test.com', + 'Email of test expected' + ) + assert( + result.data.user.password === undefined, + 'Password expected to be omited' + ) + } catch (err) { + console.log( + 'Error authenticating test user: ' + JSON.stringify(err, null, 2) + ) + throw err + } + }) + }) + }) +} + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/a08-validators.rest-e2e.js`: + +```js +/* +import { assert } from 'chai'; +import testUtils from '../../utils/test-utils.js'; +import Validators from '../../../src/controllers/rest-api/middleware/validators.js'; +import sinon from 'sinon'; +import { context as mockContext } from '../../unit/mocks/ctx-mock.js'; +import util from 'util'; +util.inspect.defaultOptions = { depth: 1 } + +const context = {} + +let sandbox +let uut +describe('Validators', () => { + before(async () => { + // console.log(`config: ${JSON.stringify(config, null, 2)}`) + + // Create a second test user. + const userObj = { + email: 'testvalidator@test.com', + password: 'pass2', + name: 'testvalidator' + } + const testUser = await testUtils.createUser(userObj) + // console.log(`testUser2: ${JSON.stringify(testUser, null, 2)}`) + + context.user = testUser.user + context.token = testUser.token + context.id = testUser.user._id + + // Get the JWT used to log in as the admin 'system' user. + const adminJWT = await testUtils.getAdminJWT() + // console.log(`adminJWT: ${adminJWT}`) + context.adminJWT = adminJWT + + // const admin = await testUtils.loginAdminUser() + // context.adminJWT = admin.token + + // const admin = await adminLib.loginAdmin() + // console.log(`admin: ${JSON.stringify(admin, null, 2)}`) + }) + beforeEach(() => { + uut = new Validators() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('ensureUser()', () => { + it('should throw 401 if user cant be found', async () => { + try { + // Force an error + sandbox.stub(uut.User, 'findById').resolves(false) + + // Mock the context object. + const ctx = mockContext() + ctx.request = { + header: { + authorization: `Bearer ${context.token}` + } + } + + await uut.ensureUser(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should throw 401 if token not found', async () => { + try { + // Mock the context object. + const ctx = mockContext() + + await uut.ensureUser(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should throw 401 if token is invalid', async () => { + try { + // Mock the context object. + const ctx = mockContext() + ctx.request = { + header: { + authorization: 'Bearer 1' + } + } + await uut.ensureUser(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should return true if user is admin', async () => { + // Mock the context object. + const ctx = mockContext() + ctx.params = { id: context.id } + + ctx.request = { + header: { + authorization: `Bearer ${context.adminJWT}` + } + } + + const result = await uut.ensureUser(ctx) + + assert.equal(result, true) + }) + }) + + describe('ensureAdmin()', () => { + it('should throw 401 if token not found', async () => { + try { + // Mock the context object. + const ctx = mockContext() + + await uut.ensureAdmin(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should throw 401 if token is invalid', async () => { + try { + // Mock the context object. + const ctx = mockContext() + ctx.request = { + header: { + authorization: 'Bearer 1' + } + } + await uut.ensureAdmin(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should throw 401 if user cant be found', async () => { + try { + // Force an error + sandbox.stub(uut.User, 'findById').resolves(false) + + // Mock the context object. + const ctx = mockContext() + ctx.request = { + header: { + authorization: `Bearer ${context.token}` + } + } + await uut.ensureAdmin(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should throw 401 if user is not admin type', async () => { + try { + // Mock the context object. + const ctx = mockContext() + ctx.request = { + header: { + authorization: `Bearer ${context.token}` + } + } + await uut.ensureAdmin(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'not admin') + } + }) + + it('should return true if user is admin', async () => { + // Mock the context object. + const ctx = mockContext() + ctx.request = { + header: { + authorization: `Bearer ${context.adminJWT}` + } + } + + const result = await uut.ensureAdmin(ctx) + + assert.equal(result, true) + }) + }) + + describe('ensureTargetUserOrAdmin()', () => { + it('should throw 401 if token not found', async () => { + try { + // Mock the context object. + const ctx = mockContext() + ctx.params = { id: context.id } + await uut.ensureTargetUserOrAdmin(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should throw 401 if token is invalid', async () => { + try { + // Mock the context object. + const ctx = mockContext() + ctx.params = { id: context.id } + + ctx.request = { + header: { + authorization: 'Bearer 1' + } + } + await uut.ensureTargetUserOrAdmin(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should throw 401 if user cant be found', async () => { + try { + // Force an error + sandbox.stub(uut.User, 'findById').resolves(false) + + // Mock the context object. + const ctx = mockContext() + ctx.params = { id: context.id } + + ctx.request = { + header: { + authorization: `Bearer ${context.token}` + } + } + await uut.ensureTargetUserOrAdmin(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'Unauthorized') + } + }) + + it('should throw 401 if user is not admin type', async () => { + try { + // Mock the context object. + const ctx = mockContext() + ctx.params = { id: 'Target Id' } + + ctx.request = { + header: { + authorization: `Bearer ${context.token}` + } + } + await uut.ensureTargetUserOrAdmin(ctx) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.status, 401) + assert.include(err.message, 'not admin') + } + }) + + it('should return true if user is admin', async () => { + // Mock the context object. + const ctx = mockContext() + ctx.params = { id: context.id } + + ctx.request = { + header: { + authorization: `Bearer ${context.adminJWT}` + } + } + + const result = await uut.ensureTargetUserOrAdmin(ctx) + + assert.equal(result, true) + }) + }) +}) +*/ + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/a10-usage.rest-e2e.js`: + +```js +/* +End-to-end tests for /usage endpoints. +*/ + +import config from '../../../config/index.js' +import { assert } from 'chai' +import axios from 'axios' +import sinon from 'sinon' +import util from 'util' + +util.inspect.defaultOptions = { depth: 1 } + +const LOCALHOST = `http://localhost:${config.port}` + +let sandbox + +describe('Usage', () => { + beforeEach(() => { + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('GET /usage', () => { + it('should return usage status', async () => { + try { + const options = { + method: 'get', + url: `${LOCALHOST}/usage` + } + + const result = await axios(options) + + assert.property(result.data, 'status') + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) + + describe('GET /usage/ips', () => { + it('should return ips', async () => { + try { + const options = { + method: 'get', + url: `${LOCALHOST}/usage/ips` + } + + const result = await axios(options) + + assert.property(result.data, 'ips') + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) + + describe('GET /usage/endpoints', () => { + it('should return ips', async () => { + try { + const options = { + method: 'get', + url: `${LOCALHOST}/usage/endpoints` + } + + const result = await axios(options) + + assert.property(result.data, 'endpoints') + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/README.md`: + +```md +# Automated End-to-end Tests + +This contains the original boilerplate tests, which are end-to-end tests. These tests are fully automated and test the system directly by making REST API calls with axios. + +These tests function exactly the same as a normal user would, by making real REST API calls to the software. As a result, they are fine for testing internal system components like authorization and user handling. However, they are inappropriate for testing sophisticated endpoints that involve complex operations. For example, interacting with a blockchain, pinging other network systems, or writing data to a secondary database. + +There is some redundancy between these tests and the unit tests. The focus is on *how* the tests are executed. The unit tests call the libraries directly (internally). These e2e tests use the REST API (externally). + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/a09-admin.rest-e2e.js`: + +```js +import { assert } from 'chai' +import Admin from '../../../src/adapters/admin.js' +import sinon from 'sinon' +import util from 'util' +import config from '../../../config/index.js' + +util.inspect.defaultOptions = { depth: 1 } + +let sandbox +let uut +describe('Admin', () => { + beforeEach(() => { + uut = new Admin() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + if (!config.noMongo) { + describe('loginAdmin()', () => { + it('should logind admin', async () => { + try { + const error = new Error('test error') + error.response = { + status: 422 + } + // sandbox.stub(uut.axios, 'request').onFirstCall().throws(error) + + const result = await uut.loginAdmin() + const user = result.data.user + + assert.property(user, '_id') + assert.property(user, 'email') + assert.property(user, 'type') + + assert.isString(user._id) + assert.isString(user.email) + assert.isString(user.type) + + assert.equal(user.type, 'admin') + } catch (err) { + assert(false, 'Unexpected result') + } + }) + + it('should handle axios error', async () => { + try { + // Returns an erroneous password to force + // an auth error + sandbox.stub(uut.jsonFiles, 'readJSON').resolves({ password: 'wrong' }) + + await uut.loginAdmin() + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.response.status, 401) + assert.include(err.response.data, 'Unauthorized') + } + }) + }) + + describe('createSystemUser()', () => { + it('should create admin', async () => { + try { + await uut.deleteExistingSystemUser() + const result = await uut.createSystemUser() + + assert.property(result, 'email') + assert.property(result, 'password') + assert.property(result, 'id') + assert.property(result, 'token') + } catch (err) { + assert(false, 'Unexpected result') + } + }) + it('should update admin password', async () => { + try { + uut.config.adminPassword = 'newpassword' + + const fakeUser = { + password: 'oldpassword', + save: () => { return 'token' }, + generateToken: () => { return 'token' } + } + + sandbox.stub(uut.User, 'findOne').resolves(fakeUser) + const result = await uut.createSystemUser() + + assert.property(result, 'email') + assert.property(result, 'password') + assert.property(result, 'id') + assert.property(result, 'token') + + assert.equal(fakeUser.password, 'newpassword', 'password should be updated') + } catch (err) { + console.log(err) + assert(false, 'Unexpected result') + } + }) + + it('should handle error', async () => { + try { + sandbox.stub(uut.User, 'findOne').throws(new Error('test error')) + await uut.createSystemUser() + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) + + describe('deleteExistingSystemUser()', () => { + it('should delete admin', async () => { + try { + sandbox.stub(uut.User, 'deleteOne').resolves(true) + const result = await uut.deleteExistingSystemUser() + assert.isTrue(result) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + + it('should handle error when deleting admin', async () => { + try { + sandbox.stub(uut.User, 'deleteOne').throws(new Error('test error')) + await uut.deleteExistingSystemUser() + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + }) + } +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/a06-logapi.rest-e2e.js`: + +```js +import config from '../../../config/index.js' +import { assert } from 'chai' +import axios from 'axios' +import sinon from 'sinon' +import util from 'util' + +import LogsController from '../../../src/controllers/rest-api/logs/controller.js' +import { context as mockContext } from '../../unit/mocks/ctx-mock.js' +util.inspect.defaultOptions = { depth: 1 } + +const LOCALHOST = `http://localhost:${config.port}` + +let sandbox +let uut +describe('LogsApi', () => { + beforeEach(() => { + uut = new LogsController() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('POST /logs', () => { + it('should return false if password is not provided', async () => { + try { + const options = { + method: 'post', + url: `${LOCALHOST}/logs`, + data: {} + } + + const result = await axios(options) + assert.isFalse(result.data.success) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + + it('should return log', async () => { + try { + const options = { + method: 'post', + url: `${LOCALHOST}/logs`, + data: { + password: 'test' + } + } + + const result = await axios(options) + + assert.isTrue(result.data.success) + assert.isArray(result.data.data) + assert.property(result.data.data[0], 'message') + assert.property(result.data.data[0], 'level') + assert.property(result.data.data[0], 'timestamp') + } catch (err) { + assert(false, 'Unexpected result') + } + }) + + it('should return false if files are not found!', async () => { + try { + sandbox.stub(uut.logsApiLib, 'getLogs').resolves({ + success: false, + data: 'file does not exist' + }) + + const ctx = mockContext() + ctx.request = { + body: { + password: 'test' + } + } + await uut.getLogs(ctx) + + assert.isFalse(ctx.body.success) + assert.include(ctx.body.data, 'file does not exist') + } catch (err) { + assert.fail('Unexpected result') + } + }) + + it('should catch and handle errors', async () => { + try { + // Force an error + sandbox + .stub(uut.logsApiLib.fs, 'existsSync') + .throws(new Error('test error')) + + // Mock the context object. + const ctx = mockContext() + + ctx.request = { + body: { + password: 'test' + } + } + + await uut.getLogs(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'test error') + } + }) + + it('should throw unhandled error', async () => { + try { + // Force an error + sandbox.stub(uut.logsApiLib.fs, 'existsSync').throws(new Error()) + + // Mock the context object. + const ctx = mockContext() + + ctx.request = { + body: { + password: 'test' + } + } + + await uut.getLogs(ctx) + + assert.fail('Unexpected result') + } catch (err) { + assert.include(err.message, 'Unhandled error') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/a04-contact.rest-e2e.js`: + +```js +import config from '../../../config/index.js' +import axios from 'axios' +import { assert } from 'chai' +import sinon from 'sinon' + +import { context as mockContext } from '../../unit/mocks/ctx-mock.js' +import ContactController from '../../../src/controllers/rest-api/contact/controller.js' + +// Mock data +// const mockData = require('./mocks/contact-mocks') + +const LOCALHOST = `http://localhost:${config.port}` +let uut +let sandbox + +describe('Contact', () => { + beforeEach(() => { + uut = new ContactController() + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('POST /contact/email', () => { + it('should throw error if email property is not provided', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/contact/email`, + data: { + obj: { + formMessage: 'message' + } + } + } + + await axios(options) + + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // console.log(`result stringified: ${JSON.stringify(result, null, 2)}`) + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include(err.response.data, "Property 'email' must be a string!") + } + }) + + it('should throw error if formMessage property is not provided', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/contact/email`, + data: { + obj: { + email: 'email@email.com' + } + } + } + + await axios(options) + + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // console.log(`result stringified: ${JSON.stringify(result, null, 2)}`) + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include( + err.response.data, + "Property 'formMessage' must be a string!" + ) + } + }) + + it('should throw error if email list provided is not a array', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/contact/email`, + data: { + obj: { + email: 'email@email.com', + formMessage: 'test message', + emailList: 1 + } + } + } + + await axios(options) + + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // console.log(`result stringified: ${JSON.stringify(result, null, 2)}`) + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include( + err.response.data, + "Property 'emailList' must be a array of emails!" + ) + } + }) + + it('should throw error if email list provided is a empty array', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/contact/email`, + data: { + obj: { + email: 'email@email.com', + formMessage: 'test message', + emailList: [] + } + } + } + + await axios(options) + + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // console.log(`result stringified: ${JSON.stringify(result, null, 2)}`) + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include( + err.response.data, + "Property 'emailList' must be a array of emails!" + ) + } + }) + + it('should send email with minimun input', async () => { + try { + // Mock live network calls. + sandbox.stub(uut.contactLib, 'sendEmail').resolves(true) + + // Mock the context object. + const ctx = mockContext() + ctx.request = { + body: { + obj: { + email: 'email@email.com', + formMessage: 'test message' + } + } + } + await uut.email(ctx) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + + it('should send email with all inputs', async () => { + try { + // Mock live network calls. + sandbox.stub(uut.contactLib, 'sendEmail').resolves(true) + + // Mock the context object. + const ctx = mockContext() + ctx.request = { + body: { + obj: { + email: 'email@email.com', + formMessage: 'test message', + emailList: ['email@email.com'] + } + } + } + await uut.email(ctx) + } catch (err) { + assert(false, 'Unexpected result') + } + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/automated/a02-users.rest-e2e.js`: + +```js +import testUtils from '../../utils/test-utils.js' +import { assert } from 'chai' +import config from '../../../config/index.js' +import axios from 'axios' +import sinon from 'sinon' +import util from 'util' + +// import UserController from '../../../src/controllers/rest-api/users/controller.js' +// import Adapters from '../../../src/adapters/index.js' +// import UseCases from '../../../src/use-cases/index.js' +util.inspect.defaultOptions = { depth: 1 } + +const LOCALHOST = `http://localhost:${config.port}` + +const context = {} +// const adapters = new Adapters() +// let uut +let sandbox + +// const mockContext = require('../../unit/mocks/ctx-mock').context + +if (!config.noMongo) { + describe('Users', () => { + before(async () => { + // console.log(`config: ${JSON.stringify(config, null, 2)}`) + + // Create a second test user. + const userObj = { + email: 'test2@test.com', + password: 'pass2', + name: 'test2' + } + const testUser = await testUtils.createUser(userObj) + // console.log(`testUser2: ${JSON.stringify(testUser, null, 2)}`) + + context.user2 = testUser.user + context.token2 = testUser.token + context.id2 = testUser.user._id + + // Get the JWT used to log in as the admin 'system' user. + const adminJWT = await testUtils.getAdminJWT() + console.log(`adminJWT: ${adminJWT}`) + context.adminJWT = adminJWT + + // const admin = await testUtils.loginAdminUser() + // context.adminJWT = admin.token + + // const admin = await adminLib.loginAdmin() + // console.log(`admin: ${JSON.stringify(admin, null, 2)}`) + }) + + beforeEach(() => { + // const useCases = new UseCases({ adapters }) + // uut = new UserController({ adapters, useCases }) + + sandbox = sinon.createSandbox() + }) + + afterEach(() => sandbox.restore()) + + describe('POST /users - Create User', () => { + it('should reject signup when data is incomplete', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/users`, + data: { + email: 'test2@test.com' + } + } + + await axios(options) + + assert(false, 'Unexpected result') + } catch (err) { + assert(err.response.status === 422, 'Error code 422 expected.') + } + }) + + it('should reject signup if no email property is provided', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/users`, + data: { + user: { + password: 'pass2' + } + } + } + await axios(options) + + assert(false, 'Unexpected result') + } catch (err) { + // console.log('err', err) + assert.equal(err.response.status, 422) + assert.include(err.response.data, "Property 'email' must be a string") + } + }) + + it('should reject signup if no password property is provided', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/users`, + data: { + user: { + email: 'test2@test.com' + } + } + } + await axios(options) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include( + err.response.data, + "Property 'password' must be a string" + ) + } + }) + + it('should reject if name property property is not string', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/users`, + data: { + user: { + email: 'test322@test.com', + password: 'supersecretpassword', + name: 1234 + } + } + } + await axios(options) + + assert.fail('Unexpected result') + } catch (err) { + // console.log(err) + assert.equal(err.response.status, 422) + assert.include(err.response.data, "Property 'name' must be a string") + } + }) + + it("should signup of type 'user' by default", async () => { + const options = { + method: 'post', + url: `${LOCALHOST}/users`, + data: { + user: { + email: 'test3@test.com', + password: 'supersecretpassword', + name: 'test3' + } + } + } + const result = await axios(options) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + context.user = result.data.user + context.token = result.data.token + + assert(result.status === 200, 'Status Code 200 expected.') + assert( + result.data.user.email === 'test3@test.com', + 'Email of test expected' + ) + assert( + result.data.user.password === undefined, + 'Password expected to be omited' + ) + assert.property(result.data, 'token', 'Token property exists.') + assert.equal(result.data.user.type, 'user') + assert.property(result.data.user, 'mnemonic') + }) + it('should reject signup when DISABLE_NEW_ACCOUNTS is true', async () => { + try { + process.env.DISABLE_NEW_ACCOUNTS = true + const options = { + method: 'POST', + url: `${LOCALHOST}/users`, + data: { + email: 'test2@test.com', + password: 'supersecretpassword', + name: 'test3' + } + } + + await axios(options) + + assert(false, 'Unexpected result') + } catch (err) { + assert(err.response.status === 401, 'Error code 401 expected.') + } + }) + it('admin can create a user when DISABLE_NEW_ACCOUNTS is true', async () => { + process.env.DISABLE_NEW_ACCOUNTS = true + const options = { + method: 'post', + url: `${LOCALHOST}/users`, + headers: { + Authorization: `Bearer ${context.adminJWT}` + }, + data: { + user: { + email: 'fromAdmin@test.com', + password: 'supersecretpassword', + name: 'test3' + } + } + } + const result = await axios(options) + + context.user = result.data.user + context.token = result.data.token + + assert(result.status === 200, 'Status Code 200 expected.') + assert( + result.data.user.email === 'fromAdmin@test.com', + 'Email of test expected' + ) + assert( + result.data.user.password === undefined, + 'Password expected to be omited' + ) + assert.property(result.data, 'token', 'Token property exists.') + assert.equal(result.data.user.type, 'user') + }) + }) + + describe('GET /users', () => { + it('should not fetch users if the authorization header is missing', async () => { + try { + const options = { + method: 'GET', + url: `${LOCALHOST}/users`, + headers: { + Accept: 'application/json' + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should not fetch users if the authorization header is missing the scheme', async () => { + try { + const options = { + method: 'GET', + url: `${LOCALHOST}/users`, + headers: { + Accept: 'application/json', + Authorization: '1' + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should not fetch users if the authorization header has invalid scheme', async () => { + const { token } = context + try { + const options = { + method: 'GET', + url: `${LOCALHOST}/users`, + headers: { + Accept: 'application/json', + Authorization: `Unknown ${token}` + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should not fetch users if token is invalid', async () => { + try { + const options = { + method: 'GET', + url: `${LOCALHOST}/users`, + headers: { + Accept: 'application/json', + Authorization: 'Bearer 1' + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + // it('should fetch all users', async () => { + // const { token } = context + + // const options = { + // method: 'GET', + // url: `${LOCALHOST}/users`, + // headers: { + // Accept: 'application/json', + // Authorization: `Bearer ${token}` + // } + // } + // const result = await axios(options) + + // const users = result.data.users + // // console.log(`users: ${util.inspect(users)}`) + + // assert.hasAnyKeys(users[0], ['type', '_id', 'email', 'mnemonic']) + // assert.isNumber(users.length) + // }) + + // it('should return a 422 http status if biz-logic throws an error', async () => { + // try { + // const { token } = context + + // // Force an error + // sandbox + // .stub(uut.useCases.user, 'getAllUsers') + // .rejects(new Error('test error')) + + // const options = { + // method: 'GET', + // url: `${LOCALHOST}/users`, + // headers: { + // Accept: 'application/json', + // Authorization: `Bearer ${token}` + // } + // } + // await axios(options) + + // assert.fail('Unexpected code path!') + // } catch (err) { + // // console.log(err) + // assert.equal(err.response.status, 422) + // assert.equal(err.response.data, 'test error') + // } + // }) + }) + + describe('GET /users/:id', () => { + it('should not fetch user if token is invalid', async () => { + try { + const options = { + method: 'GET', + url: `${LOCALHOST}/users/1`, + headers: { + Accept: 'application/json', + Authorization: 'Bearer 1' + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + // it("should throw 404 if user doesn't exist", async () => { + // const { token } = context + + // try { + // const options = { + // method: 'GET', + // url: `${LOCALHOST}/users/5fa4bd7ee1828f5f4d8ed004`, + // headers: { + // Accept: 'application/json', + // Authorization: `Bearer ${token}` + // } + // } + // await axios(options) + + // assert.equal(true, false, 'Unexpected behavior') + // } catch (err) { + // assert.equal(err.response.status, 404) + // } + // }) + + // it('should throw 422 for invalid input', async () => { + // const { token } = context + + // try { + // const options = { + // method: 'GET', + // url: `${LOCALHOST}/users/1`, + // headers: { + // Accept: 'application/json', + // Authorization: `Bearer ${token}` + // } + // } + // await axios(options) + + // assert.equal(true, false, 'Unexpected behavior') + // } catch (err) { + // assert.equal(err.response.status, 422) + // } + // }) + + it('should fetch own user', async () => { + const _id = context.user._id + const token = context.token + + const options = { + method: 'GET', + url: `${LOCALHOST}/users/${_id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + } + } + const result = await axios(options) + + const user = result.data.user + // console.log(`user: ${util.inspect(user)}`) + + assert.property(user, 'type') + assert.property(user, 'email') + assert.property(user, 'mnemonic') + + assert.property(user, '_id') + assert.equal(user._id, _id) + + assert.notProperty( + user, + 'password', + 'Password property should not be returned' + ) + }) + }) + + describe('PUT /users/:id', () => { + it('should not update user if token is invalid', async () => { + try { + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/1`, + headers: { + Accept: 'application/json', + Authorization: 'Bearer 1' + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should throw 401 if non-admin updating other user', async () => { + const { token } = context + + try { + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/1`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should not be able to update user type', async () => { + try { + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${context.user._id.toString()}`, + headers: { + Authorization: `Bearer ${context.token}` + }, + data: { + user: { + email: 'test@test.com', + password: 'password', + name: 'new name', + type: 'test' + } + } + } + await axios(options) + + // console.log(`Users: ${JSON.stringify(result.data, null, 2)}`) + + // assert(result.status === 200, 'Status Code 200 expected.') + // assert(result.data.user.type === 'user', 'Type should be unchanged.') + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include( + err.response.data, + "Property 'type' can only be changed by Admin user" + ) + } + }) + + it('should not be able to update other user when not admin', async () => { + try { + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${context.user2._id.toString()}`, + headers: { + Authorization: `Bearer ${context.token}` + }, + data: { + user: { + name: 'This should not work' + } + } + } + await axios(options) + + // console.log(`result: ${JSON.stringify(result.data, null, 2)}`) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should not be able to update if name property is wrong', async () => { + try { + const _id = context.user._id + const token = context.token + + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${_id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + }, + data: { + user: { + email: 'testToUpdate@test.com', + name: {}, + password: 'password' + } + } + } + await axios(options) + } catch (error) { + assert.equal(error.response.status, 422) + assert.include(error.response.data, "Property 'name' must be a string!") + } + }) + + it('should not be able to update if password property is not string', async () => { + const { token } = context + const _id = context.user._id + try { + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${_id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + }, + data: { + user: { + password: 1234, + email: 'test@test.com', + name: 'test' + } + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include( + err.response.data, + "Property 'password' must be a string!" + ) + } + }) + + it('should not be able to update if email is not string', async () => { + const { token } = context + const _id = context.user._id + try { + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${_id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + }, + data: { + user: { + email: 1234 + } + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include(err.response.data, "Property 'email' must be a string!") + } + }) + + it('should not be able to update type property if is not string', async () => { + try { + const _id = context.user._id + const token = context.token + + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${_id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + }, + data: { + user: { + type: 1, + email: 'test@test.com', + name: 'test', + password: 'password' + } + } + } + await axios(options) + } catch (err) { + assert.equal(err.response.status, 422) + assert.include(err.response.data, "Property 'type' must be a string!") + } + }) + + it('should be able to update other user when admin', async () => { + const adminJWT = context.adminJWT + + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${context.user2._id.toString()}`, + headers: { + Authorization: `Bearer ${adminJWT}` + }, + data: { + user: { + name: 'This should work', + email: 'test4@test.com', + password: 'password' + } + } + } + + const result = await axios(options) + // console.log(`result stringified: ${JSON.stringify(result, null, 2)}`) + + const userName = result.data.user.name + assert.equal(userName, 'This should work') + }) + + it('should update user with minimum inputs', async () => { + const _id = context.user._id + const token = context.token + + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${_id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + }, + data: { + user: { email: 'testToUpdate@test.com' } + } + } + + const result = await axios(options) + const user = result.data.user + // console.log(`user: ${util.inspect(user)}`) + + assert.property(user, 'type') + assert.property(user, 'email') + + assert.property(user, '_id') + assert.equal(user._id, _id) + + assert.notProperty( + user, + 'password', + 'Password property should not be returned' + ) + assert.equal(user.email, 'testToUpdate@test.com') + }) + + it('should update user with all inputs', async () => { + const _id = context.user._id + const token = context.token + + const options = { + method: 'PUT', + url: `${LOCALHOST}/users/${_id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + }, + data: { + user: { + email: 'testToUpdate@test.com', + name: 'my name', + username: 'myUsername' + } + } + } + const result = await axios(options) + + const user = result.data.user + // console.log(`user: ${util.inspect(user)}`) + + assert.property(user, 'type') + assert.property(user, 'email') + assert.property(user, 'name') + + assert.property(user, '_id') + assert.equal(user._id, _id) + assert.notProperty( + user, + 'password', + 'Password property should not be returned' + ) + assert.equal(user.name, 'my name') + assert.equal(user.email, 'testToUpdate@test.com') + assert.equal(user.username, 'myUsername') + }) + }) + + describe('DELETE /users/:id', () => { + it('should not delete user if token is invalid', async () => { + try { + const options = { + method: 'DELETE', + url: `${LOCALHOST}/users/1`, + headers: { + Accept: 'application/json', + Authorization: 'Bearer 1' + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should throw 401 if deleting invalid user', async () => { + const { token } = context + + try { + const options = { + method: 'DELETE', + url: `${LOCALHOST}/users/1`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + } + } + await axios(options) + + assert.equal(true, false, 'Unexpected behavior') + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should not be able to delete other users unless admin', async () => { + try { + const options = { + method: 'DELETE', + url: `${LOCALHOST}/users/${context.user2._id.toString()}`, + headers: { + Authorization: `Bearer ${context.token}` + } + } + await axios(options) + } catch (err) { + assert.equal(err.response.status, 401) + } + }) + + it('should delete own user', async () => { + const _id = context.user._id + const token = context.token + + const options = { + method: 'DELETE', + url: `${LOCALHOST}/users/${_id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + } + } + const result = await axios(options) + // console.log(`result: ${util.inspect(result.data.success)}`) + + assert.equal(result.data.success, true) + }) + + it('should be able to delete other users when admin', async () => { + const id = context.id2 + const adminJWT = context.adminJWT + + const options = { + method: 'DELETE', + url: `${LOCALHOST}/users/${id}`, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${adminJWT}` + } + } + const result = await axios(options) + // console.log(`result: ${util.inspect(result.data)}`) + + assert.equal(result.data.success, true) + }) + }) + }) +} + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/manual/02-take-offer.js`: + +```js +/* + Part 2 of 3: Take an offer by submiting a counter-offer. +*/ + +import axios from 'axios' + +const LOCALHOST = 'http://localhost:5700' + +async function start () { + try { + const options = { + method: 'post', + url: `${LOCALHOST}/offer/take`, + data: { + offerCid: 'zdpuAkv76xbgqFEdFvcz28yNvtVjoZS7wsMo5wvuxWstycLRg' + } + } + + const result = await axios(options) + console.log('result.data: ', result.data) + } catch (err) { + console.log(err) + } +} +start() + +``` + +`/home/trout/work/psf/code/bch-dex/test/e2e/manual/01-create-order.js`: + +```js +/* + A manual e2e test for creating an Order, which then generates an Offer through + the P2WDB webhook. + + Ensure the REST API is up an running before running this test. +*/ + +import axios from 'axios' + +const LOCALHOST = 'http://localhost:5700' + +async function start () { + try { + const mockOrder = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: + 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + buyOrSell: 'sell', + rateInBaseUnit: 5000, + minUnitsToExchange: 5000, + numTokens: 1 + } + + const options = { + method: 'post', + url: `${LOCALHOST}/order`, + data: { order: mockOrder } + } + + const result = await axios(options) + console.log('result.data: ', result.data) + } catch (err) { + console.log(err) + } +} +start() + +``` + +`/home/trout/work/psf/code/bch-dex/test/integration/adapters/bch-adapter-integration.js`: + +```js +/* + Integration tests for the bch.js adapter. +*/ + +// Local libraries. +// const BchAdapter = require('../../../src/adapters/bch') +// +// describe('#wallet', () => { +// let uut +// +// beforeEach(() => { +// uut = new BchAdapter() +// }) +// +// // describe('#getPSFTokenBalance', () => { +// // it('should get the PSF balance for the root address of the wallet', async () => { +// // await uut.wallet.walletInfoPromise +// // console.log('bch.wallet.walletInfo: ', uut.wallet.walletInfo) +// // }) +// // }) +// }) + +``` + +`/home/trout/work/psf/code/bch-dex/test/integration/adapters/p2wdb-adapter-integration.js`: + +```js +/* + Integration tests for hte p2wdb-adapter.js library + + These integration tests may not necessarily pass. They require a WIF set + as an environment variable, and loaded with enough BCH and PSF to make + a write to the P2WDB. + + If these tests fail, it does not necessarily mean there is a problem with the + code. Check that the WIF envrionment variable meets the requirements. +*/ + +// Public npm libraries +import BCHJS from '@psf/bch-js' + +// Local libraries +import P2wdbAdapter from '../../../src/adapters/p2wdb-adapter' + +const wif = process.env.WIF +if (!wif) { + throw new Error('You must provide a BCH WIF private key as an environment variable to run this test.') +} + +describe('#p2wdb-adapter.js', () => { + let uut + + beforeEach(() => { + const bchjs = new BCHJS() + + uut = new P2wdbAdapter({ bchjs }) + }) + + describe('#checkForSufficientFunds', () => { + it('should check for sufficient funds', async () => { + const result = await uut.checkForSufficientFunds(wif) + + console.log('Provided WIF has funds for making a write: ', result) + }) + }) + + describe('#write', () => { + it('should write data to the P2WDB', async () => { + const inObj = { + appId: 'test234', + data: { + key: 'value' + }, + wif + } + + const result = await uut.write(inObj) + console.log('result: ', result) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/integration/adapters/wallet-adapter-integration.js`: + +```js +/* + Integration tests for the wallet.js adapter library. +*/ + +// Public npm libraries. +// const assert = require('chai').assert + +// Local libraries. +import WalletAdapter from '../../../src/adapters/wallet' + +describe('#wallet', () => { + let uut + + beforeEach(() => { + uut = new WalletAdapter() + }) + + // describe('#instanceWallet', () => { + // it('should instance the wallet using the web 3 infra by default', async () => { + // const walletData = await uut.openWallet() + // // console.log('walletData: ', walletData) + // + // const walletInstance = await uut.instanceWallet(walletData) + // // console.log('walletInstance: ', walletInstance) + // + // assert.equal(walletInstance.ar.interface, 'consumer-api') + // }) + // + // it('should instance using web 2 FullStack.cash infra', async () => { + // const walletData = await uut.openWallet() + // + // // Force usage of FullStack.cash + // uut.config.useFullStackCash = true + // + // const walletInstance = await uut.instanceWallet(walletData) + // // console.log('walletInstance: ', walletInstance) + // + // assert.equal(walletInstance.ar.interface, 'rest-api') + // }) + // }) + // + // describe('#moveTokens', () => { + // it('should move tokens to a new address in the HD wallet', async () => { + // const walletData = await uut.openWallet() + // + // // Force usage of FullStack.cash + // uut.config.useFullStackCash = true + // + // await uut.instanceWallet(walletData) + // + // const inObj = { + // tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + // qty: 1 + // } + // + // const result = await uut.moveTokens(inObj) + // // console.log('result: ', result) + // + // assert.property(result, 'txid') + // assert.property(result, 'vout') + // assert.property(result, 'hdIndex') + // }) + // }) + // + // describe('#moveBch', () => { + // it('should move BCH to a new address in the HD wallet', async () => { + // const walletData = await uut.openWallet() + // + // // Force usage of FullStack.cash + // uut.config.useFullStackCash = true + // + // await uut.instanceWallet(walletData) + // + // const amountSat = 1000 + // + // const result = await uut.moveBch(amountSat) + // console.log('result: ', result) + // }) + // }) + + describe('#completeTx', () => { + it('should complete the transaction with bchjs.TransactionBuilder', async () => { + const walletData = await uut.openWallet() + + // Force usage of FullStack.cash + uut.config.useFullStackCash = true + + await uut.instanceWallet(walletData) + + const hex = '0200000002cf24c6f6e55fc84e7699223f7dac568aae991f1a49747758a797d06a516f718c0100000000ffffffff0c7a53c39a7f215c9fa0f409710cf5cb8926e40c104efcedb43d69d5e113fd9d000000006a47304402204d5d1ce837594a151ef8ccecf95b5c7ebb2e71560c6d2597fa559b92f9f032bc02206ef67cd2ef4b4df7207225c26c9982df184959ac389c3f49f1ff5dce641a72ee412103fdc2366a32184220e77fd50e7fff30e7c76b2b7246dea6d56b8177f9fca6fec7ffffffff030000000000000000376a04534c500001010453454e4420a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b208000000000000006422020000000000001976a914d46461bf6a5f3a8e0e0e92b85465ad79696ccb7688ac88130000000000001976a914d46461bf6a5f3a8e0e0e92b85465ad79696ccb7688ac00000000' + + const result = await uut.completeTx(hex, 10) + console.log('result: ', result) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/integration/use-cases/offer-use-case-integration.js`: + +```js +/* + Integration tests for the offer-use-case.js library + + For these tests to pass, the app wallet must have Trout test tokens with + a token ID of a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2 +*/ + +// Public npm libraries +import { assert } from 'chai' + +// Local npm libraries +import Adapters from '../../../src/adapters' + +import Offer from '../../../src/use-cases/offer' + +describe('#offer-use-case.js', () => { + let uut + + before(async () => { + const adapters = new Adapters() + adapters.config.getJwtAtStartup = false + await adapters.start() + + uut = new Offer({ adapters }) + }) + + describe('#ensureFunds', () => { + it('should return true if wallet has enough funds', async () => { + const offerEntity = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + buyOrSell: 'sell', + rateInBaseUnit: 1000, + minUnitsToExchange: 1250, + numTokens: 1 + } + + const result = await uut.ensureFunds(offerEntity) + + assert.equal(result, true) + }) + }) +}) + +``` + +`/home/trout/work/psf/code/bch-dex/test/utils/test-utils.js`: + +```js +/* + Utility functions used to prepare the environment for tests. +*/ + +// Public NPM libraries +import mongoose from 'mongoose' +import axios from 'axios' + +// Local libraries +import config from '../../config/index.js' +import User from '../../src/adapters/localdb/models/users.js' +import JsonFiles from '../../src/adapters/json-files.js' + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' + +const jsonFiles = new JsonFiles() + +const LOCALHOST = `http://localhost:${config.port}` +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +// Remove all collections from the DB. +async function cleanDb () { + for (const collection in mongoose.connection.collections) { + const collections = mongoose.connection.collections + if (collections.collection) { + // const thisCollection = mongoose.connection.collections[collection] + // console.log(`thisCollection: ${JSON.stringify(thisCollection, null, 2)}`) + + await collection.deleteMany() + } + } +} + +// Delete all users in the database. This ensures there is no previous state +// to confuse tests. +async function deleteAllUsers () { + try { + // Get all the users in the DB. + const users = await User.find({}, '-password') + // console.log(`users: ${JSON.stringify(users, null, 2)}`) + + // Delete each user. + for (let i = 0; i < users.length; i++) { + const thisUser = users[i] + await thisUser.remove() + } + } catch (err) { + console.error('Error in test-utils.js/deleteAllUsers()') + } +} + +// This function is used to create new users. +// userObj = { +// username, +// password +// } +async function createUser (userObj) { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/users`, + data: { + user: { + email: userObj.email, + password: userObj.password, + name: userObj.name + } + } + } + + const result = await axios(options) + + const retObj = { + user: result.data.user, + token: result.data.token + } + + return retObj + } catch (err) { + console.log( + 'Error in utils.js/createUser(): ' + JSON.stringify(err, null, 2) + ) + throw err + } +} + +async function loginTestUser () { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/auth`, + data: { + email: 'test@test.com', + password: 'pass' + } + } + + const result = await axios(options) + + // console.log(`result: ${JSON.stringify(result.data, null, 2)}`) + + const retObj = { + token: result.data.token, + user: result.data.user.username, + id: result.data.user._id.toString() + } + + return retObj + } catch (err) { + console.log( + 'Error authenticating test user: ' + JSON.stringify(err, null, 2) + ) + throw err + } +} + +async function loginAdminUser () { + try { + const FILENAME = `${__dirname.toString()}../../config/system-user-${config.env}.json` + // console.log('FILENAME: ', FILENAME) + + const adminUserData = await jsonFiles.readJSON(FILENAME) + // console.log(`adminUserData: ${JSON.stringify(adminUserData, null, 2)}`) + + const options = { + method: 'POST', + url: `${LOCALHOST}/auth`, + data: { + email: adminUserData.email, + password: adminUserData.password, + name: 'admin' + } + } + + const result = await axios(options) + + // console.log(`result: ${JSON.stringify(result.data, null, 2)}`) + + const retObj = { + token: result.data.token, + user: result.data.user.username, + id: result.data.user._id.toString() + } + + return retObj + } catch (err) { + console.log( + 'Error authenticating test admin user: ' + JSON.stringify(err, null, 2) + ) + throw err + } +} + +// Retrieve the admin user JWT token from the JSON file it's saved at. +async function getAdminJWT () { + try { + // process.env.KOA_ENV = process.env.KOA_ENV || 'dev' + // console.log(`env: ${process.env.KOA_ENV}`) + + const FILENAME = `${__dirname.toString()}../../config/system-user-${config.env}.json` + // console.log('FILENAME: ', FILENAME) + const adminUserData = await jsonFiles.readJSON(FILENAME) + // console.log(`adminUserData: ${JSON.stringify(adminUserData, null, 2)}`) + + return adminUserData.token + } catch (err) { + console.error('Error in test/utils.js/getAdminJWT()') + throw err + } +} + +export default { + cleanDb, + createUser, + loginTestUser, + loginAdminUser, + getAdminJWT, + deleteAllUsers +} + +``` + +`/home/trout/work/psf/code/bch-dex/bin/server.js`: + +```js +/* + This Koa server has two interfaces: + - REST API over HTTP + - JSON RPC over IPFS + + The architecture of the code follows the Clean Architecture pattern: + https://troutsblog.com/blog/clean-architecture +*/ + +// npm libraries +import Koa from 'koa' + +import bodyParser from 'koa-bodyparser' +import convert from 'koa-convert' +import logger from 'koa-logger' +import mongoose from 'mongoose' +import session from 'koa-generic-session' +import passport from 'koa-passport' +import mount from 'koa-mount' +import serve from 'koa-static' +import cors from 'kcors' + +// Local libraries +import config from '../config/index.js' // this first. + +import AdminLib from '../src/adapters/admin.js' +import errorMiddleware from '../src/controllers/rest-api/middleware/error.js' +import { usageMiddleware } from '../src/use-cases/usage-use-cases.js' +// import wlogger from '../src/adapters/wlogger.js' +import Controllers from '../src/controllers/index.js' +import { applyPassportMods } from '../config/passport.js' + +class Server { + constructor () { + // Encapsulate dependencies + this.adminLib = new AdminLib() + this.controllers = new Controllers() + this.mongoose = mongoose + this.config = config + this.process = process + } + + async startServer () { + try { + // Create a Koa instance. + const app = new Koa() + app.keys = [this.config.session] + + if (!this.config.noMongo) { + // Connect to the Mongo Database. + this.mongoose.Promise = global.Promise + this.mongoose.set('useCreateIndex', true) // Stop deprecation warning. + console.log( + `Connecting to MongoDB with this connection string: ${this.config.database}` + ) + await this.mongoose.connect(this.config.database, { + useUnifiedTopology: true, + useNewUrlParser: true + }) + } + + console.log(`Starting environment: ${this.config.env}`) + console.log(`Debug level: ${this.config.debugLevel}\n`) + console.log(`Using this web3 CashStack service: ${this.config.consumerUrl}`) + console.log('Alternative web services listed here: https://gist.github.com/christroutner/63c5513782181f8b8ea3eb89f7cadeb6') + console.log('This app is built on top of the CashStack. Find out more: https://CashStack.info\n') + + // MIDDLEWARE START + + app.use(convert(logger())) + app.use(bodyParser()) + app.use(session()) + app.use(errorMiddleware()) + app.use(usageMiddleware()) + + // Used to generate the docs. + app.use(mount('/', serve(`${process.cwd()}/docs`))) + + // Mount the page for displaying logs. + app.use(mount('/logs', serve(`${process.cwd()}/config/logs`))) + + // User Authentication + // require('../config/passport') + applyPassportMods(passport) + app.use(passport.initialize()) + app.use(passport.session()) + + // Enable CORS for testing + // THIS IS A SECURITY RISK. COMMENT OUT FOR PRODUCTION + // Dev Note: This line must come BEFORE controllers.attachRESTControllers() + app.use(cors({ origin: '*' })) + + // Wait for any adapters to initialize. + await this.controllers.initAdapters() + + // Wait for any use-libraries to initialize. + await this.controllers.initUseCases() + + // Attach REST API and JSON RPC controllers to the app. + await this.controllers.attachRESTControllers(app) + + app.controllers = this.controllers + + // MIDDLEWARE END + + // 7/7/22 CT: This code paragraph can be deleted + // Delay startup to give the P2WDB time to start first, so that it accepts the webook call + // if (this.config.env !== 'test') { + // await this.sleep(20000) + // } + // Create webhook + // try { + // try { + // // Delete an old webhook if it exists. + // await webhookLib.deleteWebhook(config.webhookTarget) + // } catch (err) { + // /* exit quietly */ + // // console.log('err deleting webhook: ', err) + // } + // + // await webhookLib.createWebhook(config.webhookTarget) + // console.log('Webhook created') + // } catch (error) { + // console.log('Webhook cant be created') + // } + + // startServer() + this.server = await app.listen(config.port) + console.log(`Server started on ${config.port}`) + + if (!this.config.noMongo) { + // Create the system admin user. + const success = await this.adminLib.createSystemUser() + if (success) console.log('System admin user created.') + } + + // Attach the other IPFS controllers. + // Skip if this is a test environment. + if (this.config.env !== 'test') { + await this.controllers.attachControllers(app) + } + + // Display configuration settings + console.log('\nConfiguration:') + console.log(`Circuit Relay: ${this.config.isCircuitRelay}`) + console.log(`IPFS TCP port: ${this.config.ipfsTcpPort}`) + console.log(`IPFS WS port: ${this.config.ipfsWsPort}`) + console.log(`IPFS WebRTC port: ${this.config.ipfsWebRtcPort}`) + console.log(`Connection preference: ${this.config.connectPref}\n`) + + return app + } catch (err) { + console.error('Could not start server. Error: ', err) + + console.log( + 'Exiting after 5 seconds. Depending on process manager to restart.' + ) + await this.sleep(5000) + this.process.exit(1) + } + } + + sleep (ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) + } +} + +export default Server + +``` + +`/home/trout/work/psf/code/bch-dex/README.md`: + +```md +# bch-dex + +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) + +`bch-dex` is a decentralized exchange *protocol* for permissionless trading of [SLP tokens](https://github.com/simpleledger/slp-specifications/blob/master/slp-token-type-1.md) and [NFTs](https://github.com/simpleledger/slp-specifications/blob/master/slp-nft-1.md). Trading fees are incredibly small, compared to other DEX platforms. The software is based entirely on open protocols and open source software. `bch-dex` software is maintained by the [Permissionless Software Foundation](https://psfoundation.info). + +- [High-level Overview of bch-dex](https://youtu.be/LVX8CLi4sHw) (Video) + +This is a prototype web service that monitors one or more [Nostr relays](https://nostr.com) for trading signals, to trade BCH and SLP tokens. It's inspired by the [SWaP Protocol](https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md). + +This repository contains the back end code. The user interface is contained in the [bch-dex-ui-v3](https://github.com/Permissionless-Software-Foundation/bch-dex-ui-v3) repository. + +**Warning**: This repository is under active development. Things will be constantly changing and breaking. + +## Media +- [High-level Overview of bch-dex](https://youtu.be/LVX8CLi4sHw) (Video) +- [Developer walk-through for installing and hacking on bch-dex](https://youtu.be/T5XI43-SWJo) (Video) + - This video is out of date. Follow the instructions below. + +## Participate +This is an open source project, and we encourage other JavaScript developers to participate in its creation and maintenance. We have two chat rooms for the community: +- [Telegram Channel](https://t.me/bch_js_toolkit) + +## Installation +Running the DEX requires composition of these different software packages: +- bch-dex - This repository is the back end software that tracks trade data on the network, generates [Offers and Counter Offers](https://github.com/Permissionless-Software-Foundation/bch-dex/tree/ct-unstable/dev-docs#definitions), and finalizes trades by accepting Counter Offers. +- [bch-dex-ui-v3](https://github.com/Permissionless-Software-Foundation/bch-dex-ui-v3) web app and user interface (UI) for bch-dex focused on Sellers of tokens. +- [MongoDB](https://www.mongodb.com/) is a database used by bch-dex to store and manage local data, user accounts, etc. + +The above software is orchestrated using [Docker](https://www.docker.com/) and Docker Compose. The target operating system is Ubuntu 20+, and the target hardware is amd64 (normal desktop PCs). Trying to operate this software on other operating systems or hardware is possible, but not supported. + +Setup instructions: + +1. Follow the direction in [this Gist](https://gist.github.com/christroutner/a39f656850dc022b60f25c9663dd1cdd) to install Node.js, Docker, and Docker Compose. +1. Clone the repository with `git clone https://github.com/Permissionless-Software-Foundation/bch-dex` and enter it with `cd bch-dex`. +1. Install dependencies by running `npm install` +1. Create a wallet: + - `cd production/scripts` + - `node create-wallet.js` +1. Change directory to the `production/docker` folder. +1. Pull the Docker images down from Docker Hub: `docker-compose pull` +1. Build the core software: `docker-compose build --no-cache` +1. Start the Docker containers with `docker-compose up -d` +1. Open a web browser and navigate the `http://localhost:4500`. You'll be able to see new Offers as they come in and are detected by bch-dex. +1. To take the other side of the trade, click the `Take` button in the UI. +1. You can add the 12-word mnemonic from the `wallet.json` file to the the web wallet, which will mirror your wallet in the UI, and allow you to perform basic wallet functions (send and receive BCH and tokens). + +## Blockchain Infrastructure + +bch-dex requires a [Cash Stack](https://cashstack.info) back end in order to connect to the blockchain. By default, the Docker containers connect to [free-bch.fullstack.cash](https://free-bch.fullstack.cash/). Several community-provided servers are provided and can be [viewed here](https://consumers.psfoundation.info/consumers.json). The back end can be changed by setting the `CONSUMER_URL` environment variable in the `docker-compose.yml` file. + +## License + +[MIT](./LICENSE.md) + +``` + +`/home/trout/work/psf/code/bch-dex/shell-scripts/ipfs-service-provider-generic.sh`: + +```sh +#!/bin/bash + +# This script is an example for running a generic ipfs-service-provider instance. + +# Ports +export PORT=5001 # REST API port +export IPFS_TCP_PORT=5268 +export IPFS_WS_PORT=5269 + +# The human-readible name that is used when displaying data about this node. +export COORD_NAME=ipfs-service-provider-generic + +# This is used for end-to-end encryption (e2ee). +export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran" + +# 0 = less verbose. 3 = most verbose +export DEBUG_LEVEL=1 + +# MongoDB connection string. +#export DBURL=mongodb://localhost:27017/bch-service-dev + +npm start + +``` + +`/home/trout/work/psf/code/bch-dex/shell-scripts/ipfs-service-provider-relay.sh`: + +```sh +#!/bin/bash + +# This script is an example for running a ipfs-service-provider as a Circuit Relay. +# Circuit Relays are help other nodes on the network communicate. They are +# critical for reliable functioning of the network, and for circumventing +# censorship. + +# Ports +export PORT=5001 # REST API port +export IPFS_TCP_PORT=5268 +export IPFS_WS_PORT=5269 + +# The human-readible name that is used when displaying data about this node. +export COORD_NAME=ipfs-service-provider-generic + +# This is used for end-to-end encryption (e2ee). +export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran" + +# 0 = less verbose. 3 = most verbose +export DEBUG_LEVEL=1 + +# MongoDB connection string. +#export DBURL=mongodb://localhost:27017/bch-service-dev + +# Comment to disable circuit relay functionality. Or set to 1 to enable. +export ENABLE_CIRCUIT_RELAY=1 +# For browsers to use your circuit realy, you must set up a domain, SSL certificate, +# and you must forward that subdomain to the IPFS_WS_PORT. +#export CR_DOMAIN=subdomain.yourdomain.com + +npm start + +``` + +`/home/trout/work/psf/code/bch-dex/shell-scripts/local-external-ipfs-node.sh`: + +```sh +#!/bin/bash + +# This script is an example for running a production environment, which is +# defined by running an external go-ipfs node. + +# Ports +export PORT=5010 # REST API port + +# The human-readible name that is used when displaying data about this node. +export COORD_NAME=ipfs-service-provider-generic + +# This is used for end-to-end encryption (e2ee). +export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran" + +# 0 = less verbose. 3 = most verbose +export DEBUG_LEVEL=0 + +# Production settings that use external IPFS node. +# https://github.com/christroutner/docker-ipfs +export SVC_ENV=production +export IPFS_HOST=localhost +export IPFS_API_PORT=5001 + +# Configure IPFS ports +export IPFS_TCP_PORT=4001 +#export IPFS_WS_PORT=5269 + +# MongoDB connection string. +export DBURL=mongodb://localhost:27017/ipfs-service-dev + +npm start + +``` + +`/home/trout/work/psf/code/bch-dex/production/rpi-docker/cleanup-images.sh`: + +```sh +#!/bin/bash + +# Remove all untagged docker images. +docker rmi $(docker images | grep "^" | awk '{print $3}') + + +``` + +`/home/trout/work/psf/code/bch-dex/production/rpi-docker/bch-dex-ui/Dockerfile`: + +``` +# Create a Dockerized API server +# + +#IMAGE BUILD COMMANDS +# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS +#FROM christroutner/ct-base-ubuntu +FROM ubuntu:20.04 as builder +MAINTAINER Chris Troutner + +#Update the OS and install any OS packages needed. +RUN apt-get update +RUN apt-get install -y sudo git curl nano gnupg wget + +#Install Node and NPM +RUN curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh +RUN bash nodesource_setup.sh +RUN apt-get install -y nodejs build-essential + +#Create the user 'safeuser' and add them to the sudo group. +#RUN useradd -ms /bin/bash safeuser +#RUN adduser safeuser sudo + +#Set password to 'password' change value below if you want a different password +#RUN echo safeuser:password | chpasswd + +#Set the working directory to be the home directory +WORKDIR /home/safeuser + +#Setup NPM for non-root global install +#RUN mkdir /home/safeuser/.npm-global +#RUN chown -R safeuser .npm-global +#RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/safeuser/.profile +#RUN runuser -l safeuser -c "npm config set prefix '~/.npm-global'" + +# Update to the latest version of npm. +#RUN npm install -g npm@7.23.0 +RUN npm install -g npm + +# npm mirror to prevent direct dependency on npm. +RUN npm set registry http://94.130.170.209:4873/ + +# Switch to user account. +#USER safeuser +# Prep 'sudo' commands. +#RUN echo 'abcd8765' | sudo -S pwd + +# Clone the rest.bitcoin.com repository +WORKDIR /home/safeuser +RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui-v2 + +# Switch to the desired branch. `master` is usually stable, +# and `stage` has the most up-to-date changes. +WORKDIR /home/safeuser/bch-dex-ui-v2 + +# For development: switch to unstable branch +RUN git checkout ct-unstable + +# Install dependencies +#RUN mkdir .ipfsdata +#RUN npm install -g @mapbox/node-pre-gyp +RUN npm install + +# Build the site +RUN CI=true npm run build + +# Load the NGINX image. +FROM nginx +EXPOSE 80 + +# Copy the files built in the first container to the new NGINX container. +COPY --from=builder /home/safeuser/bch-dex-ui-v2/build /usr/share/nginx/html + +#USER safeuser + +``` + +`/home/trout/work/psf/code/bch-dex/production/rpi-docker/bch-dex/start-production.sh`: + +```sh +#!/bin/bash + +# BEGIN: Optional configuration settings + +# The human readable name this IPFS node identifies as. +export COORD_NAME=bch-dex-generic + +# Allow this node to function as a circuit relay. It must not be behind a firewall. +#export ENABLE_CIRCUIT_RELAY=true +# For browsers to use your circuit realy, you must set up a domain, SSL certificate, +# and you must forward that subdomain to the IPFS_WS_PORT. +#export CR_DOMAIN=subdomain.yourdomain.com + +# Debug level. 0 = minimal info. 2 = max info. +export DEBUG_LEVEL=1 + +# END: Optional configuration settings + + +# Production database connection string. +export DBURL=mongodb://172.17.0.1:5666/bch-swap-service-prod + +# Configure REST API port +export PORT=5700 + +# bch-dex specific env vars +export BCH_DEX=prod +export WEBHOOKSERVICE=http://172.17.0.1:5667/webhook +export WEBHOOKTARGET=http://172.17.0.1:5700/p2wdb +export APP_ID=bch-dex-001 + +npm start + +``` + +`/home/trout/work/psf/code/bch-dex/production/rpi-docker/bch-dex/Dockerfile`: + +``` +# Create a Dockerized API server +# + +#IMAGE BUILD COMMANDS +# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS +#FROM christroutner/ct-base-ubuntu +FROM ubuntu:20.04 +MAINTAINER Chris Troutner + +#Update the OS and install any OS packages needed. +RUN apt-get update +RUN apt-get install -y sudo git curl nano gnupg wget + +#Install Node and NPM +RUN sudo apt-get install -y ca-certificates curl gnupg +RUN sudo mkdir -p /etc/apt/keyrings +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list +RUN sudo apt-get update +RUN sudo apt-get install -y nodejs build-essential + +#Create the user 'safeuser' and add them to the sudo group. +#RUN useradd -ms /bin/bash safeuser +#RUN adduser safeuser sudo + +#Set password to 'password' change value below if you want a different password +#RUN echo safeuser:password | chpasswd + +#Set the working directory to be the home directory +WORKDIR /home/safeuser + +#Setup NPM for non-root global install +#RUN mkdir /home/safeuser/.npm-global +#RUN chown -R safeuser .npm-global +#RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/safeuser/.profile +#RUN runuser -l safeuser -c "npm config set prefix '~/.npm-global'" + +# Update to the latest version of npm. +#RUN npm install -g npm@7.23.0 +#RUN npm install -g npm + +# npm mirror to prevent direct dependency on npm. +RUN npm set registry http://94.130.170.209:4873/ + +# Switch to user account. +#USER safeuser +# Prep 'sudo' commands. +#RUN echo 'abcd8765' | sudo -S pwd + +# Clone the rest.bitcoin.com repository +WORKDIR /home/safeuser +RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex + +# Switch to the desired branch. `master` is usually stable, +# and `stage` has the most up-to-date changes. +WORKDIR /home/safeuser/bch-dex + +# For development: switch to unstable branch +RUN git checkout master + +# Install dependencies +#RUN mkdir .ipfsdata +#RUN npm install -g @mapbox/node-pre-gyp +RUN npm install + +# Generate the API docs +RUN npm run docs + +# Start the application. +#COPY start-production.sh start-production.sh +CMD ["./start-production.sh"] + +#CMD ["npm", "start"] + +``` + +`/home/trout/work/psf/code/bch-dex/production/rpi-docker/docker-compose.yml`: + +```yml +# Start the service with the command 'docker-compose up -d' + +version: '3.9' + +services: + mongo-bch-dex: + image: mongo:4.2.0 + container_name: mongo-bch-dex + ports: + - '5666:27017' # : + volumes: + - ../data/database:/data/db + command: mongod --logpath=/dev/null # -- quiet + restart: always + + ipfs: + image: christroutner/trickle-ipfs-rpi:v1.0.1 + #image: odanado/go-ipfs:v0.11.0 + container_name: ipfs + environment: + IPFS_DAEMON_ARGUMENTS: '--enable-pubsub-experiment --migrate=true --agent-version-suffix=docker --routing=dhtclient' + UPLOAD_KBPS: '25' + DOWNLOAD_KBPS: '25' + logging: + driver: 'json-file' + options: + max-size: '10m' + max-file: '10' + mem_limit: 1000mb + ports: + - 4001:4001 + - 4003:4003 + - 172.17.0.1:5001:5001 + - 172.17.0.1:8080:8080 + volumes: + - ./data/go-ipfs:/root/.ipfs + command: [ + './start-ipfs.sh' + ] + restart: always + + p2wdb: + #build: + # context: ./p2wdb/ + # dockerfile: Dockerfile + image: christroutner/p2wdb-rpi:v3.1.9 + container_name: p2wdb + environment: + CONSUMER_URL: 'https://wa-usa-bch-consumer.fullstackcash.nl' + DEBUG_LEVEL: 1 + logging: + driver: 'json-file' + options: + max-size: '10m' + max-file: '10' + mem_limit: 1gb + links: + - mongo-bch-dex + ports: + # : + - 5667:5667 # REST API + #- 5668:5668 # IPFS TCP port + #- 5669:5669 # IPFS WS Port + volumes: + - ../data/ipfsdata/p2wdb:/home/safeuser/ipfs-p2wdb-service/.ipfsdata/p2wdb + - ./p2wdb/start-production.sh:/home/safeuser/ipfs-p2wdb-service/start-production.sh + restart: always + + bch-dex: + #build: + # context: ./bch-dex/ + # dockerfile: Dockerfile + image: christroutner/bch-dex-rpi:v2.0.8 + container_name: bch-dex + environment: + #CONSUMER_URL: 'https://free-bch.fullstack.cash' + CONSUMER_URL: 'https://wa-usa-bch-consumer.fullstackcash.nl' + logging: + driver: 'json-file' + options: + max-size: '10m' + max-file: '10' + mem_limit: 1000mb + links: + - mongo-bch-dex + - p2wdb + ports: + - '5700:5700' # : + volumes: + - ../scripts/wallet.json:/home/safeuser/bch-dex/wallet.json + - ./bch-dex/start-production.sh:/home/safeuser/bch-dex/start-production.sh + restart: always + + dex-ui: + #build: + # context: ./bch-dex-ui/ + # dockerfile: Dockerfile + image: christroutner/bch-dex-ui-rpi:v1.2.4 + container_name: dex-ui + logging: + driver: 'json-file' + options: + max-size: '10m' + max-file: '10' + mem_limit: 500mb + links: + - bch-dex + ports: + - '4500:80' # : + # volumes: + # - ../data/ipfsdata:/home/safeuser/ipfs-service-provider/.ipfsdata + restart: always + +``` + +`/home/trout/work/psf/code/bch-dex/production/rpi-docker/p2wdb/start-production.sh`: + +```sh +#!/bin/bash + +# BEGIN: Optional configuration settings + +# This mnemonic is used to set up persistent public key for e2ee +# Replace this with your own 12-word mnemonic. +export MNEMONIC="mass response fiscal world message exact series swallow forward confirm canoe festival" + +# The human readable name this IPFS node identifies as. +export COORD_NAME=generic-p2wdb-production + +# Allow this node to function as a circuit relay. It must not be behind a firewall. +#export ENABLE_CIRCUIT_RELAY=true +# For browsers to use your circuit realy, you must set up a domain, SSL certificate, +# and you must forward that subdomain to the IPFS_WS_PORT. +#export CR_DOMAIN=subdomain.yourdomain.com + +# Debug level. 0 = minimal info. 2 = max info. +# This value set by docker-compose.yml +#export DEBUG_LEVEL=1 + +# Log-in information for retrieving a JWT token from FullStack.cash. +export FULLSTACKLOGIN=demo@demo.com +export FULLSTACKPASS=demo + +# END: Optional configuration settings + + +# Production database connection string. +export DBURL=mongodb://172.17.0.1:5666/p2wdb-service-dev + +# Configure IPFS ports +export IPFS_TCP_PORT=5668 +export IPFS_WS_PORT=5669 + +# Configure REST API port +export PORT=5667 + +export P2W_ENV=production +export IPFS_HOST=172.17.0.1 +export IPFS_API_PORT=5001 +export IPFS_TCP_PORT=4001 +export IPFS_WS_PORT=4003 +export IPFS_WEB_RTC_PORT=4005 +# Set the debug level for helia-coord. 0-3. +# 0 = no debug logs. 3 = maximum debug logs. +export DEBUG_LEVEL=0 + +# Use this if the IPFS node has a publically accessible IP address. +#export CONNECT_PREF=direct +# Use this if the IPFS node is behind a NAT or Firewall and cannot be accessed directly. +export CONNECT_PREF=cr + +npm start + +``` + +`/home/trout/work/psf/code/bch-dex/production/rpi-docker/p2wdb/dummyapp.js`: + +```js +setInterval(function () { + const now = new Date() + console.log(`ping ${now.toLocaleString()}`) +}, 10000) + +``` + +`/home/trout/work/psf/code/bch-dex/production/rpi-docker/p2wdb/Dockerfile`: + +``` +# Create a Docker container for the P2WDB +# + +#IMAGE BUILD COMMANDS +FROM ubuntu:20.04 +MAINTAINER Chris Troutner + +#Update the OS and install any OS packages needed. +RUN apt-get update +RUN apt-get install -y sudo git curl nano gnupg wget + +#Install Node and NPM +RUN curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh +RUN bash nodesource_setup.sh +RUN apt-get install -y nodejs build-essential + +#Create the user 'safeuser' and add them to the sudo group. +RUN useradd -ms /bin/bash safeuser +RUN adduser safeuser sudo + +#Set password to 'abcd8765' change value below if you want a different password +RUN echo safeuser:abcd8765 | chpasswd + +#Set the working directory to be the users home directory +WORKDIR /home/safeuser + +#Setup NPM for non-root global install (like on a mac) +RUN mkdir /home/safeuser/.npm-global +RUN chown -R safeuser .npm-global +RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/safeuser/.profile +RUN runuser -l safeuser -c "npm config set prefix '~/.npm-global'" + +# Update to the latest version of npm. +#RUN npm install -g npm@7.23.0 +RUN npm install -g npm + +# npm mirror to prevent direct dependency on npm. +RUN npm set registry http://94.130.170.209:4873/ + +# Switch to user account. +#USER safeuser +# Prep 'sudo' commands. +#RUN echo 'abcd8765' | sudo -S pwd + +# Clone the rest.bitcoin.com repository +RUN git clone https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service +WORKDIR /home/safeuser/ipfs-p2wdb-service +RUN mkdir .ipfsdata +RUN git checkout ct-unstable + +#RUN npm install fsevents + +# Install dependencies +#RUN mkdir .ipfsdata +RUN npm install + +# Generate the API docs +RUN npm run docs + +# Expose the port the API will be served on. +#EXPOSE 5010 + +# Start the application. +#COPY start-production.sh start-production.sh +CMD ["./start-production.sh"] + +#CMD ["npm", "start"] + +# Used for debugging +#COPY dummyapp.js dummyapp.js +#CMD ["node", "dummyapp.js"] + +``` + +`/home/trout/work/psf/code/bch-dex/production/scripts/fullstack-sweep-wallet.js`: + +```js +/* + This script is the same as sweep-wallet.js, but it requires a FullStack.cash + account, which makes the scanning much faster. +*/ + +// Public npm libraries +// const BCHJS = require('@psf/bch-js') +import BchTokenSweep from 'bch-token-sweep/index.js' + +// Local libraries +import WalletAdapter from '../../src/adapters/wallet.js' + +// Constants +// const EMTPY_ADDR_CUTOFF = 10 +const START_INDEX = 1 +const LAST_ADDR_INDEX = 100 + +if (!process.env.BCHJSTOKEN) { + console.log('You will need a JWT token from FullStack.cash to execute this script. Export it to the BCHJSTOKEN environment variable and try again.') + process.exit(0) +} + +async function sweepFunds () { + try { + // Configure the wallet library to use a FullStack.cash or a local Cash Stack + const walletLib = new WalletAdapter() + walletLib.config.useFullStackCash = true + // walletLib.config.apiServer = 'http://192.168.2.129:3000/v5/' + walletLib.config.apiServer = 'https://api.fullstack.cash/v5/' + + // Open the wallet files. + const walletInfo = await openWallet(walletLib) + const wallet = await walletLib.instanceWallet(walletInfo) + console.log('walletInfo: ', walletInfo) + + const rootAddr = walletInfo.cashAddress + const rootWif = walletInfo.privateKey + console.log(`Sweeping all funds into root address ${rootAddr}...`) + + // Generate an HD tree + const bchjs = wallet.bchjs + const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic) + const masterHDNode = bchjs.HDNode.fromSeed(rootSeed) + + let emptyAddrCnt = 0 + let hdIndex = START_INDEX + + do { + // Generate a keypair from the HD wallet. + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + const cashAddress = bchjs.HDNode.toCashAddress(childNode) + const wifToSweep = bchjs.HDNode.toWIF(childNode) + + console.log(`\nSweeping ${cashAddress} with private key ${wifToSweep}`) + + try { + // Sweep tokens from address + const sweeper = new BchTokenSweep( + wifToSweep, + rootWif, + wallet, + 550, + rootAddr + ) + await sweeper.populateObjectFromNetwork() + + const hex = await sweeper.sweepTo(rootAddr) + // console.log(`hex: ${hex}`) + + const txid = await sweeper.blockchain.broadcast(hex) + + // console.log('Transaction ID', txid) + console.log(`Swept HD index ${hdIndex}. TXID: ${txid}`) + + emptyAddrCnt = 0 + + // Wait between loop iterations. + await bchjs.Util.sleep(3000) + } catch (err) { + console.log(`error message with index ${hdIndex}: ${err.message}`) + // console.log(err) + emptyAddrCnt++ + } + + hdIndex++ + // } while (emptyAddrCnt < EMTPY_ADDR_CUTOFF) + // console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`) + } while (hdIndex < LAST_ADDR_INDEX) + console.log(`Last index of ${LAST_ADDR_INDEX} reached. emptyAddrCnt: ${emptyAddrCnt}`) + + console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n') + } catch (err) { + console.error('Error in sweepFunds(): ', err) + } +} +sweepFunds() + +// Open the wallet file, or create one if the file doesn't exist. +// Does not instance the wallet. The output of this function is expected to +// be passed to instanceWallet(). +async function openWallet (walletLib) { + try { + // console.log('this.WALLET_FILE: ', this.WALLET_FILE) + const walletData = await walletLib.jsonFiles.readJSON('./wallet.json') + + return walletData + } catch (err) { + console.error('Error in openWallet()') + throw err + } +} + +``` + +`/home/trout/work/psf/code/bch-dex/production/scripts/bulk-sweep-wallet.js`: + +```js +/* + This script is similar ot sweep-wallet.js, but it can do a much faster (bulk) + scanning of addresses. However, this requires a subscription to a FullStack.cash + or access to a web2 Cash Stack. + + This script will scan 20 addresses at a time. If a balance is found in any + of the addresses, it will sweep the funds from that address. +*/ +/* +// Public npm libraries +import BchTokenSweep from 'bch-token-sweep/index.js' + +// Local libraries +import WalletAdapter from '../../src/adapters/wallet.js' +import BCHJS from '@psf/bch-js' +import JwtLib from 'jwt-bch-lib' + +// Constants +// const EMTPY_ADDR_CUTOFF = 100 +const LAST_ADDR_INDEX = 100 + +if (!process.env.BCHJSTOKEN) { + console.log('You will need a JWT token from FullStack.cash to execute this script. Export it to the BCHJSTOKEN environment variable and try again.') + exit(0) +} + +async function sweepFunds () { + try { + // Configure the wallet library to use a FullStack.cash or a local Cash Stack + const walletLib = new WalletAdapter() + walletLib.config.useFullStackCash = true + walletLib.config.apiServer = 'http://192.168.2.129:3000/v5/' + + // const walletInfo = await walletLib.openWallet() + const walletInfo = await openWallet(walletLib) + const wallet = await walletLib.instanceWallet(walletInfo) + console.log('walletInfo: ', walletInfo) + + const rootAddr = walletInfo.cashAddress + const rootWif = walletInfo.privateKey + console.log(`Sweeping all funds into root address ${rootAddr}...`) + + // Instantiate bch-js, and use the JWT token saved to environment variable. + + // Generate an HD tree + // const bchjs = wallet.bchjs + const bchjs = new BCHJS() + const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic) + const masterHDNode = bchjs.HDNode.fromSeed(rootSeed) + + const emptyAddrCnt = 0 + const hdIndex = 1 + + // Divide all the addresses by 20, since that's how many will be checked at once. + const numOfLoops = Math.ceil(LAST_ADDR_INDEX / 20) + + for (let i = 1; i < numOfLoops; i++) { + const startIndex = i + const stopIndex = i * 20 + console.log(`startIndex: ${startIndex}, stopIndex: ${stopIndex}`) + + // Generate the next block of 20 key pairs to scan. + const addrsToScan = [] + const wifsToScan = [] + for (let j = startIndex; j < stopIndex; j++) { + // Generate a keypair from the HD wallet. + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${j}`) + const cashAddress = bchjs.HDNode.toCashAddress(childNode) + const wifToSweep = bchjs.HDNode.toWIF(childNode) + + addrsToScan.push(cashAddress) + wifsToScan.push(wifToSweep) + } + console.log(`Scanning these addresses for a balance: ${JSON.stringify(addrsToScan, null, 2)}`) + + // Scan a block of 20 addresses for a balance. + const balances = await bchjs.Electrumx.balance(addrsToScan) + console.log(`balances: ${JSON.stringify(balances, null, 2)}`) + + // Scan through the results and look for a balance. + for (let j = 0; j < balances.balances.length; j++) { + const thisBalance = balances.balances[j] + + // const combinedBal = thisBalance.balance.confirmed + thisBalance.balance. + + // if(thisBalance.) + } + } + + // do { + // // Generate a keypair from the HD wallet. + // const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + // const cashAddress = bchjs.HDNode.toCashAddress(childNode) + // const wifToSweep = bchjs.HDNode.toWIF(childNode) + // + // console.log(`\nSweeping ${cashAddress} with private key ${wifToSweep}`) + // + // try { + // // Sweep tokens from address + // const sweeper = new BchTokenSweep( + // wifToSweep, + // rootWif, + // wallet, + // 550, + // rootAddr + // ) + // await sweeper.populateObjectFromNetwork() + // + // const hex = await sweeper.sweepTo(rootAddr) + // // console.log(`hex: ${hex}`) + // + // const txid = await sweeper.blockchain.broadcast(hex) + // + // // console.log('Transaction ID', txid) + // console.log(`Swept HD index ${hdIndex}. TXID: ${txid}`) + // + // emptyAddrCnt = 0 + // + // // Wait between loop iterations. + // await bchjs.Util.sleep(3000) + // } catch (err) { + // console.log(`error message with index ${hdIndex}: ${err.message}`) + // // console.log(err) + // emptyAddrCnt++ + // } + // + // hdIndex++ + // } while (emptyAddrCnt < EMTPY_ADDR_CUTOFF) + // + // console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`) + // + // console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n') + } catch (err) { + console.error('Error in sweepFunds(): ', err) + } +} +sweepFunds() + +// Open the wallet file, or create one if the file doesn't exist. +// Does not instance the wallet. The output of this function is expected to +// be passed to instanceWallet(). +async function openWallet (walletLib) { + try { + // console.log('this.WALLET_FILE: ', this.WALLET_FILE) + const walletData = await walletLib.jsonFiles.readJSON('./wallet.json') + + return walletData + } catch (err) { + console.error('Error in openWallet()') + throw err + } +} +*/ + +``` + +`/home/trout/work/psf/code/bch-dex/production/scripts/sweep-wallet.js`: + +```js +/* + This script will travers the HD wallet and sweep funds and tokens back + into the root address (index 0). That root address needs to have funds + to pay for the transactions. +*/ + +// Public npm libraries +// const BCHJS = require('@psf/bch-js') +import BchTokenSweep from 'bch-token-sweep/index.js' + +// Local libraries +import WalletAdapter from '../../src/adapters/wallet.js' + +// Constants +const EMTPY_ADDR_CUTOFF = 10 + +async function sweepFunds () { + try { + // Open the wallet files. + const walletLib = new WalletAdapter() + // const walletInfo = await walletLib.openWallet() + const walletInfo = await openWallet(walletLib) + const wallet = await walletLib.instanceWallet(walletInfo) + console.log('walletInfo: ', walletInfo) + + const rootAddr = walletInfo.cashAddress + const rootWif = walletInfo.privateKey + console.log(`Sweeping all funds into root address ${rootAddr}...`) + + // Generate an HD tree + const bchjs = wallet.bchjs + const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic) + const masterHDNode = bchjs.HDNode.fromSeed(rootSeed) + + let emptyAddrCnt = 0 + let hdIndex = 1 + + do { + // Generate a keypair from the HD wallet. + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + const cashAddress = bchjs.HDNode.toCashAddress(childNode) + const wifToSweep = bchjs.HDNode.toWIF(childNode) + + console.log(`\nSweeping ${cashAddress} with private key ${wifToSweep}`) + + try { + // Sweep tokens from address + const sweeper = new BchTokenSweep( + wifToSweep, + rootWif, + wallet, + 550, + rootAddr + ) + await sweeper.populateObjectFromNetwork() + + const hex = await sweeper.sweepTo(rootAddr) + // console.log(`hex: ${hex}`) + + const txid = await sweeper.blockchain.broadcast(hex) + + // console.log('Transaction ID', txid) + console.log(`Swept HD index ${hdIndex}. TXID: ${txid}`) + + emptyAddrCnt = 0 + + // Wait between loop iterations. + await bchjs.Util.sleep(3000) + } catch (err) { + console.log(`error message with index ${hdIndex}: ${err.message}`) + // console.log(err) + emptyAddrCnt++ + } + + hdIndex++ + } while (emptyAddrCnt < EMTPY_ADDR_CUTOFF) + + console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`) + + console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n') + } catch (err) { + console.error('Error in sweepFunds(): ', err) + } +} +sweepFunds() + +// Open the wallet file, or create one if the file doesn't exist. +// Does not instance the wallet. The output of this function is expected to +// be passed to instanceWallet(). +async function openWallet (walletLib) { + try { + // console.log('this.WALLET_FILE: ', this.WALLET_FILE) + const walletData = await walletLib.jsonFiles.readJSON('./wallet.json') + + return walletData + } catch (err) { + console.error('Error in openWallet()') + throw err + } +} + +``` + +`/home/trout/work/psf/code/bch-dex/production/scripts/sweep-nfts.js`: + +```js +/* + This script will sweep the HD wallet, looking for NFTs. When found, it will + send the NFT to the root (index 0) address. It will pay transaction fees from + the root address. +*/ + +// Global npm libraries +import BchWallet from 'minimal-slp-wallet' + +// Local libraries +import WalletAdapter from '../../src/adapters/wallet.js' + +// Constants +const EMTPY_ADDR_CUTOFF = 10 +const WEB3_SERVER = 'https://free-bch.fullstack.cash' + +async function sweepNfts () { + try { + // Open the wallet files. + const walletLib = new WalletAdapter() + // const walletInfo = await walletLib.openWallet() + const walletInfo = await openWallet(walletLib) + // const walletRoot = await walletLib.instanceWallet(walletInfo) + const walletRoot = new BchWallet(walletInfo.mnemonic, { + interface: 'consumer-api', + restURL: WEB3_SERVER + }) + await walletRoot.walletInfoPromise + console.log('walletInfo: ', walletInfo) + + const rootAddr = walletInfo.cashAddress + // const rootWif = walletInfo.privateKey + console.log(`Sweeping all funds into root address ${rootAddr}...`) + + // Generate an HD tree + const bchjs = walletRoot.bchjs + const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic) + const masterHDNode = bchjs.HDNode.fromSeed(rootSeed) + + let emptyAddrCnt = 0 + let hdIndex = 1 + + do { + // Generate a keypair from the HD wallet. + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + const cashAddress = bchjs.HDNode.toCashAddress(childNode) + const wifToSweep = bchjs.HDNode.toWIF(childNode) + + console.log(`\n${hdIndex}: Sweeping ${cashAddress} with private key ${wifToSweep}`) + + const walletChild = new BchWallet(wifToSweep, { interface: 'consumer-api', restURL: WEB3_SERVER }) + await walletChild.walletInfoPromise + + try { + const tokens = await walletChild.tokens.listTokensFromAddress(cashAddress) + // console.log(`tokens: ${JSON.stringify(tokens, null, 2)}`) + + await walletChild.utxos.initUtxoStore(cashAddress) + // console.log(`utxoStore: ${JSON.stringify(utxoStore, null, 2)}`) + + for (let i = 0; i < tokens.length; i++) { + const thisToken = tokens[i] + + if (thisToken.tokenType === 65) { + console.log(`NFT ${thisToken.ticker} (${thisToken.name}) found. Sweeping to ${rootAddr}`) + + await walletRoot.initialize() + + // Send BCH to the child address, to pay for transaction fees. + const receiver1 = [{ + address: cashAddress, + amountSat: 10000 + }] + const txid1 = await walletRoot.send(receiver1) + console.log(`10,000 sats sent to child address. TXID: ${txid1}`) + + // Wait for indexers to update. + console.log('Waiting for indexers to update...') + await bchjs.Util.sleep(120000) + + await walletChild.initialize() + + // Send NFT to root address. + const receiver2 = [{ + address: rootAddr, + tokenId: thisToken.tokenId, + qty: thisToken.qty + }] + const txid2 = await walletChild.sendTokens(receiver2) + console.log(`NFT sent from child address to root address. TXID: ${txid2}`) + + // Wait for indexers to update. + console.log('Waiting for indexers to update...') + await bchjs.Util.sleep(3000) + + // Refresh the UTXO store. + await walletChild.utxos.initUtxoStore(cashAddress) + + // Send the rest of the BCH back to the root address. + const txid3 = await walletChild.sendAll(rootAddr) + console.log(`Leftover BCH in child address sent to root address. TXID: ${txid3}`) + + emptyAddrCnt = 0 + } + } + + // Wait between loop iterations. + await bchjs.Util.sleep(3000) + + // emptyAddrCnt++ + } catch (err) { + console.log(`error message with index ${hdIndex}: ${err.message}`) + console.log(err) + // emptyAddrCnt++ + } + + emptyAddrCnt++ + hdIndex++ + } while (emptyAddrCnt < EMTPY_ADDR_CUTOFF) + + console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`) + + console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n') + } catch (err) { + console.log('Error while sweeping NFTs: ', err) + } +} +sweepNfts() + +// Open the wallet file, or create one if the file doesn't exist. +// Does not instance the wallet. The output of this function is expected to +// be passed to instanceWallet(). +async function openWallet (walletLib) { + try { + // console.log('this.WALLET_FILE: ', this.WALLET_FILE) + const walletData = await walletLib.jsonFiles.readJSON('./wallet.json') + + return walletData + } catch (err) { + console.error('Error in openWallet()') + throw err + } +} + +``` + +`/home/trout/work/psf/code/bch-dex/production/scripts/create-wallet.js`: + +```js +/* + Generate a wallet.json file for use with the DEX. +*/ + +// Public NPM libraries +import BchWallet from 'minimal-slp-wallet' + +import { promises as fs } from 'fs' + +async function createWallet () { + try { + // Configure the minimal-slp-wallet library to use the JSON RPC over IPFS. + const advancedConfig = { + interface: 'consumer-api', + noUpdate: true + } + + // Wait for the wallet to be created. + const bchWallet = new BchWallet(undefined, advancedConfig) + await bchWallet.walletInfoPromise + const walletData = bchWallet.walletInfo + walletData.nextAddress = 1 + + // Save the wallet file to disk. + await fs.writeFile('wallet.json', JSON.stringify(walletData, null, 2)) + + console.log('Generated wallet.json. Copy this file to the docker/bch-dex folder to be used inside the Docker container.') + console.log(`${JSON.stringify(walletData, null, 2)}`) + } catch (err) { + console.error('Error: ', err) + } +} +createWallet() + +``` + +`/home/trout/work/psf/code/bch-dex/production/scripts/create-order.js`: + +```js +/* + This script can be used to generate new Orders and Offers, until the UI for + that is built. + + Customize the settings below to add your own Order. The token must exist in + the DEX app wallet in order to be acceped. +*/ + +import axios from 'axios' + +const LOCALHOST = 'http://localhost:5700' +// const LOCALHOST = 'http://172.17.0.1:5700' + +async function start () { + try { + const mockOrder = { + lokadId: 'SWP', + messageType: 1, + messageClass: 1, + tokenId: + 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', + buyOrSell: 'sell', + rateInBaseUnit: 5000, + minUnitsToExchange: 5000, + numTokens: 2 + } + + const options = { + method: 'post', + url: `${LOCALHOST}/order`, + data: { order: mockOrder } + } + + const result = await axios(options) + console.log('result.data: ', result.data) + } catch (err) { + console.log(err) + } +} +start() + +``` + +`/home/trout/work/psf/code/bch-dex/production/scripts/list-addrs.js`: + +```js +/* + This script is the same as sweep-wallet.js, but instead of sweeping the keys, + it simply lists out the addresses in the HD keychain. This is hany when trying + to figure out which address a token was sent to. +*/ + +// Public npm libraries + +// Local libraries +import WalletAdapter from '../../src/adapters/wallet.js' + +// Constants +const START_INDEX = 1 +const LAST_ADDR_INDEX = 100 + +async function listAddrs () { + try { + // Configure the wallet library to use a FullStack.cash or a local Cash Stack + const walletLib = new WalletAdapter() + + // Open the wallet files. + const walletInfo = await openWallet(walletLib) + const wallet = await walletLib.instanceWallet(walletInfo) + console.log('walletInfo: ', walletInfo) + + const rootAddr = walletInfo.cashAddress + // const rootWif = walletInfo.privateKey + console.log(`Sweeping all funds into root address ${rootAddr}...`) + + // Generate an HD tree + const bchjs = wallet.bchjs + const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic) + const masterHDNode = bchjs.HDNode.fromSeed(rootSeed) + + let hdIndex = START_INDEX + + do { + // Generate a keypair from the HD wallet. + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + const cashAddress = bchjs.HDNode.toCashAddress(childNode) + // const wifToSweep = bchjs.HDNode.toWIF(childNode) + + console.log(`HD Index ${hdIndex}: ${cashAddress}`) + + hdIndex++ + } while (hdIndex < LAST_ADDR_INDEX) + console.log(`Last index of ${LAST_ADDR_INDEX} reached.`) + } catch (err) { + console.error('Error in sweepFunds(): ', err) + } +} +listAddrs() + +// Open the wallet file, or create one if the file doesn't exist. +// Does not instance the wallet. The output of this function is expected to +// be passed to instanceWallet(). +async function openWallet (walletLib) { + try { + // console.log('this.WALLET_FILE: ', this.WALLET_FILE) + const walletData = await walletLib.jsonFiles.readJSON('./wallet.json') + + return walletData + } catch (err) { + console.error('Error in openWallet()') + throw err + } +} + +``` + +`/home/trout/work/psf/code/bch-dex/production/docker/cleanup-images.sh`: + +```sh +#!/bin/bash + +# Remove all untagged docker images. +docker rmi $(docker images | grep "^" | awk '{print $3}') + + +``` + +`/home/trout/work/psf/code/bch-dex/production/docker/bch-dex-ui/Dockerfile`: + +``` +# Create a Dockerized API server +# + +#IMAGE BUILD COMMANDS +# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS +#FROM christroutner/ct-base-ubuntu +FROM ubuntu:20.04 as builder +MAINTAINER Chris Troutner + +#Update the OS and install any OS packages needed. +RUN apt-get update +RUN apt-get install -y sudo git curl nano gnupg wget + +#Install Node and NPM +RUN curl -sL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh +RUN bash nodesource_setup.sh +RUN apt-get install -y nodejs build-essential + +#Create the user 'safeuser' and add them to the sudo group. +#RUN useradd -ms /bin/bash safeuser +#RUN adduser safeuser sudo + +#Set password to 'password' change value below if you want a different password +#RUN echo safeuser:password | chpasswd + +#Set the working directory to be the home directory +WORKDIR /home/safeuser + +#Setup NPM for non-root global install +#RUN mkdir /home/safeuser/.npm-global +#RUN chown -R safeuser .npm-global +#RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/safeuser/.profile +#RUN runuser -l safeuser -c "npm config set prefix '~/.npm-global'" + +# Update to the latest version of npm. +#RUN npm install -g npm@7.23.0 +#RUN npm install -g npm + +# npm mirror to prevent direct dependency on npm. +#RUN npm set registry http://94.130.170.209:4873/ + +# Switch to user account. +#USER safeuser +# Prep 'sudo' commands. +#RUN echo 'abcd8765' | sudo -S pwd + +# Clone the rest.bitcoin.com repository +WORKDIR /home/safeuser +RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui-v3 + +# Switch to the desired branch. `master` is usually stable, +# and `stage` has the most up-to-date changes. +WORKDIR /home/safeuser/bch-dex-ui-v3 + +# For development: switch to unstable branch +RUN git checkout ct-unstable + +# Install dependencies +#RUN mkdir .ipfsdata +#RUN npm install -g @mapbox/node-pre-gyp +RUN npm install + +# Build the site +RUN npm run build + +# Load the NGINX image. +FROM nginx +EXPOSE 80 + +# Copy the files built in the first container to the new NGINX container. +COPY --from=builder /home/safeuser/bch-dex-ui-v3/build /usr/share/nginx/html + +#USER safeuser + +``` + +`/home/trout/work/psf/code/bch-dex/production/docker/bch-dex/start-production.sh`: + +```sh +#!/bin/bash + +# BEGIN: Optional configuration settings + +# The human readable name this IPFS node identifies as. +export COORD_NAME=bch-dex-generic + +# Allow this node to function as a circuit relay. It must not be behind a firewall. +#export ENABLE_CIRCUIT_RELAY=true +# For browsers to use your circuit realy, you must set up a domain, SSL certificate, +# and you must forward that subdomain to the IPFS_WS_PORT. +#export CR_DOMAIN=subdomain.yourdomain.com + +# Debug level. 0 = minimal info. 2 = max info. +export DEBUG_LEVEL=1 + +# END: Optional configuration settings + + +# Production database connection string. +export DBURL=mongodb://172.17.0.1:5666/bch-swap-service-prod + +# Configure REST API port +export PORT=5700 + +# bch-dex specific env vars +export BCH_DEX=prod +export WEBHOOKSERVICE=http://172.17.0.1:5667/webhook +export WEBHOOKTARGET=http://172.17.0.1:5700/p2wdb +export APP_ID=bch-dex-001 + +#export P2WDB_URL=http://172.17.0.1:5667 + +npm start + +``` + +`/home/trout/work/psf/code/bch-dex/production/docker/bch-dex/dummy-app.js`: + +```js +setInterval(function () { + const now = new Date() + console.log(`timestamp: ${now.toLocaleString()}`) +}, 5000) + +``` + +`/home/trout/work/psf/code/bch-dex/production/docker/bch-dex/Dockerfile`: + +``` +# Create a Dockerized API server +# + +#IMAGE BUILD COMMANDS +# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS +#FROM christroutner/ct-base-ubuntu +FROM ubuntu:20.04 +MAINTAINER Chris Troutner + +#Update the OS and install any OS packages needed. +RUN apt-get update +RUN apt-get install -y sudo git curl nano gnupg wget + +#Install Node and NPM +RUN curl -sL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh +RUN bash nodesource_setup.sh +RUN apt-get install -y nodejs build-essential + +#Create the user 'safeuser' and add them to the sudo group. +#RUN useradd -ms /bin/bash safeuser +#RUN adduser safeuser sudo + +#Set password to 'password' change value below if you want a different password +#RUN echo safeuser:password | chpasswd + +#Set the working directory to be the home directory +WORKDIR /home/safeuser + +#Setup NPM for non-root global install +#RUN mkdir /home/safeuser/.npm-global +#RUN chown -R safeuser .npm-global +#RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/safeuser/.profile +#RUN runuser -l safeuser -c "npm config set prefix '~/.npm-global'" + +# Update to the latest version of npm. +#RUN npm install -g npm@7.23.0 +#RUN npm install -g npm + +# npm mirror to prevent direct dependency on npm. +RUN npm set registry http://94.130.170.209:4873/ + +# Switch to user account. +#USER safeuser +# Prep 'sudo' commands. +#RUN echo 'abcd8765' | sudo -S pwd + +# Clone the rest.bitcoin.com repository +WORKDIR /home/safeuser +RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex + +# Switch to the desired branch. `master` is usually stable, +# and `stage` has the most up-to-date changes. +WORKDIR /home/safeuser/bch-dex + +# For development: switch to unstable branch +RUN git checkout ct-unstable + +# Install dependencies +#RUN mkdir .ipfsdata +#RUN npm install -g @mapbox/node-pre-gyp +RUN npm install + +# Generate the API docs +RUN npm run docs + +# Copy the wallet files +#COPY wallet.json wallet.json + +#VOLUME /home/safeuser/keys + +# Expose the port the API will be served on. +#EXPOSE 5010 + +# Start the application. +CMD ["./start-production.sh"] + +#CMD ["npm", "start"] + +# Used for debugging +#COPY dummy-app.js dummy-app.js +#CMD ["node", "dummy-app.js"] + +``` + +`/home/trout/work/psf/code/bch-dex/production/docker/docker-compose.yml`: + +```yml +# Start the service with the command 'docker-compose up -d' + +version: '3.9' + +services: + mongo-dex: + image: mongo:4.2.0 + container_name: mongo-dex + ports: + - '5666:27017' # : + volumes: + - ../data/database:/data/db + command: mongod --logpath=/dev/null # -- quiet + restart: always + + bch-dex: + build: + context: ./bch-dex/ + dockerfile: Dockerfile + #image: christroutner/bch-dex:v2.2.4 + container_name: bch-dex + environment: + CONSUMER_URL: 'https://free-bch.fullstack.cash' + logging: + driver: 'json-file' + options: + max-size: '10m' + max-file: '10' + mem_limit: 1000mb + links: + - mongo-dex + #- p2wdb + ports: + # : + - '5700:5700' # REST API + - '4001:4001' # TCP + - '4003:4003' # Websockets + - '4005:4005' # WebRTC + + volumes: + - ../scripts/wallet.json:/home/safeuser/bch-dex/wallet.json + - ./bch-dex/start-production.sh:/home/safeuser/bch-dex/start-production.sh + restart: always + + dex-ui: + build: + context: ./bch-dex-ui/ + dockerfile: Dockerfile + #image: christroutner/bch-dex-ui:v1.2.4 + container_name: dex-ui + environment: + SERVER: 'http://172.17.0.1' + logging: + driver: 'json-file' + options: + max-size: '10m' + max-file: '10' + mem_limit: 1000mb + links: + - bch-dex + ports: + - '4500:80' # : + # volumes: + # - ../data/ipfsdata:/home/safeuser/ipfs-service-provider/.ipfsdata + restart: always + +``` + +`/home/trout/work/psf/code/bch-dex/util/orders/deleteOrders.js`: + +```js +import mongoose from 'mongoose' + +// Force test environment +// make sure environment variable is set before this file gets called. +// see test script in package.json. +// process.env.KOA_ENV = 'test' +import config from '../../config' + +import User from '../../src/models/users' + +async function deleteUsers () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect(config.database, { + useUnifiedTopology: true, + useNewUrlParser: true + }) + + // Get all the users in the DB. + const users = await User.find({}, '-password') + // console.log(`users: ${JSON.stringify(users, null, 2)}`) + + // Delete each user. + for (let i = 0; i < users.length; i++) { + const thisUser = users[i] + await thisUser.remove() + } + + mongoose.connection.close() +} + +deleteUsers() + +``` + +`/home/trout/work/psf/code/bch-dex/util/orders/getOrders.js`: + +```js +import mongoose from 'mongoose' +import config from '../../config/index.js' +import Order from '../../src/adapters/localdb/models/order.js' + +async function getOrder () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect(config.database, { + useNewUrlParser: true, + useUnifiedTopology: true + }) + + const orders = await Order.find({}) + console.log(`orders: ${JSON.stringify(orders, null, 2)}`) + + mongoose.connection.close() +} +getOrder() + +``` + +`/home/trout/work/psf/code/bch-dex/util/users/delete-all-test-users.js`: + +```js +import mongoose from 'mongoose' + +// Force test environment +// make sure environment variable is set before this file gets called. +// see test script in package.json. +// process.env.KOA_ENV = 'test' +import config from '../../config/index.js' + +import User from '../../src/models/users/js' + +async function deleteUsers () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect(config.database, { + useUnifiedTopology: true, + useNewUrlParser: true + }) + + // Get all the users in the DB. + const users = await User.find({}, '-password') + // console.log(`users: ${JSON.stringify(users, null, 2)}`) + + // Delete each user. + for (let i = 0; i < users.length; i++) { + const thisUser = users[i] + await thisUser.remove() + } + + mongoose.connection.close() +} + +deleteUsers() + +``` + +`/home/trout/work/psf/code/bch-dex/util/users/production/createUser.js`: + +```js +/* + Log in as an admin user to create a new user. +*/ + +// Global npm libraries +import axios from 'axios' +// import fs from 'fs' + +// Local libraries +// import config from '../../../config/index.js' +// import User from '../../../src/adapters/localdb/models/users.js' + +// Customize these variables +const EMAIL = 'someone@somewhere.com' +const NAME = 'Someone' +const PASSWORD = 'test' + +const ADMIN_EMAIL = 'system@system.com' +const ADMIN_PASSWORD = 'admin' + +async function createUser () { + try { + // Open the system-user-prod.json file + // const systemUser = JSON.parse(fs.readFileSync('../../../config/system-user-prod.json', 'utf8')) + + // Log in as the admin user + const adminLogin = { + email: ADMIN_EMAIL, + password: ADMIN_PASSWORD + } + const response = await axios.post('http://localhost:5700/auth', adminLogin) + console.log(`response: ${JSON.stringify(response.data, null, 2)}`) + + const jwt = response.data.token + + // Create a new user, using the admin credentials + const options = { + method: 'post', + url: 'http://localhost:5700/users/', + headers: { + Authorization: `Bearer ${jwt}` + }, + data: { + user: { + email: EMAIL, + name: NAME, + password: PASSWORD + } + } + } + const result = await axios(options) + console.log(`result: ${JSON.stringify(result.data, null, 2)}`) + } catch (err) { + console.error(err) + } +} +createUser() + +``` + +`/home/trout/work/psf/code/bch-dex/util/users/production/getUsers.js`: + +```js +import mongoose from 'mongoose' +// import config from '../../config/index.js' +import User from '../../../src/adapters/localdb/models/users.js' + +const mongooseConnectStr = 'mongodb://172.17.0.1:5666/bch-swap-service-prod' + +async function getUsers () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect( + mongooseConnectStr, + { useNewUrlParser: true, useUnifiedTopology: true } + ) + + const users = await User.find({}, '-password') + console.log(`users: ${JSON.stringify(users, null, 2)}`) + + mongoose.connection.close() +} +getUsers() + +``` + +`/home/trout/work/psf/code/bch-dex/util/users/createUsers.js`: + +```js +import mongoose from 'mongoose' +import config from '../../config/index.js' +import User from '../../src/adapters/localdb/models/users.js' + +const EMAIL = process.env.EMAIL || 'test@test3.com' +const PASSWORD = process.env.PASSWORD || 'pass' + +async function addUser () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect( + config.database, + { useNewUrlParser: true, useUnifiedTopology: true } + ) + + const userData = { + email: EMAIL, + password: PASSWORD + } + + const user = new User(userData) + + // Enforce default value of 'user' + user.type = 'user' + + await user.save() + + await mongoose.connection.close() + + console.log(`User ${EMAIL} created.`) +} +addUser() + +export default { + addUser +} + +``` + +`/home/trout/work/psf/code/bch-dex/util/users/dev/createUser.js`: + +```js +/* + Use the system-user-dev.json file to log in as the admin user + and create a new user. +*/ + +// Global npm libraries +import axios from 'axios' +import fs from 'fs' + +// Local libraries +// import config from '../../../config/index.js' +// import User from '../../../src/adapters/localdb/models/users.js' + +// Customize these variables +const EMAIL = 'test@test.com' +const NAME = 'tester' +const PASSWORD = 'test' + +async function createUser () { + try { + // Open the system-user-dev.json file + const systemUser = JSON.parse(fs.readFileSync('../../../config/system-user-dev.json', 'utf8')) + + // Log in as the admin user + const adminLogin = { + email: systemUser.email, + password: systemUser.password + } + const response = await axios.post('http://localhost:5700/auth', adminLogin) + console.log(`response: ${JSON.stringify(response.data, null, 2)}`) + + const jwt = response.data.token + + // Create a new user, using the admin credentials + const options = { + method: 'post', + url: 'http://localhost:5700/users/', + headers: { + Authorization: `Bearer ${jwt}` + }, + data: { + user: { + email: EMAIL, + name: NAME, + password: PASSWORD + } + } + } + const result = await axios(options) + console.log(`result: ${JSON.stringify(result.data, null, 2)}`) + } catch (err) { + console.error(err) + } +} +createUser() + +``` + +`/home/trout/work/psf/code/bch-dex/util/users/dev/getUsers.js`: + +```js +import mongoose from 'mongoose' +import config from '../../../config/index.js' +import User from '../../../src/adapters/localdb/models/users.js' + +async function getUsers () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect( + config.database, + { useNewUrlParser: true, useUnifiedTopology: true } + ) + + const users = await User.find({}, '-password') + console.log(`users: ${JSON.stringify(users, null, 2)}`) + + mongoose.connection.close() +} +getUsers() + +``` + +`/home/trout/work/psf/code/bch-dex/util/README.md`: + +```md +This directory contains utility functions for managing the database. + +``` + +`/home/trout/work/psf/code/bch-dex/util/wipe-test-db.js`: + +```js +/* + Utility app to wipe the test database. +*/ + +'use strict' + +import mongoose from 'mongoose' +import config from '../config/index.js' + +// Force test environment +process.env.KOA_ENV = 'test' + +async function cleanDb () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect(config.database, { useNewUrlParser: true }) + + console.log(`mongoose.connection.collections: ${JSON.stringify(mongoose.connection.collections, null, 2)}`) + + for (const collection in mongoose.connection.collections) { + const collections = mongoose.connection.collections + if (collections.collection) { + // const thisCollection = mongoose.connection.collections[collection] + // console.log(`thisCollection: ${JSON.stringify(thisCollection, null, 2)}`) + + await collection.deleteMany() + } + } + + mongoose.connection.close() +} +cleanDb() + +``` + +`/home/trout/work/psf/code/bch-dex/util/wallet/sweep-funds2.js`: + +```js +/* + This script will travers the HD wallet and sweep funds and tokens back + into the root address (index 0). That root address needs to have funds + to pay for the transactions. + + This version will traverse the HD index of the wallet until it reaches + the value in the nextAddress property. This ensures that all UTXOs + that could be used by the wallet have been swept. +*/ + +// Public npm libraries +import BCHJS from '@psf/bch-js' + +import BchTokenSweep from 'bch-token-sweep' + +// Local libraries +import WalletAdapter from '../../src/adapters/wallet.js' + +async function sweepFunds () { + try { + // Open the wallet files. + const wallet = new WalletAdapter() + const walletInfo = await wallet.openWallet() + const bchWallet = await wallet.instanceWallet(walletInfo) + console.log('walletInfo: ', walletInfo) + + const lastIndex = walletInfo.nextAddress + + const rootAddr = walletInfo.cashAddress + const rootWif = walletInfo.privateKey + console.log(`Sweeping all funds into root address ${rootAddr}...`) + + // Generate an HD tree + const bchjs = new BCHJS() + const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic) + const masterHDNode = bchjs.HDNode.fromSeed(rootSeed) + + let hdIndex = 1 + + do { + // Generate a keypair from the HD wallet. + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + const cashAddress = bchjs.HDNode.toCashAddress(childNode) + const wifToSweep = bchjs.HDNode.toWIF(childNode) + + console.log(`\nSweeping HD Index ${hdIndex} with address ${cashAddress}`) + + try { + // Sweep tokens from address + const sweeper = new BchTokenSweep( + wifToSweep, + rootWif, + bchWallet, + 550, + rootAddr + ) + await sweeper.populateObjectFromNetwork() + + const hex = await sweeper.sweepTo(rootAddr) + // console.log(`hex: ${hex}`) + + const txid = await sweeper.blockchain.broadcast(hex) + + // console.log('Transaction ID', txid) + console.log(`Swept HD index ${hdIndex}. TXID: ${txid}`) + + // Wait between loop iterations. + await bchjs.Util.sleep(3000) + } catch (err) { + console.log(`error message with index ${hdIndex}: ${err}`) + } + + hdIndex++ + } while (hdIndex <= lastIndex) + + console.log(`${lastIndex} empty addresses detected. Exiting.`) + + console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n') + } catch (err) { + console.error('Error in sweepFunds(): ', err) + } +} +sweepFunds() + +``` + +`/home/trout/work/psf/code/bch-dex/util/wallet/sweep-funds.js`: + +```js +/* + This script will travers the HD wallet and sweep funds and tokens back + into the root address (index 0). That root address needs to have funds + to pay for the transactions. + + The root address will make a final transaction to consolidate all tokens. +*/ + +// Public npm libraries +import BCHJS from '@psf/bch-js' + +import BchTokenSweep from 'bch-token-sweep' + +// Local libraries +import WalletAdapter from '../../src/adapters/wallet.js' + +// Constants +const EMTPY_ADDR_CUTOFF = 15 + +async function sweepFunds () { + try { + // Open the wallet files. + const wallet = new WalletAdapter() + const walletInfo = await wallet.openWallet() + const bchWallet = await wallet.instanceWallet(walletInfo) + console.log('walletInfo: ', walletInfo) + + const rootAddr = walletInfo.cashAddress + const rootWif = walletInfo.privateKey + console.log(`Sweeping all funds into root address ${rootAddr}...`) + + // Generate an HD tree + const bchjs = new BCHJS() + const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic) + const masterHDNode = bchjs.HDNode.fromSeed(rootSeed) + + let emptyAddrCnt = 0 + let hdIndex = 1 + + do { + // Generate a keypair from the HD wallet. + const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`) + const cashAddress = bchjs.HDNode.toCashAddress(childNode) + const wifToSweep = bchjs.HDNode.toWIF(childNode) + + console.log(`\nSweeping ${cashAddress}`) + + try { + // Sweep tokens from address + const sweeper = new BchTokenSweep( + wifToSweep, + rootWif, + bchWallet, + 550, + rootAddr + ) + await sweeper.populateObjectFromNetwork() + + const hex = await sweeper.sweepTo(rootAddr) + // console.log(`hex: ${hex}`) + + const txid = await sweeper.blockchain.broadcast(hex) + + // console.log('Transaction ID', txid) + console.log(`Swept HD index ${hdIndex}. TXID: ${txid}`) + + emptyAddrCnt = 0 + + // Wait between loop iterations. + await bchjs.Util.sleep(3000) + } catch (err) { + console.log(`error message with index ${hdIndex}: ${err}`) + emptyAddrCnt++ + } + + hdIndex++ + } while (emptyAddrCnt < EMTPY_ADDR_CUTOFF) + + console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`) + + console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n') + } catch (err) { + console.error('Error in sweepFunds(): ', err) + } +} +sweepFunds() + +``` + +`/home/trout/work/psf/code/bch-dex/util/offers/getOffers.js`: + +```js +/* + Get all Offers in the database. +*/ + +import mongoose from 'mongoose' + +import config from '../../config/index.js' +import Offer from '../../src/adapters/localdb/models/offer.js' + +async function getOffers () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect(config.database, { + useNewUrlParser: true, + useUnifiedTopology: true + }) + + const offers = await Offer.find({}) + console.log(`offers: ${JSON.stringify(offers, null, 2)}`) + + mongoose.connection.close() +} +getOffers() + +``` + +`/home/trout/work/psf/code/bch-dex/util/offers/deleteOffers.js`: + +```js +/* + This script has not been customized for offers yet. +*/ + +import mongoose from 'mongoose' + +// Force test environment +// make sure environment variable is set before this file gets called. +// see test script in package.json. +// process.env.KOA_ENV = 'test' +import config from '../../config' + +import User from '../../src/models/users' + +async function deleteUsers () { + // Connect to the Mongo Database. + mongoose.Promise = global.Promise + mongoose.set('useCreateIndex', true) // Stop deprecation warning. + await mongoose.connect(config.database, { + useUnifiedTopology: true, + useNewUrlParser: true + }) + + // Get all the users in the DB. + const users = await User.find({}, '-password') + // console.log(`users: ${JSON.stringify(users, null, 2)}`) + + // Delete each user. + for (let i = 0; i < users.length; i++) { + const thisUser = users[i] + await thisUser.remove() + } + + mongoose.connection.close() +} + +deleteUsers() + +``` + +`/home/trout/work/psf/code/bch-dex/util/wipe-db.md`: + +```md + +Here's how to wipe the db: +1. mongo +2. use koa-server-dev +3. db.dropDatabase() +4. exit + +``` + +`/home/trout/work/psf/code/bch-dex/CONTRIBUTING.md`: + +```md +# Permissionless Software Foundation Community Contributing Guide 1.0 + +This document describes a very simple process suitable for most projects under +the PSF umbrella. It is based on [this Medium article](https://medium.com/the-node-js-collection/healthy-open-source-967fa8be7951) and the [Node.js Community Contribution Guide](https://github.com/nodejs/TSC/blob/master/BasePolicies/CONTRIBUTING.md). +Projects are encouraged to adopt this whether they +are hosted under the PSF or not. + +The goal of this document is to create a contribution process that: + +* Encourages new contributions. +* Encourages contributors to remain involved. +* Avoids unnecessary processes and bureaucracy whenever possible. +* Creates a transparent decision making process which makes it clear how +contributors can be involved in decision making. + +This document is based on much prior art in the Node.js community, io.js, +and the Node.js project. + +Additional guidance can be found at the [Permissionless Software Foundation Telegram Channel](https://t.me/permissionless_software). + +## Vocabulary + +* A **Contributor** is any individual creating or commenting on an issue or pull request. +* A **Committer** is a subset of contributors who have been given write access to the repository. +* A **TC (Technical Committee)** is a group of committers representing the required technical +expertise to resolve rare disputes. + +# Logging Issues + +Log an issue for any question or problem you might have. When in doubt, log an issue, +any additional policies about what to include will be provided in the responses. The only +exception is security disclosures which should be sent privately. + +Committers may direct you to another repository, ask for additional clarifications, and +add appropriate metadata before the issue is addressed. + +Please be courteous, respectful, and every participant is expected to follow the +project's Code of Conduct. + +# Contributions + +Any change to resources in this repository must be through pull requests. This applies to all changes +to documentation, code, binary files, etc. Even long term committers and TC members must use +pull requests. + +No pull request can be merged without being reviewed. + +For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that +contributors in other timezones have time to review. Consideration should also be given to +weekends and other holiday periods to ensure active committers all have reasonable time to +become involved in the discussion and review process if they wish. + +The default for each contribution is that it is accepted once no committer has an objection. +During review committers may also request that a specific contributor who is most versed in a +particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off" +process for contributions to land. Once all issues brought by committers are addressed it can +be landed by any committer. + +In the case of an objection being raised in a pull request by another committer, all involved +committers should seek to arrive at a consensus by way of addressing concerns being expressed +by discussion, compromise on the proposed change, or withdrawal of the proposed change. + +If a contribution is controversial and committers cannot agree about how to get it to land +or if it should land then it should be escalated to the TC. TC members should regularly +discuss pending contributions in order to find a resolution. It is expected that only a +small minority of issues be brought to the TC for resolution and that discussion and +compromise among committers be the default resolution mechanism. + +# Becoming a Committer + +All contributors who land a non-trivial contribution should be on-boarded in a timely manner, +and added as a committer, and be given write access to the repository. + +Committers are expected to follow this policy and continue to send pull requests, go through +proper review, and have other committers merge their pull requests. + +# TC Process + +The TC uses a "consensus seeking" process for issues that are escalated to the TC. +The group tries to find a resolution that has no open objections among TC members. +If a consensus cannot be reached that has no objections then a majority wins vote +is called. It is also expected that the majority of decisions made by the TC are via +a consensus seeking process and that voting is only used as a last-resort. + +Resolution may involve returning the issue to committers with suggestions on how to +move forward towards a consensus. It is not expected that a meeting of the TC +will resolve all issues on its agenda during that meeting and may prefer to continue +the discussion happening among the committers. + +Members can be added to the TC at any time. Any committer can nominate another committer +to the TC and the TC uses its standard consensus seeking process to evaluate whether or +not to add this new member. Members who do not participate consistently at the level of +a majority of the other members are expected to resign. + +``` + +`/home/trout/work/psf/code/bch-dex/LICENSE.md`: + +```md +The MIT License (MIT) +Copyright (c) 2021-2024 Permissionless Software Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +``` + +`/home/trout/work/psf/code/bch-dex/install-mongo.sh`: + +```sh +#!/bin/bash +curl -fsSL https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add - +echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list +sudo apt-get update +sudo apt-get install -y mongodb-org +sudo service mongod start +sudo systemctl enable mongod + +``` + +`/home/trout/work/psf/code/bch-dex/dev-docs/README.md`: + +```md +# Developer Documentation + +This is living documentation that will be updated, edited, and changed over time, using the same version control as the rest of the code. The purpose of this documentation is to capture and explain how the `bch-dex` interacts with the [P2WDB](https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service), to create a permissionless, censorship-resistant database for storing trading orders. A web client will be built in the future that will interact with the REST API of this app. + +- [Specification](./specification.md) + +# Overview + +There are three major pieces of software behind the bch-dex concept. They work together to form a censorship-resistant application for exchanging transaction data for building trades. + +![bch-dex major subcomponents](./diagrams/software-interaction.png) + +- _Client_ could be a web browser like [wallet.fullstack.cash](https://bchn-wallet.fullstack.cash), or a command-line client like [psf-bch-wallet](https://github.com/Permissionless-Software-Foundation/psf-bch-wallet) or [psf-avax-wallet](https://github.com/Permissionless-Software-Foundation/psf-avax-wallet). +- [bch-dex](https://github.com/Permissionless-Software-Foundation/bch-dex) is the back end REST API that maintains a local database of information that the client reads from. +- [P2WDB](https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service) is the pay-to-write global database with a REST API for interfacing with the other two pieces of software. + +The arrows in the image represent the information flow between the three pieces of software: + +- The _Client_ is essentially a 'dummy terminal' with a bidirectional interface to bch-dex. bch-dex does the heavy lifting, and the _Client_ is a 'thin' UI wrapper. +- `bch-dex` imports data from the global P2WDB database into its local database, using a [webhook](https://en.wikipedia.org/wiki/Webhook) (dashed line). It can also custody funds, pay transaction fees, and create an _Offer_ by creating an _Order_ and submitting the data to the P2WDB (solid line). + +This architecture keeps the global database highly censorship resistant, while allowing local installations to maintain tight control over the user experience. The goal is to have many redundant copies of `bch-dex` on the network, and to empower individual traders to run their own, private copy, while maintaining a single source of truth via the P2WDB. + +# Definitions + +The workflow of a token trade has three parts: +1. **Make** - An *Offer* to buy or sell tokens is generated by a user, known as the *Maker*. +2. **Take** - A second user, known as a *Taker*, will *take* the *Offer* by issuing a *Counter Offer* +3. **Accept** - The original *Maker* checks the *Counter Offer* and *Accepts* it by signing and then broadcasting the transaction. + +Trades done in this way are both *trustless* and *atomic*: +- **Trustless** - This means that neither party needs to trust the other. The *Maker* gets to review the *Counter Offer* before broadcasting it. The *Maker* can not alter the *Counter Offer* after the *Taker* has signed it. +- **Atomic** - The trade happens in a single transaction. There is no middle-state where the trade can get stuck. It either happens or doesn't, it's state is binary and atomic. + +Specific *Entities* are defined in the [specification](./specification.md), but here is a brief summary: +- **Order** represents the *Maker* side of the trade. This entity is internal to `bch-dex`. It is used to track tokens set aside for sale and managed by the wallet controlled by `bch-dex`. +- **Offer** contains most of the same information as an **Order**, but is external to `bch-dex`. This is data submitted to the P2WDB and visible to all users on the network. +- **Counter Offer** is generated by a *Taker*, in order to take the other side of the trade. It contains a partially-signed transaction, ready for review by the *Maker*. + +# Back End + +This section provides additional information on `bch-dex` and P2WDB back end software. + +## P2WDB + +The heart of the censorship resistance is the pay-to-write database ([P2WDB](https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service)). This is an [OrbitDB](https://orbitdb.org/) peer-to-peer (p2p) database. The write-access rules have been customized to allow anyone to write to the database, so long as they prove that a sufficient quantity of [PSF tokens](https://psfoundation.cash) have been burned, to pay for the write. + +Because OrbitDB is a p2p database, no one party holds the 'official' copy of the database. Instead, like a blockchain, the database is replicated among several peers, and they coordinate updates to the database using consensus rules. Peers are free to leave or enter the network. Each peer independently verifies the database entries have sufficient proof-of-burn. + +## `bch-dex` + +The `bch-dex` replicates a copy of the global P2WDB, but has the ability to apply localized filters to the data before passing it on to the _Client_, to be displayed. + +`bch-dex` is based on this [ipfs-service-provider boilerplate](https://github.com/Permissionless-Software-Foundation/ipfs-service-provider). It's a production-ready template for a web server, providing interfaces via REST API over HTTP, as well as JSON RPC over IPFS. It includes many features for building a web app. This includes user management and authentication, REST API and JSON RPC scaffolding, API documentation, Docker container generation, and extensive test coverage. It's intended to be customized for the needs of the website administrator. + +- [Specification](./specification.md) + +# Workflows + +This section describes the protocols for the database interactions between the three main software components. + +These are just a brief, high-level overview. Review the [Specifications](./specification.md) for more details. + +## Reading from the Local Database + +The *Client* reads data from the local database stored by `bch-dex`, and does not read the P2WDB global database directly. This gives `bch-dex` the opportunity to filter and modify the data locally, for a more controlled user experience. + +## Making an Offer + +Adding data to the global P2WDB is triggered by the _Client_ calling a REST API endpoint on `bch-dex`. The [p2wdb npm library](https://www.npmjs.com/package/p2wdb) can be leveraged for easy reading and writing to the P2WDB. + +Writing data follows these steps: + +- Tokens and BCH are held by a wallet which is under the controlled of `bch-dex`. +- The _Client_ submits data to the POST `/order` REST API endpoint to create a new Order. +- `bch-dex` will move the funds into a segregated UTXO, and will use that UTXO to create an Order. The Order data is written to the P2WDB. The Order data is also saved to the local MongoDB. +- After submitting the data to the P2WDB, `bch-dex` will receive a webhook call to its POST `/p2wdb` endpoint by the P2WDB. This event will trigger the import of the new data into the apps local Mongo database, and generate a new Offer model. +- This webhook event is mirrored by every instance of `bch-dex` on the network. Each P2WDB peer on the network will independently validate the new database entry and create a new Offer model. + +## Taking an Offer + +Users can browse the Offers tracked by a local `bch-dex` by using a *Client*. When they find an Offer they want to to take, they'll use some UI element that will send data to the POST `/offer/take` REST API endpoint. These series of steps happen: + +- The `bch-dex` checks to see if the wallet it controls has enough BCH to take the other side of the Offer. If it does, the funds for the offer are moved to a segregated UTXO. +- The new UTXO is used to generate a *Counter Offer*, which contains a partially signed transaction saved as a hex string. +- The *Counter Offer* is uploaded to the P2WDB. This triggers a webhook event in every running instance of `bch-dex` on the network. +- When the webhook is triggered, `bch-dex` will check to see if the *Counter Offer* matches an *Order* under its control. If a match is found, it will trigger an *Accept* event. + +## Accepting a Counter Offer + +This part of the process is automated and does not require input from the user. + +- When a *Counter Offer* is received that matches an *Order* tracked by the local copy of `bch-dex`, it will trigger the *Acceptance* phase. +- In the *Acceptance* phase, the transaction will be checked to see if it matches the conditions in the original *Order*. If all checks pass, `bch-dex` will sign the transaction and broadcast it, completing the trade. +- A 'garbage collection' function that runs periodically will delete Orders and Offers in bch-dex that have had their UTXO spent, automatically cleaning up stale trade data that is no longer valid. + +## Maintenance + +Occasional maintenance functions will be called by an interval timer. The primary purpose of these functions is to check the UTXOs in the Order, Offer, and Counter Offer entities. If any of these UTXOs are spent, the entity is deleted from the local Mongo database. + +``` + +`/home/trout/work/psf/code/bch-dex/dev-docs/specification.md`: + +```md +# bch-dex Specification + +This document contains a high-level, human-readable specification for the four major architectural areas of the bch-dex: + +- Entities +- Use Cases +- Controllers (inputs) +- Adapters (outputs) + +This reflects the [Clean Architecture](https://bafybeiajggd4zju7oen627bcy5l32hrxqomoqzvwqfir6phzgducozksv4.ipfs.dweb.link/blog/clean-architecture) design pattern. + +## Entities + +Entities make up the core business concepts. If these entities change, they fundamentally change the entire app. + +### Order + +An Order Entity is nearly the same as an Offer. The Order is generated first, but is always internal to the bch-dex system. Most of the data in an Order is submitted to the P2WDB, which generates an Offer (external) Entity. + +The Order tracks the [HD index address](https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch05.asciidoc#hd-wallets-bip-32bip-44) used to hold tokens or BCH for sale. This is the part of the app concerned with the custody of the funds. It creates a segregated [UTXO](https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch06.asciidoc#transaction-outputs-and-inputs) to hold the offered asset. The Order is automatically destroyed if the UTXO is spent. + +Order entities have the following properties: + +- Token Data: + - _tokenId_ - The unique ID that identifies the class of token being offered for sale. + - _utxoTxid_ - The TXID of the UTXO representing the token or BCH being offered for sale. + - _utxoVout_ - The vout of the UTXO representing the token or BCH being offered for sale. + +- Trade Data: + - _buyOrSell_ - A string with a value `buy` or `sell` indicating which type of offer this is. + - _numTokens_ - The maximum number of tokens offered for sale. + - _rateInBaseUnit_ - The rate in terms of currency-unit-per-token. Ex: 1000 = 1000 sats per token + - For Bitcoin, the min currency is sats. + - For AVAX, the min currency is nano-Avax. + - for eCash, the min currency is bits. + - _minUnitsToExchange_ - The minimum order size accepted. + - _makerAddr_ - The address for the taker to send money to. + - _p2wdbTxid_ - The TXID proof-of-burn used to add the order to the P2WDB. + - _p2wdbHash_ - The CID used to identify the order entry in the P2WDB. + +- Authentication Data: + - _signature_ - A message signed by the address which created the order. + - _sigMsg_ - The clear-text message used to generate the signature. + - _offerBchAddr_ - The BCH address controlling the offer. + - _offerPubKey_ - The public key used to generate the BCH address, used for encryption. + +- Wallet Data: + - _hdIndex_ - The HD index of the wallet used to generate the keypair to store the UTXO being offered for sale. + +- SWaP Protocol properties: + - _lokadId_ - Not used. Provided for future functionality. + - _messageType_ - Not used. Provided for future functionality. + - _messageClass_ - Not used. Provided for future functionality. + + +### Offer + +An offer is created from data passed to the app by the P2WDB webhook. +It is destroyed when the UTXO described in the Signal has been detected as spent. + +Offer entities have the following properties: + +- Token Data: + - _tokenId_ - The unique ID that identifies the class of token being offered for sale. + - _utxoTxid_ - The TXID of the UTXO representing the token or BCH being offered for sale. + - _utxoVout_ - The vout of the UTXO representing the token or BCH being offered for sale. + +- Trade Data: + - _buyOrSell_ - A string with a value `buy` or `sell` indicating which type of offer this is. + - _numTokens_ - The maximum number of tokens offered for sale. + - _rateInBaseUnit_ - The rate in terms of currency-unit-per-token. Ex: 1000 = 1000 sats per token + - For Bitcoin, the min currency is sats. + - For AVAX, the min currency is nano-Avax. + - for eCash, the min currency is bits. + - _minUnitsToExchange_ - The minimum order size accepted. + - _makerAddr_ - The address for the taker to send money to. + - _p2wdbTxid_ - The TXID proof-of-burn used to add the order to the P2WDB. + - _p2wdbHash_ - The CID used to identify the order entry in the P2WDB. + - _offerStatus_ - The state of the offer. When the data is added to the P2WDB, it gets a value of 'posted', but the database model internal to bch-dex can have the following properties: + - *posted* - The offer is posted and can be countered by a taker. + - *taken* - The offer was countered and accepted. + - *dead* - The UTXO was spent outside the trade, which automatically makes the offer dead. + +- Authentication Data: + - _signature_ - A message signed by the address which created the order. + - _sigMsg_ - The clear-text message used to generate the signature. + - _offerBchAddr_ - The BCH address controlling the offer. + - _offerPubKey_ - The public key used to generate the BCH address, used for encryption. + +- Utility Data: + - _timestamp_ - The ISO time when the order was created. + - _localTimestamp_ - The localized time when the order was created. + +- SWaP Protocol properties: + - _lokadId_ - Not used. Provided for future functionality. + - _messageType_ - Not used. Provided for future functionality. + - _messageClass_ - Not used. Provided for future functionality. + +When an Offer is uploaded to the P2WDB, the following properties are added to the data: + +- Added properties to P2WDB data: + - *dataType* - Has a value of 'offer'. This is used to route the data correctly when the P2WDB webhook passes the data to `bch-dex`. + +### Counter Offer + +A Counter Offer is the other side of the trade, a mirror image to an Offer. It contains a partially signed transaction, created by the Taker. The Maker will review the Counter Offer before accepting and finalizing the trade. + +Counter Offers are not tracked via database models like Offers and Orders are. They are processed by `bch-dex` as soon as they are received. A garbage collection function will be called periodically, to sweep the segregated UTXOs used to generate a Counter Offer back into the root address of the wallet, if it is not accepted after a period of time. + +To generate a Counter Offer, a segregated UTXO is created that matches the requirements in the Offer. A partially signed transaction is created that includes the Offer UTXO and the Counter Offer UTXO. The Taker signs the input consuming the Counter Offer UTXO. The partially signed transaction and other trade data is uploaded to P2WDB. + +When the Counter Offer data is uploaded to the P2WDB, the data must have the following properties: + +- *partialTxHex* - A hexidecimal representation of the partially-signed transaction, which includes the UTXO in the Offer and a second UTXO for that matches the conditions in the Offer. +- *dataType* - Must have a value of `counter-offer` + + +## Use Cases + +Use cases are verbs or actions that is done _to_ an Entity or _between_ Entities. + +### Order + +- **`createOrder()`** - A macro command that leverages the other functions in this library to create a new Order and submit it to the P2WDB. +- **`ensureFunds()`** - Ensure that the wallet has enough BCH and tokens to complete the requested trade. +- **`findOrderByHash()`** - Given a P2WDB CID 'hash', this function will return the corresponding Order model associated with that CID. + +### Offer + +- **`createOffer()`** - This method is triggered by a webhook from the P2WDB. It will take the data provided by the P2WDB and create a new Offer entity in the local database. +- **`listOffers()`** - Returns a list of all the active Offers tracked by `bch-dex`. +- **`takeOffer()`** - Generate a segregated UTXO and partially signed transaction, then upload the Counter Offer data to the P2WDB. +- **`ensureFunds()`** - Ensure the wallet has enough BCH and tokens to make a Counter Offer. +- **`findOfferByHash()`** - Given a P2WDB CID 'hash', this function will return the corresponding Offer model associated with that CID. +- **`acceptCounterOffer()`** - This function is triggered by the P2WDB webhook REST API handler. When a Counter Offer is passed to `bch-dex` by the P2WDB, the data is then passed to this function. It does due diligence on the Counter Offer, then signs and broadcasts the transaction to accept the Counter Offer. + +## Controllers + +Controllers are inputs to the system. When a controller is activated, it causes the system to react in some way. + +### Orders + +- **POST /order** - This POST REST API endpoint can be triggered by the Client or a simple curl call. It passes in the data needed for `bch-dex` to generate and track a new Order, then submits the data to the P2WDB to generate an Offer that is tracked by all other instances of `bch-dex` on the network. + +### Offers + +- **GET /offer/list** - Returns an array of objects, where each object represents an active Offer. + +- **POST /offer/take** - Given the P2WDB CID of an Offer, calling this endpoint will attempt to generate a Counter Offer and upload it to the P2WDB. + +### P2WDB + +- **POST /p2wdb** - This POST REST API endpoint will be called by a webhook generated from the P2WDB. This will notify the `bch-dex` that a new entry has been added to the P2WDB that matches the `appId` of `swap-`, where `` has a value of `avax`, `bch`, or `ecash`. It's a new entry that should be evaluated for inclusion in the `bch-dex` local database. Based on the `dataType` property, the data is routed to either create a new Offer or to process a new Counter Offer. + +## Adapters + +Adapters are outputs. These libraries exist so that the business logic doesn't need to know any specific information about the I/O. They handle the low-level mechanics of the various subsystems. + +- **localdb** - An adapter for the local database (MongoDB). +- **ipfs** - An adapter for IPFS and the ipfs-coord library. It allows the app to use the JSON-RPC over IPFS. +- **wallet** - Handles low-level wallet tasks. + - **`moveTokens()`** - Move the tokens indicated in the order to a temporary holding address. This will generate the segregated UTXOs used in the trade. This function moves the funds and returns the UTXO information. + - **`moveBCH()`** - Same idea as `moveTokens()`, but creates a non-SLP segregated UTXO, used when generating a Counter Offer. + - **`openWallet()`** - Opens the JSON file containing the wallet data for the app. + - **`instanceWallet()`** - Given the wallet data returned by `openWallet()`, it generates an instance of the [minimal-slp-wallet](https://www.npmjs.com/package/minimal-slp-wallet) for generating UTXOs and interacting with the blockchain. + - **`incrementNextAddress()`** - Increments the index of the [HD wallet](https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch05.asciidoc#hd_wallets) used to generate keypairs for storing segregated UTXOs. + - **`getKeyPair()`** - Generates a keypair from the HD wallet. + - **`generateSignature()`** - Generate a cryptographic signature. + - **`generatePartialTx()`** - Create a partial transaction as part of a Counter Offer. + - **`deseralizeTx()`** - Used only for debugging purposes. Expands a hex transaction into a JSON object. + - **`completeTx()`** - Complete the partially signed transaction by signing the first input, then broadcasting the transaction to the network. + +``` + +`/home/trout/work/psf/code/bch-dex/examples/README.md`: + +```md +# Examples + +Below are a series of JSON RPC calls that can be manually entered at chat.fullstack.cash to interact with the JSON RPC of this IPFS Service Provider. + +- `{"jsonrpc":"2.0","id":"555","method":"users","params":{ "endpoint": "createUser", "email": "test555@test.com", "name": "testy tester", "password": "password"}}`
+ +- `{"jsonrpc":"2.0","id":"556","method":"auth","params":{ "endpoint": "authUser", "login": "test555@test.com", "password": "password"}}`
+ +- `{"jsonrpc":"2.0","id":"123","method":"users","params":{ "endpoint": "getAllUsers", "apiToken": ""}}`
+ +- `{"jsonrpc":"2.0","id":"123","method":"users","params":{ "endpoint": "updateUser", "apiToken": "", "userId": "<_id>", "name": "test999"}}`
+ +- `{"jsonrpc":"2.0","id":"123","method":"users","params":{ "endpoint": "getUser", "apiToken": "", "userId": "<_id>"}}`
+ +- `{"jsonrpc":"2.0","id":"123","method":"users","params":{ "endpoint": "deleteUser", "userId": "<_id>", "apiToken": ""}}` + +``` + +`/home/trout/work/psf/code/bch-dex/apidoc.json`: + +```json +{ + "sampleUrl": null + + } +``` + +`/home/trout/work/psf/code/bch-dex/config/index.js`: + +```js +import common from './env/common.js' + +import development from './env/development.js' +import production from './env/production.js' +import test from './env/test.js' + +const env = process.env.BCH_DEX || 'development' +console.log(`Loading config for this environment: ${env}`) + +let config = development +if (env === 'test') { + config = test +} else if (env === 'prod') { + config = production +} + +export default Object.assign({}, common, config) + +``` + +`/home/trout/work/psf/code/bch-dex/config/logs/index.html`: + +```html + + + + + Logs + + + + + + + + + + +
+
+
+
+
+

+

+
+
+ + +
+
+
+ +
+ +
+
+ +
+
+ +
+
+
+
+ + +
+ + + + + + + + +``` + +`/home/trout/work/psf/code/bch-dex/config/passport.js`: + +```js +// import passport from 'koa-passport'; +import User from '../src/adapters/localdb/models/users.js' +import Strategy from 'passport-local' + +async function passportCallback (email, password, done) { + try { + const user = await User.findOne({ email }) + if (!user) { + return done(null, false) + } + + try { + const isMatch = await user.validatePassword(password) + + if (!isMatch) { + return done(null, false) + } + + done(null, user) + } catch (err) { + done(err) + } + } catch (err) { + return done(err) + } +} + +function applyPassportMods (passport) { + passport.serializeUser((user, done) => { + done(null, user.id) + }) + + passport.deserializeUser(async (id, done) => { + try { + const user = await User.findById(id, '-password') + done(null, user) + } catch (err) { + done(err) + } + }) + + passport.use( + 'local', + new Strategy( + { + usernameField: 'email', + passwordField: 'password' + }, + passportCallback + ) + ) + + return true +} + +export { applyPassportMods, passportCallback } + +``` + +`/home/trout/work/psf/code/bch-dex/config/env/common.js`: + +```js +/* + This file is used to store unsecure, application-specific data common to all + environments. + + Additional Environent Variables: + - CONNECT_PREF: should have a value of 'cr' (default), or 'direct'. This is + used by helia-coord to select a connection preference between peers. Servers + with an ip4 or ip6 address should use 'direct'. +*/ + +/* eslint no-unneeded-ternary:0 */ + +// Hack to get __dirname back. +// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/ +import * as url from 'url' + +// Get the version from the package.json file. +import { readFileSync } from 'fs' +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) +const pkgInfo = JSON.parse(readFileSync(`${__dirname.toString()}/../../package.json`)) + +const version = pkgInfo.version + +const ipfsCoordName = process.env.COORD_NAME + ? process.env.COORD_NAME + : 'ipfs-torlist-service-generic' + +export default { + // Configure TCP port. + port: process.env.PORT || 5700, + + // Password for HTML UI that displays logs. + logPass: 'test', + + // Email server settings if nodemailer email notifications are used. + emailServer: process.env.EMAILSERVER + ? process.env.EMAILSERVER + : 'mail.someserver.com', + emailUser: process.env.EMAILUSER + ? process.env.EMAILUSER + : 'noreply@someserver.com', + emailPassword: process.env.EMAILPASS + ? process.env.EMAILPASS + : 'emailpassword', + + // PSF Web 3 community infrastructure + useFullStackCash: process.env.USE_FULLSTACKCASH ? true : false, + consumerUrl: process.env.CONSUMER_URL + ? process.env.CONSUMER_URL + : 'https://free-bch.fullstack.cash', + // : 'https://wa-usa-bch-consumer.fullstackcash.nl', + + // P2WDB URL that will accept API calls from the p2wdb npm library. + p2wdbUrl: process.env.P2WDB_URL ? process.env.P2WDB_URL : 'https://p2wdb.fullstack.cash', + // p2wdbUrl: process.env.P2WDB_URL ? process.env.P2WDB_URL : 'http://localhost:5010', + + // Enable or Disable the usage of Mongo DB. + noMongo: process.env.NO_MONGO ? true : false, + + // BEGIN WALLET CONFIGURATION + + // BCH Mnemonic for generating encryption keys and payment address + mnemonic: process.env.MNEMONIC ? process.env.MNEMONIC : '', + + // (Optional) use a wallet file generated by psf-bch-wallet. + walletFile: process.env.WALLET_FILE + ? process.env.WALLET_FILE + : `${__dirname.toString()}/../../wallet.json`, + + // Wallet Configuration + // Default value: web3 - connect to bch-api through web 3 JSON RPC over IPFS. + // Alternate value: web2 - connect to bch-api through a web 2 REST API over HTTP. + walletInterface: process.env.WALLET_INTERFACE ? process.env.WALLET_INTERFACE : 'web3', + + // Wallet API Server + // Default web2 server: https://api.fullstack.cash/v5/ + // Default web3 server: https://free-bch.fullstack.cash/ + apiServer: process.env.WALLET_INTERFACE === 'web2' + ? ( + process.env.APISERVER + ? process.env.APISERVER + : 'https://api.fullstack.cash/v5/' + ) + : 'https://free-bch.fullstack.cash/', + + // Basic Authentication Password for connecting to bch-api through a web 2 + // REST API over HTTP. + authPass: process.env.WALLET_AUTH_PASS + ? process.env.WALLET_AUTH_PASS + : '', + + // FullStack.cash account information, used for automatic JWT handling. + getJwtAtStartup: process.env.GET_JWT_AT_STARTUP ? true : false, + authServer: process.env.AUTHSERVER + ? process.env.AUTHSERVER + : 'https://auth.fullstack.cash', + fullstackLogin: process.env.FULLSTACKLOGIN + ? process.env.FULLSTACKLOGIN + : 'demo@demo.com', + fullstackPassword: process.env.FULLSTACKPASS + ? process.env.FULLSTACKPASS + : 'demo', + // authPass: process.env.FULLSTACK_AUTH_PASS + // ? process.env.FULLSTACK_AUTH_PASS + // : '', + + // END WALLET CONFIGURATION + + // BEGIN IPFS CONFIGURATION + + // Debug verbosity level of helia-coord. + // 0 = no debug logs. 3 = maximum logs. + debugLevel: process.env.DEBUG_LEVEL ? parseInt(process.env.DEBUG_LEVEL) : 2, + + // Enable/Disable the IPFS node at startup. Enabled by default. + // useIpfs: process.env.DISABLE_IPFS ? false : true, + useIpfs: false, + + isCircuitRelay: process.env.ENABLE_CIRCUIT_RELAY ? true : false, + // SSL domain used for websocket connection via browsers. + crDomain: process.env.CR_DOMAIN ? process.env.CR_DOMAIN : '', + + // Information passed to other IPFS peers about this node. + apiInfo: 'https://ipfs-service-provider.fullstack.cash/', + + // JSON-LD and Schema.org schema with info about this app. + announceJsonLd: { + '@context': 'https://schema.org/', + '@type': 'WebAPI', + name: ipfsCoordName, + version, + protocol: 'generic-service', + description: 'This is a generic IPFS Serivice Provider that uses JSON RPC over IPFS to communicate with it. This instance has not been customized. Source code: https://github.com/Permissionless-Software-Foundation/ipfs-service-provider', + documentation: 'https://ipfs-service-provider.fullstack.cash/', + provider: { + '@type': 'Organization', + name: 'Permissionless Software Foundation', + url: 'https://PSFoundation.cash' + }, + + // If this node has an IP4 address or domain name used to provide a REST API. + web2Api: process.env.WEB2_API ? process.env.WEB2_API : null + }, + + // P2WDB webhook endpoint + p2wdbPort: process.env.P2WDB_PORT ? process.env.P2WDB_PORT : 5010, + webhookService: process.env.WEBHOOKSERVICE + ? process.env.WEBHOOKSERVICE + : 'http://localhost:5010/webhook', // P2WDB. + p2wdbAppId: process.env.APP_ID ? process.env.APP_ID : 'bch-dex-001', + webhookTarget: process.env.WEBHOOKTARGET + ? process.env.WEBHOOKTARGET + : 'http://localhost:5700/p2wdb', + + // IPFS Ports + ipfsTcpPort: process.env.IPFS_TCP_PORT ? process.env.IPFS_TCP_PORT : 4001, + ipfsWsPort: process.env.IPFS_WS_PORT ? process.env.IPFS_WS_PORT : 4003, + ipfsWebRtcPort: process.env.IPFS_WEB_RTC_PORT ? process.env.IPFS_WEB_RTC_PORT : 4005, + connectPref: process.env.CONNECT_PREF, // Used in helia-coord to select connection preference. + + // Settings for production, using external go-ipfs node. + isProduction: process.env.SVC_ENV === 'prod' ? true : false, + ipfsHost: process.env.IPFS_HOST ? process.env.IPFS_HOST : 'localhost', + ipfsApiPort: process.env.IPFS_API_PORT + ? parseInt(process.env.IPFS_API_PORT) + : 5001, + + chatPubSubChan: 'psf-ipfs-chat-001', + + // IPFS gateway + ipfsGateway: process.env.IPFS_GATEWAY ? process.env.IPFS_GATEWAY : 'https://pin.fullstack.cash/ipfs/download/', + + // This can add specific Circuit Relay v2 servers to connect to. + bootstrapRelays: [ + // v2 Circuit Relay (Token Tiger) + // '/ip4/137.184.93.145/tcp/8001/p2p/12D3KooWGMEKkdJfyZbwdH9EafZbRTtMn7FnhWPrE4MhRty2763g', + + // v2 Circuit Relay server (FullStack.cash) + // '/ip4/78.46.129.7/tcp/4001/p2p/12D3KooWFQ11GQ5NubsJGhYZ4X3wrAGimLevxfm6HPExCrMYhpSL' + ], + + // END IPFS CONFIGURATION + + // Nostr + nostrRelay: process.env.NOSTR_RELAY ? process.env.NOSTR_RELAY : 'wss://nostr-relay.psfoundation.info', + nostrTopic: process.env.NOSTR_TOPIC ? process.env.NOSTR_TOPIC : 'bch-dex-test-topic-02', + + // Account Configuration + disableNewAccounts: process.env.DISABLE_NEW_ACCOUNTS ? true : false, + + // Admin password + adminPassword: process.env.ADMIN_PASSWORD +} + +``` + +`/home/trout/work/psf/code/bch-dex/config/env/production.js`: + +```js +/* + These are the environment settings for the PRODUCTION environment. + This is the environment run with `npm start` if KOA_ENV=production. + This is the environment run inside the Docker container. + + It is assumed the MonogDB Docker container is accessed by port 5555 + so as not to conflict with the default host port of 27017 for MongoDB. +*/ + +export default { + session: 'secret-boilerplate-token', + token: 'secret-jwt-token', + // database: 'mongodb://172.17.0.1:5555/ipfs-service-prod', + database: process.env.DBURL + ? process.env.DBURL + : 'mongodb://172.17.0.1:5555/bch-swap-service-prod', + env: 'prod' +} + +``` + +`/home/trout/work/psf/code/bch-dex/config/env/development.js`: + +```js +/* + These are the environment settings for the DEVELOPMENT environment. + This is the environment run by default with `npm start` if KOA_ENV is not + specified. +*/ + +export default { + session: 'secret-boilerplate-token', + token: 'secret-jwt-token', + database: 'mongodb://localhost:27017/bch-swap-service-dev', + env: 'dev' +} + +``` + +`/home/trout/work/psf/code/bch-dex/config/env/test.js`: + +```js +/* + These are the environment settings for the TEST environment. + This is the environment run with `npm start` if KOA_ENV=test. + This is the environment run by the test suite. +*/ + +export default { + session: 'secret-boilerplate-token', + token: 'secret-jwt-token', + database: 'mongodb://localhost:27017/bch-swap-service-test', + env: 'test', + nostrRelay: 'wss://' +} + +``` + +`/home/trout/work/psf/code/bch-dex/package.json`: + +```json +{ + "name": "bch-dex", + "version": "3.0.0", + "description": "A DEX on BCH for trading SLP tokens.", + "main": "index.js", + "type": "module", + "scripts": { + "start": "node index.js", + "test": "npm run test:all", + "test:all": "export BCH_DEX=test && c8 --reporter=text mocha --exit --timeout 15000 --recursive test/unit test/e2e/automated/", + "test:unit": "export BCH_DEX=test && mocha --exit --timeout 15000 --recursive test/unit/", + "test:e2e:auto": "export BCH_DEX=test && mocha --exit --timeout 30000 test/e2e/automated/", + "test:integration": "export BCH_DEX=test && mocha --exit --timeout 45000 --recursive test/integration", + "test:temp": "export BCH_DEX=test && mocha --exit --timeout 15000 -g '#rate-limit' test/unit/json-rpc/", + "lint": "standard --env mocha --fix", + "docs": "./node_modules/.bin/apidoc -i src/ -o docs", + "coverage": "c8 report --reporter=text-lcov | coveralls", + "coverage:report": "export BCH_DEX=test && c8 --reporter=html mocha --exit --timeout 15000 --recursive test/unit/ test/e2e/automated/" + }, + "author": "Chris Troutner ", + "contributors": [ + "Gary Nadir" + ], + "license": "MIT", + "apidoc": { + "title": "bch-dex", + "url": "localhost:5000" + }, + "repository": "Permissionless-Software-Foundation/bch-dex", + "dependencies": { + "@chainsafe/libp2p-gossipsub": "14.1.0", + "@chainsafe/libp2p-noise": "16.0.1", + "@chainsafe/libp2p-yamux": "7.0.1", + "@chris.troutner/retry-queue": "1.0.8", + "@helia/unixfs": "4.0.2", + "@libp2p/bootstrap": "11.0.26", + "@libp2p/circuit-relay-v2": "3.2.2", + "@libp2p/config": "1.1.0", + "@libp2p/identify": "3.0.22", + "@libp2p/keychain": "5.0.14", + "@libp2p/logger": "5.1.8", + "@libp2p/ping": "2.0.22", + "@libp2p/tcp": "10.1.2", + "@libp2p/webrtc": "5.2.2", + "@libp2p/websockets": "9.2.2", + "@multiformats/multiaddr": "12.3.5", + "axios": "0.27.2", + "bch-message-lib": "2.2.1", + "bch-nostr": "1.3.3", + "bch-token-sweep": "2.2.1", + "bcryptjs": "2.4.3", + "bitcoincashjs-lib": "3.3.3", + "blockstore-fs": "2.0.2", + "datastore-fs": "10.0.2", + "glob": "7.1.6", + "helia": "5.2.1", + "helia-coord": "1.7.2", + "ipfs-coord-esm": "9.1.7", + "ipfs-http-client": "58.0.0", + "jsonrpc-lite": "2.2.0", + "jsonwebtoken": "8.5.1", + "jwt-bch-lib": "1.3.0", + "kcors": "2.2.2", + "koa": "2.13.1", + "koa-bodyparser": "4.3.0", + "koa-convert": "2.0.0", + "koa-generic-session": "2.1.1", + "koa-logger": "3.2.1", + "koa-mount": "4.0.0", + "koa-passport": "4.1.3", + "koa-router": "10.0.0", + "koa-static": "5.0.0", + "koa2-ratelimit": "0.9.1", + "libp2p": "2.7.2", + "line-reader": "0.4.0", + "minimal-slp-wallet": "5.13.2", + "mongoose": "5.13.14", + "node-fetch": "npm:@achingbrain/node-fetch@2.6.7", + "nodemailer": "6.7.5", + "nostr-tools": "2.10.4", + "p2wdb-esm": "2.2.9", + "passport-local": "1.0.0", + "public-ip": "6.0.1", + "winston": "3.3.3", + "winston-daily-rotate-file": "4.5.0" + }, + "devDependencies": { + "apidoc": "0.51.1", + "c8": "7.12.0", + "chai": "4.3.0", + "coveralls": "2.11.4", + "husky": "4.3.8", + "lodash.clonedeep": "4.5.0", + "mocha": "10.0.0", + "semantic-release": "19.0.3", + "sinon": "9.2.4", + "standard": "17.0.0", + "uuid": "8.3.2" + }, + "release": { + "publish": [ + { + "path": "@semantic-release/npm", + "npmPublish": false + } + ] + }, + "husky": { + "hooks": { + "pre-commit": "npm run lint" + } + }, + "standard": { + "ignore": [ + "/test/unit/mocks/**/*.js" + ] + } +} + +``` + +`/home/trout/work/psf/code/bch-dex/tools/burn-and-write.js`: + +```js +/* + This example burns a token and writes an Object as clear-text JSON string to + the P2WDB. The data is crafted to trigger a webhook and add an entry to + Torlist. + + For reference, this curl will delete the webhook in P2WDB: + curl -H "Content-Type: application/json" -X DELETE -d '{ "url": "http://localhost:5002/entry", "appId": "torlist" }' localhost:5001/webhook/ +*/ + +const axios = require('axios') + +// CUSTOMIZE THESE VALUES FOR YOUR USE +// Private key holding the tokens and some BCH. +const WIF = process.env.WIF +if (!WIF) throw new Error('Add WIF to environment variable.') + +// The BCH address corresponding to the WIF. +const BCHADDR = 'bitcoincash:qqp2fu2y8wra8afkefcx04yach8lhuaqvq3dxs5ddv' +const TOKENID = + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0' +const TOKENQTY = 0.01 +const MESSAGE = 'test' +const SIGNATURE = + 'H7Io3txwhjqOYFrAE/xBUzYGow510HL0U+G0LqelbHcDfqH/vQig/xcGfvTTBZpVoZtCoqOdvpPrsAFuL8VHWws=' + +const SERVER = 'http://localhost:5001/entry/write' +// const SERVER = 'http://192.168.0.76:5001/entry/write' +// const SERVER = 'https://p2wdb.fullstackcash.nl/entry/write' + +const now = new Date() + +const dataObj = { + appId: 'torlist', + title: Math.floor(Math.random() * 100000).toString(), + sourceUrl: Math.floor(Math.random() * 100000).toString(), + ipfsUrl: Math.floor(Math.random() * 100000).toString(), + timestamp: now.toISOString(), + localTimestamp: now.toLocaleString() +} +console.log( + `Adding this object to the P2WDB: ${JSON.stringify(dataObj, null, 2)}` +) + +// REST API servers. +const BCHN_MAINNET = 'https://bchn.fullstack.cash/v5/' +// bch-js-examples require code from the main bch-js repo +const BCHJS = require('@psf/bch-js') +const bchjs = new BCHJS({ restURL: BCHN_MAINNET }) + +async function burnAndWrite () { + try { + const keyPair = bchjs.ECPair.fromWIF(WIF) + + // Get UTXOs held by this address. + const data = await bchjs.Electrumx.utxo(BCHADDR) + const utxos = data.utxos + // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`) + + if (utxos.length === 0) throw new Error('No UTXOs to spend! Exiting.') + + // Identify the SLP token UTXOs. + let tokenUtxos = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`tokenUtxos: ${JSON.stringify(tokenUtxos, null, 2)}`) + + // Filter out the non-SLP token UTXOs. + const bchUtxos = utxos.filter((utxo, index) => { + const tokenUtxo = tokenUtxos[index] + + if (!tokenUtxo.isValid) return true + + return false + }) + // console.log(`bchUTXOs: ${JSON.stringify(bchUtxos, null, 2)}`) + + if (bchUtxos.length === 0) { + throw new Error('Wallet does not have a BCH UTXO to pay miner fees.') + } + + // Filter out the token UTXOs that match the user-provided token ID. + tokenUtxos = tokenUtxos.filter((utxo, index) => { + if ( + utxo && // UTXO is associated with a token. + utxo.tokenId === TOKENID && // UTXO matches the token ID. + utxo.utxoType === 'token' // UTXO is not a minting baton. + ) { + return true + } + + return false + }) + // console.log(`tokenUtxos: ${JSON.stringify(tokenUtxos, null, 2)}`); + + if (tokenUtxos.length === 0) { + throw new Error('No token UTXOs for the specified token could be found.') + } + + // Choose a UTXO to pay for the transaction. + const bchUtxo = bchjs.Utxo.findBiggestUtxo(bchUtxos) + console.log(`bchUtxo: ${JSON.stringify(bchUtxo, null, 2)}`) + + // Generate the SLP OP_RETURN. + const slpData = bchjs.SLP.TokenType1.generateBurnOpReturn( + tokenUtxos, + TOKENQTY + ) + + // BEGIN transaction construction. + + // instance of transaction builder + const transactionBuilder = new bchjs.TransactionBuilder() + + // Add the BCH UTXO as input to pay for the transaction. + const originalAmount = bchUtxo.value + transactionBuilder.addInput(bchUtxo.tx_hash, bchUtxo.tx_pos) + + // add each token UTXO as an input. + for (let i = 0; i < tokenUtxos.length; i++) { + transactionBuilder.addInput(tokenUtxos[i].tx_hash, tokenUtxos[i].tx_pos) + } + + // get byte count to calculate fee. paying 1 sat + // Note: This may not be totally accurate. Just guessing on the byteCount size. + // const byteCount = this.BITBOX.BitcoinCash.getByteCount( + // { P2PKH: 3 }, + // { P2PKH: 5 } + // ) + // //console.log(`byteCount: ${byteCount}`) + // const satoshisPerByte = 1.1 + // const txFee = Math.floor(satoshisPerByte * byteCount) + // console.log(`txFee: ${txFee} satoshis\n`) + const txFee = 250 + + // amount to send back to the sending address. It's the original amount - 1 sat/byte for tx size + const remainder = originalAmount - txFee - 546 + if (remainder < 1) { + throw new Error('Selected UTXO does not have enough satoshis') + } + // console.log(`remainder: ${remainder}`) + + // Add OP_RETURN as first output. + transactionBuilder.addOutput(slpData, 0) + + // Send the token back to the same wallet if the user hasn't specified a + // different address. + // if (TO_SLPADDR === "") TO_SLPADDR = walletInfo.slpAddress; + + // Send dust transaction representing tokens being sent. + transactionBuilder.addOutput( + bchjs.SLP.Address.toLegacyAddress(BCHADDR), + 546 + ) + + // Last output: send the BCH change back to the wallet. + transactionBuilder.addOutput( + bchjs.Address.toLegacyAddress(BCHADDR), + remainder + ) + + // Sign the transaction with the private key for the BCH UTXO paying the fees. + let redeemScript + transactionBuilder.sign( + 0, + keyPair, + redeemScript, + transactionBuilder.hashTypes.SIGHASH_ALL, + originalAmount + ) + + // Sign each token UTXO being consumed. + for (let i = 0; i < tokenUtxos.length; i++) { + const thisUtxo = tokenUtxos[i] + + transactionBuilder.sign( + 1 + i, + keyPair, + redeemScript, + transactionBuilder.hashTypes.SIGHASH_ALL, + thisUtxo.value + ) + } + + // build tx + const tx = transactionBuilder.build() + + // output rawhex + const hex = tx.toHex() + // console.log(`Transaction raw hex: `, hex) + + // END transaction construction. + + // Broadcast transation to the network + const txidStr = await bchjs.RawTransactions.sendRawTransaction([hex]) + console.log(`Transaction ID: ${txidStr}`) + + console.log('Check the status of your transaction on this block explorer:') + console.log(`https://explorer.bitcoin.com/bch/tx/${txidStr}`) + console.log(' ') + + // Sleep for 5 seconds. + await bchjs.Util.sleep(5000) + + const bodyData = { + // const result = await axios.post('https://p2wdb.fullstackcash.nl/p2wdb', { + txid: txidStr[0], + message: MESSAGE, + signature: SIGNATURE, + data: JSON.stringify(dataObj) + } + console.log(`bodyData: ${JSON.stringify(bodyData, null, 2)}`) + + // Submit the txid as proof-of-burn to write data to the database. + const result = await axios.post(SERVER, bodyData) + console.log(`Response from API: ${JSON.stringify(result.data, null, 2)}`) + } catch (err) { + console.error('Error in burnTokens: ', err) + console.log(`Error message: ${err.message}`) + } +} +burnAndWrite() + +``` diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 550646b..0000000 --- a/package-lock.json +++ /dev/null @@ -1,24565 +0,0 @@ -{ - "name": "bch-dex", - "version": "3.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "bch-dex", - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "@chainsafe/libp2p-gossipsub": "14.1.0", - "@chainsafe/libp2p-noise": "16.0.1", - "@chainsafe/libp2p-yamux": "7.0.1", - "@chris.troutner/retry-queue": "1.0.8", - "@helia/unixfs": "4.0.2", - "@libp2p/bootstrap": "11.0.26", - "@libp2p/circuit-relay-v2": "3.2.2", - "@libp2p/config": "1.1.0", - "@libp2p/identify": "3.0.22", - "@libp2p/keychain": "5.0.14", - "@libp2p/logger": "5.1.8", - "@libp2p/ping": "2.0.22", - "@libp2p/tcp": "10.1.2", - "@libp2p/webrtc": "5.2.2", - "@libp2p/websockets": "9.2.2", - "@multiformats/multiaddr": "12.3.5", - "axios": "0.27.2", - "bch-message-lib": "2.2.1", - "bch-nostr": "1.3.3", - "bch-token-sweep": "2.2.1", - "bcryptjs": "2.4.3", - "bitcoincashjs-lib": "3.3.3", - "blockstore-fs": "2.0.2", - "datastore-fs": "10.0.2", - "glob": "7.1.6", - "helia": "5.2.1", - "helia-coord": "1.7.2", - "ipfs-coord-esm": "9.1.7", - "ipfs-http-client": "58.0.0", - "jsonrpc-lite": "2.2.0", - "jsonwebtoken": "8.5.1", - "jwt-bch-lib": "1.3.0", - "kcors": "2.2.2", - "koa": "2.13.1", - "koa-bodyparser": "4.3.0", - "koa-convert": "2.0.0", - "koa-generic-session": "2.1.1", - "koa-logger": "3.2.1", - "koa-mount": "4.0.0", - "koa-passport": "4.1.3", - "koa-router": "10.0.0", - "koa-static": "5.0.0", - "koa2-ratelimit": "0.9.1", - "libp2p": "2.7.2", - "line-reader": "0.4.0", - "minimal-slp-wallet": "5.13.2", - "mongoose": "5.13.14", - "node-fetch": "npm:@achingbrain/node-fetch@2.6.7", - "nodemailer": "6.7.5", - "nostr-tools": "2.10.4", - "p2wdb-esm": "2.2.9", - "passport-local": "1.0.0", - "public-ip": "6.0.1", - "winston": "3.3.3", - "winston-daily-rotate-file": "4.5.0" - }, - "devDependencies": { - "apidoc": "0.51.1", - "c8": "7.12.0", - "chai": "4.3.0", - "coveralls": "2.11.4", - "husky": "4.3.8", - "lodash.clonedeep": "4.5.0", - "mocha": "10.0.0", - "semantic-release": "19.0.3", - "sinon": "9.2.4", - "standard": "17.0.0", - "uuid": "8.3.2" - } - }, - "node_modules/@achingbrain/http-parser-js": { - "version": "0.5.9", - "resolved": "http://94.130.170.209:4873/@achingbrain%2fhttp-parser-js/-/http-parser-js-0.5.9.tgz", - "integrity": "sha512-nPuMf2zVzBAGRigH/1jFpb/6HmJsps+15f4BPlGDp3vsjYB2ZgruAErUpKpcFiVRz3DHLXcGNmuwmqZx/sVI7A==", - "license": "MIT", - "dependencies": { - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@achingbrain/nat-port-mapper": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/@achingbrain%2fnat-port-mapper/-/nat-port-mapper-4.0.2.tgz", - "integrity": "sha512-cOV/mPL8ouLko487f37LXl6t76NwksLbyib2Y2T72HK2bm7y2QP0+3+1xxqKqaffoo30CJm8E8IHN9hmJ/LiSA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@achingbrain/ssdp": "^4.1.0", - "@chainsafe/is-ip": "^2.0.2", - "@libp2p/logger": "^5.0.1", - "abort-error": "^1.0.0", - "err-code": "^3.0.1", - "netmask": "^2.0.2", - "p-defer": "^4.0.0", - "race-signal": "^1.1.0", - "xml2js": "^0.6.0" - } - }, - "node_modules/@achingbrain/ssdp": { - "version": "4.2.2", - "resolved": "http://94.130.170.209:4873/@achingbrain%2fssdp/-/ssdp-4.2.2.tgz", - "integrity": "sha512-Lp/IKQY4Gu+2yKmUtlSKYAEdjtP7Zz1MZ3ihDE3o2IdU5WgSBHDi+gOcbmCI74v8PWCqAGT/CYxwMOWqtDgbUg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.0", - "freeport-promise": "^2.0.0", - "merge-options": "^3.0.4", - "xml2js": "^0.6.2" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/@ampproject%2fremapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@assemblyscript/loader": { - "version": "0.9.4", - "resolved": "http://94.130.170.209:4873/@assemblyscript%2floader/-/loader-0.9.4.tgz", - "integrity": "sha512-HazVq9zwTVwGmqdwYzu7WyQ6FQVZ7SwET0KKQuKm55jD0IfUpZgN0OPIiZG3zV1iSrVYcN0bdwLRXI/VNCYsUA==", - "license": "Apache-2.0" - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "http://94.130.170.209:4873/@babel%2fcode-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "http://94.130.170.209:4873/@babel%2fcompat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "http://94.130.170.209:4873/@babel%2fcore/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.4.0", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "http://94.130.170.209:4873/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2fgenerator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2fhelper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "http://94.130.170.209:4873/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "http://94.130.170.209:4873/@babel%2fhelper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "http://94.130.170.209:4873/@babel%2fhelper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "http://94.130.170.209:4873/@babel%2fhelper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "http://94.130.170.209:4873/@babel%2fhelper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "http://94.130.170.209:4873/@babel%2fhelper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "http://94.130.170.209:4873/@babel%2fhelper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2fhelpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2fparser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.27.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "http://94.130.170.209:4873/@babel%2fplugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2fruntime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "license": "MIT", - "peer": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "http://94.130.170.209:4873/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT", - "peer": true - }, - "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2ftemplate/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2ftraverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse--for-generate-function-map": { - "name": "@babel/traverse", - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2ftraverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse--for-generate-function-map/node_modules/debug": { - "version": "4.4.0", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.4.0", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@babel%2ftypes/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "http://94.130.170.209:4873/@bcoe%2fv8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@chainsafe/as-chacha20poly1305": { - "version": "0.1.0", - "resolved": "http://94.130.170.209:4873/@chainsafe%2fas-chacha20poly1305/-/as-chacha20poly1305-0.1.0.tgz", - "integrity": "sha512-BpNcL8/lji/GM3+vZ/bgRWqJ1q5kwvTFmGPk7pxm/QQZDbaMI98waOHjEymTjq2JmdD/INdNBFOVSyJofXg7ew==", - "license": "Apache-2.0" - }, - "node_modules/@chainsafe/as-sha256": { - "version": "0.6.1", - "resolved": "http://94.130.170.209:4873/@chainsafe%2fas-sha256/-/as-sha256-0.6.1.tgz", - "integrity": "sha512-bYDOK5aK7NYE/ZZ/A3C+Q8ZrEWdzpH80fcEotjgX3pmntv3SJfOTTYE53mjnPSEZFlv/rST0H/ZETsz8Wab9iw==", - "license": "Apache-2.0" - }, - "node_modules/@chainsafe/is-ip": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/@chainsafe%2fis-ip/-/is-ip-2.0.2.tgz", - "integrity": "sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA==", - "license": "MIT" - }, - "node_modules/@chainsafe/libp2p-gossipsub": { - "version": "14.1.0", - "resolved": "http://94.130.170.209:4873/@chainsafe%2flibp2p-gossipsub/-/libp2p-gossipsub-14.1.0.tgz", - "integrity": "sha512-nzFBbHOoRFa/bXUSzmJaXOgHI+EttTldhLJ33yWcM0DxnWhLKychHkCDLoJO3THa1+dnzrDJoxj3N3/V0WoPVw==", - "license": "Apache-2.0", - "dependencies": { - "@libp2p/crypto": "^5.0.0", - "@libp2p/interface": "^2.0.0", - "@libp2p/interface-internal": "^2.0.0", - "@libp2p/peer-id": "^5.0.0", - "@libp2p/pubsub": "^10.0.0", - "@multiformats/multiaddr": "^12.1.14", - "denque": "^2.1.0", - "it-length-prefixed": "^9.0.4", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.3", - "multiformats": "^13.0.1", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.0.1" - }, - "engines": { - "npm": ">=8.7.0" - } - }, - "node_modules/@chainsafe/libp2p-noise": { - "version": "16.0.1", - "resolved": "http://94.130.170.209:4873/@chainsafe%2flibp2p-noise/-/libp2p-noise-16.0.1.tgz", - "integrity": "sha512-U3fbVFbznVoHRbv+3mhMz8QPWSBF46erXxhDlFuhy55XTluVsQTvsokf/NnvU9zrjEpNfOnGcl36JkiKj7Bj3w==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/as-chacha20poly1305": "^0.1.0", - "@chainsafe/as-sha256": "^0.6.1", - "@libp2p/crypto": "^5.0.0", - "@libp2p/interface": "^2.0.0", - "@libp2p/peer-id": "^5.0.0", - "@noble/ciphers": "^0.6.0", - "@noble/curves": "^1.1.0", - "@noble/hashes": "^1.3.1", - "it-length-prefixed": "^9.0.1", - "it-length-prefixed-stream": "^1.0.0", - "it-pair": "^2.0.6", - "it-pipe": "^3.0.1", - "it-stream-types": "^2.0.1", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^5.0.0", - "wherearewe": "^2.0.1" - } - }, - "node_modules/@chainsafe/libp2p-yamux": { - "version": "7.0.1", - "resolved": "http://94.130.170.209:4873/@chainsafe%2flibp2p-yamux/-/libp2p-yamux-7.0.1.tgz", - "integrity": "sha512-949MI0Ll0AsYq1gUETZmL/MijwX0jilOQ1i4s8wDEXGiMhuPWWiMsPgEnX6n+VzFmTrfNYyGaaJj5/MqxV9y/g==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.0.0", - "@libp2p/utils": "^6.0.0", - "get-iterator": "^2.0.1", - "it-foreach": "^2.0.6", - "it-pushable": "^3.2.3", - "it-stream-types": "^2.0.1", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@chainsafe/netmask": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/@chainsafe%2fnetmask/-/netmask-2.0.0.tgz", - "integrity": "sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg==", - "license": "MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1" - } - }, - "node_modules/@chris.troutner/bip32-utils": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/@chris.troutner%2fbip32-utils/-/bip32-utils-1.0.5.tgz", - "integrity": "sha512-pa9dh5VpPmfol1bdLy+FyqONmxlf/QH6Q01a57OP6C9gTVOZM1Rt0kCLXxXKC6e2AnNIrXpYN1UtlyBm+r6P0g==", - "license": "MIT", - "dependencies": { - "keccak": "^3.0.1", - "tape": "*" - }, - "engines": { - "node": ">=10.15.1" - } - }, - "node_modules/@chris.troutner/retry-queue": { - "version": "1.0.8", - "resolved": "http://94.130.170.209:4873/@chris.troutner%2fretry-queue/-/retry-queue-1.0.8.tgz", - "integrity": "sha512-ucyUGWTeXhOcXLglwb8alR3dNATPy+3vGea2uQJ0J8jnJufWrUr/NEq4b53op1tOTF029qrun6OmIN6Ls58pqw==", - "license": "MIT", - "dependencies": { - "p-queue": "7.3.0", - "p-retry": "5.1.1" - } - }, - "node_modules/@chris.troutner/retry-queue-commonjs": { - "version": "1.0.8", - "resolved": "http://94.130.170.209:4873/@chris.troutner%2fretry-queue-commonjs/-/retry-queue-commonjs-1.0.8.tgz", - "integrity": "sha512-jEHmCKffjIXTm0d/YcRQzCDPbzW2NFTEO72b1vmETnmATO57MmO39F37gEaq7J7lnF5JMxuM3Oq+FWa1L7HXxA==", - "license": "MIT", - "dependencies": { - "p-queue": "4.0.0", - "p-retry": "4.6.2" - } - }, - "node_modules/@chris.troutner/retry-queue-commonjs/node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "http://94.130.170.209:4873/@types%2fretry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "license": "MIT" - }, - "node_modules/@chris.troutner/retry-queue-commonjs/node_modules/eventemitter3": { - "version": "3.1.2", - "resolved": "http://94.130.170.209:4873/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "license": "MIT" - }, - "node_modules/@chris.troutner/retry-queue-commonjs/node_modules/p-queue": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/p-queue/-/p-queue-4.0.0.tgz", - "integrity": "sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^3.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@chris.troutner/retry-queue-commonjs/node_modules/p-retry": { - "version": "4.6.2", - "resolved": "http://94.130.170.209:4873/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "http://94.130.170.209:4873/@colors%2fcolors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/@dabh%2fdiagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", - "license": "MIT", - "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "http://94.130.170.209:4873/@discoveryjs%2fjson-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.16.17", - "resolved": "http://94.130.170.209:4873/@esbuild%2flinux-x64/-/linux-x64-0.16.17.tgz", - "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "http://94.130.170.209:4873/@eslint-community%2feslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "http://94.130.170.209:4873/@eslint-community%2fregexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "http://94.130.170.209:4873/@eslint%2feslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "http://94.130.170.209:4873/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "http://94.130.170.209:4873/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "http://94.130.170.209:4873/@eslint%2fjs/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/@fastify%2fbusboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/@hapi/bourne": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/@hapi%2fbourne/-/bourne-3.0.0.tgz", - "integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==", - "license": "BSD-3-Clause" - }, - "node_modules/@helia/bitswap": { - "version": "2.0.5", - "resolved": "http://94.130.170.209:4873/@helia%2fbitswap/-/bitswap-2.0.5.tgz", - "integrity": "sha512-LdvjagmArJ6d67yFKIxU+H29be+u8teP3yQzL8CLPU2J6uG66Pwh0Bb7bU+D1uUyUcfLS4TqDrRh1VKR+EghYw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@helia/interface": "^5.2.1", - "@helia/utils": "^1.2.2", - "@libp2p/interface": "^2.2.1", - "@libp2p/logger": "^5.1.4", - "@libp2p/peer-collections": "^6.0.12", - "@libp2p/utils": "^6.2.1", - "@multiformats/multiaddr": "^12.3.3", - "any-signal": "^4.1.1", - "interface-blockstore": "^5.3.1", - "interface-store": "^6.0.2", - "it-drain": "^3.0.7", - "it-length-prefixed": "^10.0.1", - "it-length-prefixed-stream": "^1.2.0", - "it-map": "^3.1.1", - "it-pipe": "^3.0.1", - "it-take": "^3.0.6", - "multiformats": "^13.3.1", - "p-defer": "^4.0.1", - "progress-events": "^1.0.1", - "protons-runtime": "^5.5.0", - "race-event": "^1.3.0", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@helia/bitswap/node_modules/it-length-prefixed": { - "version": "10.0.1", - "resolved": "http://94.130.170.209:4873/it-length-prefixed/-/it-length-prefixed-10.0.1.tgz", - "integrity": "sha512-BhyluvGps26u9a7eQIpOI1YN7mFgi8lFwmiPi07whewbBARKAG9LE09Odc8s1Wtbt2MB6rNUrl7j9vvfXTJwdQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-reader": "^6.0.1", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.1", - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@helia/block-brokers": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/@helia%2fblock-brokers/-/block-brokers-4.1.0.tgz", - "integrity": "sha512-pzIhJeDLdF0VFkj9+LeLI6ZZORdH6/FwV7Q+IlIi2m5kAExqaYh8Oob6Dc7J5luu1atf69q4PWNIPYRiySmsmg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@helia/bitswap": "^2.0.5", - "@helia/interface": "^5.2.1", - "@helia/utils": "^1.2.2", - "@libp2p/interface": "^2.2.1", - "@libp2p/utils": "^6.2.1", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "@multiformats/multiaddr-to-uri": "^11.0.0", - "interface-blockstore": "^5.3.1", - "interface-store": "^6.0.2", - "multiformats": "^13.3.1", - "progress-events": "^1.0.1" - } - }, - "node_modules/@helia/delegated-routing-v1-http-api-client": { - "version": "4.2.2", - "resolved": "http://94.130.170.209:4873/@helia%2fdelegated-routing-v1-http-api-client/-/delegated-routing-v1-http-api-client-4.2.2.tgz", - "integrity": "sha512-SQuyIZAbfvXUkGiralGI7sWq44Ztd1Cf+3pz/paCzq1J3Jvl7JnofWB0spsZjwSu0jYPdwAL60Nmg1TSTm6ZVg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.2.0", - "@libp2p/logger": "^5.0.1", - "@libp2p/peer-id": "^5.0.1", - "@multiformats/multiaddr": "^12.3.1", - "any-signal": "^4.1.1", - "browser-readablestream-to-it": "^2.0.7", - "ipns": "^10.0.0", - "it-first": "^3.0.6", - "it-map": "^3.1.1", - "it-ndjson": "^1.0.7", - "multiformats": "^13.3.0", - "p-defer": "^4.0.1", - "p-queue": "^8.0.1", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@helia/delegated-routing-v1-http-api-client/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/@helia/delegated-routing-v1-http-api-client/node_modules/p-queue": { - "version": "8.1.0", - "resolved": "http://94.130.170.209:4873/p-queue/-/p-queue-8.1.0.tgz", - "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@helia/interface": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/@helia%2finterface/-/interface-5.2.1.tgz", - "integrity": "sha512-8eH3wOoOAHqcux2erXOm33oFBtKdpfHclepzn28bBYEl5wXhrc9JFeo2X3SYJeE0o/jxq0L39BprkYjgSSC91Q==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.2.1", - "@multiformats/dns": "^1.0.6", - "interface-blockstore": "^5.3.1", - "interface-datastore": "^8.3.1", - "interface-store": "^6.0.2", - "multiformats": "^13.3.1", - "progress-events": "^1.0.1" - } - }, - "node_modules/@helia/routers": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/@helia%2frouters/-/routers-3.0.1.tgz", - "integrity": "sha512-Eshr/8XJU4c0H8s1m5oBFB2YM0n3HBbxB3ny8DbsRFS8cAQ/L8ujnQomniMjZuuOhcNz8EEGwkUc07HCtAqAFA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@helia/delegated-routing-v1-http-api-client": "^4.2.1", - "@helia/interface": "^5.2.1", - "@libp2p/interface": "^2.2.1", - "@libp2p/peer-id": "^5.0.8", - "@multiformats/uri-to-multiaddr": "^8.0.0", - "ipns": "^10.0.0", - "it-first": "^3.0.6", - "it-map": "^3.1.1", - "multiformats": "^13.3.1", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@helia/unixfs": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/@helia%2funixfs/-/unixfs-4.0.2.tgz", - "integrity": "sha512-7xrIQsbU4MfTlgFsBuIRARAAXzD+rx/RsSugv/CrZSp0AA57Eg2iKxbQ+UkunobDUKf5YecoMf1iLCqM4zjpbw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@helia/interface": "^5.2.0", - "@ipld/dag-pb": "^4.1.3", - "@libp2p/interface": "^2.2.1", - "@libp2p/logger": "^5.1.4", - "@multiformats/murmur3": "^2.1.8", - "hamt-sharding": "^3.0.6", - "interface-blockstore": "^5.3.1", - "ipfs-unixfs": "^11.2.0", - "ipfs-unixfs-exporter": "^13.6.1", - "ipfs-unixfs-importer": "^15.3.1", - "it-all": "^3.0.6", - "it-glob": "^3.0.1", - "it-last": "^3.0.6", - "it-pipe": "^3.0.1", - "merge-options": "^3.0.4", - "multiformats": "^13.3.1", - "progress-events": "^1.0.1", - "sparse-array": "^1.3.2", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@helia/utils": { - "version": "1.2.2", - "resolved": "http://94.130.170.209:4873/@helia%2futils/-/utils-1.2.2.tgz", - "integrity": "sha512-f8TC+gTQkMTVPaSDB8sSV+8W5/QIMX9XNWY2Xf0Y/WVzGm+Nz5o5wpVTT1kgBpILngXHSs4Xo+6aBQlafL15EA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@helia/interface": "^5.2.1", - "@ipld/dag-cbor": "^9.2.2", - "@ipld/dag-json": "^10.2.3", - "@ipld/dag-pb": "^4.1.3", - "@libp2p/interface": "^2.5.0", - "@libp2p/logger": "^5.1.8", - "@libp2p/utils": "^6.5.1", - "@multiformats/dns": "^1.0.6", - "any-signal": "^4.1.1", - "blockstore-core": "^5.0.2", - "cborg": "^4.2.6", - "interface-blockstore": "^5.3.1", - "interface-datastore": "^8.3.1", - "interface-store": "^6.0.2", - "it-drain": "^3.0.7", - "it-filter": "^3.1.1", - "it-foreach": "^2.1.1", - "it-merge": "^3.0.5", - "mortice": "^3.0.6", - "multiformats": "^13.3.1", - "p-defer": "^4.0.1", - "progress-events": "^1.0.1", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "http://94.130.170.209:4873/@humanwhocodes%2fconfig-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/@humanwhocodes%2fmodule-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/@humanwhocodes%2fobject-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@ipld/dag-cbor": { - "version": "9.2.2", - "resolved": "http://94.130.170.209:4873/@ipld%2fdag-cbor/-/dag-cbor-9.2.2.tgz", - "integrity": "sha512-uIEOuruCqKTP50OBWwgz4Js2+LhiBQaxc57cnP71f45b1mHEAo1OCR1Zn/TbvSW/mV1x+JqhacIktkKyaYqhCw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "cborg": "^4.0.0", - "multiformats": "^13.1.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@ipld/dag-json": { - "version": "10.2.3", - "resolved": "http://94.130.170.209:4873/@ipld%2fdag-json/-/dag-json-10.2.3.tgz", - "integrity": "sha512-itacv1j1hvYgLox2B42Msn70QLzcr0MEo5yGIENuw2SM/lQzq9bmBiMky+kDsIrsqqblKTXcHBZnnmK7D4a6ZQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "cborg": "^4.0.0", - "multiformats": "^13.1.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@ipld/dag-pb": { - "version": "4.1.3", - "resolved": "http://94.130.170.209:4873/@ipld%2fdag-pb/-/dag-pb-4.1.3.tgz", - "integrity": "sha512-ueULCaaSCcD+dQga6nKiRr+RSeVgdiYiEPKVUu5iQMNYDN+9osd0KpR3UDd9uQQ+6RWuv9L34SchfEwj7YIbOA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^13.1.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@ipshipyard/libp2p-auto-tls": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/@ipshipyard%2flibp2p-auto-tls/-/libp2p-auto-tls-1.0.0.tgz", - "integrity": "sha512-wV1smnqbg3xUCHmPB8KWFuP8G9MKlx8KDuiJvhCWPi7B03xJq2FMybMDPI8tM9boa9sHD+5+NFu+Teo3Lz76fw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@libp2p/crypto": "^5.0.9", - "@libp2p/http-fetch": "^2.1.0", - "@libp2p/interface": "^2.4.0", - "@libp2p/interface-internal": "^2.2.2", - "@libp2p/keychain": "^5.0.12", - "@libp2p/utils": "^6.3.1", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "@peculiar/x509": "^1.12.3", - "acme-client": "^5.4.0", - "any-signal": "^4.1.1", - "delay": "^6.0.0", - "interface-datastore": "^8.3.1", - "multiformats": "^13.3.1", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@ipshipyard/node-datachannel": { - "version": "0.26.5", - "resolved": "http://94.130.170.209:4873/@ipshipyard%2fnode-datachannel/-/node-datachannel-0.26.5.tgz", - "integrity": "sha512-GOxqgCI4scLTSFwFO7ClK5eDgSCJQgf7mbmJu0qgPu9zNlRp0VJl6rNJScQBllHP7IhmBf3VXRWVvwWfOrplww==", - "hasInstallScript": true, - "license": "MPL 2.0", - "dependencies": { - "prebuild-install": "^7.1.2" - }, - "engines": { - "node": ">=18.20.0" - } - }, - "node_modules/@isaacs/ttlcache": { - "version": "1.4.1", - "resolved": "http://94.130.170.209:4873/@isaacs%2fttlcache/-/ttlcache-1.4.1.tgz", - "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@istanbuljs%2fload-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "http://94.130.170.209:4873/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "peer": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/esprima": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "peer": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "http://94.130.170.209:4873/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "license": "MIT", - "peer": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "license": "MIT", - "peer": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "license": "MIT", - "peer": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "license": "MIT", - "peer": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "http://94.130.170.209:4873/@istanbuljs%2fschema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/create-cache-key-function": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/@jest%2fcreate-cache-key-function/-/create-cache-key-function-29.7.0.tgz", - "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/@jest%2fenvironment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/@jest%2ffake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "http://94.130.170.209:4873/@jest%2fschemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/@jest%2ftransform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "http://94.130.170.209:4873/@jest%2ftypes/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "http://94.130.170.209:4873/@jridgewell%2fgen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "http://94.130.170.209:4873/@jridgewell%2fresolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/@jridgewell%2fset-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "http://94.130.170.209:4873/@jridgewell%2fsource-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "http://94.130.170.209:4873/@jridgewell%2fsourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "http://94.130.170.209:4873/@jridgewell%2ftrace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "http://94.130.170.209:4873/@leichtgewicht%2fip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "license": "MIT" - }, - "node_modules/@libp2p/autonat": { - "version": "2.0.29", - "resolved": "http://94.130.170.209:4873/@libp2p%2fautonat/-/autonat-2.0.29.tgz", - "integrity": "sha512-8vpqEtEjDa5TU+D8gMF01yPqEH9actMDKlqi731OnsChOPfjMnvdm0jYd82u/OFygoibh6PGaKpzekspfuHXQQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@libp2p/interface-internal": "^2.3.10", - "@libp2p/peer-collections": "^6.0.26", - "@libp2p/peer-id": "^5.1.1", - "@libp2p/utils": "^6.6.1", - "@multiformats/multiaddr": "^12.3.3", - "any-signal": "^4.1.1", - "it-protobuf-stream": "^2.0.1", - "multiformats": "^13.3.1", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/autonat/node_modules/it-byte-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/it-byte-stream/-/it-byte-stream-2.0.1.tgz", - "integrity": "sha512-WccB179tWRNjTyXJ9wLshQdKSLdVIexmnNjLfCT7UnsiLisTVUY092YqFhkL+da1WFR0paGzB24L+pAzFhRI4Q==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "it-queueless-pushable": "^2.0.0", - "it-stream-types": "^2.0.2", - "race-signal": "^1.1.3", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/autonat/node_modules/it-length-prefixed-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/it-length-prefixed-stream/-/it-length-prefixed-stream-2.0.1.tgz", - "integrity": "sha512-TFohjVrQKRLQgRrPdVL9ARqP4CHUHnsRkbkX4nEhSOBjOvZtVV/pHh5Z2C8EH50MnfNDjVSKvEbaIFVLS3/QMA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "it-byte-stream": "^2.0.0", - "it-stream-types": "^2.0.2", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/autonat/node_modules/it-protobuf-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/it-protobuf-stream/-/it-protobuf-stream-2.0.1.tgz", - "integrity": "sha512-szhw8w2aIENUa1yv0vFgGZDs7e81dQ/7dM10c4Rf6+rs5tqzWVCSLbpgxIYM0cA8KlcI66XGdzu6lyYp6jKdvw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "it-length-prefixed-stream": "^2.0.0", - "it-stream-types": "^2.0.2", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/autonat/node_modules/it-queueless-pushable": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/it-queueless-pushable/-/it-queueless-pushable-2.0.0.tgz", - "integrity": "sha512-MlNnefWT/ntv5fesrHpxwVIu6ZdtlkN0A4aaJiE5wnmPMBv9ttiwX3UEMf78dFwIj5ZNaU9usYXg4swMEpUNJQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "p-defer": "^4.0.1", - "race-signal": "^1.1.3" - } - }, - "node_modules/@libp2p/bootstrap": { - "version": "11.0.26", - "resolved": "http://94.130.170.209:4873/@libp2p%2fbootstrap/-/bootstrap-11.0.26.tgz", - "integrity": "sha512-Q2r3RsedwpgUv8gtsapsegs8wxGAbm2rUTjEuTK3wasQoixZ2Q6Kjw4hq+cq4SlbH3XaAO2UXqUEhGT2KLhfoQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.6.0", - "@libp2p/interface-internal": "^2.3.4", - "@libp2p/peer-id": "^5.0.13", - "@multiformats/mafmt": "^12.1.6", - "@multiformats/multiaddr": "^12.3.3" - } - }, - "node_modules/@libp2p/circuit-relay-v2": { - "version": "3.2.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2fcircuit-relay-v2/-/circuit-relay-v2-3.2.2.tgz", - "integrity": "sha512-NoPJt64AaTFwhsbr+fxi5n4lqCHs9QcfwiftDp/11lX7giNXI6RnIMBfPgqXniAN8eKhSSMktqGjDyFE21eiwg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.12", - "@libp2p/interface": "^2.6.0", - "@libp2p/interface-internal": "^2.3.4", - "@libp2p/peer-collections": "^6.0.20", - "@libp2p/peer-id": "^5.0.13", - "@libp2p/peer-record": "^8.0.20", - "@libp2p/utils": "^6.5.4", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "any-signal": "^4.1.1", - "it-protobuf-stream": "^1.1.5", - "it-stream-types": "^2.0.2", - "multiformats": "^13.3.1", - "nanoid": "^5.0.9", - "progress-events": "^1.0.1", - "protons-runtime": "^5.5.0", - "retimeable-signal": "^1.0.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/circuit-relay-v2/node_modules/nanoid": { - "version": "5.1.5", - "resolved": "http://94.130.170.209:4873/nanoid/-/nanoid-5.1.5.tgz", - "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, - "node_modules/@libp2p/config": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@libp2p%2fconfig/-/config-1.1.0.tgz", - "integrity": "sha512-dowkLTEPvfvjgA0DrAMJFNM8MaLU7lOgWV2TWK4zUYPU4+JJYBF3arDoD/zSYj2agt5ABERk39F3puMK0sxv4A==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.12", - "@libp2p/interface": "^2.6.0", - "@libp2p/keychain": "^5.1.0", - "@libp2p/logger": "^5.1.9", - "interface-datastore": "^8.3.1" - } - }, - "node_modules/@libp2p/config/node_modules/@libp2p/keychain": { - "version": "5.2.0", - "resolved": "http://94.130.170.209:4873/@libp2p%2fkeychain/-/keychain-5.2.0.tgz", - "integrity": "sha512-m/jJ58xYl4o5Z/pRXSZBv19OaNgETdgLtrLc2u+CzvEWLEJSCei1ws9y83t34NSdbznepTvATZtpeJrlsCSbLQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.1.0", - "@libp2p/interface": "^2.8.0", - "@noble/hashes": "^1.6.1", - "asn1js": "^3.0.5", - "interface-datastore": "^8.3.1", - "merge-options": "^3.0.4", - "multiformats": "^13.3.1", - "sanitize-filename": "^1.6.3", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/config/node_modules/@libp2p/logger": { - "version": "5.1.14", - "resolved": "http://94.130.170.209:4873/@libp2p%2flogger/-/logger-5.1.14.tgz", - "integrity": "sha512-rJeEq7iuKMMjel0zzH10dXzcWn4Q2yywbv5vM9B1xTQpkD4uxTbBlQs+EL9+pmwaaQrrriEGqluZOTzHvUzJUg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@multiformats/multiaddr": "^12.3.3", - "interface-datastore": "^8.3.1", - "multiformats": "^13.3.1", - "weald": "^1.0.4" - } - }, - "node_modules/@libp2p/crypto": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/@libp2p%2fcrypto/-/crypto-5.1.0.tgz", - "integrity": "sha512-hcmScz9m7Ae7R7b/w3x9DX+i60ZIUVsMmsHyIo0vSlGsxO0+tyM4UKUia5EpSp/i1SB/W1IFXxlURwpiX7R5eQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@noble/curves": "^1.7.0", - "@noble/hashes": "^1.6.1", - "multiformats": "^13.3.1", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/dcutr": { - "version": "2.0.28", - "resolved": "http://94.130.170.209:4873/@libp2p%2fdcutr/-/dcutr-2.0.28.tgz", - "integrity": "sha512-qH8jpU/qZH0/F3GvIY5hGOZhRc/C3oPV90P7zVR6w1NUSvgRU6erp0/N0J0v5YjAxpYSCsgz+Wtb5ggBhGqd/w==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@libp2p/interface-internal": "^2.3.10", - "@libp2p/utils": "^6.6.1", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "delay": "^6.0.0", - "it-protobuf-stream": "^2.0.1", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/dcutr/node_modules/it-byte-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/it-byte-stream/-/it-byte-stream-2.0.1.tgz", - "integrity": "sha512-WccB179tWRNjTyXJ9wLshQdKSLdVIexmnNjLfCT7UnsiLisTVUY092YqFhkL+da1WFR0paGzB24L+pAzFhRI4Q==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "it-queueless-pushable": "^2.0.0", - "it-stream-types": "^2.0.2", - "race-signal": "^1.1.3", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/dcutr/node_modules/it-length-prefixed-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/it-length-prefixed-stream/-/it-length-prefixed-stream-2.0.1.tgz", - "integrity": "sha512-TFohjVrQKRLQgRrPdVL9ARqP4CHUHnsRkbkX4nEhSOBjOvZtVV/pHh5Z2C8EH50MnfNDjVSKvEbaIFVLS3/QMA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "it-byte-stream": "^2.0.0", - "it-stream-types": "^2.0.2", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/dcutr/node_modules/it-protobuf-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/it-protobuf-stream/-/it-protobuf-stream-2.0.1.tgz", - "integrity": "sha512-szhw8w2aIENUa1yv0vFgGZDs7e81dQ/7dM10c4Rf6+rs5tqzWVCSLbpgxIYM0cA8KlcI66XGdzu6lyYp6jKdvw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "it-length-prefixed-stream": "^2.0.0", - "it-stream-types": "^2.0.2", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/dcutr/node_modules/it-queueless-pushable": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/it-queueless-pushable/-/it-queueless-pushable-2.0.0.tgz", - "integrity": "sha512-MlNnefWT/ntv5fesrHpxwVIu6ZdtlkN0A4aaJiE5wnmPMBv9ttiwX3UEMf78dFwIj5ZNaU9usYXg4swMEpUNJQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "p-defer": "^4.0.1", - "race-signal": "^1.1.3" - } - }, - "node_modules/@libp2p/http-fetch": { - "version": "2.2.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2fhttp-fetch/-/http-fetch-2.2.2.tgz", - "integrity": "sha512-dMPo2pe2h/AHAljgwDEErdiB8JbiJM5b0LzuF/Yq4HcplfJZf33VtzUHN1n8x+3K+F8fntWUKN30SwSisSoVaw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@achingbrain/http-parser-js": "^0.5.8", - "@libp2p/crypto": "^5.0.6", - "@libp2p/interface": "^2.2.0", - "@libp2p/interface-internal": "^2.0.10", - "@libp2p/peer-id": "^5.0.7", - "@multiformats/multiaddr": "^12.3.0", - "@multiformats/multiaddr-to-uri": "^11.0.0", - "http-cookie-agent": "^6.0.7", - "p-defer": "^4.0.1", - "tough-cookie": "^5.0.0", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0", - "undici": "^6.21.0" - } - }, - "node_modules/@libp2p/http-fetch/node_modules/undici": { - "version": "6.21.2", - "resolved": "http://94.130.170.209:4873/undici/-/undici-6.21.2.tgz", - "integrity": "sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==", - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, - "node_modules/@libp2p/identify": { - "version": "3.0.22", - "resolved": "http://94.130.170.209:4873/@libp2p%2fidentify/-/identify-3.0.22.tgz", - "integrity": "sha512-NrnFliv2oaS9B1oOmdICaSeIN+3jpbmcVGDuVOSr9mQn5Rn9myds91YuBHSgifYeBWFgaz8XiWxsceYo16srFg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.12", - "@libp2p/interface": "^2.6.0", - "@libp2p/interface-internal": "^2.3.4", - "@libp2p/peer-id": "^5.0.13", - "@libp2p/peer-record": "^8.0.20", - "@libp2p/utils": "^6.5.4", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "it-drain": "^3.0.7", - "it-parallel": "^3.0.8", - "it-protobuf-stream": "^1.1.5", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/interface": { - "version": "2.8.0", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface/-/interface-2.8.0.tgz", - "integrity": "sha512-QnIjqqUv2aDiBho6OGcNNhLT3Ac4RKrh41qoQmqG6csMRkUUx/xZMkfFJx3j0wGCIP8GS4sGspkTt4wCpPbSWw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@multiformats/multiaddr": "^12.3.3", - "it-pushable": "^3.2.3", - "it-stream-types": "^2.0.2", - "multiformats": "^13.3.1", - "progress-events": "^1.0.1", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/interface-connection": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-connection/-/interface-connection-3.1.1.tgz", - "integrity": "sha512-+hxfYLv4jf+MruQEJiJeIyo/wI33/53wRL0XJTkxwQQPAkLHfZWCUY4kY9sXALd3+ASjXAENvJj9VvzZTlkRDQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface-peer-id": "^2.0.0", - "@libp2p/interfaces": "^3.0.0", - "@multiformats/multiaddr": "^12.0.0", - "it-stream-types": "^1.0.4", - "uint8arraylist": "^2.1.2" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-connection/node_modules/@libp2p/interface-peer-id": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-peer-id/-/interface-peer-id-2.0.2.tgz", - "integrity": "sha512-9pZp9zhTDoVwzRmp0Wtxw0Yfa//Yc0GqBCJi3EznBDE6HGIAVvppR91wSh2knt/0eYg0AQj7Y35VSesUTzMCUg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^11.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-connection/node_modules/it-stream-types": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/it-stream-types/-/it-stream-types-1.0.5.tgz", - "integrity": "sha512-I88Ka1nHgfX62e5mi5LLL+oueqz7Ltg0bUdtsUKDe9SoUqbQPf2Mp5kxDTe9pNhHQGs4pvYPAINwuZ1HAt42TA==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-connection/node_modules/multiformats": { - "version": "11.0.2", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-internal": { - "version": "2.3.10", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-internal/-/interface-internal-2.3.10.tgz", - "integrity": "sha512-ULUilEvRUVMy0qB7VWkW0v7Ceg66VqkZ0pheff3gkHj5tXaH4VNE0SSFKfK7b8dK1Wd/HBwS2QheX5uLrEt84w==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@libp2p/peer-collections": "^6.0.26", - "@multiformats/multiaddr": "^12.3.3", - "progress-events": "^1.0.1" - } - }, - "node_modules/@libp2p/interface-keychain": { - "version": "1.0.8", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-keychain/-/interface-keychain-1.0.8.tgz", - "integrity": "sha512-JqI7mMthIafP8cGhhsmIs/M0Ey+ivHLcpzqbVVzMFiFVi1dC03R7EHlalcaPn8yaLSvlmI0MqjC8lJYuvlFjfw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^10.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-keychain/node_modules/multiformats": { - "version": "10.0.3", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-10.0.3.tgz", - "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-peer-id": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-peer-id/-/interface-peer-id-1.1.2.tgz", - "integrity": "sha512-S5iyVzG2EUgxm4NLe8W4ya9kpKuGfHs7Wbbos0wOUB4GXsbIKgOOxIr4yf+xGFgtEBaoximvlLkpob6dn8VFgA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^10.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-peer-id/node_modules/multiformats": { - "version": "10.0.3", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-10.0.3.tgz", - "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-peer-info": { - "version": "1.0.10", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-peer-info/-/interface-peer-info-1.0.10.tgz", - "integrity": "sha512-HQlo8NwQjMyamCHJrnILEZz+YwEOXCB2sIIw3slIrhVUYeYlTaia1R6d9umaAeLHa255Zmdm4qGH8rJLRqhCcg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface-peer-id": "^2.0.0", - "@multiformats/multiaddr": "^12.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-peer-info/node_modules/@libp2p/interface-peer-id": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-peer-id/-/interface-peer-id-2.0.2.tgz", - "integrity": "sha512-9pZp9zhTDoVwzRmp0Wtxw0Yfa//Yc0GqBCJi3EznBDE6HGIAVvppR91wSh2knt/0eYg0AQj7Y35VSesUTzMCUg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^11.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-peer-info/node_modules/multiformats": { - "version": "11.0.2", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interface-pubsub": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-pubsub/-/interface-pubsub-2.1.0.tgz", - "integrity": "sha512-X+SIqzfeCO8ZDGrFTzH9EMwMf8ojW5nk20rxv3h1sCXEdfvyJCARZ51r9UlwJcnucnHqvFChfkbubAkrr3R4Cw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface-connection": "^3.0.0", - "@libp2p/interface-peer-id": "^1.0.0", - "@libp2p/interfaces": "^3.0.0", - "it-pushable": "^3.0.0", - "uint8arraylist": "^2.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/interfaces": { - "version": "3.3.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterfaces/-/interfaces-3.3.2.tgz", - "integrity": "sha512-p/M7plbrxLzuQchvNwww1Was7ZeGE2NaOFulMaZBYIihU8z3fhaV+a033OqnC/0NTX/yhfdNOG7znhYq3XoR/g==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/kad-dht": { - "version": "14.2.15", - "resolved": "http://94.130.170.209:4873/@libp2p%2fkad-dht/-/kad-dht-14.2.15.tgz", - "integrity": "sha512-iARZsaKrm9LlOE0nRTsqMasYGfWbh+zw1TAMWOY/QHTszFGb9ol7FZoI9WUzoif9ltKLu3BjJpy00b8CVofCBw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.15", - "@libp2p/interface": "^2.7.0", - "@libp2p/interface-internal": "^2.3.9", - "@libp2p/peer-collections": "^6.0.25", - "@libp2p/peer-id": "^5.1.0", - "@libp2p/record": "^4.0.5", - "@libp2p/utils": "^6.6.0", - "@multiformats/multiaddr": "^12.3.3", - "any-signal": "^4.1.1", - "interface-datastore": "^8.3.1", - "it-all": "^3.0.6", - "it-drain": "^3.0.7", - "it-length": "^3.0.6", - "it-length-prefixed": "^10.0.1", - "it-map": "^3.1.1", - "it-merge": "^3.0.5", - "it-parallel": "^3.0.8", - "it-pipe": "^3.0.1", - "it-protobuf-stream": "^1.1.5", - "it-take": "^3.0.6", - "mortice": "^3.0.6", - "multiformats": "^13.3.1", - "p-defer": "^4.0.1", - "p-event": "^6.0.1", - "progress-events": "^1.0.1", - "protons-runtime": "^5.5.0", - "race-signal": "^1.1.2", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/kad-dht/node_modules/it-length-prefixed": { - "version": "10.0.1", - "resolved": "http://94.130.170.209:4873/it-length-prefixed/-/it-length-prefixed-10.0.1.tgz", - "integrity": "sha512-BhyluvGps26u9a7eQIpOI1YN7mFgi8lFwmiPi07whewbBARKAG9LE09Odc8s1Wtbt2MB6rNUrl7j9vvfXTJwdQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-reader": "^6.0.1", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.1", - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/keychain": { - "version": "5.0.14", - "resolved": "http://94.130.170.209:4873/@libp2p%2fkeychain/-/keychain-5.0.14.tgz", - "integrity": "sha512-WTxHrLu8Dx8DNmVTOvlYtODQVsFNPgjL/tmyp61HwhBqKLqeEefH5BeU7W/W3YDlnwcL0JaUi5tIdMeu2qwRLw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.11", - "@libp2p/interface": "^2.5.0", - "@noble/hashes": "^1.6.1", - "asn1js": "^3.0.5", - "interface-datastore": "^8.3.1", - "merge-options": "^3.0.4", - "multiformats": "^13.3.1", - "sanitize-filename": "^1.6.3", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/logger": { - "version": "5.1.8", - "resolved": "http://94.130.170.209:4873/@libp2p%2flogger/-/logger-5.1.8.tgz", - "integrity": "sha512-Mevhz+dTQuV5UbwqLMOJZv2IpMg+/89x/Ouq0iKtkgB5vAgTwJ3DlM7+IYOeyzQRUpCPfaRiJet3aBB5wnPMRg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.5.0", - "@multiformats/multiaddr": "^12.3.3", - "interface-datastore": "^8.3.1", - "multiformats": "^13.3.1", - "weald": "^1.0.4" - } - }, - "node_modules/@libp2p/mdns": { - "version": "11.0.33", - "resolved": "http://94.130.170.209:4873/@libp2p%2fmdns/-/mdns-11.0.33.tgz", - "integrity": "sha512-DHG9uXlVsHg4LIbeIowiV75P54X0xTPOwr9yiDzWH3PHzWLiUEdR6gHB+9VPwUeSFrnvOiDg7ygNnj3iXuRyBw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@libp2p/interface-internal": "^2.3.10", - "@libp2p/peer-id": "^5.1.1", - "@libp2p/utils": "^6.6.1", - "@multiformats/multiaddr": "^12.3.3", - "@types/multicast-dns": "^7.2.4", - "dns-packet": "^5.6.1", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/@libp2p/mplex": { - "version": "11.0.33", - "resolved": "http://94.130.170.209:4873/@libp2p%2fmplex/-/mplex-11.0.33.tgz", - "integrity": "sha512-JVD6qM7mvqZsmHBHPcSomJy/eMC8J98kOVzhHVO3IleVHZ5Iof7ilBEOAKxnpC+IG60CJYMaCC1kfv0c3u13zA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@libp2p/utils": "^6.6.1", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.3", - "it-stream-types": "^2.0.2", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/multistream-select": { - "version": "6.0.21", - "resolved": "http://94.130.170.209:4873/@libp2p%2fmultistream-select/-/multistream-select-6.0.21.tgz", - "integrity": "sha512-l1c70p8ljrrqnm0y9m/3mvtkYhbGt5zPOpxRKVveWR2+OyqiPFa48uRktmpJcl4zwG5dHWMG/klhdHoNpetJpw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "it-length-prefixed": "^10.0.1", - "it-length-prefixed-stream": "^2.0.1", - "it-stream-types": "^2.0.2", - "p-defer": "^4.0.1", - "race-signal": "^1.1.2", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/multistream-select/node_modules/it-byte-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/it-byte-stream/-/it-byte-stream-2.0.1.tgz", - "integrity": "sha512-WccB179tWRNjTyXJ9wLshQdKSLdVIexmnNjLfCT7UnsiLisTVUY092YqFhkL+da1WFR0paGzB24L+pAzFhRI4Q==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "it-queueless-pushable": "^2.0.0", - "it-stream-types": "^2.0.2", - "race-signal": "^1.1.3", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/multistream-select/node_modules/it-length-prefixed": { - "version": "10.0.1", - "resolved": "http://94.130.170.209:4873/it-length-prefixed/-/it-length-prefixed-10.0.1.tgz", - "integrity": "sha512-BhyluvGps26u9a7eQIpOI1YN7mFgi8lFwmiPi07whewbBARKAG9LE09Odc8s1Wtbt2MB6rNUrl7j9vvfXTJwdQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-reader": "^6.0.1", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.1", - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/multistream-select/node_modules/it-length-prefixed-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/it-length-prefixed-stream/-/it-length-prefixed-stream-2.0.1.tgz", - "integrity": "sha512-TFohjVrQKRLQgRrPdVL9ARqP4CHUHnsRkbkX4nEhSOBjOvZtVV/pHh5Z2C8EH50MnfNDjVSKvEbaIFVLS3/QMA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "it-byte-stream": "^2.0.0", - "it-stream-types": "^2.0.2", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/multistream-select/node_modules/it-queueless-pushable": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/it-queueless-pushable/-/it-queueless-pushable-2.0.0.tgz", - "integrity": "sha512-MlNnefWT/ntv5fesrHpxwVIu6ZdtlkN0A4aaJiE5wnmPMBv9ttiwX3UEMf78dFwIj5ZNaU9usYXg4swMEpUNJQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "p-defer": "^4.0.1", - "race-signal": "^1.1.3" - } - }, - "node_modules/@libp2p/peer-collections": { - "version": "6.0.26", - "resolved": "http://94.130.170.209:4873/@libp2p%2fpeer-collections/-/peer-collections-6.0.26.tgz", - "integrity": "sha512-bpo4Oim+pvZh6AiIPjYDVb2Us6siJnRBWmyEzrV5t+EmGdLUjOKmRD3NnBp2WoO3RYAMESDyBrpxjnZo5ydHCA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@libp2p/peer-id": "^5.1.1", - "@libp2p/utils": "^6.6.1", - "multiformats": "^13.3.1" - } - }, - "node_modules/@libp2p/peer-id": { - "version": "5.1.1", - "resolved": "http://94.130.170.209:4873/@libp2p%2fpeer-id/-/peer-id-5.1.1.tgz", - "integrity": "sha512-dVpgln2gWybglCC8hiQqyGlyXU7F7ovoOqwnnMs8HxurGEH9QxgmCfxRP4p8s86bQwl1MFbyj0AqYPy/zbKLrA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.1.0", - "@libp2p/interface": "^2.8.0", - "multiformats": "^13.3.1", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/peer-record": { - "version": "8.0.26", - "resolved": "http://94.130.170.209:4873/@libp2p%2fpeer-record/-/peer-record-8.0.26.tgz", - "integrity": "sha512-uZrGsZ7JLwY2B60El60AGcYjdcB87J596vyY722adQshLLiTTafkEZeHDSVVC3k5R8EP0gwrIEidi3xtPYRT5w==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.1.0", - "@libp2p/interface": "^2.8.0", - "@libp2p/peer-id": "^5.1.1", - "@libp2p/utils": "^6.6.1", - "@multiformats/multiaddr": "^12.3.3", - "multiformats": "^13.3.1", - "protons-runtime": "^5.5.0", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/peer-store": { - "version": "11.1.3", - "resolved": "http://94.130.170.209:4873/@libp2p%2fpeer-store/-/peer-store-11.1.3.tgz", - "integrity": "sha512-RTSFHLXklOcGVXbuEZMfn4qFKxELGnSJkIRfh9RHxSWUbD8gwisrp9+Wecd9QYAu5sVeCmk2tPt/EhPdJDWCeQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.1.0", - "@libp2p/interface": "^2.8.0", - "@libp2p/peer-id": "^5.1.1", - "@libp2p/peer-record": "^8.0.26", - "@multiformats/multiaddr": "^12.3.3", - "interface-datastore": "^8.3.1", - "it-all": "^3.0.6", - "mortice": "^3.0.6", - "multiformats": "^13.3.1", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/ping": { - "version": "2.0.22", - "resolved": "http://94.130.170.209:4873/@libp2p%2fping/-/ping-2.0.22.tgz", - "integrity": "sha512-vMmw7adYNaySHqKoRDOp7VS3iJRPn/jzfMzC4qcaFM/v81JqYmFEx4UopmYQr4YY+N04jhRu0zYbTN4c8e2shQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.12", - "@libp2p/interface": "^2.6.0", - "@libp2p/interface-internal": "^2.3.4", - "@multiformats/multiaddr": "^12.3.3", - "it-byte-stream": "^1.1.0", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/pubsub": { - "version": "10.1.9", - "resolved": "http://94.130.170.209:4873/@libp2p%2fpubsub/-/pubsub-10.1.9.tgz", - "integrity": "sha512-8QZmkOs11kivHtxm02PT/HEdfuDEYeA+NEcW/Gdq/lle0W/5jLzHxAJ3DJBteRjYkvAfZqVx5I53DUaabQgYAA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.1.0", - "@libp2p/interface": "^2.8.0", - "@libp2p/interface-internal": "^2.3.10", - "@libp2p/peer-collections": "^6.0.26", - "@libp2p/peer-id": "^5.1.1", - "@libp2p/utils": "^6.6.1", - "it-length-prefixed": "^10.0.1", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.3", - "multiformats": "^13.3.1", - "p-queue": "^8.0.1", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/pubsub/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/@libp2p/pubsub/node_modules/it-length-prefixed": { - "version": "10.0.1", - "resolved": "http://94.130.170.209:4873/it-length-prefixed/-/it-length-prefixed-10.0.1.tgz", - "integrity": "sha512-BhyluvGps26u9a7eQIpOI1YN7mFgi8lFwmiPi07whewbBARKAG9LE09Odc8s1Wtbt2MB6rNUrl7j9vvfXTJwdQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-reader": "^6.0.1", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.1", - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/pubsub/node_modules/p-queue": { - "version": "8.1.0", - "resolved": "http://94.130.170.209:4873/p-queue/-/p-queue-8.1.0.tgz", - "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@libp2p/record": { - "version": "4.0.5", - "resolved": "http://94.130.170.209:4873/@libp2p%2frecord/-/record-4.0.5.tgz", - "integrity": "sha512-HfKugY+ZKizhxE/hbLqI8zcFLfYly2gakaL0k8wBXCfmOTrAV7UajeJWkWqrKkIEMHASUyapm746KF+i9e7Xmw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/tcp": { - "version": "10.1.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2ftcp/-/tcp-10.1.2.tgz", - "integrity": "sha512-/DovSsAxTX3nwr+kr5NHDuy0vboFgBA9AaUOPXOA8AqbYnRjX8HDeUIRf77pRGja/cAW0W9euIxJmQNtFYWHuA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.6.0", - "@libp2p/utils": "^6.5.4", - "@multiformats/mafmt": "^12.1.6", - "@multiformats/multiaddr": "^12.3.3", - "@types/sinon": "^17.0.3", - "p-defer": "^4.0.1", - "p-event": "^6.0.1", - "progress-events": "^1.0.1", - "race-event": "^1.3.0", - "stream-to-it": "^1.0.1" - } - }, - "node_modules/@libp2p/tls": { - "version": "2.1.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2ftls/-/tls-2.1.2.tgz", - "integrity": "sha512-ExtpXzoD3ZKlIS5I5n+hRzC0uZjplM2VkGUEKBYNgA3KLZEkA12fiuFao24h0znEF9DlSmREvxSpDssNxaFx2Q==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.1.0", - "@libp2p/interface": "^2.8.0", - "@libp2p/peer-id": "^5.1.1", - "@peculiar/asn1-schema": "^2.3.13", - "@peculiar/asn1-x509": "^2.3.13", - "@peculiar/webcrypto": "^1.5.0", - "@peculiar/x509": "^1.12.3", - "asn1js": "^3.0.5", - "it-queueless-pushable": "^1.0.2", - "it-stream-types": "^2.0.2", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/upnp-nat": { - "version": "3.1.12", - "resolved": "http://94.130.170.209:4873/@libp2p%2fupnp-nat/-/upnp-nat-3.1.12.tgz", - "integrity": "sha512-nmhuCZjme3ZjCIWlBxzYJIzmUT4x9/kVEaiWATdPAMY9P8sBhP8DOQ8wwXe9mt35SRN+HC1W88mevzyXbGGcWQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@achingbrain/nat-port-mapper": "^4.0.0", - "@chainsafe/is-ip": "^2.0.2", - "@libp2p/interface": "^2.8.0", - "@libp2p/interface-internal": "^2.3.10", - "@libp2p/utils": "^6.6.1", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "p-defer": "^4.0.1", - "race-signal": "^1.1.2" - } - }, - "node_modules/@libp2p/utils": { - "version": "6.6.1", - "resolved": "http://94.130.170.209:4873/@libp2p%2futils/-/utils-6.6.1.tgz", - "integrity": "sha512-7/oJ+GX+pvM8bDe55VsmpuuBZS/HIYp/+DCyHqnm6o6d6rFSpF/yuVhKGK29P0MNgApzHeHrwfnvzPXrz64d3A==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@chainsafe/netmask": "^2.0.0", - "@libp2p/crypto": "^5.1.0", - "@libp2p/interface": "^2.8.0", - "@libp2p/logger": "^5.1.14", - "@multiformats/multiaddr": "^12.3.3", - "@sindresorhus/fnv1a": "^3.1.0", - "any-signal": "^4.1.1", - "delay": "^6.0.0", - "get-iterator": "^2.0.1", - "is-loopback-addr": "^2.0.2", - "it-foreach": "^2.1.1", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.3", - "it-stream-types": "^2.0.2", - "netmask": "^2.0.2", - "p-defer": "^4.0.1", - "race-event": "^1.3.0", - "race-signal": "^1.1.2", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/utils/node_modules/@libp2p/logger": { - "version": "5.1.14", - "resolved": "http://94.130.170.209:4873/@libp2p%2flogger/-/logger-5.1.14.tgz", - "integrity": "sha512-rJeEq7iuKMMjel0zzH10dXzcWn4Q2yywbv5vM9B1xTQpkD4uxTbBlQs+EL9+pmwaaQrrriEGqluZOTzHvUzJUg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@multiformats/multiaddr": "^12.3.3", - "interface-datastore": "^8.3.1", - "multiformats": "^13.3.1", - "weald": "^1.0.4" - } - }, - "node_modules/@libp2p/webrtc": { - "version": "5.2.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2fwebrtc/-/webrtc-5.2.2.tgz", - "integrity": "sha512-hbyUBvGzLKvZMDZQEk84T3gDm44PxOFbVL+9+Y5KOk+kKGp9RYVtWyNpiYxHi3kF/U/y7EEPd8Zwbn5wRjLIAw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@chainsafe/libp2p-noise": "^16.0.0", - "@ipshipyard/node-datachannel": "^0.26.4", - "@libp2p/interface": "^2.6.0", - "@libp2p/interface-internal": "^2.3.4", - "@libp2p/peer-id": "^5.0.13", - "@libp2p/utils": "^6.5.4", - "@multiformats/multiaddr": "^12.4.0", - "@multiformats/multiaddr-matcher": "^1.6.0", - "@peculiar/webcrypto": "^1.5.0", - "@peculiar/x509": "^1.11.0", - "any-signal": "^4.1.1", - "detect-browser": "^5.3.0", - "get-port": "^7.1.0", - "it-length-prefixed": "^10.0.1", - "it-protobuf-stream": "^1.1.5", - "it-pushable": "^3.2.3", - "it-stream-types": "^2.0.2", - "multiformats": "^13.3.1", - "p-defer": "^4.0.1", - "p-timeout": "^6.1.3", - "p-wait-for": "^5.0.2", - "progress-events": "^1.0.1", - "protons-runtime": "^5.5.0", - "race-event": "^1.3.0", - "race-signal": "^1.1.2", - "react-native-webrtc": "^124.0.4", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/webrtc/node_modules/@multiformats/multiaddr": { - "version": "12.4.0", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr/-/multiaddr-12.4.0.tgz", - "integrity": "sha512-FL7yBTLijJ5JkO044BGb2msf+uJLrwpD6jD6TkXlbjA9N12+18HT40jvd4o5vL4LOJMc86dPX6tGtk/uI9kYKg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@chainsafe/netmask": "^2.0.0", - "@multiformats/dns": "^1.0.3", - "multiformats": "^13.0.0", - "uint8-varint": "^2.0.1", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/@libp2p/webrtc/node_modules/it-length-prefixed": { - "version": "10.0.1", - "resolved": "http://94.130.170.209:4873/it-length-prefixed/-/it-length-prefixed-10.0.1.tgz", - "integrity": "sha512-BhyluvGps26u9a7eQIpOI1YN7mFgi8lFwmiPi07whewbBARKAG9LE09Odc8s1Wtbt2MB6rNUrl7j9vvfXTJwdQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-reader": "^6.0.1", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.1", - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@libp2p/websockets": { - "version": "9.2.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2fwebsockets/-/websockets-9.2.2.tgz", - "integrity": "sha512-R5nuufJU3ORPdlrhcXG8UBM/SJASDR7UYmRfr+AALY8EMvtJpFBfA+4ob2da8wZEJJSV7TnCcp57QKnMciENKw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.6.0", - "@libp2p/utils": "^6.5.4", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "@multiformats/multiaddr-to-uri": "^11.0.0", - "@types/ws": "^8.5.13", - "it-ws": "^6.1.5", - "p-defer": "^4.0.1", - "p-event": "^6.0.1", - "progress-events": "^1.0.1", - "race-signal": "^1.1.2", - "ws": "^8.18.0" - } - }, - "node_modules/@ljharb/resumer": { - "version": "0.1.3", - "resolved": "http://94.130.170.209:4873/@ljharb%2fresumer/-/resumer-0.1.3.tgz", - "integrity": "sha512-d+tsDgfkj9X5QTriqM4lKesCkMMJC3IrbPKHvayP00ELx2axdXvDfWkqjxrLXIzGcQzmj7VAUT1wopqARTvafw==", - "license": "MIT", - "dependencies": { - "@ljharb/through": "^2.3.13", - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@ljharb/through": { - "version": "2.3.13", - "resolved": "http://94.130.170.209:4873/@ljharb%2fthrough/-/through-2.3.13.tgz", - "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@multiformats/dns": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/@multiformats%2fdns/-/dns-1.0.6.tgz", - "integrity": "sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@types/dns-packet": "^5.6.5", - "buffer": "^6.0.3", - "dns-packet": "^5.6.1", - "hashlru": "^2.3.0", - "p-queue": "^8.0.1", - "progress-events": "^1.0.0", - "uint8arrays": "^5.0.2" - } - }, - "node_modules/@multiformats/dns/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/@multiformats/dns/node_modules/p-queue": { - "version": "8.0.1", - "resolved": "http://94.130.170.209:4873/p-queue/-/p-queue-8.0.1.tgz", - "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@multiformats/mafmt": { - "version": "12.1.6", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmafmt/-/mafmt-12.1.6.tgz", - "integrity": "sha512-tlJRfL21X+AKn9b5i5VnaTD6bNttpSpcqwKVmDmSHLwxoz97fAHaepqFOk/l1fIu94nImIXneNbhsJx/RQNIww==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@multiformats/multiaddr": "^12.0.0" - } - }, - "node_modules/@multiformats/multiaddr": { - "version": "12.3.5", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr/-/multiaddr-12.3.5.tgz", - "integrity": "sha512-f3I7FDd6VM4s3X5dXbmwk8Y99pnvATWj7RorIr+qgeiYCDySp4cwybAFnxdRWeKs6XLPE9meB0p8tK4lQqO8gQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@chainsafe/netmask": "^2.0.0", - "@multiformats/dns": "^1.0.3", - "multiformats": "^13.0.0", - "uint8-varint": "^2.0.1", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/@multiformats/multiaddr-matcher": { - "version": "1.6.0", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr-matcher/-/multiaddr-matcher-1.6.0.tgz", - "integrity": "sha512-E77lLvQR+50kTAfvjV3g4wr9qCu77Z+6yT0s1hgfh8B4sAXZ8u/YdQJGhjgstgW1kmGy7BXPppROKYijqQsesQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@multiformats/multiaddr": "^12.0.0", - "multiformats": "^13.0.0" - } - }, - "node_modules/@multiformats/multiaddr-to-uri": { - "version": "11.0.0", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr-to-uri/-/multiaddr-to-uri-11.0.0.tgz", - "integrity": "sha512-9RNmlIGwZbBLsHekT50dbt4o4u8Iciw9kGjv+WHiGxQdsJ6xKKjU1+C0Vbas6RilMbaVOAOnEyfNcXbUmTkLxQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@multiformats/multiaddr": "^12.3.0" - } - }, - "node_modules/@multiformats/murmur3": { - "version": "2.1.8", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmurmur3/-/murmur3-2.1.8.tgz", - "integrity": "sha512-6vId1C46ra3R1sbJUOFCZnsUIveR9oF20yhPmAFxPm0JfrX3/ZRCgP3YDrBzlGoEppOXnA9czHeYc0T9mB6hbA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^13.0.0", - "murmurhash3js-revisited": "^3.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@multiformats/uri-to-multiaddr": { - "version": "8.1.0", - "resolved": "http://94.130.170.209:4873/@multiformats%2furi-to-multiaddr/-/uri-to-multiaddr-8.1.0.tgz", - "integrity": "sha512-NHFqdKEwJ0A6JDXzC645Lgyw72zWhbM1QfaaD00ZYRrNvtx64p1bD9aIrWZIhLWZN87/lsV4QkJSNRF3Fd3ryw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@multiformats/multiaddr": "^12.1.14", - "is-ip": "^5.0.0" - } - }, - "node_modules/@noble/ciphers": { - "version": "0.6.0", - "resolved": "http://94.130.170.209:4873/@noble%2fciphers/-/ciphers-0.6.0.tgz", - "integrity": "sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves": { - "version": "1.8.1", - "resolved": "http://94.130.170.209:4873/@noble%2fcurves/-/curves-1.8.1.tgz", - "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.7.1" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "http://94.130.170.209:4873/@noble%2fhashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "http://94.130.170.209:4873/@nodelib%2ffs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "http://94.130.170.209:4873/@nodelib%2ffs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "http://94.130.170.209:4873/@nodelib%2ffs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@octokit/auth-token": { - "version": "3.0.4", - "resolved": "http://94.130.170.209:4873/@octokit%2fauth-token/-/auth-token-3.0.4.tgz", - "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/core": { - "version": "4.2.4", - "resolved": "http://94.130.170.209:4873/@octokit%2fcore/-/core-4.2.4.tgz", - "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/endpoint": { - "version": "7.0.6", - "resolved": "http://94.130.170.209:4873/@octokit%2fendpoint/-/endpoint-7.0.6.tgz", - "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/endpoint/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@octokit/graphql": { - "version": "5.0.6", - "resolved": "http://94.130.170.209:4873/@octokit%2fgraphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "18.1.1", - "resolved": "http://94.130.170.209:4873/@octokit%2fopenapi-types/-/openapi-types-18.1.1.tgz", - "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "http://94.130.170.209:4873/@octokit%2fplugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=4" - } - }, - "node_modules/@octokit/plugin-retry": { - "version": "4.1.6", - "resolved": "http://94.130.170.209:4873/@octokit%2fplugin-retry/-/plugin-retry-4.1.6.tgz", - "integrity": "sha512-obkYzIgEC75r8+9Pnfiiqy3y/x1bc3QLE5B7qvv9wi9Kj0R5tGQFC6QMBg1154WQ9lAVypuQDGyp3hNpp15gQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^9.0.0", - "bottleneck": "^2.15.3" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-throttling": { - "version": "5.2.3", - "resolved": "http://94.130.170.209:4873/@octokit%2fplugin-throttling/-/plugin-throttling-5.2.3.tgz", - "integrity": "sha512-C9CFg9mrf6cugneKiaI841iG8DOv6P5XXkjmiNNut+swePxQ7RWEdAZRp5rJoE1hjsIqiYcKa/ZkOQ+ujPI39Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^9.0.0", - "bottleneck": "^2.15.3" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": "^4.0.0" - } - }, - "node_modules/@octokit/request": { - "version": "6.2.8", - "resolved": "http://94.130.170.209:4873/@octokit%2frequest/-/request-6.2.8.tgz", - "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/@octokit%2frequest-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/@octokit%2ftsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/types": { - "version": "9.3.2", - "resolved": "http://94.130.170.209:4873/@octokit%2ftypes/-/types-9.3.2.tgz", - "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^18.0.0" - } - }, - "node_modules/@peculiar/asn1-cms": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-cms/-/asn1-cms-2.3.15.tgz", - "integrity": "sha512-B+DoudF+TCrxoJSTjjcY8Mmu+lbv8e7pXGWrhNp2/EGJp9EEcpzjBCar7puU57sGifyzaRVM03oD5L7t7PghQg==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "@peculiar/asn1-x509-attr": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-csr": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-csr/-/asn1-csr-2.3.15.tgz", - "integrity": "sha512-caxAOrvw2hUZpxzhz8Kp8iBYKsHbGXZPl2KYRMIPvAfFateRebS3136+orUpcVwHRmpXWX2kzpb6COlIrqCumA==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-ecc": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-ecc/-/asn1-ecc-2.3.15.tgz", - "integrity": "sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-pfx": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-pfx/-/asn1-pfx-2.3.15.tgz", - "integrity": "sha512-E3kzQe3J2xV9DP6SJS4X6/N1e4cYa2xOAK46VtvpaRk8jlheNri8v0rBezKFVPB1rz/jW8npO+u1xOvpATFMWg==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-cms": "^2.3.15", - "@peculiar/asn1-pkcs8": "^2.3.15", - "@peculiar/asn1-rsa": "^2.3.15", - "@peculiar/asn1-schema": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-pkcs8": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-pkcs8/-/asn1-pkcs8-2.3.15.tgz", - "integrity": "sha512-/PuQj2BIAw1/v76DV1LUOA6YOqh/UvptKLJHtec/DQwruXOCFlUo7k6llegn8N5BTeZTWMwz5EXruBw0Q10TMg==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-pkcs9": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-pkcs9/-/asn1-pkcs9-2.3.15.tgz", - "integrity": "sha512-yiZo/1EGvU1KiQUrbcnaPGWc0C7ElMMskWn7+kHsCFm+/9fU0+V1D/3a5oG0Jpy96iaXggQpA9tzdhnYDgjyFg==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-cms": "^2.3.15", - "@peculiar/asn1-pfx": "^2.3.15", - "@peculiar/asn1-pkcs8": "^2.3.15", - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "@peculiar/asn1-x509-attr": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-rsa": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-rsa/-/asn1-rsa-2.3.15.tgz", - "integrity": "sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-schema": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-schema/-/asn1-schema-2.3.15.tgz", - "integrity": "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==", - "license": "MIT", - "dependencies": { - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-x509": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-x509/-/asn1-x509-2.3.15.tgz", - "integrity": "sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-x509-attr": { - "version": "2.3.15", - "resolved": "http://94.130.170.209:4873/@peculiar%2fasn1-x509-attr/-/asn1-x509-attr-2.3.15.tgz", - "integrity": "sha512-TWJVJhqc+IS4MTEML3l6W1b0sMowVqdsnI4dnojg96LvTuP8dga9f76fjP07MUuss60uSyT2ckoti/2qHXA10A==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/json-schema": { - "version": "1.1.12", - "resolved": "http://94.130.170.209:4873/@peculiar%2fjson-schema/-/json-schema-1.1.12.tgz", - "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@peculiar/webcrypto": { - "version": "1.5.0", - "resolved": "http://94.130.170.209:4873/@peculiar%2fwebcrypto/-/webcrypto-1.5.0.tgz", - "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2", - "webcrypto-core": "^1.8.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/@peculiar/x509": { - "version": "1.12.3", - "resolved": "http://94.130.170.209:4873/@peculiar%2fx509/-/x509-1.12.3.tgz", - "integrity": "sha512-+Mzq+W7cNEKfkNZzyLl6A6ffqc3r21HGZUezgfKxpZrkORfOqgRXnS80Zu0IV6a9Ue9QBJeKD7kN0iWfc3bhRQ==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-cms": "^2.3.13", - "@peculiar/asn1-csr": "^2.3.13", - "@peculiar/asn1-ecc": "^2.3.14", - "@peculiar/asn1-pkcs9": "^2.3.13", - "@peculiar/asn1-rsa": "^2.3.13", - "@peculiar/asn1-schema": "^2.3.13", - "@peculiar/asn1-x509": "^2.3.13", - "pvtsutils": "^1.3.5", - "reflect-metadata": "^0.2.2", - "tslib": "^2.7.0", - "tsyringe": "^4.8.0" - } - }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@pnpm%2fconfig.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/@pnpm%2fnetwork.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "4.2.10" - }, - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "http://94.130.170.209:4873/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "license": "ISC" - }, - "node_modules/@pnpm/npm-conf": { - "version": "2.3.1", - "resolved": "http://94.130.170.209:4873/@pnpm%2fnpm-conf/-/npm-conf-2.3.1.tgz", - "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/@protobufjs%2faspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/@protobufjs%2fbase64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "http://94.130.170.209:4873/@protobufjs%2fcodegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@protobufjs%2feventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@protobufjs%2ffetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/@protobufjs%2ffloat/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@protobufjs%2finquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/@protobufjs%2fpath/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@protobufjs%2fpool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@protobufjs%2futf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, - "node_modules/@psf/bch-js": { - "version": "6.7.3", - "resolved": "http://94.130.170.209:4873/@psf%2fbch-js/-/bch-js-6.7.3.tgz", - "integrity": "sha512-z6oJvPAXxSObPhqUAxCkCuPL2bp3Bs1oyhBZpQ5SR6cbJzcOMhuI4bHho2srH5agSCU+bbjehBMRGvo18eGW0A==", - "license": "MIT", - "dependencies": { - "@chris.troutner/bip32-utils": "1.0.5", - "@psf/bip21": "2.0.1", - "@psf/bitcoincash-ops": "2.0.0", - "@psf/bitcoincashjs-lib": "4.0.3", - "@psf/coininfo": "4.0.0", - "axios": "0.26.1", - "bc-bip68": "1.0.5", - "bchaddrjs-slp": "0.2.5", - "bigi": "1.4.2", - "bignumber.js": "9.0.0", - "bip-schnorr": "0.3.0", - "bip38": "2.0.2", - "bip39": "3.0.2", - "bip66": "1.1.5", - "bitcoinjs-message": "2.0.0", - "bs58": "4.0.1", - "ecashaddrjs": "1.0.7", - "ini": "1.3.8", - "randombytes": "2.0.6", - "safe-buffer": "5.1.2", - "satoshi-bitcoin": "1.0.4", - "slp-mdm": "0.0.6", - "slp-parser": "0.0.4", - "wif": "2.0.6" - } - }, - "node_modules/@psf/bch-js/node_modules/axios": { - "version": "0.26.1", - "resolved": "http://94.130.170.209:4873/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/@psf/bip21": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/@psf%2fbip21/-/bip21-2.0.1.tgz", - "integrity": "sha512-U9c8xBV31n+D7qxOPBO0vQ015DNvKskWCUbVgoMfH5AUNHLYrSDWIrCx4P7v9etfdu6LpPdsYr53KDSAIk0b7Q==", - "license": "ISC", - "dependencies": { - "qs": "^6.3.0" - } - }, - "node_modules/@psf/bitcoincash-ops": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/@psf%2fbitcoincash-ops/-/bitcoincash-ops-2.0.0.tgz", - "integrity": "sha512-M3PWqRpeJq6rli2NqWGbas76z9TrdGOmNuDFACBWBMctPucEAsFQY2AmyFHRSa7hEwythwvrPh9AG/n6ehmEog==", - "license": "MIT" - }, - "node_modules/@psf/bitcoincashjs-lib": { - "version": "4.0.3", - "resolved": "http://94.130.170.209:4873/@psf%2fbitcoincashjs-lib/-/bitcoincashjs-lib-4.0.3.tgz", - "integrity": "sha512-sJYi7jYUqR7S+Z8TjN3W/5Lcju7xcIBxYLhIEpnOF+jR9kMt0ftpVjQBt8vVsJZUD8ArL9bf59oDETjdOUcdGQ==", - "license": "MIT", - "dependencies": { - "@psf/bitcoincash-ops": "^2.0.0", - "@psf/pushdata-bitcoin": "^1.2.2", - "bech32": "^1.1.2", - "bigi": "^1.4.0", - "bip66": "^1.1.0", - "bs58check": "^2.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "ecurve": "^1.0.0", - "merkle-lib": "^2.0.10", - "randombytes": "^2.0.1", - "safe-buffer": "^5.0.1", - "typeforce": "^1.18.0", - "varuint-bitcoin": "^1.0.4", - "wif": "^2.0.1" - }, - "engines": { - "node": ">=10.15.1" - } - }, - "node_modules/@psf/coininfo": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/@psf%2fcoininfo/-/coininfo-4.0.0.tgz", - "integrity": "sha512-RwBc09790kbaOt8uZJMyvLqf1UziTd20FXu78bM8bMlkClnZQTJyNDdLCsFSBkJQYAJtGMkjdQ/o3/UaSC7c2Q==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, - "node_modules/@psf/pushdata-bitcoin": { - "version": "1.2.2", - "resolved": "http://94.130.170.209:4873/@psf%2fpushdata-bitcoin/-/pushdata-bitcoin-1.2.2.tgz", - "integrity": "sha512-e1qkZLJFU6Ldg7TMBgSkiR5U1NfpRgSIr2ppk8BeED/Q9wUc9DEVAjXfPMD65xgXdqnlyFEtLbpPMWwyydMVUQ==", - "license": "MIT", - "dependencies": { - "@psf/bitcoincash-ops": "^2.0.0" - } - }, - "node_modules/@react-native/assets-registry": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fassets-registry/-/assets-registry-0.79.0.tgz", - "integrity": "sha512-Rwvpu3A05lM1HVlX4klH4UR52JbQPDKc8gi2mst2REZL1KeVgJRJxPPw8d8euVlYcq/s8XI1Ol827JaRtSZBTA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/codegen": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fcodegen/-/codegen-0.79.0.tgz", - "integrity": "sha512-D8bFlD0HH9SMUI00svdg64hEvLbu4ETeWQDlmEP8WmNbuILjwoLFqbnBmlGn69Tot0DM1PuBd1l1ooIzs8sU7w==", - "license": "MIT", - "peer": true, - "dependencies": { - "glob": "^7.1.1", - "hermes-parser": "0.25.1", - "invariant": "^2.2.4", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/core": "*" - } - }, - "node_modules/@react-native/codegen/node_modules/cliui": { - "version": "8.0.1", - "resolved": "http://94.130.170.209:4873/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@react-native/codegen/node_modules/yargs": { - "version": "17.7.2", - "resolved": "http://94.130.170.209:4873/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "peer": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@react-native/codegen/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "http://94.130.170.209:4873/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@react-native/community-cli-plugin": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fcommunity-cli-plugin/-/community-cli-plugin-0.79.0.tgz", - "integrity": "sha512-pl+aSXxGj3ug80FpMDrArjxUbJWY2ibWiSP3MLKX+Xk7An2GUmFFjCzNVSbs0jzWv8814EG2oI60/GH2RXwE4g==", - "license": "MIT", - "peer": true, - "dependencies": { - "@react-native/dev-middleware": "0.79.0", - "chalk": "^4.0.0", - "debug": "^2.2.0", - "invariant": "^2.2.4", - "metro": "^0.82.0", - "metro-config": "^0.82.0", - "metro-core": "^0.82.0", - "semver": "^7.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@react-native-community/cli": "*" - }, - "peerDependenciesMeta": { - "@react-native-community/cli": { - "optional": true - } - } - }, - "node_modules/@react-native/community-cli-plugin/node_modules/debug": { - "version": "2.6.9", - "resolved": "http://94.130.170.209:4873/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@react-native/community-cli-plugin/node_modules/ms": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/debugger-frontend": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fdebugger-frontend/-/debugger-frontend-0.79.0.tgz", - "integrity": "sha512-chwKEWAmQMkOKZWwBra+utquuJ/2uFqh+ZgZbJfNX+U0YsBx6AQ3dVbfAaXW3bSLYEJyf9Wb3Opsal4fmcD9Ww==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/dev-middleware": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fdev-middleware/-/dev-middleware-0.79.0.tgz", - "integrity": "sha512-8Mh5L8zJXis2qhgkfXnWMbSmcvb07wrbxQe8KIgIO7C1rS97idg7BBtoPEtmARsaQgmbSGu/wdE7UWFkGYp0OQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.79.0", - "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^0.2.0", - "connect": "^3.6.5", - "debug": "^2.2.0", - "invariant": "^2.2.4", - "nullthrows": "^1.1.1", - "open": "^7.0.3", - "serve-static": "^1.16.2", - "ws": "^6.2.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/dev-middleware/node_modules/debug": { - "version": "2.6.9", - "resolved": "http://94.130.170.209:4873/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@react-native/dev-middleware/node_modules/ms": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/dev-middleware/node_modules/ws": { - "version": "6.2.3", - "resolved": "http://94.130.170.209:4873/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "license": "MIT", - "peer": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/@react-native/gradle-plugin": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fgradle-plugin/-/gradle-plugin-0.79.0.tgz", - "integrity": "sha512-c+/qKnmTx3kf8xZesp2BkZ9pAQVSnEPZziQUwviSJaq9jm8tKb/B8fyGG8yIuw/ZTKyGprD+ByzUSzJmCpC/Ow==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/js-polyfills": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fjs-polyfills/-/js-polyfills-0.79.0.tgz", - "integrity": "sha512-+8lk/zP90JC9xZBGhI8TPqqR1Y5dYXwXvfhXygr/LlHoo+H8TeQxcPrXWdT+PWOJl6Gf7dbCOGh9Std8J7CSQA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/normalize-colors": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fnormalize-colors/-/normalize-colors-0.79.0.tgz", - "integrity": "sha512-RmM7Dgb69a4qwdguKR+8MhT0u1IAKa/s0uy8/7JP9b/fm8zjUV9HctMgRgIpZTOELsowEyQodyTnhHQf4HPX0A==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/virtualized-lists": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/@react-native%2fvirtualized-lists/-/virtualized-lists-0.79.0.tgz", - "integrity": "sha512-tCT1sHSI1O5KSclDwNfnkLTLe3cgiyYWjIlmNxWJHqhCCz017HGOS/oH0zs0ZgxYwN7xCzTkqY330XMDo+yj2g==", - "license": "MIT", - "peer": true, - "dependencies": { - "invariant": "^2.2.4", - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/react": "^19.0.0", - "react": "*", - "react-native": "*" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@redis/bloom": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/@redis%2fbloom/-/bloom-1.2.0.tgz", - "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/client": { - "version": "1.6.0", - "resolved": "http://94.130.170.209:4873/@redis%2fclient/-/client-1.6.0.tgz", - "integrity": "sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@redis/client/node_modules/yallist": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, - "node_modules/@redis/graph": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/@redis%2fgraph/-/graph-1.1.1.tgz", - "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/json": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/@redis%2fjson/-/json-1.0.7.tgz", - "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/search": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/@redis%2fsearch/-/search-1.2.0.tgz", - "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/time-series": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@redis%2ftime-series/-/time-series-1.1.0.tgz", - "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@rtsao%2fscc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@scure/base": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/@scure%2fbase/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@scure/bip32": { - "version": "1.3.1", - "resolved": "http://94.130.170.209:4873/@scure%2fbip32/-/bip32-1.3.1.tgz", - "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.1.0", - "@noble/hashes": "~1.3.1", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/@noble%2fcurves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.1" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "http://94.130.170.209:4873/@noble%2fhashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "http://94.130.170.209:4873/@noble%2fhashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/@scure%2fbip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "http://94.130.170.209:4873/@noble%2fhashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@semantic-release/commit-analyzer": { - "version": "9.0.2", - "resolved": "http://94.130.170.209:4873/@semantic-release%2fcommit-analyzer/-/commit-analyzer-9.0.2.tgz", - "integrity": "sha512-E+dr6L+xIHZkX4zNMe6Rnwg4YQrWNXK+rNsvwOPpdFppvZO1olE2fIgWhv89TkQErygevbjsZFSIxp+u6w2e5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-changelog-angular": "^5.0.0", - "conventional-commits-filter": "^2.0.0", - "conventional-commits-parser": "^3.2.3", - "debug": "^4.0.0", - "import-from": "^4.0.0", - "lodash": "^4.17.4", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=14.17" - }, - "peerDependencies": { - "semantic-release": ">=18.0.0-beta.1" - } - }, - "node_modules/@semantic-release/commit-analyzer/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@semantic-release/error": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/@semantic-release%2ferror/-/error-3.0.0.tgz", - "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.17" - } - }, - "node_modules/@semantic-release/github": { - "version": "8.1.0", - "resolved": "http://94.130.170.209:4873/@semantic-release%2fgithub/-/github-8.1.0.tgz", - "integrity": "sha512-erR9E5rpdsz0dW1I7785JtndQuMWN/iDcemcptf67tBNOmBUN0b2YNOgcjYUnBpgRpZ5ozfBHrK7Bz+2ets/Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/core": "^4.2.1", - "@octokit/plugin-paginate-rest": "^6.1.2", - "@octokit/plugin-retry": "^4.1.3", - "@octokit/plugin-throttling": "^5.2.3", - "@semantic-release/error": "^3.0.0", - "aggregate-error": "^3.0.0", - "debug": "^4.0.0", - "dir-glob": "^3.0.0", - "fs-extra": "^11.0.0", - "globby": "^11.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "issue-parser": "^6.0.0", - "lodash": "^4.17.4", - "mime": "^3.0.0", - "p-filter": "^2.0.0", - "url-join": "^4.0.0" - }, - "engines": { - "node": ">=14.17" - }, - "peerDependencies": { - "semantic-release": ">=18.0.0-beta.1" - } - }, - "node_modules/@semantic-release/github/node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@semantic-release/github/node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@semantic-release/github/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@semantic-release/github/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "http://94.130.170.209:4873/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@semantic-release/github/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@semantic-release/npm": { - "version": "9.0.2", - "resolved": "http://94.130.170.209:4873/@semantic-release%2fnpm/-/npm-9.0.2.tgz", - "integrity": "sha512-zgsynF6McdzxPnFet+a4iO9HpAlARXOM5adz7VGVCvj0ne8wtL2ZOQoDV2wZPDmdEotDIbVeJjafhelZjs9j6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@semantic-release/error": "^3.0.0", - "aggregate-error": "^3.0.0", - "execa": "^5.0.0", - "fs-extra": "^11.0.0", - "lodash": "^4.17.15", - "nerf-dart": "^1.0.0", - "normalize-url": "^6.0.0", - "npm": "^8.3.0", - "rc": "^1.2.8", - "read-pkg": "^5.0.0", - "registry-auth-token": "^5.0.0", - "semver": "^7.1.2", - "tempy": "^1.0.0" - }, - "engines": { - "node": ">=16 || ^14.17" - }, - "peerDependencies": { - "semantic-release": ">=19.0.0" - } - }, - "node_modules/@semantic-release/npm/node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@semantic-release/npm/node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@semantic-release/npm/node_modules/execa": { - "version": "5.1.1", - "resolved": "http://94.130.170.209:4873/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/@semantic-release/npm/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "http://94.130.170.209:4873/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@semantic-release/npm/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/@semantic-release/npm/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@semantic-release/npm/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@semantic-release/npm/node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "http://94.130.170.209:4873/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@semantic-release/npm/node_modules/onetime": { - "version": "5.1.2", - "resolved": "http://94.130.170.209:4873/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@semantic-release/release-notes-generator": { - "version": "10.0.3", - "resolved": "http://94.130.170.209:4873/@semantic-release%2frelease-notes-generator/-/release-notes-generator-10.0.3.tgz", - "integrity": "sha512-k4x4VhIKneOWoBGHkx0qZogNjCldLPRiAjnIpMnlUh6PtaWXp/T+C9U7/TaNDDtgDa5HMbHl4WlREdxHio6/3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-changelog-angular": "^5.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-filter": "^2.0.0", - "conventional-commits-parser": "^3.2.3", - "debug": "^4.0.0", - "get-stream": "^6.0.0", - "import-from": "^4.0.0", - "into-stream": "^6.0.0", - "lodash": "^4.17.4", - "read-pkg-up": "^7.0.0" - }, - "engines": { - "node": ">=14.17" - }, - "peerDependencies": { - "semantic-release": ">=18.0.0-beta.1" - } - }, - "node_modules/@semantic-release/release-notes-generator/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "http://94.130.170.209:4873/@sinclair%2ftypebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "license": "MIT", - "peer": true - }, - "node_modules/@sindresorhus/fnv1a": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/@sindresorhus%2ffnv1a/-/fnv1a-3.1.0.tgz", - "integrity": "sha512-KV321z5m/0nuAg83W1dPLy85HpHDk7Sdi4fJbwvacWsEhAh+rZUW4ZfGcXmUIvjZg4ss2bcwNlRhJ7GBEUG08w==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "http://94.130.170.209:4873/@sindresorhus%2fis/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/@sinonjs%2fcommons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/commons/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "http://94.130.170.209:4873/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "http://94.130.170.209:4873/@sinonjs%2ffake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "http://94.130.170.209:4873/@sinonjs%2fsamsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "http://94.130.170.209:4873/@sinonjs%2fcommons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "http://94.130.170.209:4873/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "http://94.130.170.209:4873/@sinonjs%2ftext-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" - }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/@szmarczak%2fhttp-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.1" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "http://94.130.170.209:4873/@types%2fbabel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "http://94.130.170.209:4873/@types%2fbabel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "http://94.130.170.209:4873/@types%2fbabel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "http://94.130.170.209:4873/@types%2fbabel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/bson": { - "version": "4.0.5", - "resolved": "http://94.130.170.209:4873/@types%2fbson/-/bson-4.0.5.tgz", - "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/dns-packet": { - "version": "5.6.5", - "resolved": "http://94.130.170.209:4873/@types%2fdns-packet/-/dns-packet-5.6.5.tgz", - "integrity": "sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "http://94.130.170.209:4873/@types%2feslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "http://94.130.170.209:4873/@types%2feslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/@types%2festree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "license": "MIT" - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "http://94.130.170.209:4873/@types%2fgraceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "http://94.130.170.209:4873/@types%2fhttp-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "http://94.130.170.209:4873/@types%2fistanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/@types%2fistanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "http://94.130.170.209:4873/@types%2fistanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "http://94.130.170.209:4873/@types%2fjson-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "http://94.130.170.209:4873/@types%2fjson5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "http://94.130.170.209:4873/@types%2fminimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "license": "MIT" - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "http://94.130.170.209:4873/@types%2fminimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mongodb": { - "version": "3.6.20", - "resolved": "http://94.130.170.209:4873/@types%2fmongodb/-/mongodb-3.6.20.tgz", - "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==", - "license": "MIT", - "dependencies": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "node_modules/@types/multicast-dns": { - "version": "7.2.4", - "resolved": "http://94.130.170.209:4873/@types%2fmulticast-dns/-/multicast-dns-7.2.4.tgz", - "integrity": "sha512-ib5K4cIDR4Ro5SR3Sx/LROkMDa0BHz0OPaCBL/OSPDsAXEGZ3/KQeS6poBKYVN7BfjXDL9lWNwzyHVgt/wkyCw==", - "license": "MIT", - "dependencies": { - "@types/dns-packet": "*", - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "22.9.1", - "resolved": "http://94.130.170.209:4873/@types%2fnode/-/node-22.9.1.tgz", - "integrity": "sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.8" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "http://94.130.170.209:4873/@types%2fnormalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/@types%2fparse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/retry": { - "version": "0.12.1", - "resolved": "http://94.130.170.209:4873/@types%2fretry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "license": "MIT" - }, - "node_modules/@types/sinon": { - "version": "17.0.3", - "resolved": "http://94.130.170.209:4873/@types%2fsinon/-/sinon-17.0.3.tgz", - "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", - "license": "MIT", - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "http://94.130.170.209:4873/@types%2fsinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "license": "MIT" - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/@types%2fstack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "http://94.130.170.209:4873/@types%2ftriple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "http://94.130.170.209:4873/@types%2fws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "http://94.130.170.209:4873/@types%2fyargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "http://94.130.170.209:4873/@types%2fyargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/@ungap%2fpromise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/@ungap%2fstructured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2ffloating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fhelper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fhelper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fhelper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fhelper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fhelper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fleb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "license": "Apache-2.0", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2futf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fwasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fwasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fwasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fwasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/@webassemblyjs%2fwast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/@webpack-cli%2fconfigtest/-/configtest-1.2.0.tgz", - "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", - "license": "MIT", - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.5.0", - "resolved": "http://94.130.170.209:4873/@webpack-cli%2finfo/-/info-1.5.0.tgz", - "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", - "license": "MIT", - "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "1.7.0", - "resolved": "http://94.130.170.209:4873/@webpack-cli%2fserve/-/serve-1.7.0.tgz", - "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", - "license": "MIT", - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/@xtuc%2fieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "license": "BSD-3-Clause" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "http://94.130.170.209:4873/@xtuc%2flong/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "license": "Apache-2.0" - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "license": "MIT", - "peer": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/abort-error": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/abort-error/-/abort-error-1.0.1.tgz", - "integrity": "sha512-fxqCblJiIPdSXIUrxI0PL+eJG49QdP9SQ70qtB65MVAoMr2rASlOyAbJFOylfB467F/f+5BCLJJq58RYi7mGfg==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "http://94.130.170.209:4873/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acme-client": { - "version": "5.4.0", - "resolved": "http://94.130.170.209:4873/acme-client/-/acme-client-5.4.0.tgz", - "integrity": "sha512-mORqg60S8iML6XSmVjqjGHJkINrCGLMj2QvDmFzI9vIlv1RGlyjmw3nrzaINJjkNsYXC41XhhD5pfy7CtuGcbA==", - "license": "MIT", - "dependencies": { - "@peculiar/x509": "^1.11.0", - "asn1js": "^3.0.5", - "axios": "^1.7.2", - "debug": "^4.3.5", - "node-forge": "^1.3.1" - }, - "engines": { - "node": ">= 16" - } - }, - "node_modules/acme-client/node_modules/axios": { - "version": "1.8.4", - "resolved": "http://94.130.170.209:4873/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/acme-client/node_modules/debug": { - "version": "4.4.0", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "http://94.130.170.209:4873/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "http://94.130.170.209:4873/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/aes-js": { - "version": "3.1.2", - "resolved": "http://94.130.170.209:4873/aes-js/-/aes-js-3.1.2.tgz", - "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", - "license": "MIT" - }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "http://94.130.170.209:4873/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", - "license": "MIT", - "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "http://94.130.170.209:4873/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "http://94.130.170.209:4873/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/anser": { - "version": "1.4.10", - "resolved": "http://94.130.170.209:4873/anser/-/anser-1.4.10.tgz", - "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", - "license": "MIT", - "peer": true - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "http://94.130.170.209:4873/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "http://94.130.170.209:4873/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "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": "http://94.130.170.209:4873/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "http://94.130.170.209:4873/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "license": "MIT" - }, - "node_modules/any-signal": { - "version": "4.1.1", - "resolved": "http://94.130.170.209:4873/any-signal/-/any-signal-4.1.1.tgz", - "integrity": "sha512-iADenERppdC+A2YKbOXXB2WUeABLaM6qnpZ70kZbPZ1cZMMJ7eF+3CaYm+/PhBizgkzlvssC7QuHS30oOiQYWA==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "http://94.130.170.209:4873/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/apidoc": { - "version": "0.51.1", - "resolved": "http://94.130.170.209:4873/apidoc/-/apidoc-0.51.1.tgz", - "integrity": "sha512-0dcL7NSUWDibgQ051ne/wXT0Dp+ArD66jwofuurxzRAPMuf2cRwa7GxRm9xlGXbOLaU7dVSZDr8LVeVBdI/oTQ==", - "dev": true, - "license": "MIT", - "os": [ - "darwin", - "freebsd", - "linux", - "openbsd", - "win32" - ], - "dependencies": { - "bootstrap": "3.4.1", - "commander": "^8.3.0", - "diff-match-patch": "^1.0.5", - "esbuild-loader": "^2.16.0", - "expose-loader": "^3.1.0", - "fs-extra": "^10.0.0", - "glob": "^7.2.0", - "handlebars": "^4.7.7", - "iconv-lite": "^0.6.3", - "jquery": "^3.6.0", - "klaw-sync": "^6.0.0", - "lodash": "^4.17.21", - "markdown-it": "^12.2.0", - "nodemon": "^2.0.15", - "prismjs": "^1.25.0", - "semver": "^7.3.5", - "style-loader": "^3.3.1", - "webpack": "^5.64.2", - "webpack-cli": "^4.9.1", - "winston": "^3.3.3" - }, - "bin": { - "apidoc": "bin/apidoc" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/apidoc/node_modules/glob": { - "version": "7.2.3", - "resolved": "http://94.130.170.209:4873/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/argparse": { - "version": "0.1.16", - "resolved": "http://94.130.170.209:4873/argparse/-/argparse-0.1.16.tgz", - "integrity": "sha512-LjmC2dNpdn2L4UzyoaIr11ELYoLn37ZFy9zObrQFHsSuOepeUEMKnM8w5KL4Tnrp2gy88rRuQt6Ky8Bjml+Baw==", - "dev": true, - "license": "MIT", - "dependencies": { - "underscore": "~1.7.0", - "underscore.string": "~2.4.0" - } - }, - "node_modules/argv-formatter": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/argv-formatter/-/argv-formatter-1.0.0.tgz", - "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", - "dev": true, - "license": "MIT" - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true, - "license": "MIT" - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "http://94.130.170.209:4873/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.every": { - "version": "1.1.6", - "resolved": "http://94.130.170.209:4873/array.prototype.every/-/array.prototype.every-1.1.6.tgz", - "integrity": "sha512-gNEqZD97w6bfQRNmHkFv7rNnGM+VWyHZT+h/rf9C+22owcXuENr66Lfo0phItpU5KoXW6Owb34q2+8MnSIZ57w==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "http://94.130.170.209:4873/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "http://94.130.170.209:4873/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "http://94.130.170.209:4873/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "http://94.130.170.209:4873/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "license": "MIT", - "peer": true - }, - "node_modules/asn1": { - "version": "0.1.11", - "resolved": "http://94.130.170.209:4873/asn1/-/asn1-0.1.11.tgz", - "integrity": "sha512-Fh9zh3G2mZ8qM/kwsiKwL2U2FmXxVsboP4x1mXjnhKHv3SmzaBZoYvxEQJz/YS2gnCgd8xlAVWcZnQyC9qZBsA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.4.9" - } - }, - "node_modules/asn1js": { - "version": "3.0.5", - "resolved": "http://94.130.170.209:4873/asn1js/-/asn1js-3.0.5.tgz", - "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", - "license": "BSD-3-Clause", - "dependencies": { - "pvtsutils": "^1.3.2", - "pvutils": "^1.1.3", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/assert-plus": { - "version": "0.1.5", - "resolved": "http://94.130.170.209:4873/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha512-brU24g7ryhRwGCI2y+1dGQmQXiZF7TtIj583S96y0jjdajIe6wn8BuXyELYhvD22dtIxDQVFk04YTJwwdwOYJw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "http://94.130.170.209:4873/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT" - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "license": "MIT", - "peer": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "http://94.130.170.209:4873/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sign2": { - "version": "0.5.0", - "resolved": "http://94.130.170.209:4873/aws-sign2/-/aws-sign2-0.5.0.tgz", - "integrity": "sha512-oqUX0DM5j7aPWPCnpWebiyNIj2wiNI87ZxnOMoGv0aE4TGlBy2N+5iWc6dQ/NOKZaBD2W6PVz8jtOGkWzSC5EA==", - "dev": true, - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/axios": { - "version": "0.27.2", - "resolved": "http://94.130.170.209:4873/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "http://94.130.170.209:4873/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "http://94.130.170.209:4873/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.25.1", - "resolved": "http://94.130.170.209:4873/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", - "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "hermes-parser": "0.25.1" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "http://94.130.170.209:4873/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "license": "MIT", - "peer": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/base-x": { - "version": "3.0.10", - "resolved": "http://94.130.170.209:4873/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base58-js": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/base58-js/-/base58-js-2.0.0.tgz", - "integrity": "sha512-nAV5d32QXuGcGptSApkKpC1gGakWBnfJMNjKrYTBh4tb0szfZF+ooueFLy8T4VrY+o4SrE/TyrtUnRZcwZchaA==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "http://94.130.170.209:4873/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" - } - ], - "license": "MIT" - }, - "node_modules/bc-bip68": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/bc-bip68/-/bc-bip68-1.0.5.tgz", - "integrity": "sha512-GzaMlN7pNthrY5BhReVhnfr4Ixx+GUSfyNRHYh0QiMUF0d0+0YaD8MpEdv6AjFBksg/zlqL1fVCBBm6PpTt2Rg==", - "license": "ISC", - "engines": { - "node": ">=4.5.0" - } - }, - "node_modules/bch-consumer": { - "version": "1.6.2", - "resolved": "http://94.130.170.209:4873/bch-consumer/-/bch-consumer-1.6.2.tgz", - "integrity": "sha512-PclXVzmWtwqxe2ba6Mo9QbqxJ+5rUog8c+Ro5PV/W3IxkKNotVRa71bLei99AIELDO3A3ljfXkoCNsSM7tR37A==", - "license": "MIT", - "dependencies": { - "@psf/bch-js": "6.7.3", - "apidoc": "0.51.0", - "axios": "0.25.0" - } - }, - "node_modules/bch-consumer/node_modules/apidoc": { - "version": "0.51.0", - "resolved": "http://94.130.170.209:4873/apidoc/-/apidoc-0.51.0.tgz", - "integrity": "sha512-3P4srhm6NA+kE/YRM4qL5jESElpQQJL+Z8n7hyr4uC+1DSwGzmE6adXPVxuT/hpDyShrqmRlHk8hf40RSqEsNw==", - "license": "MIT", - "os": [ - "darwin", - "freebsd", - "linux", - "openbsd", - "win32" - ], - "dependencies": { - "bootstrap": "3.4.1", - "commander": "^8.3.0", - "diff-match-patch": "^1.0.5", - "esbuild-loader": "^2.16.0", - "expose-loader": "^3.1.0", - "fs-extra": "^10.0.0", - "glob": "^7.2.0", - "handlebars": "^4.7.7", - "iconv-lite": "^0.6.3", - "jquery": "^3.6.0", - "klaw-sync": "^6.0.0", - "lodash": "^4.17.21", - "markdown-it": "^12.2.0", - "nodemon": "^2.0.15", - "path-to-regexp": "^6.2.0", - "prismjs": "^1.25.0", - "semver": "^7.3.5", - "style-loader": "^3.3.1", - "url-parse": "^1.5.3", - "webpack": "^5.64.2", - "webpack-cli": "^4.9.1", - "winston": "^3.3.3" - }, - "bin": { - "apidoc": "bin/apidoc" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/bch-consumer/node_modules/axios": { - "version": "0.25.0", - "resolved": "http://94.130.170.209:4873/axios/-/axios-0.25.0.tgz", - "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.7" - } - }, - "node_modules/bch-consumer/node_modules/glob": { - "version": "7.2.3", - "resolved": "http://94.130.170.209:4873/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/bch-donation": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/bch-donation/-/bch-donation-1.1.2.tgz", - "integrity": "sha512-V7xQ23M6Ocavb1Nj4/pATwaLX/uF/9s2nWir3f+F3aetD3kMmsRHFRuXJwGQG3dSC5fJtRR/M5Z2zynY3t91Xg==", - "license": "MIT", - "dependencies": { - "apidoc": "0.51.0" - } - }, - "node_modules/bch-donation/node_modules/apidoc": { - "version": "0.51.0", - "resolved": "http://94.130.170.209:4873/apidoc/-/apidoc-0.51.0.tgz", - "integrity": "sha512-3P4srhm6NA+kE/YRM4qL5jESElpQQJL+Z8n7hyr4uC+1DSwGzmE6adXPVxuT/hpDyShrqmRlHk8hf40RSqEsNw==", - "license": "MIT", - "os": [ - "darwin", - "freebsd", - "linux", - "openbsd", - "win32" - ], - "dependencies": { - "bootstrap": "3.4.1", - "commander": "^8.3.0", - "diff-match-patch": "^1.0.5", - "esbuild-loader": "^2.16.0", - "expose-loader": "^3.1.0", - "fs-extra": "^10.0.0", - "glob": "^7.2.0", - "handlebars": "^4.7.7", - "iconv-lite": "^0.6.3", - "jquery": "^3.6.0", - "klaw-sync": "^6.0.0", - "lodash": "^4.17.21", - "markdown-it": "^12.2.0", - "nodemon": "^2.0.15", - "path-to-regexp": "^6.2.0", - "prismjs": "^1.25.0", - "semver": "^7.3.5", - "style-loader": "^3.3.1", - "url-parse": "^1.5.3", - "webpack": "^5.64.2", - "webpack-cli": "^4.9.1", - "winston": "^3.3.3" - }, - "bin": { - "apidoc": "bin/apidoc" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/bch-donation/node_modules/glob": { - "version": "7.2.3", - "resolved": "http://94.130.170.209:4873/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/bch-encrypt-lib": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/bch-encrypt-lib/-/bch-encrypt-lib-2.1.1.tgz", - "integrity": "sha512-709FHSVhUofFnZg9i5BbLWc9kwrw9d5ZZzFetNFcNOS1Be/kPhvON4Q1yD3uurIrcOdVIw+Sj7tddxEEabwrBA==", - "license": "MIT", - "dependencies": { - "eccrypto-js": "5.3.0", - "wif": "2.0.6" - }, - "peerDependencies": { - "minimal-slp-wallet": ">= 5" - } - }, - "node_modules/bch-message-lib": { - "version": "2.2.1", - "resolved": "http://94.130.170.209:4873/bch-message-lib/-/bch-message-lib-2.2.1.tgz", - "integrity": "sha512-1hWLC0v0jdPWVdxxhLNpREoW91PZGy69PxxOs4wZmlZo00bHm7OPGhmaugh7ilMw+ouLn59vY//lSX2rOn65Kw==", - "license": "MIT", - "peerDependencies": { - "minimal-slp-wallet": ">= 4" - } - }, - "node_modules/bch-nostr": { - "version": "1.3.3", - "resolved": "http://94.130.170.209:4873/bch-nostr/-/bch-nostr-1.3.3.tgz", - "integrity": "sha512-2Mod/PEDr/GJzQq20oSJKwJDtiXYm/Qj5KxIvFqsvBY1SYsHGyDu1FMBQ1UvOhY3ZP5fgiVLbIGvMRuWXqS4oQ==", - "license": "MIT", - "dependencies": { - "apidoc": "0.53.0", - "base58-js": "2.0.0", - "bch-message-lib": "2.3.1", - "nostr": "0.2.8", - "nostr-tools": "2.10.1", - "ws": "8.18.0" - } - }, - "node_modules/bch-nostr/node_modules/@noble/ciphers": { - "version": "0.5.3", - "resolved": "http://94.130.170.209:4873/@noble%2fciphers/-/ciphers-0.5.3.tgz", - "integrity": "sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/bch-nostr/node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/@noble%2fcurves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/bch-nostr/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/@noble%2fhashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/bch-nostr/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "http://94.130.170.209:4873/@noble%2fhashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/bch-nostr/node_modules/apidoc": { - "version": "0.53.0", - "resolved": "http://94.130.170.209:4873/apidoc/-/apidoc-0.53.0.tgz", - "integrity": "sha512-H4hYToCrI6TgSksdVHxS7h5/Xoqr/rR9m9/IOQaYqXbX07cPVbg0O3RM4+bR4tJKG1aqBWKKm+xojQ8+4i7O5A==", - "license": "MIT", - "os": [ - "darwin", - "freebsd", - "linux", - "openbsd", - "win32" - ], - "dependencies": { - "bootstrap": "3.4.1", - "commander": "^8.3.0", - "diff-match-patch": "^1.0.5", - "esbuild-loader": "^2.16.0", - "expose-loader": "^3.1.0", - "fs-extra": "^10.0.0", - "glob": "^7.2.0", - "handlebars": "^4.7.7", - "iconv-lite": "^0.6.3", - "jquery": "^3.6.0", - "klaw-sync": "^6.0.0", - "lodash": "^4.17.21", - "markdown-it": "^12.2.0", - "nodemon": "^2.0.15", - "prismjs": "^1.25.0", - "semver": "^7.3.5", - "style-loader": "^3.3.1", - "webpack": "^5.64.2", - "webpack-cli": "^4.9.1", - "winston": "^3.3.3" - }, - "bin": { - "apidoc": "bin/apidoc" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/bch-nostr/node_modules/bch-message-lib": { - "version": "2.3.1", - "resolved": "http://94.130.170.209:4873/bch-message-lib/-/bch-message-lib-2.3.1.tgz", - "integrity": "sha512-xAWMRvmcP2mYTdp9KgjSQfxlJF4DTloCJrjGx0TumD3HPF9mmYZ/CiCGUAFdQk3LBCavnK0AZi9v3+JTNSnrcA==", - "license": "MIT", - "peerDependencies": { - "minimal-slp-wallet": ">= 5" - } - }, - "node_modules/bch-nostr/node_modules/glob": { - "version": "7.2.3", - "resolved": "http://94.130.170.209:4873/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/bch-nostr/node_modules/nostr-tools": { - "version": "2.10.1", - "resolved": "http://94.130.170.209:4873/nostr-tools/-/nostr-tools-2.10.1.tgz", - "integrity": "sha512-fnAxLi92UgyMAEw4fMEhDKzH53uBJ0WkkVPTNfX0b3bspeWWn0n5tDZtKRJbvW0wAGOPmU6LYWi/IKPOsq3p2Q==", - "license": "Unlicense", - "dependencies": { - "@noble/ciphers": "^0.5.1", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.1", - "@scure/base": "1.1.1", - "@scure/bip32": "1.3.1", - "@scure/bip39": "1.2.1" - }, - "optionalDependencies": { - "nostr-wasm": "v0.1.0" - }, - "peerDependencies": { - "typescript": ">=5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/bch-token-sweep": { - "version": "2.2.1", - "resolved": "http://94.130.170.209:4873/bch-token-sweep/-/bch-token-sweep-2.2.1.tgz", - "integrity": "sha512-f4UGEpPXzea7HQMRSEb6h/amXiwrlsMBAjl1dVYg5//26IDWeG+e3qVNtMJhm00NMZ0BS+LasUa2xlz0UVziZA==", - "license": "MIT", - "dependencies": { - "bch-donation": "1.1.2", - "bignumber.js": "9.0.0" - }, - "peerDependencies": { - "minimal-slp-wallet": ">= 4" - } - }, - "node_modules/bchaddrjs-slp": { - "version": "0.2.5", - "resolved": "http://94.130.170.209:4873/bchaddrjs-slp/-/bchaddrjs-slp-0.2.5.tgz", - "integrity": "sha512-33flmPcqMFswerKu7477DSUNMVMQR3tHDk3lvbmsdkEva+TxVGGWWE/p5Lqx9M/8t3vkbe7fzmVhj4QhChcCyA==", - "license": "MIT", - "dependencies": { - "bs58check": "^2.1.2", - "cashaddrjs-slp": "^0.2.11" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "http://94.130.170.209:4873/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", - "license": "MIT" - }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "http://94.130.170.209:4873/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "http://94.130.170.209:4873/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "http://94.130.170.209:4873/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "license": "Unlicense", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "http://94.130.170.209:4873/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/bigi": { - "version": "1.4.2", - "resolved": "http://94.130.170.209:4873/bigi/-/bigi-1.4.2.tgz", - "integrity": "sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==" - }, - "node_modules/bignumber.js": { - "version": "9.0.0", - "resolved": "http://94.130.170.209:4873/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "http://94.130.170.209:4873/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "license": "MIT", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip-schnorr": { - "version": "0.3.0", - "resolved": "http://94.130.170.209:4873/bip-schnorr/-/bip-schnorr-0.3.0.tgz", - "integrity": "sha512-Sc1Hn2+1n+okPEW8G+JLjeaM12dsUOwr+oFlMDSKR9wYwNGMw0alskeBIHTmXxBxMZSWKhCW7PwKQVDyGmnaVg==", - "license": "MIT", - "dependencies": { - "ecurve": "^1.0.6", - "js-sha256": "^0.9.0", - "random-bytes": "^1.0.0", - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/bip38": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/bip38/-/bip38-2.0.2.tgz", - "integrity": "sha512-22KDak0RDyghFbR0Si7wyq9IgY423YzGYzWLpGeofH3DaolOQqjD3mNN08eFoubKlbyclOQKFwtONMv2SD9V3A==", - "dependencies": { - "bigi": "^1.2.0", - "browserify-aes": "^1.0.1", - "bs58check": "<3.0.0", - "buffer-xor": "^1.0.2", - "create-hash": "^1.1.1", - "ecurve": "^1.0.0", - "scryptsy": "^2.0.0" - } - }, - "node_modules/bip39": { - "version": "3.0.2", - "resolved": "http://94.130.170.209:4873/bip39/-/bip39-3.0.2.tgz", - "integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==", - "license": "ISC", - "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" - } - }, - "node_modules/bip39/node_modules/@types/node": { - "version": "11.11.6", - "resolved": "http://94.130.170.209:4873/@types%2fnode/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", - "license": "MIT" - }, - "node_modules/bip66": { - "version": "1.1.5", - "resolved": "http://94.130.170.209:4873/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bitcoin-ops": { - "version": "1.4.1", - "resolved": "http://94.130.170.209:4873/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz", - "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==", - "license": "MIT" - }, - "node_modules/bitcoincashjs-lib": { - "version": "3.3.3", - "resolved": "http://94.130.170.209:4873/bitcoincashjs-lib/-/bitcoincashjs-lib-3.3.3.tgz", - "integrity": "sha512-dk6GCVpCE+7oELy8l2Y/9vGR1ymlnsQffU7YmYNeBoUSTH9gckbKSk6xrg3O5b2P0C7+1SifQ8de7luCpq6k8g==", - "deprecated": "ooops", - "license": "MIT", - "dependencies": { - "bech32": "^1.1.2", - "bigi": "^1.4.0", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.3.0", - "bs58check": "^2.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "ecurve": "^1.0.0", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "safe-buffer": "^5.0.1", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", - "wif": "^2.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/bitcoinjs-message": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/bitcoinjs-message/-/bitcoinjs-message-2.0.0.tgz", - "integrity": "sha512-H5pJC7/eSqVjREiEOZ4jifX+7zXYP3Y28GIOIqg9hrgE7Vj8Eva9+HnVqnxwA1rJPOwZKuw0vo6k0UxgVc6q1A==", - "license": "MIT", - "dependencies": { - "bs58check": "^2.0.2", - "buffer-equals": "^1.0.3", - "create-hash": "^1.1.2", - "secp256k1": "^3.0.1", - "varuint-bitcoin": "^1.0.1" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/bl": { - "version": "2.2.1", - "resolved": "http://94.130.170.209:4873/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "license": "MIT", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bl/node_modules/isarray": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "http://94.130.170.209:4873/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/blob-to-it": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/blob-to-it/-/blob-to-it-1.0.4.tgz", - "integrity": "sha512-iCmk0W4NdbrWgRRuxOriU8aM5ijeVLI61Zulsmg/lUHNr7pYjoj+U77opLefNagevtrrbMt3JQ5Qip7ar178kA==", - "license": "ISC", - "dependencies": { - "browser-readablestream-to-it": "^1.0.3" - } - }, - "node_modules/blob-to-it/node_modules/browser-readablestream-to-it": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/browser-readablestream-to-it/-/browser-readablestream-to-it-1.0.3.tgz", - "integrity": "sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==", - "license": "ISC" - }, - "node_modules/blockstore-core": { - "version": "5.0.2", - "resolved": "http://94.130.170.209:4873/blockstore-core/-/blockstore-core-5.0.2.tgz", - "integrity": "sha512-y7/BHdYLO3YCpJMg6Ue7b4Oz4FT1HWSZoHHdlsaJTsvoE8XieXb6kUCB9UkkUBDw2x4neRDwlgYBpyK77+Ro2Q==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/logger": "^5.0.1", - "interface-blockstore": "^5.0.0", - "interface-store": "^6.0.0", - "it-drain": "^3.0.7", - "it-filter": "^3.1.1", - "it-merge": "^3.0.5", - "it-pushable": "^3.2.3", - "multiformats": "^13.2.3" - } - }, - "node_modules/blockstore-fs": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/blockstore-fs/-/blockstore-fs-2.0.2.tgz", - "integrity": "sha512-g4l4cJZqcLGPD+iOSb9DYWClAiSSGKsN7V13PTZYqQFHeg96phG15jNi9ql3urrlVC/OTzPB95FXK+GP0TX8Tw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "interface-blockstore": "^5.0.0", - "interface-store": "^6.0.0", - "it-glob": "^3.0.1", - "it-map": "^3.1.1", - "it-parallel-batch": "^3.0.6", - "multiformats": "^13.2.3", - "steno": "^4.0.2" - } - }, - "node_modules/bluebird": { - "version": "3.5.1", - "resolved": "http://94.130.170.209:4873/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", - "license": "MIT" - }, - "node_modules/bn.js": { - "version": "4.11.8", - "resolved": "http://94.130.170.209:4873/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "license": "MIT" - }, - "node_modules/boom": { - "version": "0.4.2", - "resolved": "http://94.130.170.209:4873/boom/-/boom-0.4.2.tgz", - "integrity": "sha512-OvfN8y1oAxxphzkl2SnCS+ztV/uVKTATtgLjWYg/7KwcNyf3rzpHxNQJZCKtsZd4+MteKczhWbSjtEX4bGgU9g==", - "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", - "dev": true, - "optional": true, - "dependencies": { - "hoek": "0.9.x" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/bootstrap": { - "version": "3.4.1", - "resolved": "http://94.130.170.209:4873/bootstrap/-/bootstrap-3.4.1.tgz", - "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/bottleneck": { - "version": "2.19.5", - "resolved": "http://94.130.170.209:4873/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "http://94.130.170.209:4873/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "license": "MIT" - }, - "node_modules/browser-readablestream-to-it": { - "version": "2.0.8", - "resolved": "http://94.130.170.209:4873/browser-readablestream-to-it/-/browser-readablestream-to-it-2.0.8.tgz", - "integrity": "sha512-+aDq+8QoTxIklc9m21oVg96Bm18EpeVke4/8vWPNu+9Ktd+G4PYavitE4gv/pjIndw1q+vxE/Rcnv1zYHrEQbQ==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "http://94.130.170.209:4873/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true, - "license": "ISC" - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "license": "MIT", - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "http://94.130.170.209:4873/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "license": "MIT", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "http://94.130.170.209:4873/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "license": "MIT", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/bson": { - "version": "1.1.6", - "resolved": "http://94.130.170.209:4873/bson/-/bson-1.1.6.tgz", - "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "http://94.130.170.209:4873/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" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause" - }, - "node_modules/buffer-equals": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/buffer-equals/-/buffer-equals-1.0.4.tgz", - "integrity": "sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "license": "MIT" - }, - "node_modules/builtins": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/builtins/-/builtins-5.1.0.tgz", - "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "http://94.130.170.209:4873/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/c8": { - "version": "7.12.0", - "resolved": "http://94.130.170.209:4873/c8/-/c8-7.12.0.tgz", - "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", - "dev": true, - "license": "ISC", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.1.4", - "rimraf": "^3.0.2", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/cache-content-type": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/cache-content-type/-/cache-content-type-1.0.1.tgz", - "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", - "license": "MIT", - "dependencies": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "http://94.130.170.209:4873/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "license": "MIT", - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "http://94.130.170.209:4873/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "license": "MIT", - "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/caller-callsite": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "callsites": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-callsite/node_modules/callsites": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-path": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", - "license": "MIT", - "peer": true, - "dependencies": { - "caller-callsite": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "http://94.130.170.209:4873/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "http://94.130.170.209:4873/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001683", - "resolved": "http://94.130.170.209:4873/caniuse-lite/-/caniuse-lite-1.0.30001683.tgz", - "integrity": "sha512-iqmNnThZ0n70mNwvxpEC2nBJ037ZHZUoBI5Gorh1Mw6IlEAZujEoU1tXA628iZfzm7R9FvFzxbfdgml82a3k8Q==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/cardinal": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/cardinal/-/cardinal-2.1.1.tgz", - "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansicolors": "~0.3.2", - "redeyed": "~2.1.0" - }, - "bin": { - "cdl": "bin/cdl.js" - } - }, - "node_modules/cashaddrjs-slp": { - "version": "0.2.12", - "resolved": "http://94.130.170.209:4873/cashaddrjs-slp/-/cashaddrjs-slp-0.2.12.tgz", - "integrity": "sha512-n2TTIuW6vZZxYvjvsUAA+wOM0Zkj+3RRKUtDC1XSu4Ic4XVr0yFJkl1bzQkHWda7nkVT51sxjZneygz7D0SyrQ==", - "license": "MIT", - "dependencies": { - "big-integer": "^1.6.34" - } - }, - "node_modules/cborg": { - "version": "4.2.6", - "resolved": "http://94.130.170.209:4873/cborg/-/cborg-4.2.6.tgz", - "integrity": "sha512-77vo4KlSwfjCIXcyZUVei4l2gdjesSCeYSx4U/Upwix7pcWZq8uw21sVRpjwn7mjEi//ieJPTj1MRWDHmud1Rg==", - "license": "Apache-2.0", - "bin": { - "cborg": "lib/bin.js" - } - }, - "node_modules/chai": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/chai/-/chai-4.3.0.tgz", - "integrity": "sha512-/BFd2J30EcOwmdOgXvVsmM48l0Br0nmZPlO0uOW4XKh6kpsUumRXBgPV+IlaqFaqr9cYbeoZAM1Npx0i4A+aiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "http://94.130.170.209:4873/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "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/check-error": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "http://94.130.170.209:4873/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "http://94.130.170.209:4873/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" - }, - "node_modules/chrome-launcher": { - "version": "0.15.2", - "resolved": "http://94.130.170.209:4873/chrome-launcher/-/chrome-launcher-0.15.2.tgz", - "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0" - }, - "bin": { - "print-chrome-path": "bin/print-chrome-path.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/chromium-edge-launcher": { - "version": "0.2.0", - "resolved": "http://94.130.170.209:4873/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", - "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "license": "MIT" - }, - "node_modules/cipher-base": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/cipher-base/-/cipher-base-1.0.5.tgz", - "integrity": "sha512-xq7ICKB4TMHUx7Tz1L9O2SGKOhYMOTR32oir45Bq28/AQTpHogKgHcoYFSdRbMtddl+ozNXfXY9jWcgYKmde0w==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cipher-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/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" - } - ], - "license": "MIT" - }, - "node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "http://94.130.170.209:4873/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "license": "MIT", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-stack/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "http://94.130.170.209:4873/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "http://94.130.170.209:4873/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-regexp": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/clone-regexp/-/clone-regexp-3.0.0.tgz", - "integrity": "sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw==", - "license": "MIT", - "dependencies": { - "is-regexp": "^3.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cls-bluebird": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/cls-bluebird/-/cls-bluebird-2.1.0.tgz", - "integrity": "sha512-XVb0RPmHQyy35Tz9z34gvtUcBKUK8A/1xkGCyeFc9B0C7Zr5SysgFaswRVdwI5NEMcO+3JKlIDGIOgERSn9NdA==", - "license": "BSD-2-Clause", - "dependencies": { - "is-bluebird": "^1.0.2", - "shimmer": "^1.1.0" - } - }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "http://94.130.170.209:4873/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/co-body": { - "version": "6.2.0", - "resolved": "http://94.130.170.209:4873/co-body/-/co-body-6.2.0.tgz", - "integrity": "sha512-Kbpv2Yd1NdL1V/V4cwLVxraHDV6K8ayohr2rmH0J87Er8+zJjcTa6dAn9QMPC9CRgU8+aNajKbSf1TzDB1yKPA==", - "license": "MIT", - "dependencies": { - "@hapi/bourne": "^3.0.0", - "inflation": "^2.0.0", - "qs": "^6.5.2", - "raw-body": "^2.3.3", - "type-is": "^1.6.16" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/color": { - "version": "3.2.1", - "resolved": "http://94.130.170.209:4873/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "http://94.130.170.209:4873/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "http://94.130.170.209:4873/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/color/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "http://94.130.170.209:4873/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color/node_modules/color-name": { - "version": "1.1.3", - "resolved": "http://94.130.170.209:4873/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "http://94.130.170.209:4873/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "license": "MIT" - }, - "node_modules/colorspace": { - "version": "1.1.4", - "resolved": "http://94.130.170.209:4873/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "license": "MIT", - "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "http://94.130.170.209:4873/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "http://94.130.170.209:4873/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "http://94.130.170.209:4873/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "http://94.130.170.209:4873/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "http://94.130.170.209:4873/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "http://94.130.170.209:4873/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "http://94.130.170.209:4873/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "http://94.130.170.209:4873/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/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" - } - ], - "license": "MIT" - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "http://94.130.170.209:4873/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-changelog-writer": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-writer/node_modules/semver": { - "version": "6.3.1", - "resolved": "http://94.130.170.209:4873/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/conventional-changelog-writer/node_modules/through2": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/conventional-commits-filter": { - "version": "2.0.7", - "resolved": "http://94.130.170.209:4873/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser": { - "version": "3.2.4", - "resolved": "http://94.130.170.209:4873/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser/node_modules/through2": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/convert-hrtime": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/convert-hrtime/-/convert-hrtime-5.0.0.tgz", - "integrity": "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "license": "MIT" - }, - "node_modules/cookies": { - "version": "0.8.0", - "resolved": "http://94.130.170.209:4873/cookies/-/cookies-0.8.0.tgz", - "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/copy-to": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/copy-to/-/copy-to-2.0.1.tgz", - "integrity": "sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==", - "license": "MIT" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "license": "MIT" - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "http://94.130.170.209:4873/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/coveralls": { - "version": "2.11.4", - "resolved": "http://94.130.170.209:4873/coveralls/-/coveralls-2.11.4.tgz", - "integrity": "sha512-dLHJUkWjMoQqMpGVIE4syOo5JOPk4WpLhC9G7xgrjNgCeANKmGr+mSI9VRX3LTKOXLSoRsu213EwHmuY8JAnkQ==", - "dev": true, - "license": "BSD", - "dependencies": { - "js-yaml": "3.0.1", - "lcov-parse": "0.0.6", - "log-driver": "1.2.4", - "request": "2.40.0" - }, - "bin": { - "coveralls": "bin/coveralls.js" - }, - "engines": { - "node": ">=0.8.6" - } - }, - "node_modules/crc": { - "version": "3.5.0", - "resolved": "http://94.130.170.209:4873/crc/-/crc-3.5.0.tgz", - "integrity": "sha512-3gEeEBQFvhKTyehoy0niaItHrfeB1uSuFgpYfdYfPp2fERRtPOynwycZ2+6IzR9Gl3dJ+B7pl0BY3Mex6ep78Q==", - "license": "MIT" - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "http://94.130.170.209:4873/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "http://94.130.170.209:4873/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cryptiles": { - "version": "0.2.2", - "resolved": "http://94.130.170.209:4873/cryptiles/-/cryptiles-0.2.2.tgz", - "integrity": "sha512-gvWSbgqP+569DdslUiCelxIv3IYK5Lgmq1UrRnk+s1WxQOQ16j3GPDcjdtgL5Au65DU/xQi6q3xPtf5Kta+3IQ==", - "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", - "dev": true, - "optional": true, - "dependencies": { - "boom": "0.4.x" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/crypto-js": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/crypto-js/-/crypto-js-4.0.0.tgz", - "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==", - "license": "MIT" - }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ctype": { - "version": "0.5.3", - "resolved": "http://94.130.170.209:4873/ctype/-/ctype-0.5.3.tgz", - "integrity": "sha512-T6CEkoSV4q50zW3TlTHMbzy1E5+zlnNcY+yb7tWVYlTwPhx9LpnfAkd4wecpWknDyptp4k97LUZeInlf6jdzBg==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/dag-jose": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/dag-jose/-/dag-jose-2.0.1.tgz", - "integrity": "sha512-1jCSAWOJ7oHl4A3xGQEERCl2IqqFZJYp4qnmzBbh2vifQx0ZGTtSxDR68MStjLjADvaqYgWI7a73wre5GFqVrA==", - "license": "(Apache-2.0 OR MIT)", - "dependencies": { - "@ipld/dag-cbor": "^7.0.1", - "multiformats": "^9.6.4" - } - }, - "node_modules/dag-jose/node_modules/@ipld/dag-cbor": { - "version": "7.0.3", - "resolved": "http://94.130.170.209:4873/@ipld%2fdag-cbor/-/dag-cbor-7.0.3.tgz", - "integrity": "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==", - "license": "(Apache-2.0 AND MIT)", - "dependencies": { - "cborg": "^1.6.0", - "multiformats": "^9.5.4" - } - }, - "node_modules/dag-jose/node_modules/cborg": { - "version": "1.10.2", - "resolved": "http://94.130.170.209:4873/cborg/-/cborg-1.10.2.tgz", - "integrity": "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==", - "license": "Apache-2.0", - "bin": { - "cborg": "cli.js" - } - }, - "node_modules/dag-jose/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", - "license": "(Apache-2.0 AND MIT)" - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/datastore-core": { - "version": "10.0.2", - "resolved": "http://94.130.170.209:4873/datastore-core/-/datastore-core-10.0.2.tgz", - "integrity": "sha512-B3WXxI54VxJkpXxnYibiF17si3bLXE1XOjrJB7wM5co9fx2KOEkiePDGiCCEtnapFHTnmAnYCPdA7WZTIpdn/A==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/logger": "^5.0.1", - "interface-datastore": "^8.0.0", - "interface-store": "^6.0.0", - "it-drain": "^3.0.7", - "it-filter": "^3.1.1", - "it-map": "^3.1.1", - "it-merge": "^3.0.5", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.3", - "it-sort": "^3.0.6", - "it-take": "^3.0.6" - } - }, - "node_modules/datastore-fs": { - "version": "10.0.2", - "resolved": "http://94.130.170.209:4873/datastore-fs/-/datastore-fs-10.0.2.tgz", - "integrity": "sha512-Jk4mCsahcqDry5JhiH+S6V3GYbET4J9B13zNWlxmCHWoCVnGN+13RneT8jLBOgwOj3/TMLAzE/YhE5OuQqNfgA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "datastore-core": "^10.0.0", - "interface-datastore": "^8.0.0", - "interface-store": "^6.0.0", - "it-glob": "^3.0.1", - "it-map": "^3.1.1", - "it-parallel-batch": "^3.0.6", - "steno": "^4.0.2" - } - }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-equal": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", - "license": "MIT" - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "http://94.130.170.209:4873/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "http://94.130.170.209:4873/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "http://94.130.170.209:4873/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "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": "http://94.130.170.209:4873/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "license": "MIT", - "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/defined": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/defined/-/defined-1.0.1.tgz", - "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/del": { - "version": "6.1.1", - "resolved": "http://94.130.170.209:4873/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dev": true, - "license": "MIT", - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/del/node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/del/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/del/node_modules/p-map": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/delay": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/delay/-/delay-6.0.0.tgz", - "integrity": "sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT" - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "http://94.130.170.209:4873/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-browser": { - "version": "5.3.0", - "resolved": "http://94.130.170.209:4873/detect-browser/-/detect-browser-5.3.0.tgz", - "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==", - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-match-patch": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", - "license": "Apache-2.0" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-over-http-resolver": { - "version": "2.1.3", - "resolved": "http://94.130.170.209:4873/dns-over-http-resolver/-/dns-over-http-resolver-2.1.3.tgz", - "integrity": "sha512-zjRYFhq+CsxPAouQWzOsxNMvEN+SHisjzhX8EMxd2Y0EG3thvn6wXQgMJLnTDImkhe4jhLbOQpXtL10nALBOSA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "debug": "^4.3.1", - "native-fetch": "^4.0.2", - "receptacle": "^1.3.2", - "undici": "^5.12.0" - } - }, - "node_modules/dns-over-http-resolver/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dns-over-http-resolver/node_modules/native-fetch": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/native-fetch/-/native-fetch-4.0.2.tgz", - "integrity": "sha512-4QcVlKFtv2EYVS5MBgsGX5+NWKtbDbIECdUXDBGDMAZXq3Jkv9zf+y8iS7Ub8fEdga3GpYeazp9gauNqXHJOCg==", - "license": "MIT", - "peerDependencies": { - "undici": "*" - } - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "http://94.130.170.209:4873/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "license": "MIT", - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dns-socket": { - "version": "4.2.2", - "resolved": "http://94.130.170.209:4873/dns-socket/-/dns-socket-4.2.2.tgz", - "integrity": "sha512-BDeBd8najI4/lS00HSKpdFia+OvUMytaVjfzR9n5Lq8MlZRSvtbI+uLtx1+XmQFls5wFU9dssccTmQQ6nfpjdg==", - "license": "MIT", - "dependencies": { - "dns-packet": "^5.2.4" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "http://94.130.170.209:4873/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotignore": { - "version": "0.1.2", - "resolved": "http://94.130.170.209:4873/dotignore/-/dotignore-0.1.2.tgz", - "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==", - "license": "MIT", - "dependencies": { - "minimatch": "^3.0.4" - }, - "bin": { - "ignored": "bin/ignored" - } - }, - "node_modules/dottie": { - "version": "2.0.6", - "resolved": "http://94.130.170.209:4873/dottie/-/dottie-2.0.6.tgz", - "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==", - "license": "MIT" - }, - "node_modules/drbg.js": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==", - "license": "MIT", - "dependencies": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "http://94.130.170.209:4873/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexer2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "http://94.130.170.209:4873/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/ecashaddrjs": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/ecashaddrjs/-/ecashaddrjs-1.0.7.tgz", - "integrity": "sha512-KsvHYLlYtLr/GBkEPiwwQDIDBzqRx61qC34n1puHKOjVE4Uwg3syHccjFCqNynLa6T6xI0Rd7ByCRUJcuJcoIw==", - "license": "MIT", - "dependencies": { - "big-integer": "1.6.36" - } - }, - "node_modules/ecashaddrjs/node_modules/big-integer": { - "version": "1.6.36", - "resolved": "http://94.130.170.209:4873/big-integer/-/big-integer-1.6.36.tgz", - "integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==", - "license": "Unlicense", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/eccrypto-js": { - "version": "5.3.0", - "resolved": "http://94.130.170.209:4873/eccrypto-js/-/eccrypto-js-5.3.0.tgz", - "integrity": "sha512-fCPIHNr/RDSCNY9NKkrSsjkurb6Rw/d5TYVdzjJeA3E+HcF+DdaWAvhDdsAcBOGUJ6Ygs8o6b4imuvhx9t7o+Q==", - "license": "MIT", - "dependencies": { - "aes-js": "3.1.2", - "enc-utils": "2.1.0", - "hash.js": "1.1.7", - "js-sha3": "0.8.0", - "pbkdf2": "^3.0.17", - "randombytes": "2.1.0", - "secp256k1": "3.8.0" - } - }, - "node_modules/eccrypto-js/node_modules/randombytes": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/eccrypto-js/node_modules/secp256k1": { - "version": "3.8.0", - "resolved": "http://94.130.170.209:4873/secp256k1/-/secp256k1-3.8.0.tgz", - "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.5.2", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "http://94.130.170.209:4873/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ecurve": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/ecurve/-/ecurve-1.0.6.tgz", - "integrity": "sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==", - "license": "MIT", - "dependencies": { - "bigi": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/electron-fetch": { - "version": "1.9.1", - "resolved": "http://94.130.170.209:4873/electron-fetch/-/electron-fetch-1.9.1.tgz", - "integrity": "sha512-M9qw6oUILGVrcENMSRRefE1MbHPIz0h79EKIeJWK9v563aT9Qkh8aEHPO1H5vi970wPirNY+jO9OpFoLiMsMGA==", - "license": "MIT", - "dependencies": { - "encoding": "^0.1.13" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.64", - "resolved": "http://94.130.170.209:4873/electron-to-chromium/-/electron-to-chromium-1.5.64.tgz", - "integrity": "sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==", - "license": "ISC" - }, - "node_modules/elliptic": { - "version": "6.6.1", - "resolved": "http://94.130.170.209:4873/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "http://94.130.170.209:4873/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "http://94.130.170.209:4873/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "license": "MIT" - }, - "node_modules/enc-utils": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/enc-utils/-/enc-utils-2.1.0.tgz", - "integrity": "sha512-VD0eunGDyzhojePzkORWDnW88gi6tIeGb5Z6QVHugux6mMAPiXyw94fb/7WdDQEWhKMSoYRyzFFUebCqeH20PA==", - "license": "MIT", - "dependencies": { - "bn.js": "4.11.8", - "is-typedarray": "1.0.0", - "typedarray-to-buffer": "3.1.5" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "http://94.130.170.209:4873/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "license": "MIT", - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "http://94.130.170.209:4873/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "http://94.130.170.209:4873/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-ci": { - "version": "5.5.0", - "resolved": "http://94.130.170.209:4873/env-ci/-/env-ci-5.5.0.tgz", - "integrity": "sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "fromentries": "^1.3.2", - "java-properties": "^1.0.0" - }, - "engines": { - "node": ">=10.17" - } - }, - "node_modules/env-ci/node_modules/execa": { - "version": "5.1.1", - "resolved": "http://94.130.170.209:4873/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/env-ci/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/env-ci/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/env-ci/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/env-ci/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/env-ci/node_modules/onetime": { - "version": "5.1.2", - "resolved": "http://94.130.170.209:4873/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/env-ci/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/envinfo": { - "version": "7.14.0", - "resolved": "http://94.130.170.209:4873/envinfo/-/envinfo-7.14.0.tgz", - "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", - "license": "MIT", - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/err-code": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/err-code/-/err-code-3.0.1.tgz", - "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==", - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "http://94.130.170.209:4873/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "stackframe": "^1.3.4" - } - }, - "node_modules/es-abstract": { - "version": "1.23.5", - "resolved": "http://94.130.170.209:4873/es-abstract/-/es-abstract-1.23.5.tgz", - "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "http://94.130.170.209:4873/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "http://94.130.170.209:4873/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", - "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.3", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "http://94.130.170.209:4873/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "license": "MIT" - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.16.17", - "resolved": "http://94.130.170.209:4873/esbuild/-/esbuild-0.16.17.tgz", - "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.16.17", - "@esbuild/android-arm64": "0.16.17", - "@esbuild/android-x64": "0.16.17", - "@esbuild/darwin-arm64": "0.16.17", - "@esbuild/darwin-x64": "0.16.17", - "@esbuild/freebsd-arm64": "0.16.17", - "@esbuild/freebsd-x64": "0.16.17", - "@esbuild/linux-arm": "0.16.17", - "@esbuild/linux-arm64": "0.16.17", - "@esbuild/linux-ia32": "0.16.17", - "@esbuild/linux-loong64": "0.16.17", - "@esbuild/linux-mips64el": "0.16.17", - "@esbuild/linux-ppc64": "0.16.17", - "@esbuild/linux-riscv64": "0.16.17", - "@esbuild/linux-s390x": "0.16.17", - "@esbuild/linux-x64": "0.16.17", - "@esbuild/netbsd-x64": "0.16.17", - "@esbuild/openbsd-x64": "0.16.17", - "@esbuild/sunos-x64": "0.16.17", - "@esbuild/win32-arm64": "0.16.17", - "@esbuild/win32-ia32": "0.16.17", - "@esbuild/win32-x64": "0.16.17" - } - }, - "node_modules/esbuild-loader": { - "version": "2.21.0", - "resolved": "http://94.130.170.209:4873/esbuild-loader/-/esbuild-loader-2.21.0.tgz", - "integrity": "sha512-k7ijTkCT43YBSZ6+fBCW1Gin7s46RrJ0VQaM8qA7lq7W+OLsGgtLyFV8470FzYi/4TeDexniTBTPTwZUnXXR5g==", - "license": "MIT", - "dependencies": { - "esbuild": "^0.16.17", - "joycon": "^3.0.1", - "json5": "^2.2.0", - "loader-utils": "^2.0.0", - "tapable": "^2.2.0", - "webpack-sources": "^1.4.3" - }, - "funding": { - "url": "https://github.com/privatenumber/esbuild-loader?sponsor=1" - }, - "peerDependencies": { - "webpack": "^4.40.0 || ^5.0.0" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "http://94.130.170.209:4873/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-standard": { - "version": "17.0.0", - "resolved": "http://94.130.170.209:4873/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", - "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0", - "eslint-plugin-promise": "^6.0.0" - } - }, - "node_modules/eslint-config-standard-jsx": { - "version": "11.0.0", - "resolved": "http://94.130.170.209:4873/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", - "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "peerDependencies": { - "eslint": "^8.8.0", - "eslint-plugin-react": "^7.28.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "http://94.130.170.209:4873/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "http://94.130.170.209:4873/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-es": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", - "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-es/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "http://94.130.170.209:4873/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "http://94.130.170.209:4873/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "http://94.130.170.209:4873/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-n": { - "version": "15.7.0", - "resolved": "http://94.130.170.209:4873/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", - "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "builtins": "^5.0.1", - "eslint-plugin-es": "^4.1.0", - "eslint-utils": "^3.0.0", - "ignore": "^5.1.1", - "is-core-module": "^2.11.0", - "minimatch": "^3.1.2", - "resolve": "^1.22.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-promise": { - "version": "6.6.0", - "resolved": "http://94.130.170.209:4873/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz", - "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.2", - "resolved": "http://94.130.170.209:4873/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", - "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.1.0", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "http://94.130.170.209:4873/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "http://94.130.170.209:4873/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "http://94.130.170.209:4873/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "http://94.130.170.209:4873/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "http://94.130.170.209:4873/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "http://94.130.170.209:4873/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "http://94.130.170.209:4873/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "http://94.130.170.209:4873/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha512-rp5dMKN8zEs9dfi9g0X1ClLmV//WRyk/R15mppFNICIFRG5P92VP7Z04p8pk++gABo9W2tY+kHyu6P1mEHgmTA==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "http://94.130.170.209:4873/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "http://94.130.170.209:4873/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "http://94.130.170.209:4873/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-iterator": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/event-iterator/-/event-iterator-2.0.0.tgz", - "integrity": "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==", - "license": "MIT" - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "http://94.130.170.209:4873/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "license": "MIT" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "http://94.130.170.209:4873/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "license": "MIT", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "license": "(MIT OR WTFPL)", - "engines": { - "node": ">=6" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.2", - "resolved": "http://94.130.170.209:4873/exponential-backoff/-/exponential-backoff-3.1.2.tgz", - "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", - "license": "Apache-2.0", - "peer": true - }, - "node_modules/expose-loader": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/expose-loader/-/expose-loader-3.1.0.tgz", - "integrity": "sha512-2RExSo0yJiqP+xiUue13jQa2IHE8kLDzTI7b6kn+vUlBVvlzNSiLDzo4e5Pp5J039usvTUnxZ8sUOhv0Kg15NA==", - "license": "MIT", - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "http://94.130.170.209:4873/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "http://94.130.170.209:4873/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "http://94.130.170.209:4873/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "http://94.130.170.209:4873/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "http://94.130.170.209:4873/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fecha": { - "version": "4.2.3", - "resolved": "http://94.130.170.209:4873/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "license": "MIT" - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "http://94.130.170.209:4873/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-stream-rotator": { - "version": "0.5.7", - "resolved": "http://94.130.170.209:4873/file-stream-rotator/-/file-stream-rotator-0.5.7.tgz", - "integrity": "sha512-VYb3HZ/GiAGUCrfeakO8Mp54YGswNUHvL7P09WQcXAJNSj3iQ5QraYSp3cIn1MUyw6uzfgN/EFOarCNa4JvUHQ==", - "license": "MIT", - "dependencies": { - "moment": "^2.11.2" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT" - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "http://94.130.170.209:4873/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "http://94.130.170.209:4873/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true - }, - "node_modules/finalhandler/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "license": "MIT", - "peer": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-versions": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver-regex": "^3.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "http://94.130.170.209:4873/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.2", - "resolved": "http://94.130.170.209:4873/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", - "dev": true, - "license": "ISC" - }, - "node_modules/flow-enums-runtime": { - "version": "0.0.6", - "resolved": "http://94.130.170.209:4873/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", - "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", - "license": "MIT", - "peer": true - }, - "node_modules/fn.name": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "license": "MIT" - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "http://94.130.170.209:4873/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "http://94.130.170.209:4873/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/forever-agent": { - "version": "0.5.2", - "resolved": "http://94.130.170.209:4873/forever-agent/-/forever-agent-0.5.2.tgz", - "integrity": "sha512-PDG5Ef0Dob/JsZUxUltJOhm/Y9mlteAE+46y3M9RBz/Rd3QVENJ75aGRhN56yekTUboaBIkd8KVWX2NjF6+91A==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "http://94.130.170.209:4873/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "license": "MIT", - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/freeport-promise": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/freeport-promise/-/freeport-promise-2.0.0.tgz", - "integrity": "sha512-dwWpT1DdQcwrhmRwnDnPM/ZFny+FtzU+k50qF2eid3KxaQDsMiBrwo1i0G3qSugkN5db6Cb0zgfc68QeTOpEFg==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "http://94.130.170.209:4873/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "node_modules/from2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/from2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "http://94.130.170.209:4873/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/from2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "http://94.130.170.209:4873/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "http://94.130.170.209:4873/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function-timeout": { - "version": "0.1.1", - "resolved": "http://94.130.170.209:4873/function-timeout/-/function-timeout-0.1.1.tgz", - "integrity": "sha512-0NVVC0TaP7dSTvn1yMiy6d6Q8gifzbvQafO46RtLG/kHJUBNd+pVRGOBoK44wNBvtSPUJRfdVvkFdD3p0xvyZg==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "http://94.130.170.209:4873/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "http://94.130.170.209:4873/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "http://94.130.170.209:4873/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "http://94.130.170.209:4873/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "http://94.130.170.209:4873/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "http://94.130.170.209:4873/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "license": "MIT", - "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/get-iterator": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/get-iterator/-/get-iterator-2.0.1.tgz", - "integrity": "sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg==", - "license": "MIT" - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "http://94.130.170.209:4873/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-port": { - "version": "7.1.0", - "resolved": "http://94.130.170.209:4873/get-port/-/get-port-7.1.0.tgz", - "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "http://94.130.170.209:4873/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "http://94.130.170.209:4873/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/git-log-parser": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/git-log-parser/-/git-log-parser-1.2.1.tgz", - "integrity": "sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "argv-formatter": "~1.0.0", - "spawn-error-forwarder": "~1.0.0", - "split2": "~1.0.0", - "stream-combiner2": "~1.1.1", - "through2": "~2.0.0", - "traverse": "0.6.8" - } - }, - "node_modules/git-log-parser/node_modules/split2": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/split2/-/split2-1.0.0.tgz", - "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", - "dev": true, - "license": "ISC", - "dependencies": { - "through2": "~2.0.0" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "http://94.130.170.209:4873/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "license": "MIT" - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "http://94.130.170.209:4873/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "http://94.130.170.209:4873/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "http://94.130.170.209:4873/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "license": "BSD-2-Clause" - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "http://94.130.170.209:4873/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "http://94.130.170.209:4873/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "12.6.1", - "resolved": "http://94.130.170.209:4873/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "http://94.130.170.209:4873/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "http://94.130.170.209:4873/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/hamt-sharding": { - "version": "3.0.6", - "resolved": "http://94.130.170.209:4873/hamt-sharding/-/hamt-sharding-3.0.6.tgz", - "integrity": "sha512-nZeamxfymIWLpVcAN0CRrb7uVq3hCOGj9IcL6NMA6VVCVWqj+h9Jo/SmaWuS92AEDf1thmHsM5D5c70hM3j2Tg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "sparse-array": "^1.3.1", - "uint8arrays": "^5.0.1" - } - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "http://94.130.170.209:4873/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-dynamic-import": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/has-dynamic-import/-/has-dynamic-import-2.1.0.tgz", - "integrity": "sha512-su0anMkNEnJKZ/rB99jn3y6lV/J8Ro96hBJ28YAeVzj5rWxH+YL/AdCyiYYA1HDLV9YhmvqpWSJJj2KLo1MX6g==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/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" - } - ], - "license": "MIT" - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "http://94.130.170.209:4873/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hashlru": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/hashlru/-/hashlru-2.3.0.tgz", - "integrity": "sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==", - "license": "MIT" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hawk": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/hawk/-/hawk-1.1.1.tgz", - "integrity": "sha512-am8sVA2bCJIw8fuuVcKvmmNnGFUGW8spTkVtj2fXTEZVkfN42bwFZFtDem57eFi+NSxurJB8EQ7Jd3uCHLn8Vw==", - "deprecated": "This module moved to @hapi/hawk. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.", - "dev": true, - "optional": true, - "dependencies": { - "boom": "0.4.x", - "cryptiles": "0.2.x", - "hoek": "0.9.x", - "sntp": "0.2.x" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/helia": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/helia/-/helia-5.2.1.tgz", - "integrity": "sha512-H5oqxXV4uFae5eWRv5aopUyKfO7pxdT7sVNomw/ImZabkidz2BrHqsNy6JaZPIQTSUP9yBlkKK2Sq3tmHngYaQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/libp2p-noise": "^16.0.1", - "@chainsafe/libp2p-yamux": "^7.0.1", - "@helia/block-brokers": "^4.0.4", - "@helia/delegated-routing-v1-http-api-client": "^4.2.1", - "@helia/interface": "^5.2.0", - "@helia/routers": "^3.0.0", - "@helia/utils": "^1.2.1", - "@ipshipyard/libp2p-auto-tls": "^1.0.0", - "@libp2p/autonat": "^2.0.19", - "@libp2p/bootstrap": "^11.0.20", - "@libp2p/circuit-relay-v2": "^3.1.10", - "@libp2p/config": "^1.0.3", - "@libp2p/dcutr": "^2.0.18", - "@libp2p/identify": "^3.0.18", - "@libp2p/interface": "^2.5.0", - "@libp2p/kad-dht": "^14.2.3", - "@libp2p/keychain": "^5.0.14", - "@libp2p/mdns": "^11.0.20", - "@libp2p/mplex": "^11.0.20", - "@libp2p/ping": "^2.0.18", - "@libp2p/tcp": "^10.0.18", - "@libp2p/tls": "^2.0.15", - "@libp2p/upnp-nat": "^3.1.1", - "@libp2p/webrtc": "^5.0.26", - "@libp2p/websockets": "^9.1.5", - "@multiformats/dns": "^1.0.6", - "blockstore-core": "^5.0.2", - "datastore-core": "^10.0.2", - "interface-blockstore": "^5.3.1", - "interface-datastore": "^8.3.1", - "ipns": "^10.0.0", - "libp2p": "^2.3.1", - "multiformats": "^13.3.1" - } - }, - "node_modules/helia-coord": { - "version": "1.7.2", - "resolved": "http://94.130.170.209:4873/helia-coord/-/helia-coord-1.7.2.tgz", - "integrity": "sha512-2M2vK7GY1gRC9wgGTx8f0+g7hb6E/mxDfN0b5cl2KBrMMshPPNbTU7+/J51Xr7NY91zBX8IvP7d3SKz5Tt/9Aw==", - "license": "MIT", - "dependencies": { - "@chris.troutner/retry-queue": "1.0.10", - "bch-encrypt-lib": "2.1.1", - "uuid": "9.0.0" - }, - "peerDependencies": { - "libp2p": ">=2.6.0" - } - }, - "node_modules/helia-coord/node_modules/@chris.troutner/retry-queue": { - "version": "1.0.10", - "resolved": "http://94.130.170.209:4873/@chris.troutner%2fretry-queue/-/retry-queue-1.0.10.tgz", - "integrity": "sha512-iF+xQl3jyTATAKDVkwY85j4Npihh/MqG99bjrS0cNJDF0XQeUSMVGsdtXR6TFj8YcEgfPvgBdYGOtEFo6tTQpA==", - "license": "MIT", - "dependencies": { - "p-queue": "7.3.0", - "p-retry": "5.1.1" - } - }, - "node_modules/helia-coord/node_modules/uuid": { - "version": "9.0.0", - "resolved": "http://94.130.170.209:4873/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "http://94.130.170.209:4873/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "license": "MIT", - "peer": true - }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "http://94.130.170.209:4873/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "license": "MIT", - "peer": true, - "dependencies": { - "hermes-estree": "0.25.1" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "license": "MIT", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/hoek": { - "version": "0.9.1", - "resolved": "http://94.130.170.209:4873/hoek/-/hoek-0.9.1.tgz", - "integrity": "sha512-ZZ6eGyzGjyMTmpSPYVECXy9uNfqBR7x5CavhUaLOeD6W0vWK1mp/b7O3f86XE0Mtfo9rZ6Bh3fnuw9Xr8MF9zA==", - "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/hook-std": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/hook-std/-/hook-std-2.0.0.tgz", - "integrity": "sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-assert": { - "version": "1.5.0", - "resolved": "http://94.130.170.209:4873/http-assert/-/http-assert-1.5.0.tgz", - "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", - "license": "MIT", - "dependencies": { - "deep-equal": "~1.0.1", - "http-errors": "~1.8.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "http://94.130.170.209:4873/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "license": "BSD-2-Clause" - }, - "node_modules/http-cookie-agent": { - "version": "6.0.8", - "resolved": "http://94.130.170.209:4873/http-cookie-agent/-/http-cookie-agent-6.0.8.tgz", - "integrity": "sha512-qnYh3yLSr2jBsTYkw11elq+T361uKAJaZ2dR4cfYZChw1dt9uL5t3zSUwehoqqVb4oldk1BpkXKm2oat8zV+oA==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.3" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/3846masa" - }, - "peerDependencies": { - "tough-cookie": "^4.0.0 || ^5.0.0", - "undici": "^5.11.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "undici": { - "optional": true - } - } - }, - "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "http://94.130.170.209:4873/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors/node_modules/depd": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "http://94.130.170.209:4873/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/http-signature": { - "version": "0.10.1", - "resolved": "http://94.130.170.209:4873/http-signature/-/http-signature-0.10.1.tgz", - "integrity": "sha512-coK8uR5rq2IMj+Hen+sKPA5ldgbCc1/spPdKCL1Fw6h+D0s/2LzMcRK0Cqufs1h0ryx/niwBHGFu8HC3hwU+lA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "asn1": "0.1.11", - "assert-plus": "^0.1.5", - "ctype": "0.5.3" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "http://94.130.170.209:4873/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "http://94.130.170.209:4873/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/humanize-number": { - "version": "0.0.2", - "resolved": "http://94.130.170.209:4873/humanize-number/-/humanize-number-0.0.2.tgz", - "integrity": "sha512-un3ZAcNQGI7RzaWGZzQDH47HETM4Wrj6z6E4TId8Yeq9w5ZKUVB1nrT2jwFheTUjEmqcgTjXDc959jum+ai1kQ==" - }, - "node_modules/husky": { - "version": "4.3.8", - "resolved": "http://94.130.170.209:4873/husky/-/husky-4.3.8.tgz", - "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "compare-versions": "^3.6.0", - "cosmiconfig": "^7.0.0", - "find-versions": "^4.0.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^5.0.0", - "please-upgrade-node": "^3.2.0", - "slash": "^3.0.0", - "which-pm-runs": "^1.0.0" - }, - "bin": { - "husky-run": "bin/run.js", - "husky-upgrade": "lib/upgrader/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/husky" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "http://94.130.170.209:4873/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/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" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "http://94.130.170.209:4873/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "license": "ISC" - }, - "node_modules/image-size": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/image-size/-/image-size-1.2.1.tgz", - "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", - "license": "MIT", - "peer": true, - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=16.x" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "http://94.130.170.209:4873/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-from": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/import-from/-/import-from-4.0.0.tgz", - "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local/node_modules/find-up": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "http://94.130.170.209:4873/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "http://94.130.170.209:4873/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflation": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/inflation/-/inflation-2.1.0.tgz", - "integrity": "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/inflection": { - "version": "1.12.0", - "resolved": "http://94.130.170.209:4873/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha512-lRy4DxuIFWXlJU7ed8UiTJOSTqStqYdEb4CEbtXfNbkdj3nH1L+reUWiE10VWcJS2yR7tge8Z74pJjtBjNwj0w==", - "engines": [ - "node >= 0.4.0" - ], - "license": "MIT" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "http://94.130.170.209:4873/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "http://94.130.170.209:4873/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "license": "ISC" - }, - "node_modules/interface-blockstore": { - "version": "5.3.1", - "resolved": "http://94.130.170.209:4873/interface-blockstore/-/interface-blockstore-5.3.1.tgz", - "integrity": "sha512-nhgrQnz6yUQEqxTFLhlOBurQOy5lWlwCpgFmZ3GTObTVTQS9RZjK/JTozY6ty9uz2lZs7VFJSqwjWAltorJ4Vw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "interface-store": "^6.0.0", - "multiformats": "^13.2.3" - } - }, - "node_modules/interface-datastore": { - "version": "8.3.1", - "resolved": "http://94.130.170.209:4873/interface-datastore/-/interface-datastore-8.3.1.tgz", - "integrity": "sha512-3r0ETmHIi6HmvM5sc09QQiCD3gUfwtEM/AAChOyAd/UAKT69uk8LXfTSUBufbUIO/dU65Vj8nb9O6QjwW8vDSQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "interface-store": "^6.0.0", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/interface-store": { - "version": "6.0.2", - "resolved": "http://94.130.170.209:4873/interface-store/-/interface-store-6.0.2.tgz", - "integrity": "sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/into-stream": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/into-stream/-/into-stream-6.0.0.tgz", - "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "from2": "^2.3.0", - "p-is-promise": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "http://94.130.170.209:4873/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/ip-regex": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/ip-regex/-/ip-regex-5.0.0.tgz", - "integrity": "sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ipfs-coord-esm": { - "version": "9.1.7", - "resolved": "http://94.130.170.209:4873/ipfs-coord-esm/-/ipfs-coord-esm-9.1.7.tgz", - "integrity": "sha512-jHktLj/RG7zFp3bFsQagAA6RAG1uU+8xPACAyz9EBeQDeun12gz8boZr7HSibgcgB6l8sjgwYfA3Obijc20Ijw==", - "license": "MIT", - "dependencies": { - "bch-encrypt-lib": "2.0.0", - "uuid": "9.0.0" - }, - "peerDependencies": { - "ipfs-http-client": ">= 58.0.0" - } - }, - "node_modules/ipfs-coord-esm/node_modules/bch-encrypt-lib": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/bch-encrypt-lib/-/bch-encrypt-lib-2.0.0.tgz", - "integrity": "sha512-EAfcw2vzcKMkdO004tfLmQEEpGZA9QeIgzG9sbxDweFiGr2BP6/06G5SIJdvsJhcAd9OS9Rw5bLlPAy25kX8HQ==", - "license": "MIT", - "dependencies": { - "eccrypto-js": "^5.3.0", - "wif": "^2.0.6" - } - }, - "node_modules/ipfs-coord-esm/node_modules/uuid": { - "version": "9.0.0", - "resolved": "http://94.130.170.209:4873/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/ipfs-core-types": { - "version": "0.12.1", - "resolved": "http://94.130.170.209:4873/ipfs-core-types/-/ipfs-core-types-0.12.1.tgz", - "integrity": "sha512-MMCNlHN960kZ4Pxh85xmAGPzVkO2iVAdPQqHkxf/3179m6MwrMpaBdU8QGbjccRef4QKou2bIptKdweanvjmig==", - "deprecated": "js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@ipld/dag-pb": "^2.1.3", - "@libp2p/interface-keychain": "^1.0.3", - "@libp2p/interface-peer-id": "^1.0.4", - "@libp2p/interface-peer-info": "^1.0.2", - "@libp2p/interface-pubsub": "^2.0.0", - "@multiformats/multiaddr": "^11.0.0", - "@types/node": "^18.0.0", - "interface-datastore": "^7.0.0", - "ipfs-unixfs": "^7.0.0", - "multiformats": "^9.5.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/@ipld/dag-pb": { - "version": "2.1.18", - "resolved": "http://94.130.170.209:4873/@ipld%2fdag-pb/-/dag-pb-2.1.18.tgz", - "integrity": "sha512-ZBnf2fuX9y3KccADURG5vb9FaOeMjFkCrNysB0PtftME/4iCTjxfaLoNq/IAh5fTqUOMXvryN6Jyka4ZGuMLIg==", - "license": "(Apache-2.0 AND MIT)", - "dependencies": { - "multiformats": "^9.5.4" - } - }, - "node_modules/ipfs-core-types/node_modules/@multiformats/multiaddr": { - "version": "11.6.1", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr/-/multiaddr-11.6.1.tgz", - "integrity": "sha512-doST0+aB7/3dGK9+U5y3mtF3jq85KGbke1QiH0KE1F5mGQ9y56mFebTeu2D9FNOm+OT6UHb8Ss8vbSnpGjeLNw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "dns-over-http-resolver": "^2.1.0", - "err-code": "^3.0.1", - "multiformats": "^11.0.0", - "uint8arrays": "^4.0.2", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/@multiformats/multiaddr/node_modules/multiformats": { - "version": "11.0.2", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/@types/node": { - "version": "18.19.64", - "resolved": "http://94.130.170.209:4873/@types%2fnode/-/node-18.19.64.tgz", - "integrity": "sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/ipfs-core-types/node_modules/interface-datastore": { - "version": "7.0.4", - "resolved": "http://94.130.170.209:4873/interface-datastore/-/interface-datastore-7.0.4.tgz", - "integrity": "sha512-Q8LZS/jfFFHz6XyZazLTAc078SSCoa27ZPBOfobWdpDiFO7FqPA2yskitUJIhaCgxNK8C+/lMBUTBNfVIDvLiw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "interface-store": "^3.0.0", - "nanoid": "^4.0.0", - "uint8arrays": "^4.0.2" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/interface-store": { - "version": "3.0.4", - "resolved": "http://94.130.170.209:4873/interface-store/-/interface-store-3.0.4.tgz", - "integrity": "sha512-OjHUuGXbH4eXSBx1TF1tTySvjLldPLzRSYYXJwrEQI+XfH5JWYZofr0gVMV4F8XTwC+4V7jomDYkvGRmDSRKqQ==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/ipfs-unixfs": { - "version": "7.0.0", - "resolved": "http://94.130.170.209:4873/ipfs-unixfs/-/ipfs-unixfs-7.0.0.tgz", - "integrity": "sha512-qm3pj3jQE/WCQGIWypyXWtDjDfzQTxFMMaT57sNJ+EQlYEJryKeGQEBTubhhX+tva7ntqt+N/FD15RkDjWlh9w==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "err-code": "^3.0.1", - "protobufjs": "^7.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", - "license": "(Apache-2.0 AND MIT)" - }, - "node_modules/ipfs-core-types/node_modules/uint8arrays": { - "version": "4.0.10", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-4.0.10.tgz", - "integrity": "sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^12.0.1" - } - }, - "node_modules/ipfs-core-types/node_modules/uint8arrays/node_modules/multiformats": { - "version": "12.1.3", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-12.1.3.tgz", - "integrity": "sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "http://94.130.170.209:4873/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" - }, - "node_modules/ipfs-core-utils": { - "version": "0.16.1", - "resolved": "http://94.130.170.209:4873/ipfs-core-utils/-/ipfs-core-utils-0.16.1.tgz", - "integrity": "sha512-nRrOntMtjc6CoeAopIPyDRpwqwSJeMBYY5uq/TiS0V2MbBbD6kTtmsqdgjwXaQLQXdRyvy6/ohxP/btT4Xrg9Q==", - "deprecated": "js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/logger": "^2.0.0", - "@multiformats/multiaddr": "^11.0.0", - "@multiformats/multiaddr-to-uri": "^9.0.1", - "any-signal": "^3.0.0", - "blob-to-it": "^1.0.1", - "browser-readablestream-to-it": "^1.0.1", - "err-code": "^3.0.1", - "ipfs-core-types": "^0.12.1", - "ipfs-unixfs": "^7.0.0", - "ipfs-utils": "^9.0.6", - "it-all": "^1.0.4", - "it-map": "^1.0.6", - "it-peekable": "^1.0.2", - "it-to-stream": "^1.0.0", - "merge-options": "^3.0.4", - "multiformats": "^9.5.1", - "nanoid": "^4.0.0", - "parse-duration": "^1.0.0", - "timeout-abort-controller": "^3.0.0", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@libp2p/interface-peer-id": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-peer-id/-/interface-peer-id-2.0.2.tgz", - "integrity": "sha512-9pZp9zhTDoVwzRmp0Wtxw0Yfa//Yc0GqBCJi3EznBDE6HGIAVvppR91wSh2knt/0eYg0AQj7Y35VSesUTzMCUg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^11.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@libp2p/interface-peer-id/node_modules/multiformats": { - "version": "11.0.2", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@libp2p/logger": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/@libp2p%2flogger/-/logger-2.1.1.tgz", - "integrity": "sha512-2UbzDPctg3cPupF6jrv6abQnAUTrbLybNOj0rmmrdGm1cN2HJ1o/hBu0sXuq4KF9P1h/eVRn1HIRbVIEKnEJrA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface-peer-id": "^2.0.2", - "@multiformats/multiaddr": "^12.1.3", - "debug": "^4.3.4", - "interface-datastore": "^8.2.0", - "multiformats": "^11.0.2" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@libp2p/logger/node_modules/@multiformats/multiaddr": { - "version": "12.3.3", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr/-/multiaddr-12.3.3.tgz", - "integrity": "sha512-3POIUN7myk8JbO8oi/FEyZoLQW2XMhwM/uB7hG5Zl1PgdXJR8UTH9QdQEp1jM358kd3yn+vtS4fFJdqdRk+O7A==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@chainsafe/netmask": "^2.0.0", - "@multiformats/dns": "^1.0.3", - "multiformats": "^13.0.0", - "uint8-varint": "^2.0.1", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@libp2p/logger/node_modules/@multiformats/multiaddr/node_modules/multiformats": { - "version": "13.3.1", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-13.3.1.tgz", - "integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/ipfs-core-utils/node_modules/@libp2p/logger/node_modules/multiformats": { - "version": "11.0.2", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@libp2p/logger/node_modules/uint8arrays": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-5.1.0.tgz", - "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^13.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@libp2p/logger/node_modules/uint8arrays/node_modules/multiformats": { - "version": "13.3.1", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-13.3.1.tgz", - "integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/ipfs-core-utils/node_modules/@multiformats/multiaddr": { - "version": "11.6.1", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr/-/multiaddr-11.6.1.tgz", - "integrity": "sha512-doST0+aB7/3dGK9+U5y3mtF3jq85KGbke1QiH0KE1F5mGQ9y56mFebTeu2D9FNOm+OT6UHb8Ss8vbSnpGjeLNw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "dns-over-http-resolver": "^2.1.0", - "err-code": "^3.0.1", - "multiformats": "^11.0.0", - "uint8arrays": "^4.0.2", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@multiformats/multiaddr-to-uri": { - "version": "9.0.8", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr-to-uri/-/multiaddr-to-uri-9.0.8.tgz", - "integrity": "sha512-4eiN5iEiQfy2A98BxekUfW410L/ivg0sgjYSgSqmklnrBhK+QyMz4yqgfkub8xDTXOc7O5jp4+LVyM3ZqMeWNw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@multiformats/multiaddr": "^12.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@multiformats/multiaddr-to-uri/node_modules/@multiformats/multiaddr": { - "version": "12.3.3", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr/-/multiaddr-12.3.3.tgz", - "integrity": "sha512-3POIUN7myk8JbO8oi/FEyZoLQW2XMhwM/uB7hG5Zl1PgdXJR8UTH9QdQEp1jM358kd3yn+vtS4fFJdqdRk+O7A==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@chainsafe/netmask": "^2.0.0", - "@multiformats/dns": "^1.0.3", - "multiformats": "^13.0.0", - "uint8-varint": "^2.0.1", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@multiformats/multiaddr-to-uri/node_modules/multiformats": { - "version": "13.3.1", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-13.3.1.tgz", - "integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/ipfs-core-utils/node_modules/@multiformats/multiaddr-to-uri/node_modules/uint8arrays": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-5.1.0.tgz", - "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^13.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@multiformats/multiaddr/node_modules/multiformats": { - "version": "11.0.2", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/@multiformats/multiaddr/node_modules/uint8arrays": { - "version": "4.0.10", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-4.0.10.tgz", - "integrity": "sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^12.0.1" - } - }, - "node_modules/ipfs-core-utils/node_modules/@multiformats/multiaddr/node_modules/uint8arrays/node_modules/multiformats": { - "version": "12.1.3", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-12.1.3.tgz", - "integrity": "sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/any-signal": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/any-signal/-/any-signal-3.0.1.tgz", - "integrity": "sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==", - "license": "MIT" - }, - "node_modules/ipfs-core-utils/node_modules/browser-readablestream-to-it": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/browser-readablestream-to-it/-/browser-readablestream-to-it-1.0.3.tgz", - "integrity": "sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==", - "license": "ISC" - }, - "node_modules/ipfs-core-utils/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/ipfs-core-utils/node_modules/ipfs-unixfs": { - "version": "7.0.0", - "resolved": "http://94.130.170.209:4873/ipfs-unixfs/-/ipfs-unixfs-7.0.0.tgz", - "integrity": "sha512-qm3pj3jQE/WCQGIWypyXWtDjDfzQTxFMMaT57sNJ+EQlYEJryKeGQEBTubhhX+tva7ntqt+N/FD15RkDjWlh9w==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "err-code": "^3.0.1", - "protobufjs": "^7.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/it-all": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/it-all/-/it-all-1.0.6.tgz", - "integrity": "sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==", - "license": "ISC" - }, - "node_modules/ipfs-core-utils/node_modules/it-map": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/it-map/-/it-map-1.0.6.tgz", - "integrity": "sha512-XT4/RM6UHIFG9IobGlQPFQUrlEKkU4eBUFG3qhWhfAdh1JfF2x11ShCrKCdmZ0OiZppPfoLuzcfA4cey6q3UAQ==", - "license": "ISC" - }, - "node_modules/ipfs-core-utils/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", - "license": "(Apache-2.0 AND MIT)" - }, - "node_modules/ipfs-core-utils/node_modules/uint8arrays": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-3.1.1.tgz", - "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipfs-http-client": { - "version": "58.0.0", - "resolved": "http://94.130.170.209:4873/ipfs-http-client/-/ipfs-http-client-58.0.0.tgz", - "integrity": "sha512-8HD6wRb+czi6NW8P4n4H84mMefATHf/yWIBFal/DDqriFstrjim0BE5w7lfw7cFoueoH26kq4f70lbF95/ElKA==", - "deprecated": "js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@ipld/dag-cbor": "^7.0.0", - "@ipld/dag-json": "^8.0.1", - "@ipld/dag-pb": "^2.1.3", - "@libp2p/logger": "^2.0.0", - "@libp2p/peer-id": "^1.1.10", - "@multiformats/multiaddr": "^10.4.0", - "any-signal": "^3.0.0", - "dag-jose": "^2.0.1", - "err-code": "^3.0.1", - "ipfs-core-types": "^0.12.0", - "ipfs-core-utils": "^0.16.0", - "ipfs-utils": "^9.0.6", - "it-first": "^1.0.6", - "it-last": "^1.0.4", - "merge-options": "^3.0.4", - "multiformats": "^9.5.1", - "parse-duration": "^1.0.0", - "stream-to-it": "^0.2.2", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@ipld/dag-cbor": { - "version": "7.0.3", - "resolved": "http://94.130.170.209:4873/@ipld%2fdag-cbor/-/dag-cbor-7.0.3.tgz", - "integrity": "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==", - "license": "(Apache-2.0 AND MIT)", - "dependencies": { - "cborg": "^1.6.0", - "multiformats": "^9.5.4" - } - }, - "node_modules/ipfs-http-client/node_modules/@ipld/dag-json": { - "version": "8.0.11", - "resolved": "http://94.130.170.209:4873/@ipld%2fdag-json/-/dag-json-8.0.11.tgz", - "integrity": "sha512-Pea7JXeYHTWXRTIhBqBlhw7G53PJ7yta3G/sizGEZyzdeEwhZRr0od5IQ0r2ZxOt1Do+2czddjeEPp+YTxDwCA==", - "license": "(Apache-2.0 AND MIT)", - "dependencies": { - "cborg": "^1.5.4", - "multiformats": "^9.5.4" - } - }, - "node_modules/ipfs-http-client/node_modules/@ipld/dag-pb": { - "version": "2.1.18", - "resolved": "http://94.130.170.209:4873/@ipld%2fdag-pb/-/dag-pb-2.1.18.tgz", - "integrity": "sha512-ZBnf2fuX9y3KccADURG5vb9FaOeMjFkCrNysB0PtftME/4iCTjxfaLoNq/IAh5fTqUOMXvryN6Jyka4ZGuMLIg==", - "license": "(Apache-2.0 AND MIT)", - "dependencies": { - "multiformats": "^9.5.4" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/logger": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/@libp2p%2flogger/-/logger-2.1.1.tgz", - "integrity": "sha512-2UbzDPctg3cPupF6jrv6abQnAUTrbLybNOj0rmmrdGm1cN2HJ1o/hBu0sXuq4KF9P1h/eVRn1HIRbVIEKnEJrA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface-peer-id": "^2.0.2", - "@multiformats/multiaddr": "^12.1.3", - "debug": "^4.3.4", - "interface-datastore": "^8.2.0", - "multiformats": "^11.0.2" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/logger/node_modules/@libp2p/interface-peer-id": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/@libp2p%2finterface-peer-id/-/interface-peer-id-2.0.2.tgz", - "integrity": "sha512-9pZp9zhTDoVwzRmp0Wtxw0Yfa//Yc0GqBCJi3EznBDE6HGIAVvppR91wSh2knt/0eYg0AQj7Y35VSesUTzMCUg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^11.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/logger/node_modules/@multiformats/multiaddr": { - "version": "12.3.3", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr/-/multiaddr-12.3.3.tgz", - "integrity": "sha512-3POIUN7myk8JbO8oi/FEyZoLQW2XMhwM/uB7hG5Zl1PgdXJR8UTH9QdQEp1jM358kd3yn+vtS4fFJdqdRk+O7A==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@chainsafe/netmask": "^2.0.0", - "@multiformats/dns": "^1.0.3", - "multiformats": "^13.0.0", - "uint8-varint": "^2.0.1", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/logger/node_modules/@multiformats/multiaddr/node_modules/multiformats": { - "version": "13.3.1", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-13.3.1.tgz", - "integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/logger/node_modules/multiformats": { - "version": "11.0.2", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/logger/node_modules/uint8arrays": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-5.1.0.tgz", - "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^13.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/logger/node_modules/uint8arrays/node_modules/multiformats": { - "version": "13.3.1", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-13.3.1.tgz", - "integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/peer-id": { - "version": "1.1.18", - "resolved": "http://94.130.170.209:4873/@libp2p%2fpeer-id/-/peer-id-1.1.18.tgz", - "integrity": "sha512-Zh3gzbrQZKDMLpoJAJB8gdGtyYFSBKV0dU5vflQ18/7MJDJmjsgKO+sJTYi72yN5sWREs1eGKMhxLo+N1ust5w==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface-peer-id": "^1.0.0", - "err-code": "^3.0.1", - "multiformats": "^10.0.0", - "uint8arrays": "^4.0.2" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/peer-id/node_modules/multiformats": { - "version": "10.0.3", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-10.0.3.tgz", - "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/peer-id/node_modules/uint8arrays": { - "version": "4.0.10", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-4.0.10.tgz", - "integrity": "sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^12.0.1" - } - }, - "node_modules/ipfs-http-client/node_modules/@libp2p/peer-id/node_modules/uint8arrays/node_modules/multiformats": { - "version": "12.1.3", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-12.1.3.tgz", - "integrity": "sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/@multiformats/multiaddr": { - "version": "10.5.0", - "resolved": "http://94.130.170.209:4873/@multiformats%2fmultiaddr/-/multiaddr-10.5.0.tgz", - "integrity": "sha512-u4qHMyv25iAqCb9twJROoN1M8UDm8bureOCIzwz03fVhwJzV6DpgH1eFz9UAzDn7CpSShQ9SLS5MiC4hJjTfig==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "dns-over-http-resolver": "^2.1.0", - "err-code": "^3.0.1", - "is-ip": "^5.0.0", - "multiformats": "^9.4.5", - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/any-signal": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/any-signal/-/any-signal-3.0.1.tgz", - "integrity": "sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==", - "license": "MIT" - }, - "node_modules/ipfs-http-client/node_modules/cborg": { - "version": "1.10.2", - "resolved": "http://94.130.170.209:4873/cborg/-/cborg-1.10.2.tgz", - "integrity": "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==", - "license": "Apache-2.0", - "bin": { - "cborg": "cli.js" - } - }, - "node_modules/ipfs-http-client/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/ipfs-http-client/node_modules/get-iterator": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/get-iterator/-/get-iterator-1.0.2.tgz", - "integrity": "sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==", - "license": "MIT" - }, - "node_modules/ipfs-http-client/node_modules/it-first": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/it-first/-/it-first-1.0.7.tgz", - "integrity": "sha512-nvJKZoBpZD/6Rtde6FXqwDqDZGF1sCADmr2Zoc0hZsIvnE449gRFnGctxDf09Bzc/FWnHXAdaHVIetY6lrE0/g==", - "license": "ISC" - }, - "node_modules/ipfs-http-client/node_modules/it-last": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/it-last/-/it-last-1.0.6.tgz", - "integrity": "sha512-aFGeibeiX/lM4bX3JY0OkVCFkAw8+n9lkukkLNivbJRvNz8lI3YXv5xcqhFUV2lDJiraEK3OXRDbGuevnnR67Q==", - "license": "ISC" - }, - "node_modules/ipfs-http-client/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", - "license": "(Apache-2.0 AND MIT)" - }, - "node_modules/ipfs-http-client/node_modules/stream-to-it": { - "version": "0.2.4", - "resolved": "http://94.130.170.209:4873/stream-to-it/-/stream-to-it-0.2.4.tgz", - "integrity": "sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==", - "license": "MIT", - "dependencies": { - "get-iterator": "^1.0.2" - } - }, - "node_modules/ipfs-http-client/node_modules/uint8arrays": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-3.1.1.tgz", - "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", - "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipfs-unixfs": { - "version": "11.2.0", - "resolved": "http://94.130.170.209:4873/ipfs-unixfs/-/ipfs-unixfs-11.2.0.tgz", - "integrity": "sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/ipfs-unixfs-exporter": { - "version": "13.6.1", - "resolved": "http://94.130.170.209:4873/ipfs-unixfs-exporter/-/ipfs-unixfs-exporter-13.6.1.tgz", - "integrity": "sha512-pYPI4oBTWao2//sFzAL0pURyojn79q/u5BuK6L5/nVbVUQVw6DcVP5uB1ySdWlTM2H+0Zlhp9+OL9aJBRIICpg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@ipld/dag-cbor": "^9.2.1", - "@ipld/dag-json": "^10.2.2", - "@ipld/dag-pb": "^4.1.2", - "@multiformats/murmur3": "^2.1.8", - "hamt-sharding": "^3.0.6", - "interface-blockstore": "^5.3.0", - "ipfs-unixfs": "^11.0.0", - "it-filter": "^3.1.1", - "it-last": "^3.0.6", - "it-map": "^3.1.1", - "it-parallel": "^3.0.8", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.3", - "multiformats": "^13.2.3", - "p-queue": "^8.0.1", - "progress-events": "^1.0.1" - } - }, - "node_modules/ipfs-unixfs-exporter/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/ipfs-unixfs-exporter/node_modules/p-queue": { - "version": "8.0.1", - "resolved": "http://94.130.170.209:4873/p-queue/-/p-queue-8.0.1.tgz", - "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ipfs-unixfs-importer": { - "version": "15.3.1", - "resolved": "http://94.130.170.209:4873/ipfs-unixfs-importer/-/ipfs-unixfs-importer-15.3.1.tgz", - "integrity": "sha512-wHCTBqNsZXLJZ9/GSr7Msb3FDXD5yXF20Y9sKyUbbqNjbvaXs3n3h1+NM/5+WrgESHfwRcJIlJtaOKafL8Ymdg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@ipld/dag-pb": "^4.1.2", - "@multiformats/murmur3": "^2.1.8", - "hamt-sharding": "^3.0.6", - "interface-blockstore": "^5.3.0", - "interface-store": "^6.0.0", - "ipfs-unixfs": "^11.0.0", - "it-all": "^3.0.6", - "it-batch": "^3.0.6", - "it-first": "^3.0.6", - "it-parallel-batch": "^3.0.6", - "multiformats": "^13.2.3", - "progress-events": "^1.0.1", - "rabin-wasm": "^0.1.5", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/ipfs-utils": { - "version": "9.0.14", - "resolved": "http://94.130.170.209:4873/ipfs-utils/-/ipfs-utils-9.0.14.tgz", - "integrity": "sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "any-signal": "^3.0.0", - "browser-readablestream-to-it": "^1.0.0", - "buffer": "^6.0.1", - "electron-fetch": "^1.7.2", - "err-code": "^3.0.1", - "is-electron": "^2.2.0", - "iso-url": "^1.1.5", - "it-all": "^1.0.4", - "it-glob": "^1.0.1", - "it-to-stream": "^1.0.0", - "merge-options": "^3.0.4", - "nanoid": "^3.1.20", - "native-fetch": "^3.0.0", - "node-fetch": "^2.6.8", - "react-native-fetch-api": "^3.0.0", - "stream-to-it": "^0.2.2" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/ipfs-utils/node_modules/any-signal": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/any-signal/-/any-signal-3.0.1.tgz", - "integrity": "sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==", - "license": "MIT" - }, - "node_modules/ipfs-utils/node_modules/browser-readablestream-to-it": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/browser-readablestream-to-it/-/browser-readablestream-to-it-1.0.3.tgz", - "integrity": "sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==", - "license": "ISC" - }, - "node_modules/ipfs-utils/node_modules/get-iterator": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/get-iterator/-/get-iterator-1.0.2.tgz", - "integrity": "sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==", - "license": "MIT" - }, - "node_modules/ipfs-utils/node_modules/it-all": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/it-all/-/it-all-1.0.6.tgz", - "integrity": "sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==", - "license": "ISC" - }, - "node_modules/ipfs-utils/node_modules/it-glob": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/it-glob/-/it-glob-1.0.2.tgz", - "integrity": "sha512-Ch2Dzhw4URfB9L/0ZHyY+uqOnKvBNeS/SMcRiPmJfpHiM0TsUZn+GkpcZxAoF3dJVdPm/PuIk3A4wlV7SUo23Q==", - "license": "ISC", - "dependencies": { - "@types/minimatch": "^3.0.4", - "minimatch": "^3.0.4" - } - }, - "node_modules/ipfs-utils/node_modules/nanoid": { - "version": "3.3.7", - "resolved": "http://94.130.170.209:4873/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/ipfs-utils/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "http://94.130.170.209:4873/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/ipfs-utils/node_modules/stream-to-it": { - "version": "0.2.4", - "resolved": "http://94.130.170.209:4873/stream-to-it/-/stream-to-it-0.2.4.tgz", - "integrity": "sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==", - "license": "MIT", - "dependencies": { - "get-iterator": "^1.0.2" - } - }, - "node_modules/ipns": { - "version": "10.0.2", - "resolved": "http://94.130.170.209:4873/ipns/-/ipns-10.0.2.tgz", - "integrity": "sha512-tokCgz9X678zvHnAabVG91K64X7HnHdWOrop0ghUcXkzH5XNsmxHwVpqVATNqq/w62h7fRDhWURHU/WOfYmCpA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.0", - "@libp2p/interface": "^2.0.0", - "@libp2p/logger": "^5.0.0", - "cborg": "^4.2.3", - "interface-datastore": "^8.3.0", - "multiformats": "^13.2.2", - "protons-runtime": "^5.5.0", - "timestamp-nano": "^1.0.1", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "http://94.130.170.209:4873/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "http://94.130.170.209:4873/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-bluebird": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/is-bluebird/-/is-bluebird-1.0.2.tgz", - "integrity": "sha512-PDRu1vVip5dGQg5tfn2qVCCyxbBYu5MhYUJwSfL/RoGBI97n1fxvilVazxzptZW0gcmsMH17H4EVZZI5E/RSeA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "license": "MIT", - "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": "http://94.130.170.209:4873/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "http://94.130.170.209:4873/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "license": "MIT", - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-directory": { - "version": "0.3.1", - "resolved": "http://94.130.170.209:4873/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "http://94.130.170.209:4873/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "license": "MIT", - "peer": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-electron": { - "version": "2.2.2", - "resolved": "http://94.130.170.209:4873/is-electron/-/is-electron-2.2.2.tgz", - "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==", - "license": "MIT" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "http://94.130.170.209:4873/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "http://94.130.170.209:4873/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-ip": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/is-ip/-/is-ip-5.0.1.tgz", - "integrity": "sha512-FCsGHdlrOnZQcp0+XT5a+pYowf33itBalCl+7ovNXC/7o5BhIpG14M3OrpPPdBSIQJCm+0M5+9mO7S9VVTTCFw==", - "license": "MIT", - "dependencies": { - "ip-regex": "^5.0.0", - "super-regex": "^0.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-loopback-addr": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/is-loopback-addr/-/is-loopback-addr-2.0.2.tgz", - "integrity": "sha512-26POf2KRCno/KTNL5Q0b/9TYnL00xEsSaLfiFRmjM7m7Lw7ZMmFybzzuX4CcsLAluZGd+niLUiMRxEooVE3aqg==", - "license": "MIT" - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-network-error": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/is-network-error/-/is-network-error-1.1.0.tgz", - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "http://94.130.170.209:4873/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "http://94.130.170.209:4873/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "http://94.130.170.209:4873/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "license": "MIT", - "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-regexp": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/is-regexp/-/is-regexp-3.1.0.tgz", - "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "text-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "http://94.130.170.209:4873/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "license": "MIT" - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "http://94.130.170.209:4873/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "license": "MIT", - "peer": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "http://94.130.170.209:4873/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/iso-url": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/iso-url/-/iso-url-1.2.1.tgz", - "integrity": "sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/issue-parser": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/issue-parser/-/issue-parser-6.0.0.tgz", - "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.capitalize": "^4.2.1", - "lodash.escaperegexp": "^4.1.2", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.uniqby": "^4.7.0" - }, - "engines": { - "node": ">=10.13" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "http://94.130.170.209:4873/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "http://94.130.170.209:4873/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "http://94.130.170.209:4873/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/it-all": { - "version": "3.0.6", - "resolved": "http://94.130.170.209:4873/it-all/-/it-all-3.0.6.tgz", - "integrity": "sha512-HXZWbxCgQZJfrv5rXvaVeaayXED8nTKx9tj9fpBhmcUJcedVZshMMMqTj0RG2+scGypb9Ut1zd1ifbf3lA8L+Q==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-batch": { - "version": "3.0.6", - "resolved": "http://94.130.170.209:4873/it-batch/-/it-batch-3.0.6.tgz", - "integrity": "sha512-pQAAlSvJ4aV6xM/6LRvkPdKSKXxS4my2fGzNUxJyAQ8ccFdxPmK1bUuF5OoeUDkcdrbs8jtsmc4DypCMrGY6sg==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-byte-stream": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/it-byte-stream/-/it-byte-stream-1.1.0.tgz", - "integrity": "sha512-WWponBWdKEa6o2U3NX+wGMY8X1EkWXcQvpC+3CUqKb4ZzK30q3EPqiTjFxLf9tNVgdF/MNAtx/XclpVfgaz9KQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-queueless-pushable": "^1.0.0", - "it-stream-types": "^2.0.1", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/it-drain": { - "version": "3.0.7", - "resolved": "http://94.130.170.209:4873/it-drain/-/it-drain-3.0.7.tgz", - "integrity": "sha512-vy6S1JKjjHSIFHgBpLpD1zhkCRl3z1zYWUxE14+kAYf+BL9ssWSFImJfhl361IIcwr0ofw8etzg11VqqB+ntUA==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-filter": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/it-filter/-/it-filter-3.1.1.tgz", - "integrity": "sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-peekable": "^3.0.0" - } - }, - "node_modules/it-filter/node_modules/it-peekable": { - "version": "3.0.5", - "resolved": "http://94.130.170.209:4873/it-peekable/-/it-peekable-3.0.5.tgz", - "integrity": "sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-first": { - "version": "3.0.6", - "resolved": "http://94.130.170.209:4873/it-first/-/it-first-3.0.6.tgz", - "integrity": "sha512-ExIewyK9kXKNAplg2GMeWfgjUcfC1FnUXz/RPfAvIXby+w7U4b3//5Lic0NV03gXT8O/isj5Nmp6KiY0d45pIQ==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-foreach": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/it-foreach/-/it-foreach-2.1.1.tgz", - "integrity": "sha512-ID4Gxnavk/LVQLQESAQ9hR6dR63Ih6X+8VdxEktX8rpz2dCGAbZpey/eljTNbMfV2UKXHiu6UsneoNBZuac97g==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-peekable": "^3.0.0" - } - }, - "node_modules/it-foreach/node_modules/it-peekable": { - "version": "3.0.5", - "resolved": "http://94.130.170.209:4873/it-peekable/-/it-peekable-3.0.5.tgz", - "integrity": "sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-glob": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/it-glob/-/it-glob-3.0.1.tgz", - "integrity": "sha512-IUWE9f6XVUJLugK7pQmQPqTWj4BiQJhufnvxfsCmNIGEDQEkKVs3Ld9gFZq/Vude6g/OpndhsiuFrA730Bc59A==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "fast-glob": "^3.3.2" - } - }, - "node_modules/it-last": { - "version": "3.0.6", - "resolved": "http://94.130.170.209:4873/it-last/-/it-last-3.0.6.tgz", - "integrity": "sha512-M4/get95O85u2vWvWQinF8SJUc/RPC5bWTveBTYXvlP2q5TF9Y+QhT3nz+CRCyS2YEc66VJkyl/da6WrJ0wKhw==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-length": { - "version": "3.0.7", - "resolved": "http://94.130.170.209:4873/it-length/-/it-length-3.0.7.tgz", - "integrity": "sha512-URrszwrzPrUn6PtsSFcixG4NwHydaARmPubO0UUnFH+NSNylBaGtair1fnxX7Zf2qVJQltPBVs3PZvcmFPTLXA==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-length-prefixed": { - "version": "9.1.0", - "resolved": "http://94.130.170.209:4873/it-length-prefixed/-/it-length-prefixed-9.1.0.tgz", - "integrity": "sha512-kx2UTJuy7/lsT3QUzf50NjfxU1Z4P4wlvYp6YnR5Nc61P8XKfy+QtiJi1VLojA+Kea7vMbB4002rIij1Ol9hcw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-reader": "^6.0.1", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.1", - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/it-length-prefixed-stream": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/it-length-prefixed-stream/-/it-length-prefixed-stream-1.2.0.tgz", - "integrity": "sha512-vX7dzSl/2UMYYsAr0FQdPNVR5xYEETaeboZ+eXxNBjgARuvxnWA6OedW8lC5/J3ebMTC98JhA3eH76eTijUOsA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-byte-stream": "^1.0.0", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/it-map": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/it-map/-/it-map-3.1.1.tgz", - "integrity": "sha512-9bCSwKD1yN1wCOgJ9UOl+46NQtdatosPWzxxUk2NdTLwRPXLh+L7iwCC9QKsbgM60RQxT/nH8bKMqm3H/o8IHQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-peekable": "^3.0.0" - } - }, - "node_modules/it-map/node_modules/it-peekable": { - "version": "3.0.5", - "resolved": "http://94.130.170.209:4873/it-peekable/-/it-peekable-3.0.5.tgz", - "integrity": "sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-merge": { - "version": "3.0.5", - "resolved": "http://94.130.170.209:4873/it-merge/-/it-merge-3.0.5.tgz", - "integrity": "sha512-2l7+mPf85pyRF5pqi0dKcA54E5Jm/2FyY5GsOaN51Ta0ipC7YZ3szuAsH8wOoB6eKY4XsU4k2X+mzPmFBMayEA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-pushable": "^3.2.3" - } - }, - "node_modules/it-ndjson": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/it-ndjson/-/it-ndjson-1.1.2.tgz", - "integrity": "sha512-TPKpdYSNKjDdroCPnLamM5Up6XnPQ7F1KgNP3Ib5y5O4ayOVP+DHac/pzjUigcg9Kf9gkGVXDz8+FFKpWwoB3w==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/it-pair": { - "version": "2.0.6", - "resolved": "http://94.130.170.209:4873/it-pair/-/it-pair-2.0.6.tgz", - "integrity": "sha512-5M0t5RAcYEQYNG5BV7d7cqbdwbCAp5yLdzvkxsZmkuZsLbTdZzah6MQySYfaAQjNDCq6PUnDt0hqBZ4NwMfW6g==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-stream-types": "^2.0.1", - "p-defer": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/it-parallel": { - "version": "3.0.8", - "resolved": "http://94.130.170.209:4873/it-parallel/-/it-parallel-3.0.8.tgz", - "integrity": "sha512-URLhs6eG4Hdr4OdvgBBPDzOjBeSSmI+Kqex2rv/aAyYClME26RYHirLVhZsZP5M+ZP6M34iRlXk8Wlqtezuqpg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "p-defer": "^4.0.1" - } - }, - "node_modules/it-parallel-batch": { - "version": "3.0.6", - "resolved": "http://94.130.170.209:4873/it-parallel-batch/-/it-parallel-batch-3.0.6.tgz", - "integrity": "sha512-3wgiQGvMMHy65OXScrtrtmY+bJSF7P6St1AP+BU+SK83fEr8NNk/MrmJKrtB1+MahYX2a8I+pOGKDj8qVtuV0Q==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-batch": "^3.0.0" - } - }, - "node_modules/it-peekable": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/it-peekable/-/it-peekable-1.0.3.tgz", - "integrity": "sha512-5+8zemFS+wSfIkSZyf0Zh5kNN+iGyccN02914BY4w/Dj+uoFEoPSvj5vaWn8pNZJNSxzjW0zHRxC3LUb2KWJTQ==", - "license": "ISC" - }, - "node_modules/it-pipe": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/it-pipe/-/it-pipe-3.0.1.tgz", - "integrity": "sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-merge": "^3.0.0", - "it-pushable": "^3.1.2", - "it-stream-types": "^2.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/it-protobuf-stream": { - "version": "1.1.5", - "resolved": "http://94.130.170.209:4873/it-protobuf-stream/-/it-protobuf-stream-1.1.5.tgz", - "integrity": "sha512-H70idW45As3cEbU4uSoZ9IYHUIV3YM69/2mmXYR7gOlPabWjuyNi3/abK11geiiq3la27Sos/mXr68JljjKtEQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-length-prefixed-stream": "^1.0.0", - "it-stream-types": "^2.0.1", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/it-pushable": { - "version": "3.2.3", - "resolved": "http://94.130.170.209:4873/it-pushable/-/it-pushable-3.2.3.tgz", - "integrity": "sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "p-defer": "^4.0.0" - } - }, - "node_modules/it-queueless-pushable": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/it-queueless-pushable/-/it-queueless-pushable-1.0.2.tgz", - "integrity": "sha512-BFIm48C4O8+i+oVEPQpZ70+CaAsVUircvZtZCrpG2Q64933aLp+tDmas1mTBwqVBfIUUlg09d+e6SWW1CBuykQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "p-defer": "^4.0.1", - "race-signal": "^1.1.3" - } - }, - "node_modules/it-reader": { - "version": "6.0.4", - "resolved": "http://94.130.170.209:4873/it-reader/-/it-reader-6.0.4.tgz", - "integrity": "sha512-XCWifEcNFFjjBHtor4Sfaj8rcpt+FkY0L6WdhD578SCDhV4VUm7fCkF3dv5a+fTcfQqvN9BsxBTvWbYO6iCjTg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-stream-types": "^2.0.1", - "uint8arraylist": "^2.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/it-sort": { - "version": "3.0.7", - "resolved": "http://94.130.170.209:4873/it-sort/-/it-sort-3.0.7.tgz", - "integrity": "sha512-PsaKSd2Z0uhq8Mq5htdfsE/UagmdLCLWdBXPwi3FZGR4BTG180pFamhK+O+luFtBCNGRoqKAdtbZGTyGwA9uzw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-all": "^3.0.0" - } - }, - "node_modules/it-stream-types": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/it-stream-types/-/it-stream-types-2.0.2.tgz", - "integrity": "sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-take": { - "version": "3.0.7", - "resolved": "http://94.130.170.209:4873/it-take/-/it-take-3.0.7.tgz", - "integrity": "sha512-0+EbsTvH1XCpwhhFkjWdqJTjzS5XP3KL69woBqwANNhMLKn0j39jk/WHIlvbg9XW2vEm7cZz4p8w5DkBZR8LoA==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-to-stream": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/it-to-stream/-/it-to-stream-1.0.0.tgz", - "integrity": "sha512-pLULMZMAB/+vbdvbZtebC0nWBTbG581lk6w8P7DfIIIKUfa8FbY7Oi0FxZcFPbxvISs7A9E+cMpLDBc1XhpAOA==", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "fast-fifo": "^1.0.0", - "get-iterator": "^1.0.2", - "p-defer": "^3.0.0", - "p-fifo": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/it-to-stream/node_modules/get-iterator": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/get-iterator/-/get-iterator-1.0.2.tgz", - "integrity": "sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==", - "license": "MIT" - }, - "node_modules/it-to-stream/node_modules/p-defer": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/p-defer/-/p-defer-3.0.0.tgz", - "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/it-ws": { - "version": "6.1.5", - "resolved": "http://94.130.170.209:4873/it-ws/-/it-ws-6.1.5.tgz", - "integrity": "sha512-uWjMtpy5HqhSd/LlrlP3fhYrr7rUfJFFMABv0F5d6n13Q+0glhZthwUKpEAVhDrXY95Tb1RB5lLqqef+QbVNaw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@types/ws": "^8.2.2", - "event-iterator": "^2.0.0", - "it-stream-types": "^2.0.1", - "uint8arrays": "^5.0.0", - "ws": "^8.4.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.3", - "resolved": "http://94.130.170.209:4873/iterator.prototype/-/iterator.prototype-1.1.3.tgz", - "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/java-properties": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/java-properties/-/java-properties-1.0.2.tgz", - "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "http://94.130.170.209:4873/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "license": "MIT", - "peer": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "http://94.130.170.209:4873/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "license": "MIT", - "peer": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "http://94.130.170.209:4873/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "http://94.130.170.209:4873/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "http://94.130.170.209:4873/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/jquery": { - "version": "3.7.1", - "resolved": "http://94.130.170.209:4873/jquery/-/jquery-3.7.1.tgz", - "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", - "license": "MIT" - }, - "node_modules/js-sha256": { - "version": "0.9.0", - "resolved": "http://94.130.170.209:4873/js-sha256/-/js-sha256-0.9.0.tgz", - "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==", - "license": "MIT" - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "http://94.130.170.209:4873/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "license": "MIT" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/js-yaml/-/js-yaml-3.0.1.tgz", - "integrity": "sha512-dgxgLzZS9qLWAQd/wrVG8tOiRSBJq1Ss9gbd7+fdBhcia3efHjLLpPkcUhKOyVACxTEAgnao3RT1kj1otiW42g==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "~ 0.1.11", - "esprima": "~ 1.0.2" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - }, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/jsc-safe-url": { - "version": "0.2.4", - "resolved": "http://94.130.170.209:4873/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", - "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", - "license": "0BSD", - "peer": true - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "license": "MIT", - "peer": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "license": "MIT" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "http://94.130.170.209:4873/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "http://94.130.170.209:4873/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "http://94.130.170.209:4873/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "http://94.130.170.209:4873/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "http://94.130.170.209:4873/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/jsonrpc-lite": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/jsonrpc-lite/-/jsonrpc-lite-2.2.0.tgz", - "integrity": "sha512-/cbbSxtZWs1O7R4tWqabrCM/t3N8qKUZMAg9IUqpPvUs6UyRvm6pCNYkskyKN/XU0UgffW+NY2ZRr8t0AknX7g==", - "license": "MIT" - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "http://94.130.170.209:4873/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jsonwebtoken": { - "version": "8.5.1", - "resolved": "http://94.130.170.209:4873/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "license": "MIT", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=4", - "npm": ">=1.4.28" - } - }, - "node_modules/jsonwebtoken/node_modules/semver": { - "version": "5.7.2", - "resolved": "http://94.130.170.209:4873/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "http://94.130.170.209:4873/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "http://94.130.170.209:4873/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true, - "license": "MIT" - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "http://94.130.170.209:4873/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "http://94.130.170.209:4873/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "license": "MIT", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jwt-bch-lib": { - "version": "1.3.0", - "resolved": "http://94.130.170.209:4873/jwt-bch-lib/-/jwt-bch-lib-1.3.0.tgz", - "integrity": "sha512-CZs3jUHJlWvConvoTeLDogDEwUysKeojYJxfUhbwJKJrtDCSfi3ZWbsZZ8WN30Xs28aZPDB+qlHPJlTXQmup0w==", - "license": "MIT", - "dependencies": { - "axios": "^0.21.1" - } - }, - "node_modules/jwt-bch-lib/node_modules/axios": { - "version": "0.21.4", - "resolved": "http://94.130.170.209:4873/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/kareem": { - "version": "2.3.2", - "resolved": "http://94.130.170.209:4873/kareem/-/kareem-2.3.2.tgz", - "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==", - "license": "Apache-2.0" - }, - "node_modules/kcors": { - "version": "2.2.2", - "resolved": "http://94.130.170.209:4873/kcors/-/kcors-2.2.2.tgz", - "integrity": "sha512-rIqbKa2S0gT0wC/790jsQM6hNpABHBNWQ7+XYS1xJV6zOGxlanW+RtCmlDn6wPZsGpRk371yy8abfBgl2OTavg==", - "license": "MIT", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/keccak": { - "version": "3.0.4", - "resolved": "http://94.130.170.209:4873/keccak/-/keccak-3.0.4.tgz", - "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/keygrip": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", - "license": "MIT", - "dependencies": { - "tsscmp": "1.0.6" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "http://94.130.170.209:4873/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "http://94.130.170.209:4873/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klaw-sync": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.11" - } - }, - "node_modules/koa": { - "version": "2.13.1", - "resolved": "http://94.130.170.209:4873/koa/-/koa-2.13.1.tgz", - "integrity": "sha512-Lb2Dloc72auj5vK4X4qqL7B5jyDPQaZucc9sR/71byg7ryoD1NCaCm63CShk9ID9quQvDEi1bGR/iGjCG7As3w==", - "license": "MIT", - "dependencies": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.8.0", - "debug": "~3.1.0", - "delegates": "^1.0.0", - "depd": "^2.0.0", - "destroy": "^1.0.4", - "encodeurl": "^1.0.2", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^1.2.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" - }, - "engines": { - "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" - } - }, - "node_modules/koa-bodyparser": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", - "integrity": "sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==", - "license": "MIT", - "dependencies": { - "co-body": "^6.0.0", - "copy-to": "^2.0.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/koa-compose": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", - "license": "MIT" - }, - "node_modules/koa-convert": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/koa-convert/-/koa-convert-2.0.0.tgz", - "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", - "license": "MIT", - "dependencies": { - "co": "^4.6.0", - "koa-compose": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/koa-generic-session": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/koa-generic-session/-/koa-generic-session-2.1.1.tgz", - "integrity": "sha512-ZWsq0klIGnsDHcPWETTYVR4FKBRm+hMexJV7HxZdtALO54dQaOGV7GxMZSZNwnNqr9yVPldRUXDcJZsd9AHozw==", - "license": "MIT", - "dependencies": { - "copy-to": "~2.0.1", - "crc": "~3.5.0", - "debug": "~3.1.0", - "parseurl": "~1.3.1", - "uid-safe": "~2.1.4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/koa-logger": { - "version": "3.2.1", - "resolved": "http://94.130.170.209:4873/koa-logger/-/koa-logger-3.2.1.tgz", - "integrity": "sha512-MjlznhLLKy9+kG8nAXKJLM0/ClsQp/Or2vI3a5rbSQmgl8IJBQO0KI5FA70BvW+hqjtxjp49SpH2E7okS6NmHg==", - "license": "MIT", - "dependencies": { - "bytes": "^3.1.0", - "chalk": "^2.4.2", - "humanize-number": "0.0.2", - "passthrough-counter": "^1.0.0" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/koa-logger/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "http://94.130.170.209:4873/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/koa-logger/node_modules/chalk": { - "version": "2.4.2", - "resolved": "http://94.130.170.209:4873/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/koa-logger/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "http://94.130.170.209:4873/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/koa-logger/node_modules/color-name": { - "version": "1.1.3", - "resolved": "http://94.130.170.209:4873/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" - }, - "node_modules/koa-logger/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/koa-logger/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/koa-logger/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "http://94.130.170.209:4873/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/koa-mount": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/koa-mount/-/koa-mount-4.0.0.tgz", - "integrity": "sha512-rm71jaA/P+6HeCpoRhmCv8KVBIi0tfGuO/dMKicbQnQW/YJntJ6MnnspkodoA4QstMVEZArsCphmd0bJEtoMjQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.0.1", - "koa-compose": "^4.1.0" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/koa-mount/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/koa-passport": { - "version": "4.1.3", - "resolved": "http://94.130.170.209:4873/koa-passport/-/koa-passport-4.1.3.tgz", - "integrity": "sha512-QqKrHfp4jNfqkKThGkVb2WQtlVOSRYk5CC69Z17cmOpZ4760l8CdyJ+Bs2CfQc9BHizz557mczjPkSlVkpuluw==", - "license": "MIT", - "dependencies": { - "passport": "^0.4.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/koa-router": { - "version": "10.0.0", - "resolved": "http://94.130.170.209:4873/koa-router/-/koa-router-10.0.0.tgz", - "integrity": "sha512-gAE5J1gBQTvfR8rMMtMUkE26+1MbO3DGpGmvfmM2pR9Z7w2VIb2Ecqeal98yVO7+4ltffby7gWOzpCmdNOQe0w==", - "deprecated": "**IMPORTANT 10x+ PERFORMANCE UPGRADE**: Please upgrade to v12.0.1+ as we have fixed an issue with debuglog causing 10x slower router benchmark performance, see https://github.com/koajs/router/pull/173", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.1.0" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/koa-router/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/koa-send": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/koa-send/-/koa-send-5.0.1.tgz", - "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "resolve-path": "^1.4.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/koa-send/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/koa-static": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/koa-static/-/koa-static-5.0.0.tgz", - "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", - "license": "MIT", - "dependencies": { - "debug": "^3.1.0", - "koa-send": "^5.0.0" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/koa/node_modules/koa-convert": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/koa-convert/-/koa-convert-1.2.0.tgz", - "integrity": "sha512-K9XqjmEDStGX09v3oxR7t5uPRy0jqJdvodHa6wxWTHrTfDq0WUNnYTOOUZN6g8OM8oZQXprQASbiIXG2Ez8ehA==", - "license": "MIT", - "dependencies": { - "co": "^4.6.0", - "koa-compose": "^3.0.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/koa/node_modules/koa-convert/node_modules/koa-compose": { - "version": "3.2.1", - "resolved": "http://94.130.170.209:4873/koa-compose/-/koa-compose-3.2.1.tgz", - "integrity": "sha512-8gen2cvKHIZ35eDEik5WOo8zbVp9t4cP8p4hW4uE55waxolLRexKKrqfCpwhGVppnB40jWeF8bZeTVg99eZgPw==", - "license": "MIT", - "dependencies": { - "any-promise": "^1.1.0" - } - }, - "node_modules/koa2-ratelimit": { - "version": "0.9.1", - "resolved": "http://94.130.170.209:4873/koa2-ratelimit/-/koa2-ratelimit-0.9.1.tgz", - "integrity": "sha512-9eYPcHN7OVE2VHi5Qpy3vreDUCCEfBbwGav6LfSEybxdYXJwNDc1If8nyexvNY2q4UsYLbFGIkHmSxiNTg8kug==", - "dependencies": { - "mongoose": "^5.5.13", - "redis": "^4.0.0", - "sequelize": "^5.8.7" - }, - "engines": { - "node": ">=7.10.1" - } - }, - "node_modules/kuler": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "license": "MIT" - }, - "node_modules/lcov-parse": { - "version": "0.0.6", - "resolved": "http://94.130.170.209:4873/lcov-parse/-/lcov-parse-0.0.6.tgz", - "integrity": "sha512-chuBQJZiBq28YUM6Yr3tf3h5Lxhb+DvhbxxSNpsHURSXiZXOzp49phiWG2pKHboOehJDujivwNQGRP8mAErMvQ==", - "dev": true - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "http://94.130.170.209:4873/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libp2p": { - "version": "2.7.2", - "resolved": "http://94.130.170.209:4873/libp2p/-/libp2p-2.7.2.tgz", - "integrity": "sha512-jG2biyI+AWwjqylfaa+gRhbbelCUXLMOyH/jc7f8CVn7FG5jAAL86+19oJm3tkiG68CzjEPAm0mKZhTZNPJPTA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@chainsafe/netmask": "^2.0.0", - "@libp2p/crypto": "^5.0.12", - "@libp2p/interface": "^2.6.0", - "@libp2p/interface-internal": "^2.3.4", - "@libp2p/logger": "^5.1.9", - "@libp2p/multistream-select": "^6.0.16", - "@libp2p/peer-collections": "^6.0.20", - "@libp2p/peer-id": "^5.0.13", - "@libp2p/peer-store": "^11.0.20", - "@libp2p/utils": "^6.5.4", - "@multiformats/dns": "^1.0.6", - "@multiformats/multiaddr": "^12.3.5", - "@multiformats/multiaddr-matcher": "^1.6.0", - "any-signal": "^4.1.1", - "datastore-core": "^10.0.2", - "interface-datastore": "^8.3.1", - "it-byte-stream": "^1.1.0", - "it-merge": "^3.0.5", - "it-parallel": "^3.0.8", - "merge-options": "^3.0.4", - "multiformats": "^13.3.1", - "p-defer": "^4.0.1", - "p-retry": "^6.2.1", - "progress-events": "^1.0.1", - "race-event": "^1.3.0", - "race-signal": "^1.1.2", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/libp2p/node_modules/@libp2p/logger": { - "version": "5.1.14", - "resolved": "http://94.130.170.209:4873/@libp2p%2flogger/-/logger-5.1.14.tgz", - "integrity": "sha512-rJeEq7iuKMMjel0zzH10dXzcWn4Q2yywbv5vM9B1xTQpkD4uxTbBlQs+EL9+pmwaaQrrriEGqluZOTzHvUzJUg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.8.0", - "@multiformats/multiaddr": "^12.3.3", - "interface-datastore": "^8.3.1", - "multiformats": "^13.3.1", - "weald": "^1.0.4" - } - }, - "node_modules/libp2p/node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "http://94.130.170.209:4873/@types%2fretry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "license": "MIT" - }, - "node_modules/libp2p/node_modules/p-retry": { - "version": "6.2.1", - "resolved": "http://94.130.170.209:4873/p-retry/-/p-retry-6.2.1.tgz", - "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lighthouse-logger": { - "version": "1.4.2", - "resolved": "http://94.130.170.209:4873/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", - "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "debug": "^2.6.9", - "marky": "^1.2.2" - } - }, - "node_modules/lighthouse-logger/node_modules/debug": { - "version": "2.6.9", - "resolved": "http://94.130.170.209:4873/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/lighthouse-logger/node_modules/ms": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true - }, - "node_modules/line-reader": { - "version": "0.4.0", - "resolved": "http://94.130.170.209:4873/line-reader/-/line-reader-0.4.0.tgz", - "integrity": "sha512-AYJ8g+eE7v+Ba4s/cuYqzuNulH/WbjdKQ55fvx8fNVn8WQzTpioY6vI1MoxTuMgcHYX3VlmZWbVvnkIqkyJbCA==", - "license": "MIT" - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "http://94.130.170.209:4873/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "license": "MIT", - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "license": "MIT", - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "http://94.130.170.209:4873/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "license": "MIT", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "http://94.130.170.209:4873/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/lodash.capitalize": { - "version": "4.2.1", - "resolved": "http://94.130.170.209:4873/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", - "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "http://94.130.170.209:4873/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "http://94.130.170.209:4873/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "http://94.130.170.209:4873/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "http://94.130.170.209:4873/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" - }, - "node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "http://94.130.170.209:4873/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "http://94.130.170.209:4873/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "http://94.130.170.209:4873/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "http://94.130.170.209:4873/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT" - }, - "node_modules/lodash.throttle": { - "version": "4.1.1", - "resolved": "http://94.130.170.209:4873/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", - "license": "MIT", - "peer": true - }, - "node_modules/lodash.uniqby": { - "version": "4.7.0", - "resolved": "http://94.130.170.209:4873/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-driver": { - "version": "1.2.4", - "resolved": "http://94.130.170.209:4873/log-driver/-/log-driver-1.2.4.tgz", - "integrity": "sha512-QmyGbAcBbHk8ysCGtT6FQ+LZML6+EeT0NdotCJGu72kNhknXtdso1G/NI0r7j45whFYNTU15XMW+JGOvGX07QQ==", - "dev": true, - "engines": { - "node": ">=0.8.6" - } - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/logform": { - "version": "2.7.0", - "resolved": "http://94.130.170.209:4873/logform/-/logform-2.7.0.tgz", - "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", - "license": "MIT", - "dependencies": { - "@colors/colors": "1.6.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/logform/node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "http://94.130.170.209:4873/@colors%2fcolors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/long": { - "version": "5.2.3", - "resolved": "http://94.130.170.209:4873/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", - "license": "Apache-2.0" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "http://94.130.170.209:4873/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "http://94.130.170.209:4873/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "license": "ISC", - "peer": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "http://94.130.170.209:4873/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "http://94.130.170.209:4873/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/argparse": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/marked-terminal": { - "version": "5.2.0", - "resolved": "http://94.130.170.209:4873/marked-terminal/-/marked-terminal-5.2.0.tgz", - "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^6.2.0", - "cardinal": "^2.1.1", - "chalk": "^5.2.0", - "cli-table3": "^0.6.3", - "node-emoji": "^1.11.0", - "supports-hyperlinks": "^2.3.0" - }, - "engines": { - "node": ">=14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, - "node_modules/marked-terminal/node_modules/chalk": { - "version": "5.3.0", - "resolved": "http://94.130.170.209:4873/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/marky": { - "version": "1.2.5", - "resolved": "http://94.130.170.209:4873/marky/-/marky-1.2.5.tgz", - "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", - "license": "Apache-2.0", - "peer": true - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "http://94.130.170.209:4873/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "license": "MIT" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "http://94.130.170.209:4873/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memoize-one": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", - "license": "MIT", - "peer": true - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "http://94.130.170.209:4873/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "license": "MIT", - "optional": true - }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "http://94.130.170.209:4873/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-options": { - "version": "3.0.4", - "resolved": "http://94.130.170.209:4873/merge-options/-/merge-options-3.0.4.tgz", - "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", - "license": "MIT", - "dependencies": { - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "http://94.130.170.209:4873/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/merkle-lib": { - "version": "2.0.10", - "resolved": "http://94.130.170.209:4873/merkle-lib/-/merkle-lib-2.0.10.tgz", - "integrity": "sha512-XrNQvUbn1DL5hKNe46Ccs+Tu3/PYOlrcZILuGUhb95oKBPjc/nmIC8D462PQkipVDGKRvwhn+QFg2cCdIvmDJA==", - "license": "MIT" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/metro": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro/-/metro-0.82.1.tgz", - "integrity": "sha512-/avNIHMlZhkDRl5ZMKNGuZSFZU56M3ABtt/JFQBJWEnitHtSD3Qidnfgjglq61yDbsWBv7aVrOFhdPRPTHN92A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/core": "^7.25.2", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.3", - "@babel/types": "^7.25.2", - "accepts": "^1.3.7", - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "connect": "^3.6.5", - "debug": "^4.4.0", - "error-stack-parser": "^2.0.6", - "flow-enums-runtime": "^0.0.6", - "graceful-fs": "^4.2.4", - "hermes-parser": "0.25.1", - "image-size": "^1.0.2", - "invariant": "^2.2.4", - "jest-worker": "^29.7.0", - "jsc-safe-url": "^0.2.2", - "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.82.1", - "metro-cache": "0.82.1", - "metro-cache-key": "0.82.1", - "metro-config": "0.82.1", - "metro-core": "0.82.1", - "metro-file-map": "0.82.1", - "metro-resolver": "0.82.1", - "metro-runtime": "0.82.1", - "metro-source-map": "0.82.1", - "metro-symbolicate": "0.82.1", - "metro-transform-plugins": "0.82.1", - "metro-transform-worker": "0.82.1", - "mime-types": "^2.1.27", - "nullthrows": "^1.1.1", - "serialize-error": "^2.1.0", - "source-map": "^0.5.6", - "throat": "^5.0.0", - "ws": "^7.5.10", - "yargs": "^17.6.2" - }, - "bin": { - "metro": "src/cli.js" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-babel-transformer": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-babel-transformer/-/metro-babel-transformer-0.82.1.tgz", - "integrity": "sha512-SuDMRdJKafSj9mzIijCNRxVXWrlJZdTnVE9iTGHO85UFTp/mWOLftqCjEtEjc78/0Wq3Y8IoYayx/VkYmKUf/g==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.25.2", - "flow-enums-runtime": "^0.0.6", - "hermes-parser": "0.25.1", - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-cache": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-cache/-/metro-cache-0.82.1.tgz", - "integrity": "sha512-4ZK5EdgM8bTLLjpPCYOImirXUXVZpUU/I81BeAkScF8FFJfEHhV8yFyVp4/689bLbUBMwqz3rvYyxnrMi242lA==", - "license": "MIT", - "peer": true, - "dependencies": { - "exponential-backoff": "^3.1.1", - "flow-enums-runtime": "^0.0.6", - "metro-core": "0.82.1" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-cache-key": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-cache-key/-/metro-cache-key-0.82.1.tgz", - "integrity": "sha512-RoByg/cxJUewdO4yDx3udpxc6S59570Ub34Jm2gjvOcYQOkGxNepNgyhWFlZLM7P7aBF2UwdCqDB1hoTRtQqNw==", - "license": "MIT", - "peer": true, - "dependencies": { - "flow-enums-runtime": "^0.0.6" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-config": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-config/-/metro-config-0.82.1.tgz", - "integrity": "sha512-+w3280sUdZmEDpmEhk66vfeWs8xKhogiPim+JT6AIhrTUS4exki+yFgXDdnBXrjvAvhxUtCZcoIueFKCC/mbZw==", - "license": "MIT", - "peer": true, - "dependencies": { - "connect": "^3.6.5", - "cosmiconfig": "^5.0.5", - "flow-enums-runtime": "^0.0.6", - "jest-validate": "^29.7.0", - "metro": "0.82.1", - "metro-cache": "0.82.1", - "metro-core": "0.82.1", - "metro-runtime": "0.82.1" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "http://94.130.170.209:4873/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "peer": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/metro-config/node_modules/cosmiconfig": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "license": "MIT", - "peer": true, - "dependencies": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-config/node_modules/esprima": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "peer": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-config/node_modules/import-fresh": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "license": "MIT", - "peer": true, - "dependencies": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "http://94.130.170.209:4873/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "license": "MIT", - "peer": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/metro-config/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "license": "MIT", - "peer": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-config/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/metro-core": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-core/-/metro-core-0.82.1.tgz", - "integrity": "sha512-C1a8lPGJPs6axj9q+qLSdzK98TYjjXV6nsGnTvYuSwwXAm5sS03ewZCDimRfzu1s58oR0O28QddBgxNtYpDnJg==", - "license": "MIT", - "peer": true, - "dependencies": { - "flow-enums-runtime": "^0.0.6", - "lodash.throttle": "^4.1.1", - "metro-resolver": "0.82.1" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-file-map": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-file-map/-/metro-file-map-0.82.1.tgz", - "integrity": "sha512-6RgYYrkswBCH4GwbLiK6QGzTjNnlCdU7BwwZlf+14ApjUlbr1oBkwmAa6lMfmqfZuh2H/ET8X950kJ8uZavJNA==", - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "^4.4.0", - "fb-watchman": "^2.0.0", - "flow-enums-runtime": "^0.0.6", - "graceful-fs": "^4.2.4", - "invariant": "^2.2.4", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "nullthrows": "^1.1.1", - "walker": "^1.0.7" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-file-map/node_modules/debug": { - "version": "4.4.0", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/metro-minify-terser": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-minify-terser/-/metro-minify-terser-0.82.1.tgz", - "integrity": "sha512-3P2PY+9L9sKrlxWWAOb1Bi6HXFCdnevym1R/6stkev/kl1+khkrDs1Z40139fLXFZbn8FrvXe89sTFRC3vB+Nw==", - "license": "MIT", - "peer": true, - "dependencies": { - "flow-enums-runtime": "^0.0.6", - "terser": "^5.15.0" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-resolver": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-resolver/-/metro-resolver-0.82.1.tgz", - "integrity": "sha512-TnHK2FRTq/KMRZTqUKRXGJ4NGwJEHrPuo60UPGMUHzAS9diI22oCQ8y9888saGiXE+gi0Iplv/6AUTISxDgXqA==", - "license": "MIT", - "peer": true, - "dependencies": { - "flow-enums-runtime": "^0.0.6" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-runtime": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-runtime/-/metro-runtime-0.82.1.tgz", - "integrity": "sha512-Xg7FccIHlNtI63RX0vKmIzXlM5eSq4mjMo0ALbxXpds/P4JVT0JeJW/BqwpncKabrpbZyvPmPguhd32TiMWHXg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.25.0", - "flow-enums-runtime": "^0.0.6" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-source-map": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-source-map/-/metro-source-map-0.82.1.tgz", - "integrity": "sha512-uCf60ybpmPvkkqQpVWtPZFCIMBS1D9uQ4r2isbqWvDQ1FFTi3xrhT1Z35Dyg30RQV6638XJ4wZY+Dwh8bU9W8A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.25.3", - "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", - "@babel/types": "^7.25.2", - "flow-enums-runtime": "^0.0.6", - "invariant": "^2.2.4", - "metro-symbolicate": "0.82.1", - "nullthrows": "^1.1.1", - "ob1": "0.82.1", - "source-map": "^0.5.6", - "vlq": "^1.0.0" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-source-map/node_modules/source-map": { - "version": "0.5.7", - "resolved": "http://94.130.170.209:4873/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/metro-symbolicate": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-symbolicate/-/metro-symbolicate-0.82.1.tgz", - "integrity": "sha512-UFofSe+y0tz+nQ5XOkgXOYu5xlbX/8jEvd2eSrd8SjAX7eAjbGwN0Kjji+87jSaMJIvRHkArVMWqwF6fZVq55g==", - "license": "MIT", - "peer": true, - "dependencies": { - "flow-enums-runtime": "^0.0.6", - "invariant": "^2.2.4", - "metro-source-map": "0.82.1", - "nullthrows": "^1.1.1", - "source-map": "^0.5.6", - "vlq": "^1.0.0" - }, - "bin": { - "metro-symbolicate": "src/index.js" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-symbolicate/node_modules/source-map": { - "version": "0.5.7", - "resolved": "http://94.130.170.209:4873/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/metro-transform-plugins": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-transform-plugins/-/metro-transform-plugins-0.82.1.tgz", - "integrity": "sha512-AHFattUD9tUjG2MFV4RgZRgZZNfdRVQ7X6+ORK3cqwiItMcY2mK7psC6G2zI3WOtbydBcu/xWTilmjl7krC7FQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.25.2", - "@babel/generator": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.3", - "flow-enums-runtime": "^0.0.6", - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro-transform-worker": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/metro-transform-worker/-/metro-transform-worker-0.82.1.tgz", - "integrity": "sha512-2vaadziCaYPfPMnl3tuYimjR7Gmj5CVOcQh/bJniOiXWZ0b1v4JGcw6jOAWzQKgNJdrOq8lMfzdT3xJ/cn/m7g==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.25.2", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", - "@babel/types": "^7.25.2", - "flow-enums-runtime": "^0.0.6", - "metro": "0.82.1", - "metro-babel-transformer": "0.82.1", - "metro-cache": "0.82.1", - "metro-cache-key": "0.82.1", - "metro-minify-terser": "0.82.1", - "metro-source-map": "0.82.1", - "metro-transform-plugins": "0.82.1", - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/metro/node_modules/cliui": { - "version": "8.0.1", - "resolved": "http://94.130.170.209:4873/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/metro/node_modules/debug": { - "version": "4.4.0", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/metro/node_modules/source-map": { - "version": "0.5.7", - "resolved": "http://94.130.170.209:4873/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/metro/node_modules/ws": { - "version": "7.5.10", - "resolved": "http://94.130.170.209:4873/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/metro/node_modules/yargs": { - "version": "17.7.2", - "resolved": "http://94.130.170.209:4873/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "peer": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/metro/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "http://94.130.170.209:4873/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "http://94.130.170.209:4873/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "http://94.130.170.209:4873/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "http://94.130.170.209:4873/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimal-slp-wallet": { - "version": "5.13.2", - "resolved": "http://94.130.170.209:4873/minimal-slp-wallet/-/minimal-slp-wallet-5.13.2.tgz", - "integrity": "sha512-PU19fx1qqiotE8khD4A1wTIlncUZQum6aouMRhWj/crpdZ1+FXyGUoPV704Lei1NQ6GP+4ktzws+3zNlkDIC/Q==", - "license": "MIT", - "dependencies": { - "@chris.troutner/retry-queue-commonjs": "1.0.8", - "@psf/bch-js": "6.8.0", - "apidoc": "0.51.0", - "bch-consumer": "1.6.2", - "bch-donation": "1.1.2", - "crypto-js": "4.0.0" - } - }, - "node_modules/minimal-slp-wallet/node_modules/@psf/bch-js": { - "version": "6.8.0", - "resolved": "http://94.130.170.209:4873/@psf%2fbch-js/-/bch-js-6.8.0.tgz", - "integrity": "sha512-6my2gpIfwnMv3iL2IsdWYoHfZW6fVd4wpw4A0XGmgxra2E2fQEBWlfj8jIsu3f54ZTbcpTvO4tp5QT4dKKBlZQ==", - "license": "MIT", - "dependencies": { - "@chris.troutner/bip32-utils": "1.0.5", - "@psf/bip21": "2.0.1", - "@psf/bitcoincash-ops": "2.0.0", - "@psf/bitcoincashjs-lib": "4.0.3", - "@psf/coininfo": "4.0.0", - "axios": "0.26.1", - "bc-bip68": "1.0.5", - "bchaddrjs-slp": "0.2.5", - "bigi": "1.4.2", - "bignumber.js": "9.0.0", - "bip-schnorr": "0.3.0", - "bip38": "2.0.2", - "bip39": "3.0.2", - "bip66": "1.1.5", - "bitcoinjs-message": "2.0.0", - "bs58": "4.0.1", - "ecashaddrjs": "1.0.7", - "ini": "1.3.8", - "randombytes": "2.0.6", - "safe-buffer": "5.1.2", - "satoshi-bitcoin": "1.0.4", - "slp-mdm": "0.0.6", - "slp-parser": "0.0.4", - "wif": "2.0.6" - } - }, - "node_modules/minimal-slp-wallet/node_modules/apidoc": { - "version": "0.51.0", - "resolved": "http://94.130.170.209:4873/apidoc/-/apidoc-0.51.0.tgz", - "integrity": "sha512-3P4srhm6NA+kE/YRM4qL5jESElpQQJL+Z8n7hyr4uC+1DSwGzmE6adXPVxuT/hpDyShrqmRlHk8hf40RSqEsNw==", - "license": "MIT", - "os": [ - "darwin", - "freebsd", - "linux", - "openbsd", - "win32" - ], - "dependencies": { - "bootstrap": "3.4.1", - "commander": "^8.3.0", - "diff-match-patch": "^1.0.5", - "esbuild-loader": "^2.16.0", - "expose-loader": "^3.1.0", - "fs-extra": "^10.0.0", - "glob": "^7.2.0", - "handlebars": "^4.7.7", - "iconv-lite": "^0.6.3", - "jquery": "^3.6.0", - "klaw-sync": "^6.0.0", - "lodash": "^4.17.21", - "markdown-it": "^12.2.0", - "nodemon": "^2.0.15", - "path-to-regexp": "^6.2.0", - "prismjs": "^1.25.0", - "semver": "^7.3.5", - "style-loader": "^3.3.1", - "url-parse": "^1.5.3", - "webpack": "^5.64.2", - "webpack-cli": "^4.9.1", - "winston": "^3.3.3" - }, - "bin": { - "apidoc": "bin/apidoc" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/minimal-slp-wallet/node_modules/axios": { - "version": "0.26.1", - "resolved": "http://94.130.170.209:4873/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/minimal-slp-wallet/node_modules/glob": { - "version": "7.2.3", - "resolved": "http://94.130.170.209:4873/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "license": "ISC" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "license": "MIT" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "http://94.130.170.209:4873/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "http://94.130.170.209:4873/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minimist-options/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "http://94.130.170.209:4873/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "license": "MIT" - }, - "node_modules/mocha": { - "version": "10.0.0", - "resolved": "http://94.130.170.209:4873/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.4", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "http://94.130.170.209:4873/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "http://94.130.170.209:4873/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.3", - "resolved": "http://94.130.170.209:4873/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "http://94.130.170.209:4873/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "http://94.130.170.209:4873/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/mock-property": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/mock-property/-/mock-property-1.1.0.tgz", - "integrity": "sha512-1/JjbLoGwv87xVsutkX0XJc0M0W4kb40cZl/K41xtTViBOD9JuFPKfyMNTrLJ/ivYAd0aPqu/vduamXO0emTFQ==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "functions-have-names": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "hasown": "^2.0.2", - "isarray": "^2.0.5", - "object-inspect": "^1.13.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/modify-values": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "http://94.130.170.209:4873/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.46", - "resolved": "http://94.130.170.209:4873/moment-timezone/-/moment-timezone-0.5.46.tgz", - "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==", - "license": "MIT", - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "3.7.3", - "resolved": "http://94.130.170.209:4873/mongodb/-/mongodb-3.7.3.tgz", - "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", - "license": "Apache-2.0", - "dependencies": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.1.8", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4" - }, - "optionalDependencies": { - "saslprep": "^1.0.0" - }, - "peerDependenciesMeta": { - "aws4": { - "optional": true - }, - "bson-ext": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "mongodb-extjson": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/mongodb/node_modules/denque": { - "version": "1.5.1", - "resolved": "http://94.130.170.209:4873/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/mongodb/node_modules/optional-require": { - "version": "1.1.8", - "resolved": "http://94.130.170.209:4873/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "license": "Apache-2.0", - "dependencies": { - "require-at": "^1.0.6" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mongoose": { - "version": "5.13.14", - "resolved": "http://94.130.170.209:4873/mongoose/-/mongoose-5.13.14.tgz", - "integrity": "sha512-j+BlQjjxgZg0iWn42kLeZTB91OejcxWpY2Z50bsZTiKJ7HHcEtcY21Godw496GMkBqJMTzmW7G/kZ04mW+Cb7Q==", - "license": "MIT", - "dependencies": { - "@types/bson": "1.x || 4.0.x", - "@types/mongodb": "^3.5.27", - "bson": "^1.1.4", - "kareem": "2.3.2", - "mongodb": "3.7.3", - "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.8.4", - "mquery": "3.2.5", - "ms": "2.1.2", - "optional-require": "1.0.x", - "regexp-clone": "1.0.0", - "safe-buffer": "5.2.1", - "sift": "13.5.2", - "sliced": "1.0.1" - }, - "engines": { - "node": ">=4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" - } - }, - "node_modules/mongoose-legacy-pluralize": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", - "license": "Apache-2.0", - "peerDependencies": { - "mongoose": "*" - } - }, - "node_modules/mongoose/node_modules/ms": { - "version": "2.1.2", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "license": "MIT" - }, - "node_modules/mongoose/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/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" - } - ], - "license": "MIT" - }, - "node_modules/mortice": { - "version": "3.0.6", - "resolved": "http://94.130.170.209:4873/mortice/-/mortice-3.0.6.tgz", - "integrity": "sha512-xUjsTQreX8rO3pHuGYDZ3PY/sEiONIzqzjLeog5akdY4bz9TlDDuvYlU8fm+6qnm4rnpa6AFxLhsfSBThLijdA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "observable-webworkers": "^2.0.1", - "p-queue": "^8.0.1", - "p-timeout": "^6.0.0" - } - }, - "node_modules/mortice/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/mortice/node_modules/p-queue": { - "version": "8.1.0", - "resolved": "http://94.130.170.209:4873/p-queue/-/p-queue-8.1.0.tgz", - "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mpath": { - "version": "0.8.4", - "resolved": "http://94.130.170.209:4873/mpath/-/mpath-0.8.4.tgz", - "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mquery": { - "version": "3.2.5", - "resolved": "http://94.130.170.209:4873/mquery/-/mquery-3.2.5.tgz", - "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", - "license": "MIT", - "dependencies": { - "bluebird": "3.5.1", - "debug": "3.1.0", - "regexp-clone": "^1.0.0", - "safe-buffer": "5.1.2", - "sliced": "1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "http://94.130.170.209:4873/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "license": "MIT", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/multiformats": { - "version": "13.3.1", - "resolved": "http://94.130.170.209:4873/multiformats/-/multiformats-13.3.1.tgz", - "integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/murmurhash3js-revisited": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", - "integrity": "sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/nan": { - "version": "2.22.0", - "resolved": "http://94.130.170.209:4873/nan/-/nan-2.22.0.tgz", - "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/nanoid/-/nanoid-4.0.2.tgz", - "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^14 || ^16 || >=18" - } - }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "license": "MIT" - }, - "node_modules/native-fetch": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/native-fetch/-/native-fetch-3.0.0.tgz", - "integrity": "sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==", - "license": "MIT", - "peerDependencies": { - "node-fetch": "*" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "http://94.130.170.209:4873/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "http://94.130.170.209:4873/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "http://94.130.170.209:4873/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "license": "MIT" - }, - "node_modules/nerf-dart": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/nerf-dart/-/nerf-dart-1.0.0.tgz", - "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", - "dev": true, - "license": "MIT" - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/nise": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "http://94.130.170.209:4873/@sinonjs%2fcommons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "http://94.130.170.209:4873/@sinonjs%2ffake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/nise/node_modules/isarray": { - "version": "0.0.1", - "resolved": "http://94.130.170.209:4873/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "http://94.130.170.209:4873/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/nise/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "http://94.130.170.209:4873/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/noble-secp256k1": { - "version": "1.2.14", - "resolved": "http://94.130.170.209:4873/noble-secp256k1/-/noble-secp256k1-1.2.14.tgz", - "integrity": "sha512-GSCXyoZBUaaPwVWdYncMEmzlSUjF9J/YeEHpklYJCyg8wPuJP3NzDx0BkiwArzINkdX2HJHvUJhL6vVWPOQQcg==", - "deprecated": "Switch to namespaced @noble/secp256k1 for security and feature updates", - "license": "MIT" - }, - "node_modules/node-abi": { - "version": "3.74.0", - "resolved": "http://94.130.170.209:4873/node-abi/-/node-abi-3.74.0.tgz", - "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==", - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "license": "MIT" - }, - "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "http://94.130.170.209:4873/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.21" - } - }, - "node_modules/node-fetch": { - "name": "@achingbrain/node-fetch", - "version": "2.6.7", - "resolved": "http://94.130.170.209:4873/@achingbrain%2fnode-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g==", - "license": "MIT", - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "http://94.130.170.209:4873/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "http://94.130.170.209:4873/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "http://94.130.170.209:4873/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "license": "MIT", - "peer": true - }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "http://94.130.170.209:4873/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "license": "MIT" - }, - "node_modules/node-uuid": { - "version": "1.4.8", - "resolved": "http://94.130.170.209:4873/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==", - "deprecated": "Use uuid module instead", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/nodemailer": { - "version": "6.7.5", - "resolved": "http://94.130.170.209:4873/nodemailer/-/nodemailer-6.7.5.tgz", - "integrity": "sha512-6VtMpwhsrixq1HDYSBBHvW0GwiWawE75dS3oal48VqRhUvKJNnKnJo2RI/bCVQubj1vgrgscMNW4DHaD6xtMCg==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/nodemon": { - "version": "2.0.22", - "resolved": "http://94.130.170.209:4873/nodemon/-/nodemon-2.0.22.tgz", - "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^3.2.7", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^5.7.1", - "simple-update-notifier": "^1.0.7", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/semver": { - "version": "5.7.2", - "resolved": "http://94.130.170.209:4873/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "http://94.130.170.209:4873/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "8.0.1", - "resolved": "http://94.130.170.209:4873/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nostr": { - "version": "0.2.8", - "resolved": "http://94.130.170.209:4873/nostr/-/nostr-0.2.8.tgz", - "integrity": "sha512-p25OQiEB5x8rWWoWLRRbxtxQiaQgypaQQakSKw5+cp/SW0DXea/soMzqmTXei1I6HrcARuyfvedGTdoEU471Ow==", - "license": "MIT", - "dependencies": { - "noble-secp256k1": "^1.2.14", - "ws": "^8.8.1" - } - }, - "node_modules/nostr-tools": { - "version": "2.10.4", - "resolved": "http://94.130.170.209:4873/nostr-tools/-/nostr-tools-2.10.4.tgz", - "integrity": "sha512-biU7sk+jxHgVASfobg2T5ttxOGGSt69wEVBC51sHHOEaKAAdzHBLV/I2l9Rf61UzClhliZwNouYhqIso4a3HYg==", - "license": "Unlicense", - "dependencies": { - "@noble/ciphers": "^0.5.1", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.1", - "@scure/base": "1.1.1", - "@scure/bip32": "1.3.1", - "@scure/bip39": "1.2.1" - }, - "optionalDependencies": { - "nostr-wasm": "0.1.0" - }, - "peerDependencies": { - "typescript": ">=5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/nostr-tools/node_modules/@noble/ciphers": { - "version": "0.5.3", - "resolved": "http://94.130.170.209:4873/@noble%2fciphers/-/ciphers-0.5.3.tgz", - "integrity": "sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/nostr-tools/node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/@noble%2fcurves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/@noble%2fhashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/nostr-tools/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "http://94.130.170.209:4873/@noble%2fhashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/nostr-wasm": { - "version": "0.1.0", - "resolved": "http://94.130.170.209:4873/nostr-wasm/-/nostr-wasm-0.1.0.tgz", - "integrity": "sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==", - "license": "MIT", - "optional": true - }, - "node_modules/npm": { - "version": "8.19.4", - "resolved": "http://94.130.170.209:4873/npm/-/npm-8.19.4.tgz", - "integrity": "sha512-3HANl8i9DKnUA89P4KEgVNN28EjSeDCmvEqbzOAuxCFDzdBZzjUl99zgnGpOUumvW5lvJo2HKcjrsc+tfyv1Hw==", - "bundleDependencies": [ - "@isaacs/string-locale-compare", - "@npmcli/arborist", - "@npmcli/ci-detect", - "@npmcli/config", - "@npmcli/fs", - "@npmcli/map-workspaces", - "@npmcli/package-json", - "@npmcli/run-script", - "abbrev", - "archy", - "cacache", - "chalk", - "chownr", - "cli-columns", - "cli-table3", - "columnify", - "fastest-levenshtein", - "fs-minipass", - "glob", - "graceful-fs", - "hosted-git-info", - "ini", - "init-package-json", - "is-cidr", - "json-parse-even-better-errors", - "libnpmaccess", - "libnpmdiff", - "libnpmexec", - "libnpmfund", - "libnpmhook", - "libnpmorg", - "libnpmpack", - "libnpmpublish", - "libnpmsearch", - "libnpmteam", - "libnpmversion", - "make-fetch-happen", - "minimatch", - "minipass", - "minipass-pipeline", - "mkdirp", - "mkdirp-infer-owner", - "ms", - "node-gyp", - "nopt", - "npm-audit-report", - "npm-install-checks", - "npm-package-arg", - "npm-pick-manifest", - "npm-profile", - "npm-registry-fetch", - "npm-user-validate", - "npmlog", - "opener", - "p-map", - "pacote", - "parse-conflict-json", - "proc-log", - "qrcode-terminal", - "read", - "read-package-json", - "read-package-json-fast", - "readdir-scoped-modules", - "rimraf", - "semver", - "ssri", - "tar", - "text-table", - "tiny-relative-date", - "treeverse", - "validate-npm-package-name", - "which", - "write-file-atomic" - ], - "dev": true, - "license": "Artistic-2.0", - "workspaces": [ - "docs", - "smoke-tests", - "workspaces/*" - ], - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^5.6.3", - "@npmcli/ci-detect": "^2.0.0", - "@npmcli/config": "^4.2.1", - "@npmcli/fs": "^2.1.0", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/package-json": "^2.0.0", - "@npmcli/run-script": "^4.2.1", - "abbrev": "~1.1.1", - "archy": "~1.0.0", - "cacache": "^16.1.3", - "chalk": "^4.1.2", - "chownr": "^2.0.0", - "cli-columns": "^4.0.0", - "cli-table3": "^0.6.2", - "columnify": "^1.6.0", - "fastest-levenshtein": "^1.0.12", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "graceful-fs": "^4.2.10", - "hosted-git-info": "^5.2.1", - "ini": "^3.0.1", - "init-package-json": "^3.0.2", - "is-cidr": "^4.0.2", - "json-parse-even-better-errors": "^2.3.1", - "libnpmaccess": "^6.0.4", - "libnpmdiff": "^4.0.5", - "libnpmexec": "^4.0.14", - "libnpmfund": "^3.0.5", - "libnpmhook": "^8.0.4", - "libnpmorg": "^4.0.4", - "libnpmpack": "^4.1.3", - "libnpmpublish": "^6.0.5", - "libnpmsearch": "^5.0.4", - "libnpmteam": "^4.0.4", - "libnpmversion": "^3.0.7", - "make-fetch-happen": "^10.2.0", - "minimatch": "^5.1.0", - "minipass": "^3.1.6", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "ms": "^2.1.2", - "node-gyp": "^9.1.0", - "nopt": "^6.0.0", - "npm-audit-report": "^3.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.1.0", - "npm-pick-manifest": "^7.0.2", - "npm-profile": "^6.2.0", - "npm-registry-fetch": "^13.3.1", - "npm-user-validate": "^1.0.1", - "npmlog": "^6.0.2", - "opener": "^1.5.2", - "p-map": "^4.0.0", - "pacote": "^13.6.2", - "parse-conflict-json": "^2.0.2", - "proc-log": "^2.0.1", - "qrcode-terminal": "^0.12.0", - "read": "~1.0.7", - "read-package-json": "^5.0.2", - "read-package-json-fast": "^2.0.3", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.1", - "tar": "^6.1.11", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^2.0.0", - "validate-npm-package-name": "^4.0.0", - "which": "^2.0.2", - "write-file-atomic": "^4.0.1" - }, - "bin": { - "npm": "bin/npm-cli.js", - "npx": "bin/npx-cli.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@colors/colors": { - "version": "1.5.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/npm/node_modules/@gar/promisify": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "5.6.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/metavuln-calculator": "^3.0.1", - "@npmcli/move-file": "^2.0.0", - "@npmcli/name-from-folder": "^1.0.1", - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/package-json": "^2.0.0", - "@npmcli/query": "^1.2.0", - "@npmcli/run-script": "^4.1.3", - "bin-links": "^3.0.3", - "cacache": "^16.1.3", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^5.2.1", - "json-parse-even-better-errors": "^2.3.1", - "json-stringify-nice": "^1.1.4", - "minimatch": "^5.1.0", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^6.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.0.0", - "npm-pick-manifest": "^7.0.2", - "npm-registry-fetch": "^13.0.0", - "npmlog": "^6.0.2", - "pacote": "^13.6.1", - "parse-conflict-json": "^2.0.1", - "proc-log": "^2.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^1.0.1", - "read-package-json-fast": "^2.0.2", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.0", - "treeverse": "^2.0.0", - "walk-up-path": "^1.0.0" - }, - "bin": { - "arborist": "bin/index.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/ci-detect": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/npm/node_modules/@npmcli/config": { - "version": "4.2.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/map-workspaces": "^2.0.2", - "ini": "^3.0.0", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^6.0.0", - "proc-log": "^2.0.0", - "read-package-json-fast": "^2.0.3", - "semver": "^7.3.5", - "walk-up-path": "^1.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/disparity-colors": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ansi-styles": "^4.3.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/fs": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/git": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^3.0.0", - "lru-cache": "^7.4.4", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^7.0.0", - "proc-log": "^2.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents": { - "version": "1.0.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - }, - "bin": { - "installed-package-contents": "index.js" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled": { - "version": "1.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "2.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/name-from-folder": "^1.0.1", - "glob": "^8.0.1", - "minimatch": "^5.0.1", - "read-package-json-fast": "^2.0.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cacache": "^16.0.0", - "json-parse-even-better-errors": "^2.3.1", - "pacote": "^13.0.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/move-file": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^2.3.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "infer-owner": "^1.0.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/query": { - "version": "1.2.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^9.1.0", - "postcss-selector-parser": "^6.0.10", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "4.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@tootallnate/once": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/abbrev": { - "version": "1.1.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/agent-base": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/npm/node_modules/agentkeepalive": { - "version": "4.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/npm/node_modules/aggregate-error": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/aproba": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/archy": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/are-we-there-yet": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/asap": { - "version": "2.0.6", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/bin-links": { - "version": "3.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cmd-shim": "^5.0.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0", - "read-cmd-shim": "^3.0.0", - "rimraf": "^3.0.0", - "write-file-atomic": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/binary-extensions": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/builtins": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/npm/node_modules/cacache": { - "version": "16.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "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/npm/node_modules/chownr": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/cidr-regex": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "ip-regex": "^4.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/clean-stack": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/cli-columns": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/cli-table3": { - "version": "0.6.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/npm/node_modules/clone": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/cmd-shim": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "mkdirp-infer-owner": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/npm/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/color-support": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/npm/node_modules/columnify": { - "version": "1.6.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/console-control-strings": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/debug": { - "version": "4.3.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/debuglog": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/defaults": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/npm/node_modules/delegates": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/depd": { - "version": "1.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/dezalgo": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "node_modules/npm/node_modules/diff": { - "version": "5.1.0", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/npm/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/encoding": { - "version": "0.1.13", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/npm/node_modules/env-paths": { - "version": "2.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/err-code": { - "version": "2.0.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/fastest-levenshtein": { - "version": "1.0.12", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/fs-minipass": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/function-bind": { - "version": "1.1.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/gauge": { - "version": "4.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/glob": { - "version": "8.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/graceful-fs": { - "version": "4.2.10", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/has": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/npm/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/has-unicode": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/hosted-git-info": { - "version": "5.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/http-proxy-agent": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/https-proxy-agent": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/humanize-ms": { - "version": "1.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/npm/node_modules/iconv-lite": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/ignore-walk": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minimatch": "^5.0.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/npm/node_modules/indent-string": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/infer-owner": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/npm/node_modules/inherits": { - "version": "2.0.4", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/ini": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/init-package-json": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^9.0.1", - "promzard": "^0.3.0", - "read": "^1.0.7", - "read-package-json": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/ip": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/ip-regex": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-cidr": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "cidr-regex": "^3.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/is-core-module": { - "version": "2.10.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/npm/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-lambda": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/json-stringify-nice": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff": { - "version": "5.1.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff-apply": { - "version": "5.4.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/libnpmaccess": { - "version": "6.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "minipass": "^3.1.1", - "npm-package-arg": "^9.0.1", - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmdiff": { - "version": "4.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/disparity-colors": "^2.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "binary-extensions": "^2.2.0", - "diff": "^5.1.0", - "minimatch": "^5.0.1", - "npm-package-arg": "^9.0.1", - "pacote": "^13.6.1", - "tar": "^6.1.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmexec": { - "version": "4.0.14", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^5.6.3", - "@npmcli/ci-detect": "^2.0.0", - "@npmcli/fs": "^2.1.1", - "@npmcli/run-script": "^4.2.0", - "chalk": "^4.1.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-package-arg": "^9.0.1", - "npmlog": "^6.0.2", - "pacote": "^13.6.1", - "proc-log": "^2.0.0", - "read": "^1.0.7", - "read-package-json-fast": "^2.0.2", - "semver": "^7.3.7", - "walk-up-path": "^1.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmfund": { - "version": "3.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^5.6.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "8.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmorg": { - "version": "4.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpack": { - "version": "4.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/run-script": "^4.1.3", - "npm-package-arg": "^9.0.1", - "pacote": "^13.6.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpublish": { - "version": "6.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "normalize-package-data": "^4.0.0", - "npm-package-arg": "^9.0.1", - "npm-registry-fetch": "^13.0.0", - "semver": "^7.3.7", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmsearch": { - "version": "5.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmteam": { - "version": "4.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmversion": { - "version": "3.0.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^3.0.0", - "@npmcli/run-script": "^4.1.3", - "json-parse-even-better-errors": "^2.3.1", - "proc-log": "^2.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/lru-cache": { - "version": "7.13.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/make-fetch-happen": { - "version": "10.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/minimatch": { - "version": "5.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/minipass": { - "version": "3.3.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-collect": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-fetch": { - "version": "2.1.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/minipass-flush": { - "version": "1.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-json-stream": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "node_modules/npm/node_modules/minipass-pipeline": { - "version": "1.2.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minizlib": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/mkdirp": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/mkdirp-infer-owner": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "infer-owner": "^1.0.4", - "mkdirp": "^1.0.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/mute-stream": { - "version": "0.0.8", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/negotiator": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/node-gyp": { - "version": "9.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.22 || ^14.13 || >=16" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/nopt": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/nopt": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "4.0.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-audit-report": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-bundled": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-bundled/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-install-checks": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/npm-package-arg": { - "version": "9.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-packlist": { - "version": "5.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^8.0.1", - "ignore-walk": "^5.0.1", - "npm-bundled": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "bin": { - "npm-packlist": "bin/index.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-packlist/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^5.0.0", - "npm-normalize-package-bin": "^2.0.0", - "npm-package-arg": "^9.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-profile": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "13.3.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "make-fetch-happen": "^10.0.6", - "minipass": "^3.1.6", - "minipass-fetch": "^2.0.3", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.1", - "proc-log": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-user-validate": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/npmlog": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/once": { - "version": "1.4.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/npm/node_modules/opener": { - "version": "1.5.2", - "dev": true, - "inBundle": true, - "license": "(WTFPL OR MIT)", - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/npm/node_modules/p-map": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/pacote": { - "version": "13.6.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^3.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^4.1.0", - "cacache": "^16.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.6", - "mkdirp": "^1.0.4", - "npm-package-arg": "^9.0.0", - "npm-packlist": "^5.1.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^5.0.0", - "read-package-json-fast": "^2.0.3", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "lib/bin.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/parse-conflict-json": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^2.3.1", - "just-diff": "^5.0.1", - "just-diff-apply": "^5.2.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.0.10", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/proc-log": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/promise-all-reject-late": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-call-limit": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-inflight": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/promise-retry": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/promzard": { - "version": "0.3.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "read": "1" - } - }, - "node_modules/npm/node_modules/qrcode-terminal": { - "version": "0.12.0", - "dev": true, - "inBundle": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } - }, - "node_modules/npm/node_modules/read": { - "version": "1.0.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/read-cmd-shim": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/read-package-json": { - "version": "5.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^8.0.1", - "json-parse-even-better-errors": "^2.3.1", - "normalize-package-data": "^4.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "2.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/read-package-json/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/readdir-scoped-modules": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "node_modules/npm/node_modules/retry": { - "version": "0.12.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm/node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/safe-buffer": { - "version": "5.2.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/safer-buffer": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/npm/node_modules/semver": { - "version": "7.3.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/set-blocking": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/signal-exit": { - "version": "3.0.7", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/smart-buffer": { - "version": "4.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks": { - "version": "2.7.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/spdx-correct": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.3.0", - "dev": true, - "inBundle": true, - "license": "CC-BY-3.0" - }, - "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.11", - "dev": true, - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/npm/node_modules/ssri": { - "version": "9.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/string_decoder": { - "version": "1.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/npm/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/tar": { - "version": "6.1.11", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/treeverse": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/unique-filename": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/unique-slug": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/validate-npm-package-license": { - "version": "3.0.4", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/walk-up-path": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/wcwidth": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/npm/node_modules/which": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/wide-align": { - "version": "1.1.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/npm/node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/write-file-atomic": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/nullthrows": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/nullthrows/-/nullthrows-1.1.1.tgz", - "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", - "license": "MIT", - "peer": true - }, - "node_modules/oauth-sign": { - "version": "0.3.0", - "resolved": "http://94.130.170.209:4873/oauth-sign/-/oauth-sign-0.3.0.tgz", - "integrity": "sha512-Tr31Sh5FnK9YKm7xTUPyDMsNOvMqkVDND0zvK/Wgj7/H9q8mpye0qG2nVzrnsvLhcsX5DtqXD0la0ks6rkPCGQ==", - "dev": true, - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/ob1": { - "version": "0.82.1", - "resolved": "http://94.130.170.209:4873/ob1/-/ob1-0.82.1.tgz", - "integrity": "sha512-J4m1GAoMC0673H8LmVolj7ZERYEwJWRR4/A/M8ZB5iK9BiFLeAkjvny/VGk3XOYiMtnvq7TV6oc3MfDJ8uKpFw==", - "license": "MIT", - "peer": true, - "dependencies": { - "flow-enums-runtime": "^0.0.6" - }, - "engines": { - "node": ">=18.18" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "http://94.130.170.209:4873/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "http://94.130.170.209:4873/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "http://94.130.170.209:4873/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "license": "MIT", - "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": "http://94.130.170.209:4873/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "http://94.130.170.209:4873/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "license": "MIT", - "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/object.entries": { - "version": "1.1.8", - "resolved": "http://94.130.170.209:4873/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "http://94.130.170.209:4873/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/observable-webworkers": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/observable-webworkers/-/observable-webworkers-2.0.1.tgz", - "integrity": "sha512-JI1vB0u3pZjoQKOK1ROWzp0ygxSi7Yb0iR+7UNsw4/Zn4cQ0P3R7XL38zac/Dy2tEA7Lg88/wIJTjF8vYXZ0uw==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "http://94.130.170.209:4873/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "http://94.130.170.209:4873/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/one-time": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "license": "MIT", - "dependencies": { - "fn.name": "1.x.x" - } - }, - "node_modules/only": { - "version": "0.0.2", - "resolved": "http://94.130.170.209:4873/only/-/only-0.0.2.tgz", - "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==" - }, - "node_modules/open": { - "version": "7.4.2", - "resolved": "http://94.130.170.209:4873/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opencollective-postinstall": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true, - "license": "MIT", - "bin": { - "opencollective-postinstall": "index.js" - } - }, - "node_modules/optional-require": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/optional-require/-/optional-require-1.0.3.tgz", - "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==", - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "http://94.130.170.209:4873/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/p-defer": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/p-defer/-/p-defer-4.0.1.tgz", - "integrity": "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-each-series": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-event": { - "version": "6.0.1", - "resolved": "http://94.130.170.209:4873/p-event/-/p-event-6.0.1.tgz", - "integrity": "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==", - "license": "MIT", - "dependencies": { - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-fifo": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/p-fifo/-/p-fifo-1.0.0.tgz", - "integrity": "sha512-IjoCxXW48tqdtDFz6fqo5q1UfFVjjVZe8TC1QRflvNUJtNfCUhxOUw6MOVZhDPjqhSzc26xKdugsO17gmzd5+A==", - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.0.0", - "p-defer": "^3.0.0" - } - }, - "node_modules/p-fifo/node_modules/p-defer": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/p-defer/-/p-defer-3.0.0.tgz", - "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-filter": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/p-filter/-/p-filter-2.1.0.tgz", - "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-map": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-is-promise": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/p-is-promise/-/p-is-promise-3.0.0.tgz", - "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-queue": { - "version": "7.3.0", - "resolved": "http://94.130.170.209:4873/p-queue/-/p-queue-7.3.0.tgz", - "integrity": "sha512-5fP+yVQ0qp0rEfZoDTlP2c3RYBgxvRsw30qO+VtPPc95lyvSG+x6USSh1TuLB4n96IO6I8/oXQGsTgtna4q2nQ==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.7", - "p-timeout": "^5.0.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-queue/node_modules/p-timeout": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/p-timeout/-/p-timeout-5.1.0.tgz", - "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-reduce": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/p-reduce/-/p-reduce-2.1.0.tgz", - "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-retry": { - "version": "5.1.1", - "resolved": "http://94.130.170.209:4873/p-retry/-/p-retry-5.1.1.tgz", - "integrity": "sha512-i69WkEU5ZAL8mrmdmVviWwU+DN+IUF8f4sSJThoJ3z5A7Nn5iuO5ROX3Boye0u+uYQLOSfgFl7SuFZCjlAVbQA==", - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.1", - "retry": "^0.13.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-timeout": { - "version": "6.1.3", - "resolved": "http://94.130.170.209:4873/p-timeout/-/p-timeout-6.1.3.tgz", - "integrity": "sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-wait-for": { - "version": "5.0.2", - "resolved": "http://94.130.170.209:4873/p-wait-for/-/p-wait-for-5.0.2.tgz", - "integrity": "sha512-lwx6u1CotQYPVju77R+D0vFomni/AqRfqLmqQ8hekklqZ6gAY9rONh7lBQ0uxWMkC2AuX9b2DVAl8To0NyP1JA==", - "license": "MIT", - "dependencies": { - "p-timeout": "^6.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p2wdb-esm": { - "version": "2.2.9", - "resolved": "http://94.130.170.209:4873/p2wdb-esm/-/p2wdb-esm-2.2.9.tgz", - "integrity": "sha512-I6Pc/Jj2kQRIpDmvs0LAnIv7ssFm1kz+SW+SRkjHezw84arFeeIMkqaVk8DXnKWKfIqy3asG4E77jVGrD55IRA==", - "license": "MIT", - "dependencies": { - "@chris.troutner/retry-queue-commonjs": "1.0.8", - "axios": "0.24.0" - } - }, - "node_modules/p2wdb-esm/node_modules/axios": { - "version": "0.24.0", - "resolved": "http://94.130.170.209:4873/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.4" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-duration": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/parse-duration/-/parse-duration-1.1.0.tgz", - "integrity": "sha512-z6t9dvSJYaPoQq7quMzdEagSFtpGu+utzHqqxmpVWNNZRIXnvqyCvn9XsTdh7c/w0Bqmdz3RB3YnRaKtpRtEXQ==", - "license": "MIT" - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "http://94.130.170.209:4873/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "http://94.130.170.209:4873/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.4.1", - "resolved": "http://94.130.170.209:4873/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", - "license": "MIT", - "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-local": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", - "dependencies": { - "passport-strategy": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passthrough-counter": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/passthrough-counter/-/passthrough-counter-1.0.0.tgz", - "integrity": "sha512-Wy8PXTLqPAN0oEgBrlnsXPMww3SYJ44tQ8aVrGAI4h4JZYCS0oYqsPqtPR8OhJpv6qFbpbB7XAn0liKV7EXubA==", - "license": "MIT" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "http://94.130.170.209:4873/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" - }, - "node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "http://94.130.170.209:4873/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "http://94.130.170.209:4873/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "http://94.130.170.209:4873/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "license": "MIT", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "http://94.130.170.209:4873/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "http://94.130.170.209:4873/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-conf": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/pkg-conf/-/pkg-conf-2.1.0.tgz", - "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.0.0", - "load-json-file": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "http://94.130.170.209:4873/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-try": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/please-upgrade-node": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver-compare": "^1.0.0" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "resolved": "http://94.130.170.209:4873/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "http://94.130.170.209:4873/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "http://94.130.170.209:4873/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "http://94.130.170.209:4873/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "license": "MIT" - }, - "node_modules/progress-events": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/progress-events/-/progress-events-1.0.1.tgz", - "integrity": "sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/promise": { - "version": "8.3.0", - "resolved": "http://94.130.170.209:4873/promise/-/promise-8.3.0.tgz", - "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "license": "MIT", - "peer": true, - "dependencies": { - "asap": "~2.0.6" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "http://94.130.170.209:4873/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "http://94.130.170.209:4873/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "http://94.130.170.209:4873/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true, - "license": "ISC" - }, - "node_modules/protobufjs": { - "version": "7.4.0", - "resolved": "http://94.130.170.209:4873/protobufjs/-/protobufjs-7.4.0.tgz", - "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/protons-runtime": { - "version": "5.5.0", - "resolved": "http://94.130.170.209:4873/protons-runtime/-/protons-runtime-5.5.0.tgz", - "integrity": "sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8-varint": "^2.0.2", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^5.0.1" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "http://94.130.170.209:4873/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "license": "MIT" - }, - "node_modules/public-ip": { - "version": "6.0.1", - "resolved": "http://94.130.170.209:4873/public-ip/-/public-ip-6.0.1.tgz", - "integrity": "sha512-1/Mxa1MKrAQ4jF5IalECSBtB0W1FAtnG+9c5X16jjvV/Gx9fiRy7xXIrHlBGYjnTlai0zdZkM3LrpmASavmAEg==", - "license": "MIT", - "dependencies": { - "aggregate-error": "^4.0.1", - "dns-socket": "^4.2.2", - "got": "^12.1.0", - "is-ip": "^4.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/public-ip/node_modules/is-ip": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/is-ip/-/is-ip-4.0.0.tgz", - "integrity": "sha512-4B4XA2HEIm/PY+OSpeMBXr8pGWBYbXuHgjMAqrwbLO3CPTCAd9ArEJzBUKGZtk9viY6+aSfadGnWyjY3ydYZkw==", - "license": "MIT", - "dependencies": { - "ip-regex": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pump": { - "version": "3.0.2", - "resolved": "http://94.130.170.209:4873/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "http://94.130.170.209:4873/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pushdata-bitcoin": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz", - "integrity": "sha512-hw7rcYTJRAl4olM8Owe8x0fBuJJ+WGbMhQuLWOXEMN3PxPCKQHRkhfL+XG0+iXUmSHjkMmb3Ba55Mt21cZc9kQ==", - "license": "MIT", - "dependencies": { - "bitcoin-ops": "^1.3.0" - } - }, - "node_modules/pvtsutils": { - "version": "1.3.6", - "resolved": "http://94.130.170.209:4873/pvtsutils/-/pvtsutils-1.3.6.tgz", - "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.8.1" - } - }, - "node_modules/pvutils": { - "version": "1.1.3", - "resolved": "http://94.130.170.209:4873/pvutils/-/pvutils-1.1.3.tgz", - "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "http://94.130.170.209:4873/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qs": { - "version": "6.13.1", - "resolved": "http://94.130.170.209:4873/qs/-/qs-6.13.1.tgz", - "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "license": "MIT" - }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "http://94.130.170.209:4873/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "license": "MIT", - "peer": true, - "dependencies": { - "inherits": "~2.0.3" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "http://94.130.170.209:4873/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "http://94.130.170.209:4873/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rabin-wasm": { - "version": "0.1.5", - "resolved": "http://94.130.170.209:4873/rabin-wasm/-/rabin-wasm-0.1.5.tgz", - "integrity": "sha512-uWgQTo7pim1Rnj5TuWcCewRDTf0PEFTSlaUjWP4eY9EbLV9em08v89oCz/WO+wRxpYuO36XEHp4wgYQnAgOHzA==", - "license": "MIT", - "dependencies": { - "@assemblyscript/loader": "^0.9.4", - "bl": "^5.0.0", - "debug": "^4.3.1", - "minimist": "^1.2.5", - "node-fetch": "^2.6.1", - "readable-stream": "^3.6.0" - }, - "bin": { - "rabin-wasm": "cli/bin.js" - } - }, - "node_modules/rabin-wasm/node_modules/bl": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/rabin-wasm/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/race-event": { - "version": "1.3.0", - "resolved": "http://94.130.170.209:4873/race-event/-/race-event-1.3.0.tgz", - "integrity": "sha512-kaLm7axfOnahIqD3jQ4l1e471FIFcEGebXEnhxyLscuUzV8C94xVHtWEqDDXxll7+yu/6lW0w1Ff4HbtvHvOHg==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/race-signal": { - "version": "1.1.3", - "resolved": "http://94.130.170.209:4873/race-signal/-/race-signal-1.1.3.tgz", - "integrity": "sha512-Mt2NznMgepLfORijhQMncE26IhkmjEphig+/1fKC0OtaKwys/gpvpmswSjoN01SS+VO951mj0L4VIDXdXsjnfA==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/randombytes": { - "version": "2.0.6", - "resolved": "http://94.130.170.209:4873/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "http://94.130.170.209:4873/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", - "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/raw-body/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "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/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "http://94.130.170.209:4873/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/raw-body/node_modules/statuses": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "http://94.130.170.209:4873/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react": { - "version": "19.1.0", - "resolved": "http://94.130.170.209:4873/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-devtools-core": { - "version": "6.1.1", - "resolved": "http://94.130.170.209:4873/react-devtools-core/-/react-devtools-core-6.1.1.tgz", - "integrity": "sha512-TFo1MEnkqE6hzAbaztnyR5uLTMoz6wnEWwWBsCUzNt+sVXJycuRJdDqvL078M4/h65BI/YO5XWTaxZDWVsW0fw==", - "license": "MIT", - "peer": true, - "dependencies": { - "shell-quote": "^1.6.1", - "ws": "^7" - } - }, - "node_modules/react-devtools-core/node_modules/ws": { - "version": "7.5.10", - "resolved": "http://94.130.170.209:4873/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "http://94.130.170.209:4873/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "license": "MIT", - "peer": true - }, - "node_modules/react-native": { - "version": "0.79.0", - "resolved": "http://94.130.170.209:4873/react-native/-/react-native-0.79.0.tgz", - "integrity": "sha512-fLG/zl/YF30TWTmp2bbo3flHSFGe4WTyVkb7/wJnMEC39jjXVSCxfDtvSUVavhCc03fA/RTkWWvlmg7NEJk7Vg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/create-cache-key-function": "^29.7.0", - "@react-native/assets-registry": "0.79.0", - "@react-native/codegen": "0.79.0", - "@react-native/community-cli-plugin": "0.79.0", - "@react-native/gradle-plugin": "0.79.0", - "@react-native/js-polyfills": "0.79.0", - "@react-native/normalize-colors": "0.79.0", - "@react-native/virtualized-lists": "0.79.0", - "abort-controller": "^3.0.0", - "anser": "^1.4.9", - "ansi-regex": "^5.0.0", - "babel-jest": "^29.7.0", - "babel-plugin-syntax-hermes-parser": "0.25.1", - "base64-js": "^1.5.1", - "chalk": "^4.0.0", - "commander": "^12.0.0", - "event-target-shim": "^5.0.1", - "flow-enums-runtime": "^0.0.6", - "glob": "^7.1.1", - "invariant": "^2.2.4", - "jest-environment-node": "^29.7.0", - "memoize-one": "^5.0.0", - "metro-runtime": "^0.82.0", - "metro-source-map": "^0.82.0", - "nullthrows": "^1.1.1", - "pretty-format": "^29.7.0", - "promise": "^8.3.0", - "react-devtools-core": "^6.1.1", - "react-refresh": "^0.14.0", - "regenerator-runtime": "^0.13.2", - "scheduler": "0.25.0", - "semver": "^7.1.3", - "stacktrace-parser": "^0.1.10", - "whatwg-fetch": "^3.0.0", - "ws": "^6.2.3", - "yargs": "^17.6.2" - }, - "bin": { - "react-native": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/react": "^19.0.0", - "react": "^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-native-fetch-api": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/react-native-fetch-api/-/react-native-fetch-api-3.0.0.tgz", - "integrity": "sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==", - "license": "MIT", - "dependencies": { - "p-defer": "^3.0.0" - } - }, - "node_modules/react-native-fetch-api/node_modules/p-defer": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/p-defer/-/p-defer-3.0.0.tgz", - "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-webrtc": { - "version": "124.0.5", - "resolved": "http://94.130.170.209:4873/react-native-webrtc/-/react-native-webrtc-124.0.5.tgz", - "integrity": "sha512-LIQJKst+t53bJOcQef9VXuz3pVheSBUA4olQGkxosbF4pHW1gsWoXYmf6wmI2zrqOA+aZsjjB6aT9AKLyr6a0Q==", - "license": "MIT", - "dependencies": { - "base64-js": "1.5.1", - "debug": "4.3.4", - "event-target-shim": "6.0.2" - }, - "peerDependencies": { - "react-native": ">=0.60.0" - } - }, - "node_modules/react-native-webrtc/node_modules/debug": { - "version": "4.3.4", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/react-native-webrtc/node_modules/event-target-shim": { - "version": "6.0.2", - "resolved": "http://94.130.170.209:4873/event-target-shim/-/event-target-shim-6.0.2.tgz", - "integrity": "sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA==", - "license": "MIT", - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/react-native-webrtc/node_modules/ms": { - "version": "2.1.2", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "license": "MIT" - }, - "node_modules/react-native/node_modules/cliui": { - "version": "8.0.1", - "resolved": "http://94.130.170.209:4873/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/react-native/node_modules/commander": { - "version": "12.1.0", - "resolved": "http://94.130.170.209:4873/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/react-native/node_modules/ws": { - "version": "6.2.3", - "resolved": "http://94.130.170.209:4873/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "license": "MIT", - "peer": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/react-native/node_modules/yargs": { - "version": "17.7.2", - "resolved": "http://94.130.170.209:4873/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "peer": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/react-native/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "http://94.130.170.209:4873/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "http://94.130.170.209:4873/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "http://94.130.170.209:4873/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "http://94.130.170.209:4873/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "http://94.130.170.209:4873/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "http://94.130.170.209:4873/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "http://94.130.170.209:4873/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "http://94.130.170.209:4873/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "http://94.130.170.209:4873/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "http://94.130.170.209:4873/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "http://94.130.170.209:4873/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/receptacle": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/receptacle/-/receptacle-1.3.2.tgz", - "integrity": "sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/rechoir": { - "version": "0.7.1", - "resolved": "http://94.130.170.209:4873/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", - "license": "MIT", - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/redent/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/redeyed": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/redeyed/-/redeyed-2.1.1.tgz", - "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esprima": "~4.0.0" - } - }, - "node_modules/redeyed/node_modules/esprima": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/redis": { - "version": "4.7.0", - "resolved": "http://94.130.170.209:4873/redis/-/redis-4.7.0.tgz", - "integrity": "sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==", - "license": "MIT", - "workspaces": [ - "./packages/*" - ], - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.6.0", - "@redis/graph": "1.1.1", - "@redis/json": "1.0.7", - "@redis/search": "1.2.0", - "@redis/time-series": "1.1.0" - } - }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "http://94.130.170.209:4873/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0" - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "http://94.130.170.209:4873/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "license": "MIT", - "peer": true - }, - "node_modules/regexp-clone": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/regexp-clone/-/regexp-clone-1.0.0.tgz", - "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==", - "license": "MIT" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "http://94.130.170.209:4873/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/registry-auth-token": { - "version": "5.0.2", - "resolved": "http://94.130.170.209:4873/registry-auth-token/-/registry-auth-token-5.0.2.tgz", - "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/npm-conf": "^2.1.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/request": { - "version": "2.40.0", - "resolved": "http://94.130.170.209:4873/request/-/request-2.40.0.tgz", - "integrity": "sha512-waNoGB4Z7bPn+lgqPk7l7hhze4Vd68jKccnwLeS7vr9GMxz0iWQbYTbBNWzfIk87Urx7V44pu29qjF/omej+Fw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "license": "Apache-2.0", - "dependencies": { - "forever-agent": "~0.5.0", - "json-stringify-safe": "~5.0.0", - "mime-types": "~1.0.1", - "node-uuid": "~1.4.0", - "qs": "~1.0.0" - }, - "optionalDependencies": { - "aws-sign2": "~0.5.0", - "form-data": "~0.1.0", - "hawk": "1.1.1", - "http-signature": "~0.10.0", - "oauth-sign": "~0.3.0", - "stringstream": "~0.0.4", - "tough-cookie": ">=0.12.0", - "tunnel-agent": "~0.4.0" - } - }, - "node_modules/request/node_modules/async": { - "version": "0.9.2", - "resolved": "http://94.130.170.209:4873/async/-/async-0.9.2.tgz", - "integrity": "sha512-l6ToIJIotphWahxxHyzK9bnLR6kM4jJIIgLShZeqLY7iboHoGkdgFl7W2/Ivi4SkMJYGKqW8vSuk0uKUj6qsSw==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/request/node_modules/combined-stream": { - "version": "0.0.7", - "resolved": "http://94.130.170.209:4873/combined-stream/-/combined-stream-0.0.7.tgz", - "integrity": "sha512-qfexlmLp9MyrkajQVyjEDb0Vj+KhRgR/rxLiVhaihlT+ZkX0lReqtH6Ack40CvMDERR4b5eFp3CreskpBs1Pig==", - "dev": true, - "optional": true, - "dependencies": { - "delayed-stream": "0.0.5" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/request/node_modules/delayed-stream": { - "version": "0.0.5", - "resolved": "http://94.130.170.209:4873/delayed-stream/-/delayed-stream-0.0.5.tgz", - "integrity": "sha512-v+7uBd1pqe5YtgPacIIbZ8HuHeLFVNe4mUEyFDXL6KiqzEykjbw+5mXZXpGFgNVasdL4jWKgaKIXrEHiynN1LA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "0.1.4", - "resolved": "http://94.130.170.209:4873/form-data/-/form-data-0.1.4.tgz", - "integrity": "sha512-x8eE+nzFtAMA0YYlSxf/Qhq6vP1f8wSoZ7Aw1GuctBcmudCNuTUmmx45TfEplyb6cjsZO/jvh6+1VpZn24ez+w==", - "dev": true, - "optional": true, - "dependencies": { - "async": "~0.9.0", - "combined-stream": "~0.0.4", - "mime": "~1.2.11" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/request/node_modules/mime": { - "version": "1.2.11", - "resolved": "http://94.130.170.209:4873/mime/-/mime-1.2.11.tgz", - "integrity": "sha512-Ysa2F/nqTNGHhhm9MV8ure4+Hc+Y8AWiqUdHxsO7xu8zc92ND9f3kpALHjaP026Ft17UfxrMt95c50PLUeynBw==", - "dev": true, - "optional": true - }, - "node_modules/request/node_modules/mime-types": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/mime-types/-/mime-types-1.0.2.tgz", - "integrity": "sha512-echfutj/t5SoTL4WZpqjA1DCud1XO0WQF3/GJ48YBmc4ZMhCK77QA6Z/w6VTQERLKuJ4drze3kw2TUT8xZXVNw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/request/node_modules/qs": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/qs/-/qs-1.0.2.tgz", - "integrity": "sha512-tHuOP9TN/1VmDM/ylApGK1QF3PSIP8I6bHDEfoKNQeViREQ/sfu1bAUrA1hoDun8p8Tpm7jcsz47g+3PiGoYdg==", - "dev": true - }, - "node_modules/request/node_modules/tunnel-agent": { - "version": "0.4.3", - "resolved": "http://94.130.170.209:4873/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha512-e0IoVDWx8SDHc/hwFTqJDQ7CCDTEeGhmcT9jkWJjoGQSpgBz20nAMr80E3Tpk7PatJ1b37DQDgJR3CNSzcMOZQ==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/require-at": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "http://94.130.170.209:4873/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "http://94.130.170.209:4873/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "license": "MIT" - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-path": { - "version": "1.4.0", - "resolved": "http://94.130.170.209:4873/resolve-path/-/resolve-path-1.4.0.tgz", - "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", - "license": "MIT", - "dependencies": { - "http-errors": "~1.6.2", - "path-is-absolute": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/resolve-path/node_modules/depd": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/resolve-path/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "http://94.130.170.209:4873/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/resolve-path/node_modules/inherits": { - "version": "2.0.3", - "resolved": "http://94.130.170.209:4873/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "license": "ISC" - }, - "node_modules/resolve-path/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "license": "ISC" - }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "license": "MIT", - "dependencies": { - "lowercase-keys": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retimeable-signal": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/retimeable-signal/-/retimeable-signal-1.0.1.tgz", - "integrity": "sha512-Cy26CYfbWnYu8HMoJeDhaMpW/EYFIbne3vMf6G9RSrOyWYXbPehja/BEdzpqmM84uy2bfBD7NPZhoQ4GZEtgvg==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/retimer": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/retimer/-/retimer-3.0.0.tgz", - "integrity": "sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==", - "license": "MIT" - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "http://94.130.170.209:4873/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/retry-as-promised": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/retry-as-promised/-/retry-as-promised-3.2.0.tgz", - "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", - "license": "MIT", - "dependencies": { - "any-promise": "^1.3.0" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "http://94.130.170.209:4873/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "http://94.130.170.209:4873/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "http://94.130.170.209:4873/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "http://94.130.170.209:4873/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/sanitize-filename": { - "version": "1.6.3", - "resolved": "http://94.130.170.209:4873/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "license": "WTFPL OR ISC", - "dependencies": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "license": "MIT", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/satoshi-bitcoin": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/satoshi-bitcoin/-/satoshi-bitcoin-1.0.4.tgz", - "integrity": "sha512-YuHOmw5wsz6wuHIQdsz5b2cgtuKtV/jEcZ4NGmWN5tM/gz5T9Q+DSuLlnuf5BP/jsQWgR0ofmY4f8Dm6JnqSug==", - "license": "MIT", - "dependencies": { - "big.js": "^3.1.3" - } - }, - "node_modules/satoshi-bitcoin/node_modules/big.js": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "http://94.130.170.209:4873/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "license": "ISC" - }, - "node_modules/scheduler": { - "version": "0.25.0", - "resolved": "http://94.130.170.209:4873/scheduler/-/scheduler-0.25.0.tgz", - "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", - "license": "MIT", - "peer": true - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "http://94.130.170.209:4873/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/scryptsy": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/scryptsy/-/scryptsy-2.1.0.tgz", - "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==", - "license": "MIT" - }, - "node_modules/secp256k1": { - "version": "3.8.1", - "resolved": "http://94.130.170.209:4873/secp256k1/-/secp256k1-3.8.1.tgz", - "integrity": "sha512-tArjQw2P0RTdY7QmkNehgp6TVvQXq6ulIhxv8gaH6YubKG/wxxAoNKcbuXjDhybbc+b2Ihc7e0xxiGN744UIiQ==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.5.7", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/semantic-release": { - "version": "19.0.3", - "resolved": "http://94.130.170.209:4873/semantic-release/-/semantic-release-19.0.3.tgz", - "integrity": "sha512-HaFbydST1cDKZHuFZxB8DTrBLJVK/AnDExpK0s3EqLIAAUAHUgnd+VSJCUtTYQKkAkauL8G9CucODrVCc7BuAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@semantic-release/commit-analyzer": "^9.0.2", - "@semantic-release/error": "^3.0.0", - "@semantic-release/github": "^8.0.0", - "@semantic-release/npm": "^9.0.0", - "@semantic-release/release-notes-generator": "^10.0.0", - "aggregate-error": "^3.0.0", - "cosmiconfig": "^7.0.0", - "debug": "^4.0.0", - "env-ci": "^5.0.0", - "execa": "^5.0.0", - "figures": "^3.0.0", - "find-versions": "^4.0.0", - "get-stream": "^6.0.0", - "git-log-parser": "^1.2.0", - "hook-std": "^2.0.0", - "hosted-git-info": "^4.0.0", - "lodash": "^4.17.21", - "marked": "^4.0.10", - "marked-terminal": "^5.0.0", - "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "p-reduce": "^2.0.0", - "read-pkg-up": "^7.0.0", - "resolve-from": "^5.0.0", - "semver": "^7.3.2", - "semver-diff": "^3.1.1", - "signale": "^1.2.1", - "yargs": "^16.2.0" - }, - "bin": { - "semantic-release": "bin/semantic-release.js" - }, - "engines": { - "node": ">=16 || ^14.17" - } - }, - "node_modules/semantic-release/node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release/node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/semantic-release/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/semantic-release/node_modules/execa": { - "version": "5.1.1", - "resolved": "http://94.130.170.209:4873/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/semantic-release/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/semantic-release/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/semantic-release/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release/node_modules/onetime": { - "version": "5.1.2", - "resolved": "http://94.130.170.209:4873/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "http://94.130.170.209:4873/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "license": "MIT" - }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.1", - "resolved": "http://94.130.170.209:4873/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-regex": { - "version": "3.1.4", - "resolved": "http://94.130.170.209:4873/semver-regex/-/semver-regex-3.1.4.tgz", - "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "http://94.130.170.209:4873/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "peer": true, - "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": "http://94.130.170.209:4873/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "peer": true, - "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/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "http://94.130.170.209:4873/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "peer": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/sequelize": { - "version": "5.22.5", - "resolved": "http://94.130.170.209:4873/sequelize/-/sequelize-5.22.5.tgz", - "integrity": "sha512-ySIHof18sJbeVG4zjEvsDL490cd9S14/IhkCrZR/g0C/FPlZq1AzEJVeSAo++9/sgJH2eERltAIGqYQNgVqX/A==", - "deprecated": "Please update to v6 or higher! A migration guide can be found here: https://sequelize.org/v6/manual/upgrade-to-v6.html", - "license": "MIT", - "dependencies": { - "bluebird": "^3.5.0", - "cls-bluebird": "^2.1.0", - "debug": "^4.1.1", - "dottie": "^2.0.0", - "inflection": "1.12.0", - "lodash": "^4.17.15", - "moment": "^2.24.0", - "moment-timezone": "^0.5.21", - "retry-as-promised": "^3.2.0", - "semver": "^6.3.0", - "sequelize-pool": "^2.3.0", - "toposort-class": "^1.0.1", - "uuid": "^8.3.2", - "validator": "^13.7.0", - "wkx": "^0.4.8" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/sequelize-pool": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/sequelize-pool/-/sequelize-pool-2.3.0.tgz", - "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==", - "license": "MIT", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/sequelize/node_modules/debug": { - "version": "4.3.7", - "resolved": "http://94.130.170.209:4873/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/sequelize/node_modules/semver": { - "version": "6.3.1", - "resolved": "http://94.130.170.209:4873/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-error": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/serialize-error/-/serialize-error-2.1.0.tgz", - "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serialize-javascript/node_modules/randombytes": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "http://94.130.170.209:4873/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "peer": true, - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "http://94.130.170.209:4873/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "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/set-function-name": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "http://94.130.170.209:4873/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "http://94.130.170.209:4873/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "license": "(MIT AND BSD-3-Clause)", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "license": "MIT", - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "http://94.130.170.209:4873/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "http://94.130.170.209:4873/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "license": "MIT", - "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/sift": { - "version": "13.5.2", - "resolved": "http://94.130.170.209:4873/sift/-/sift-13.5.2.tgz", - "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==", - "license": "MIT" - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "http://94.130.170.209:4873/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/signale": { - "version": "1.4.0", - "resolved": "http://94.130.170.209:4873/signale/-/signale-1.4.0.tgz", - "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^2.3.2", - "figures": "^2.0.0", - "pkg-conf": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/signale/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "http://94.130.170.209:4873/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/signale/node_modules/chalk": { - "version": "2.4.2", - "resolved": "http://94.130.170.209:4873/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/signale/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "http://94.130.170.209:4873/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/signale/node_modules/color-name": { - "version": "1.1.3", - "resolved": "http://94.130.170.209:4873/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/signale/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/signale/node_modules/figures": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/signale/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/signale/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "http://94.130.170.209:4873/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "http://94.130.170.209:4873/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "http://94.130.170.209:4873/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT" - }, - "node_modules/simple-update-notifier": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", - "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", - "license": "MIT", - "dependencies": { - "semver": "~7.0.0" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.0.0", - "resolved": "http://94.130.170.209:4873/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/sinon": { - "version": "9.2.4", - "resolved": "http://94.130.170.209:4873/sinon/-/sinon-9.2.4.tgz", - "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", - "deprecated": "16.1.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "http://94.130.170.209:4873/@sinonjs%2fcommons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/sinon/node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "http://94.130.170.209:4873/@sinonjs%2ffake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "http://94.130.170.209:4873/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/sliced": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==", - "license": "MIT" - }, - "node_modules/slp-mdm": { - "version": "0.0.6", - "resolved": "http://94.130.170.209:4873/slp-mdm/-/slp-mdm-0.0.6.tgz", - "integrity": "sha512-fbjlIg/o8OtzgK2JydC6POJp3Qup/rLgy4yB5hoLgxWRlERyJyE29ScwS3r9TTwPxe12qK55pyivAdNOZZXL0A==", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/slp-parser": { - "version": "0.0.4", - "resolved": "http://94.130.170.209:4873/slp-parser/-/slp-parser-0.0.4.tgz", - "integrity": "sha512-AvbslJumkzGfMGWNvuE2pWx2nyHEk/VgQ7l119kDKIFRTuRUWOkyOULLauw5laGRQsBRThg6NCx/TsR3grX6GA==", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/sntp": { - "version": "0.2.4", - "resolved": "http://94.130.170.209:4873/sntp/-/sntp-0.2.4.tgz", - "integrity": "sha512-bDLrKa/ywz65gCl+LmOiIhteP1bhEsAAzhfMedPoiHP3dyYnAevlaJshdqb9Yu0sRifyP/fRqSt8t+5qGIWlGQ==", - "deprecated": "This module moved to @hapi/sntp. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.", - "dev": true, - "optional": true, - "dependencies": { - "hoek": "0.9.x" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "license": "MIT" - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "http://94.130.170.209:4873/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "http://94.130.170.209:4873/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sparse-array": { - "version": "1.3.2", - "resolved": "http://94.130.170.209:4873/sparse-array/-/sparse-array-1.3.2.tgz", - "integrity": "sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==", - "license": "ISC" - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "http://94.130.170.209:4873/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spawn-error-forwarder": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", - "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", - "dev": true, - "license": "MIT" - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "http://94.130.170.209:4873/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "http://94.130.170.209:4873/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "http://94.130.170.209:4873/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "http://94.130.170.209:4873/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "license": "ISC", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "http://94.130.170.209:4873/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "http://94.130.170.209:4873/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "http://94.130.170.209:4873/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", - "license": "MIT", - "peer": true - }, - "node_modules/stacktrace-parser": { - "version": "0.1.11", - "resolved": "http://94.130.170.209:4873/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", - "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", - "license": "MIT", - "peer": true, - "dependencies": { - "type-fest": "^0.7.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/stacktrace-parser/node_modules/type-fest": { - "version": "0.7.1", - "resolved": "http://94.130.170.209:4873/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/standard": { - "version": "17.0.0", - "resolved": "http://94.130.170.209:4873/standard/-/standard-17.0.0.tgz", - "integrity": "sha512-GlCM9nzbLUkr+TYR5I2WQoIah4wHA2lMauqbyPLV/oI5gJxqhHzhjl9EG2N0lr/nRqI3KCbCvm/W3smxvLaChA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "eslint": "^8.13.0", - "eslint-config-standard": "17.0.0", - "eslint-config-standard-jsx": "^11.0.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-n": "^15.1.0", - "eslint-plugin-promise": "^6.0.0", - "eslint-plugin-react": "^7.28.0", - "standard-engine": "^15.0.0" - }, - "bin": { - "standard": "bin/cmd.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/standard-engine": { - "version": "15.1.0", - "resolved": "http://94.130.170.209:4873/standard-engine/-/standard-engine-15.1.0.tgz", - "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "get-stdin": "^8.0.0", - "minimist": "^1.2.6", - "pkg-conf": "^3.1.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/standard-engine/node_modules/find-up": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/standard-engine/node_modules/load-json-file": { - "version": "5.3.0", - "resolved": "http://94.130.170.209:4873/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/standard-engine/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/standard-engine/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-engine/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/standard-engine/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/standard-engine/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/standard-engine/node_modules/pify": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/standard-engine/node_modules/pkg-conf": { - "version": "3.1.0", - "resolved": "http://94.130.170.209:4873/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/standard-engine/node_modules/type-fest": { - "version": "0.3.1", - "resolved": "http://94.130.170.209:4873/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=6" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "http://94.130.170.209:4873/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/steno": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/steno/-/steno-4.0.2.tgz", - "integrity": "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "license": "MIT", - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/stream-combiner2": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-combiner2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/stream-combiner2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "http://94.130.170.209:4873/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/stream-combiner2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/stream-to-it": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/stream-to-it/-/stream-to-it-1.0.1.tgz", - "integrity": "sha512-AqHYAYPHcmvMrcLNgncE/q0Aj/ajP6A4qGhxP6EVn7K3YTNs0bJpJyk57wc2Heb7MUL64jurvmnmui8D9kjZgA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-stream-types": "^2.0.1" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "http://94.130.170.209:4873/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "http://94.130.170.209:4873/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" - } - ], - "license": "MIT" - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "http://94.130.170.209:4873/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "http://94.130.170.209:4873/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", - "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "http://94.130.170.209:4873/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "http://94.130.170.209:4873/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "http://94.130.170.209:4873/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stringstream": { - "version": "0.0.6", - "resolved": "http://94.130.170.209:4873/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "http://94.130.170.209:4873/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-loader": { - "version": "3.3.4", - "resolved": "http://94.130.170.209:4873/style-loader/-/style-loader-3.3.4.tgz", - "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", - "license": "MIT", - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/super-regex": { - "version": "0.2.0", - "resolved": "http://94.130.170.209:4873/super-regex/-/super-regex-0.2.0.tgz", - "integrity": "sha512-WZzIx3rC1CvbMDloLsVw0lkZVKJWbrkJ0k1ghKFmcnPrW1+jWbgTkTEWVtD9lMdmI4jZEz40+naBxl1dCUhXXw==", - "license": "MIT", - "dependencies": { - "clone-regexp": "^3.0.0", - "function-timeout": "^0.1.0", - "time-span": "^5.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "http://94.130.170.209:4873/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "http://94.130.170.209:4873/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "http://94.130.170.209:4873/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/tape": { - "version": "5.9.0", - "resolved": "http://94.130.170.209:4873/tape/-/tape-5.9.0.tgz", - "integrity": "sha512-czbGgxSVwRlbB3Ly/aqQrNwrDAzKHDW/kVXegp4hSFmR2c8qqm3hCgZbUy1+3QAQFGhPDG7J56UsV1uNilBFCA==", - "license": "MIT", - "dependencies": { - "@ljharb/resumer": "^0.1.3", - "@ljharb/through": "^2.3.13", - "array.prototype.every": "^1.1.6", - "call-bind": "^1.0.7", - "deep-equal": "^2.2.3", - "defined": "^1.0.1", - "dotignore": "^0.1.2", - "for-each": "^0.3.3", - "get-package-type": "^0.1.0", - "glob": "^7.2.3", - "has-dynamic-import": "^2.1.0", - "hasown": "^2.0.2", - "inherits": "^2.0.4", - "is-regex": "^1.1.4", - "minimist": "^1.2.8", - "mock-property": "^1.1.0", - "object-inspect": "^1.13.2", - "object-is": "^1.1.6", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "resolve": "^2.0.0-next.5", - "string.prototype.trim": "^1.2.9" - }, - "bin": { - "tape": "bin/tape" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tape/node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "http://94.130.170.209:4873/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tape/node_modules/glob": { - "version": "7.2.3", - "resolved": "http://94.130.170.209:4873/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/tape/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "http://94.130.170.209:4873/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar-fs": { - "version": "2.1.2", - "resolved": "http://94.130.170.209:4873/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", - "license": "MIT", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "http://94.130.170.209:4873/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "license": "MIT", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/node_modules/bl": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/tar-stream/node_modules/buffer": { - "version": "5.7.1", - "resolved": "http://94.130.170.209:4873/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/tempy": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/tempy/-/tempy-1.0.1.tgz", - "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "del": "^6.0.0", - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/type-fest": { - "version": "0.16.0", - "resolved": "http://94.130.170.209:4873/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terser": { - "version": "5.36.0", - "resolved": "http://94.130.170.209:4873/terser/-/terser-5.36.0.tgz", - "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "http://94.130.170.209:4873/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "http://94.130.170.209:4873/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/randombytes": { - "version": "2.1.0", - "resolved": "http://94.130.170.209:4873/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "http://94.130.170.209:4873/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "http://94.130.170.209:4873/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "http://94.130.170.209:4873/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "http://94.130.170.209:4873/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/text-hex": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "license": "MIT" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "http://94.130.170.209:4873/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/throat": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/throat/-/throat-5.0.0.tgz", - "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", - "license": "MIT", - "peer": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "http://94.130.170.209:4873/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "http://94.130.170.209:4873/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "http://94.130.170.209:4873/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "license": "MIT" - }, - "node_modules/time-span": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/time-span/-/time-span-5.1.0.tgz", - "integrity": "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==", - "license": "MIT", - "dependencies": { - "convert-hrtime": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/timeout-abort-controller": { - "version": "3.0.0", - "resolved": "http://94.130.170.209:4873/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz", - "integrity": "sha512-O3e+2B8BKrQxU2YRyEjC/2yFdb33slI22WRdUaDx6rvysfi9anloNZyR2q0l6LnePo5qH7gSM7uZtvvwZbc2yA==", - "license": "MIT", - "dependencies": { - "retimer": "^3.0.0" - } - }, - "node_modules/timestamp-nano": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/timestamp-nano/-/timestamp-nano-1.0.1.tgz", - "integrity": "sha512-4oGOVZWTu5sl89PtCDnhQBSt7/vL1zVEwAfxH1p49JhTosxzVQWYBYFRFZ8nJmo0G6f824iyP/44BFAwIoKvIA==", - "license": "MIT", - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/tldts": { - "version": "6.1.63", - "resolved": "http://94.130.170.209:4873/tldts/-/tldts-6.1.63.tgz", - "integrity": "sha512-YWwhsjyn9sB/1rOkSRYxvkN/wl5LFM1QDv6F2pVR+pb/jFne4EOBxHfkKVWvDIBEAw9iGOwwubHtQTm0WRT5sQ==", - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.63" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "6.1.63", - "resolved": "http://94.130.170.209:4873/tldts-core/-/tldts-core-6.1.63.tgz", - "integrity": "sha512-H1XCt54xY+QPbwhTgmxLkepX0MVHu3USfMmejiCOdkMbRcP22Pn2FVF127r/GWXVDmXTRezyF3Ckvhn4Fs6j7Q==", - "license": "MIT" - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "http://94.130.170.209:4873/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/toposort-class": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==", - "license": "MIT" - }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", - "license": "ISC", - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "http://94.130.170.209:4873/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/traverse": { - "version": "0.6.8", - "resolved": "http://94.130.170.209:4873/traverse/-/traverse-0.6.8.tgz", - "integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "http://94.130.170.209:4873/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", - "license": "MIT", - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", - "license": "WTFPL", - "dependencies": { - "utf8-byte-length": "^1.0.1" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "http://94.130.170.209:4873/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "http://94.130.170.209:4873/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsscmp": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", - "license": "MIT", - "engines": { - "node": ">=0.6.x" - } - }, - "node_modules/tsyringe": { - "version": "4.9.1", - "resolved": "http://94.130.170.209:4873/tsyringe/-/tsyringe-4.9.1.tgz", - "integrity": "sha512-dJCWk0RolAnGk0j839M0lcuS/PtNUPaMsnBosn+wg5N16xy0tofcVuvsidMs0JuRbaJ0wVIT7RsuHWbVIZ5Rcg==", - "license": "MIT", - "dependencies": { - "tslib": "^1.9.3" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/tsyringe/node_modules/tslib": { - "version": "1.14.1", - "resolved": "http://94.130.170.209:4873/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "http://94.130.170.209:4873/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "http://94.130.170.209:4873/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "http://94.130.170.209:4873/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.18.1", - "resolved": "http://94.130.170.209:4873/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "http://94.130.170.209:4873/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.3", - "resolved": "http://94.130.170.209:4873/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", - "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "http://94.130.170.209:4873/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "license": "MIT", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "http://94.130.170.209:4873/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==", - "license": "MIT" - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "http://94.130.170.209:4873/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "http://94.130.170.209:4873/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "http://94.130.170.209:4873/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "license": "MIT", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uint8-varint": { - "version": "2.0.4", - "resolved": "http://94.130.170.209:4873/uint8-varint/-/uint8-varint-2.0.4.tgz", - "integrity": "sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/uint8arraylist": { - "version": "2.4.8", - "resolved": "http://94.130.170.209:4873/uint8arraylist/-/uint8arraylist-2.4.8.tgz", - "integrity": "sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arrays": "^5.0.1" - } - }, - "node_modules/uint8arrays": { - "version": "5.1.0", - "resolved": "http://94.130.170.209:4873/uint8arrays/-/uint8arrays-5.1.0.tgz", - "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^13.0.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "http://94.130.170.209:4873/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "license": "MIT" - }, - "node_modules/underscore": { - "version": "1.7.0", - "resolved": "http://94.130.170.209:4873/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==", - "dev": true - }, - "node_modules/underscore.string": { - "version": "2.4.0", - "resolved": "http://94.130.170.209:4873/underscore.string/-/underscore.string-2.4.0.tgz", - "integrity": "sha512-yxkabuCaIBnzfIvX3kBxQqCs0ar/bfJwDnFEHJUm/ZrRVhT3IItdRF5cZjARLzEnyQYtIUhsZ2LG2j3HidFOFQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/undici": { - "version": "5.28.4", - "resolved": "http://94.130.170.209:4873/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "license": "MIT", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "http://94.130.170.209:4873/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "license": "MIT" - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.1", - "resolved": "http://94.130.170.209:4873/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "http://94.130.170.209:4873/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "http://94.130.170.209:4873/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "http://94.130.170.209:4873/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true, - "license": "MIT" - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "http://94.130.170.209:4873/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/utf8-byte-length": { - "version": "1.0.5", - "resolved": "http://94.130.170.209:4873/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "license": "(WTFPL OR MIT)" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "http://94.130.170.209:4873/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "http://94.130.170.209:4873/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "http://94.130.170.209:4873/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/validator": { - "version": "13.12.0", - "resolved": "http://94.130.170.209:4873/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/varint": { - "version": "6.0.0", - "resolved": "http://94.130.170.209:4873/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "license": "MIT" - }, - "node_modules/varuint-bitcoin": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", - "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "http://94.130.170.209:4873/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vlq": { - "version": "1.0.1", - "resolved": "http://94.130.170.209:4873/vlq/-/vlq-1.0.1.tgz", - "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", - "license": "MIT", - "peer": true - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "http://94.130.170.209:4873/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "http://94.130.170.209:4873/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/weald": { - "version": "1.0.4", - "resolved": "http://94.130.170.209:4873/weald/-/weald-1.0.4.tgz", - "integrity": "sha512-+kYTuHonJBwmFhP1Z4YQK/dGi3jAnJGCYhyODFpHK73rbxnp9lnZQj7a2m+WVgn8fXr5bJaxUpF6l8qZpPeNWQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "ms": "^3.0.0-canary.1", - "supports-color": "^9.4.0" - } - }, - "node_modules/weald/node_modules/ms": { - "version": "3.0.0-canary.1", - "resolved": "http://94.130.170.209:4873/ms/-/ms-3.0.0-canary.1.tgz", - "integrity": "sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g==", - "license": "MIT", - "engines": { - "node": ">=12.13" - } - }, - "node_modules/weald/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "http://94.130.170.209:4873/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/webcrypto-core": { - "version": "1.8.1", - "resolved": "http://94.130.170.209:4873/webcrypto-core/-/webcrypto-core-1.8.1.tgz", - "integrity": "sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.13", - "@peculiar/json-schema": "^1.1.12", - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.5", - "tslib": "^2.7.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "http://94.130.170.209:4873/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/webpack": { - "version": "5.96.1", - "resolved": "http://94.130.170.209:4873/webpack/-/webpack-5.96.1.tgz", - "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.10.0", - "resolved": "http://94.130.170.209:4873/webpack-cli/-/webpack-cli-4.10.0.tgz", - "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", - "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "cross-spawn": "^7.0.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "http://94.130.170.209:4873/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "http://94.130.170.209:4873/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "http://94.130.170.209:4873/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "license": "MIT", - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "http://94.130.170.209:4873/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "http://94.130.170.209:4873/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "http://94.130.170.209:4873/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/whatwg-fetch": { - "version": "3.6.20", - "resolved": "http://94.130.170.209:4873/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", - "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", - "license": "MIT", - "peer": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "http://94.130.170.209:4873/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wherearewe": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/wherearewe/-/wherearewe-2.0.1.tgz", - "integrity": "sha512-XUguZbDxCA2wBn2LoFtcEhXL6AXo+hVjGonwhSTTTU9SzbWG8Xu3onNIpzf9j/mYUcJQ0f+m37SzG77G851uFw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "is-electron": "^2.2.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "http://94.130.170.209:4873/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.4", - "resolved": "http://94.130.170.209:4873/which-builtin-type/-/which-builtin-type-1.1.4.tgz", - "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", - "license": "MIT", - "dependencies": { - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-pm-runs": { - "version": "1.1.0", - "resolved": "http://94.130.170.209:4873/which-pm-runs/-/which-pm-runs-1.1.0.tgz", - "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "http://94.130.170.209:4873/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "license": "MIT", - "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/wif": { - "version": "2.0.6", - "resolved": "http://94.130.170.209:4873/wif/-/wif-2.0.6.tgz", - "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", - "license": "MIT", - "dependencies": { - "bs58check": "<3.0.0" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "license": "MIT" - }, - "node_modules/winston": { - "version": "3.3.3", - "resolved": "http://94.130.170.209:4873/winston/-/winston-3.3.3.tgz", - "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", - "license": "MIT", - "dependencies": { - "@dabh/diagnostics": "^2.0.2", - "async": "^3.1.0", - "is-stream": "^2.0.0", - "logform": "^2.2.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" - }, - "engines": { - "node": ">= 6.4.0" - } - }, - "node_modules/winston-daily-rotate-file": { - "version": "4.5.0", - "resolved": "http://94.130.170.209:4873/winston-daily-rotate-file/-/winston-daily-rotate-file-4.5.0.tgz", - "integrity": "sha512-/HqeWiU48dzGqcrABRlxYWVMdL6l3uKCtFSJyrqK+E2rLnSFNsgYpvwx15EgTitBLNzH69lQd/+z2ASryV2aqw==", - "license": "MIT", - "dependencies": { - "file-stream-rotator": "^0.5.7", - "object-hash": "^2.0.1", - "triple-beam": "^1.3.0", - "winston-transport": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "winston": "^3" - } - }, - "node_modules/winston-transport": { - "version": "4.9.0", - "resolved": "http://94.130.170.209:4873/winston-transport/-/winston-transport-4.9.0.tgz", - "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", - "license": "MIT", - "dependencies": { - "logform": "^2.7.0", - "readable-stream": "^3.6.2", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/winston/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "http://94.130.170.209:4873/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wkx": { - "version": "0.4.8", - "resolved": "http://94.130.170.209:4873/wkx/-/wkx-0.4.8.tgz", - "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "http://94.130.170.209:4873/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "http://94.130.170.209:4873/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "license": "MIT" - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "http://94.130.170.209:4873/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "http://94.130.170.209:4873/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "http://94.130.170.209:4873/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "license": "ISC", - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "http://94.130.170.209:4873/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "license": "MIT", - "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/xdg-basedir": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "http://94.130.170.209:4873/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "http://94.130.170.209:4873/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "http://94.130.170.209:4873/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "http://94.130.170.209:4873/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "http://94.130.170.209:4873/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC", - "peer": true - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "http://94.130.170.209:4873/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "http://94.130.170.209:4873/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "http://94.130.170.209:4873/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "http://94.130.170.209:4873/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "http://94.130.170.209:4873/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "http://94.130.170.209:4873/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ylru": { - "version": "1.4.0", - "resolved": "http://94.130.170.209:4873/ylru/-/ylru-1.4.0.tgz", - "integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==", - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "http://94.130.170.209:4873/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/swarm.key b/swarm.key deleted file mode 100644 index 6cd0b83..0000000 --- a/swarm.key +++ /dev/null @@ -1,3 +0,0 @@ -/key/swarm/psk/1.0.0/ -/base16/ -bbd935b70105b03ebd0c6a3c2d2730cd22fc0d18c490ccf689b6c8a22e1bed2a \ No newline at end of file