diff --git a/.dockerignore b/.dockerignore index df936e24..641b6d71 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ -./node_modules -./new-lamassu-admin/node_modules +**/node_modules .git .direnv .envrc \ No newline at end of file diff --git a/.gitignore b/.gitignore index da50d714..8bf015e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,9 @@ -node_modules +**/node_modules +**/.env .idea/ .settings/ -certs/ -tests/stress/machines -tests/stress/config.json - -.env +packages/server/certs/ +packages/server/tests/stress/machines +packages/server/tests/stress/config.json diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..d24fdfc6 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged diff --git a/new-lamassu-admin/.prettierrc b/.prettierrc similarity index 80% rename from new-lamassu-admin/.prettierrc rename to .prettierrc index fe83baaf..bf93fdb8 100644 --- a/new-lamassu-admin/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { - "trailingComma": "none", + "trailingComma": "all", "tabWidth": 2, "semi": false, "singleQuote": true, diff --git a/INSTALL-NIX.md b/INSTALL-NIX.md index da3994b6..34805b49 100644 --- a/INSTALL-NIX.md +++ b/INSTALL-NIX.md @@ -11,7 +11,7 @@ sudo -u postgres createdb lamassu sudo -u postgres psql postgres ``` -In ``psql``, run the following and set password to ``postgres123``: +In `psql`, run the following and set password to `postgres123`: ``` \password postgres @@ -20,14 +20,12 @@ ctrl-d ### Starting up environment -shell.nix script provided, all you need to do to setup the environment is to run `nix-shell` on the folder. +shell.nix script provided, all you need to do to setup the environment is to run `nix-shell` on the folder. ## Installation ### Install node modules -Make sure you're running NodeJS 8.3 or higher. Ignore any warnings. - ``` npm install ``` @@ -35,25 +33,25 @@ npm install ### Generate certificates ``` -bash tools/cert-gen.sh +bash packages/server/tools/cert-gen.sh ``` -Notes: - - This will create a ``.lamassu`` directory in your home directory. - +Notes: + +- This will create a `.lamassu` directory in your home directory. + ### Set up database Important: lamassu-migrate currently gripes about a QueryResultError. Ignore this, it works anyway. ``` -node bin/lamassu-migrate +node packages/server/bin/lamassu-migrate ``` ### Run new-lamassu-admin ``` -cd new-lamassu-admin/ -npm install +cd packages/admin-ui/ npm run start ``` @@ -62,7 +60,7 @@ npm run start In a second terminal window: ``` -node bin/lamassu-admin-server --dev +node packages/server/bin/lamassu-admin-server --dev ``` ### Register admin user @@ -70,7 +68,7 @@ node bin/lamassu-admin-server --dev In a third terminal window: ``` -node bin/lamassu-register admin@example.com superuser +node packages/server/bin/lamassu-register admin@example.com superuser ``` You'll use this generated URL in the brower in a moment. @@ -86,32 +84,32 @@ Go to all the required, unconfigured red fields and choose some values. Choose m ### Run lamassu-server ``` -node bin/lamassu-server --mockScoring +node packages/server/bin/lamassu-server --mockScoring ``` ### Add a lamassu-machine -Click on ``+ Add Machine`` in the sidebar. Type in a name for your machine and click **Pair**. Open up development tools to show the JavaScript console and copy the totem. You will use this to run lamassu-machine. This pairing totem expires after an hour. +Click on `+ Add Machine` in the sidebar. Type in a name for your machine and click **Pair**. Open up development tools to show the JavaScript console and copy the totem. You will use this to run lamassu-machine. This pairing totem expires after an hour. -Now continue with lamassu-machine instructions from the ``INSTALL.md`` file in [lamassu-machine repository](https://github.com/lamassu/lamassu-machine). +Now continue with lamassu-machine instructions from the `INSTALL.md` file in [lamassu-machine repository](https://github.com/lamassu/lamassu-machine). ## Subsequent runs To start the Lamassu server run: ``` -node bin/lamassu-server --mockScoring +node packages/server/bin/lamassu-server --mockScoring ``` To start the Lamassu Admin run: ``` -node bin/lamassu-admin-server --dev +node packages/server/bin/lamassu-admin-server --dev ``` and ``` -cd new-lamassu-admin/ +cd packages/admin-ui/ npm run start ``` diff --git a/INSTALL.md b/INSTALL.md index 20a7b663..bc703d4c 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -2,7 +2,7 @@ ## Preliminaries for Ubuntu 16.04 -Installation for other distros may be slightly different. This assumes NodeJS 8.3 or higher and npm 5.6 are already installed. All of this is done in the lamassu-server directory. +Installation for other distros may be slightly different. This assumes NodeJS 22 or higher is already installed. All of this is done in the lamassu-server directory. ### Packages @@ -18,33 +18,18 @@ sudo -u postgres createdb lamassu sudo -u postgres psql postgres ``` -In ``psql``, run the following and set password to ``postgres123``: +In `psql`, run the following and set password to `postgres123`: ``` \password postgres ctrl-d ``` -## Preliminaries for MacOS - -### Postgres - -Use Postgres.app: https://postgresapp.com/ - -**psql** is automatically installed. You won't need to set up users. - -### NodeJS - -``` -curl -L https://git.io/n-install | bash -s -- -y lts -. ~/.bash_profile -``` - ## Installation ### Install node modules -Make sure you're running NodeJS 8.3 or higher. Ignore any warnings. +Make sure you're running NodeJS 22 or higher. Ignore any warnings. ``` npm install @@ -53,25 +38,25 @@ npm install ### Generate certificates ``` -bash tools/cert-gen.sh +bash packages/server/tools/cert-gen.sh ``` -Notes: - - This will create a ``.lamassu`` directory in your home directory. - +Notes: + +- This will create a `.lamassu` directory in your home directory. + ### Set up database Important: lamassu-migrate currently gripes about a QueryResultError. Ignore this, it works anyway. ``` -node bin/lamassu-migrate +node packages/server/bin/lamassu-migrate ``` ### Run new-lamassu-admin ``` -cd new-lamassu-admin/ -npm install +cd packages/admin-ui/ npm run start ``` @@ -80,7 +65,7 @@ npm run start In a second terminal window: ``` -node bin/lamassu-admin-server --dev +node packages/server/bin/lamassu-admin-server --dev ``` ### Register admin user @@ -88,7 +73,7 @@ node bin/lamassu-admin-server --dev In a third terminal window: ``` -node bin/lamassu-register admin@example.com superuser +node packages/server/bin/lamassu-register admin@example.com superuser ``` You'll use this generated URL in the brower in a moment. @@ -104,39 +89,38 @@ Go to all the required, unconfigured red fields and choose some values. Choose m ### Run lamassu-server ``` -node bin/lamassu-server --mockScoring +node packages/server/bin/lamassu-server --mockScoring ``` ### Add a lamassu-machine -Click on ``+ Add Machine`` in the sidebar. Type in a name for your machine and click **Pair**. Open up development tools to show the JavaScript console and copy the totem. You will use this to run lamassu-machine. This pairing totem expires after an hour. +Click on `+ Add Machine` in the sidebar. Type in a name for your machine and click **Pair**. Open up development tools to show the JavaScript console and copy the totem. You will use this to run lamassu-machine. This pairing totem expires after an hour. -Now continue with lamassu-machine instructions from the ``INSTALL.md`` file in [lamassu-machine repository](https://github.com/lamassu/lamassu-machine). +Now continue with lamassu-machine instructions from the `INSTALL.md` file in [lamassu-machine repository](https://github.com/lamassu/lamassu-machine). ### Run a local coin node (BTC supported) -Run `node bin/lamassu-coins` in the project root and select `Bitcoin`. This process will require the existence of certain environment variables that the setup will warn about. +Run `node packages/server/bin/lamassu-coins` in the project root and select `Bitcoin`. This process will require the existence of certain environment variables that the setup will warn about. Once that is done, the node needs to be run in a terminal with the following command `/bin/bitcoind -datadir=/bitcoin` - ## Subsequent runs To start the Lamassu server run: ``` -node bin/lamassu-server --mockScoring +node packages/server/bin/lamassu-server --mockScoring ``` To start the Lamassu Admin run: ``` -node bin/lamassu-admin-server --dev +node packages/server/bin/lamassu-admin-server --dev ``` and ``` -cd new-lamassu-admin/ +cd packages/admin-ui/ npm run start ``` diff --git a/build/ci.Dockerfile b/build/ci.Dockerfile index 00ad853f..c29cf99a 100644 --- a/build/ci.Dockerfile +++ b/build/ci.Dockerfile @@ -1,3 +1,14 @@ +FROM node:22-alpine AS build-ui +RUN apk add --no-cache npm git curl build-base python3 + +COPY ["packages/admin-ui/package.json", "package-lock.json", "./"] + +RUN npm version --allow-same-version --git-tag-version false --commit-hooks false 1.0.0 +RUN npm install + +COPY packages/admin-ui/ ./ +RUN npm run build + FROM ubuntu:20.04 as base ARG VERSION @@ -20,14 +31,11 @@ RUN apt-get install nodejs -y -q WORKDIR lamassu-server -COPY ["package.json", "package-lock.json", "./"] +COPY ["packages/server/package.json", "package-lock.json", "./"] RUN npm version --allow-same-version --git-tag-version false --commit-hooks false 1.0.0 RUN npm install --production -COPY . ./ - -RUN cd new-lamassu-admin && npm install && npm run build -RUN mv new-lamassu-admin/build public/ -RUN rm -rf new-lamassu-admin/node_modules +COPY ./packages/server/ ./ +COPY --from=build-ui /build /lamassu-server/public RUN cd .. && tar -zcvf lamassu-server.tar.gz ./lamassu-server \ No newline at end of file diff --git a/build/server.Dockerfile b/build/server.Dockerfile index f28b8340..308e2f1e 100644 --- a/build/server.Dockerfile +++ b/build/server.Dockerfile @@ -3,11 +3,11 @@ RUN apk add --no-cache npm git curl build-base net-tools python3 postgresql-dev WORKDIR /lamassu-server -COPY ["package.json", "package-lock.json", "./"] +COPY ["packages/server/package.json", "package-lock.json", "./"] RUN npm version --allow-same-version --git-tag-version false --commit-hooks false 1.0.0 RUN npm install --production -COPY . ./ +COPY packages/server/ ./ FROM node:22-alpine AS l-s-base @@ -30,12 +30,12 @@ RUN apk add --no-cache npm git curl build-base python3 WORKDIR /app -COPY ["new-lamassu-admin/package.json", "new-lamassu-admin/package-lock.json", "./"] +COPY ["packages/admin-ui/package.json", "package-lock.json", "./"] RUN npm version --allow-same-version --git-tag-version false --commit-hooks false 1.0.0 RUN npm install -COPY new-lamassu-admin/ ./ +COPY packages/admin-ui/ ./ RUN npm run build @@ -46,4 +46,4 @@ RUN chmod +x /lamassu-server/bin/lamassu-admin-server-entrypoint.sh EXPOSE 443 -ENTRYPOINT [ "/lamassu-server/bin/lamassu-admin-server-entrypoint.sh" ] +ENTRYPOINT [ "/lamassu-server/bin/lamassu-admin-server-entrypoint.sh" ] \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..deb07af4 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,74 @@ +import js from '@eslint/js' +import globals from 'globals' +import pluginReact from 'eslint-plugin-react' +import json from '@eslint/json' +import { defineConfig, globalIgnores } from 'eslint/config' +import reactCompiler from 'eslint-plugin-react-compiler' +import eslintConfigPrettier from 'eslint-config-prettier/flat' +import pluginJest from 'eslint-plugin-jest' + +export default defineConfig([ + globalIgnores([ + '**/build', + '**/package.json', + '**/package-lock.json', + '**/currencies.json', + '**/countries.json', + '**/languages.json', + ]), + { + files: ['**/*.{js,mjs,cjs,jsx}'], + plugins: { js }, + extends: ['js/recommended'], + }, + { + files: ['packages/admin-ui/**/*.{js,mjs,jsx}'], + languageOptions: { + sourceType: 'module', + globals: { + ...globals.browser, + process: 'readonly', + }, + }, + }, + { + files: ['packages/server/**/*.{js,cjs}'], + languageOptions: { sourceType: 'commonjs', globals: globals.node }, + }, + { + ...pluginReact.configs.flat.recommended, + settings: { react: { version: 'detect' } }, + files: ['packages/admin-ui/**/*.{jsx,js}'], + }, + { ...reactCompiler.configs.recommended }, + eslintConfigPrettier, + { + files: ['**/*.json'], + plugins: { json }, + language: 'json/json', + extends: ['json/recommended'], + }, + { + rules: { + 'react/prop-types': 'off', + 'react/display-name': 'off', + 'react/no-unescaped-entities': 'off', + 'react-compiler/react-compiler': 'warn', + }, + }, + { + // update this to match your test files + files: ['**/*.spec.js', '**/*.test.js'], + plugins: { jest: pluginJest }, + languageOptions: { + globals: pluginJest.environments.globals.globals, + }, + rules: { + 'jest/no-disabled-tests': 'warn', + 'jest/no-focused-tests': 'error', + 'jest/no-identical-title': 'error', + 'jest/prefer-to-have-length': 'warn', + 'jest/valid-expect': 'error', + }, + }, +]) diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 0136d6f2..00000000 --- a/jsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=759670 - // for the documentation about the jsconfig.json format - "compilerOptions": { - "target": "es6", - "module": "commonjs", - "allowSyntheticDefaultImports": true - }, - "exclude": [ - "node_modules", - "bower_components", - "jspm_packages", - "tmp", - "temp" - ] -} diff --git a/lib/blockexplorers/mempool.space.js b/lib/blockexplorers/mempool.space.js deleted file mode 100644 index 383c1c72..00000000 --- a/lib/blockexplorers/mempool.space.js +++ /dev/null @@ -1,16 +0,0 @@ -const axios = require("axios"); - -const getSatBEstimateFee = () => { - return axios.get('https://mempool.space/api/v1/fees/recommended') - .then(r => r.data.hourFee) -} - -const getSatBEstimateFees = () => { - return axios.get('https://mempool.space/api/v1/fees/recommended') - .then(r => r.data) -} - -module.exports = { - getSatBEstimateFees, - getSatBEstimateFee -} \ No newline at end of file diff --git a/lib/cash-in/cash-in-low.js b/lib/cash-in/cash-in-low.js deleted file mode 100644 index d6331f0b..00000000 --- a/lib/cash-in/cash-in-low.js +++ /dev/null @@ -1,148 +0,0 @@ -const _ = require('lodash/fp') -const pgp = require('pg-promise')() - -const BN = require('../bn') -const T = require('../time') -const logger = require('../logger') -const E = require('../error') - -const PENDING_INTERVAL_MS = 60 * T.minutes - -const massageFields = ['direction', 'cryptoNetwork', 'bills', 'blacklisted', 'blacklistMessage', 'addressReuse', 'promoCodeApplied', 'validWalletScore', 'cashInFeeCrypto'] -const massageUpdateFields = _.concat(massageFields, 'cryptoAtoms') - -const massage = _.flow(_.omit(massageFields), - convertBigNumFields, _.mapKeys(_.snakeCase)) - -const massageUpdates = _.flow(_.omit(massageUpdateFields), - convertBigNumFields, _.mapKeys(_.snakeCase)) - -module.exports = {toObj, upsert, insert, update, massage, isClearToSend} - -function convertBigNumFields (obj) { - const convert = value => - value && BN.isBigNumber(value) - ? value.toString() - : value - return _.mapValues(convert, obj) -} - -function toObj (row) { - if (!row) return null - - const keys = _.keys(row) - let newObj = {} - - keys.forEach(key => { - const objKey = _.camelCase(key) - if (_.includes(key, ['crypto_atoms', 'fiat', 'cash_in_fee', 'commission_percentage', 'raw_ticker_price'])) { - newObj[objKey] = new BN(row[key]) - return - } - - newObj[objKey] = row[key] - }) - - newObj.direction = 'cashIn' - - return newObj -} - -function upsert (t, dbTx, preProcessedTx) { - if (!dbTx) { - return insert(t, preProcessedTx) - .then(tx => ({dbTx, tx})) - } - - return update(t, dbTx, diff(dbTx, preProcessedTx)) - .then(tx => ({dbTx, tx})) -} - -function insert (t, tx) { - const dbTx = massage(tx) - const sql = pgp.helpers.insert(dbTx, null, 'cash_in_txs') + ' returning *' - return t.one(sql) - .then(toObj) -} - -function update (t, tx, changes) { - if (_.isEmpty(changes)) return Promise.resolve(tx) - - const dbChanges = isFinalTxStage(changes) ? massage(changes) : massageUpdates(changes) - const sql = pgp.helpers.update(dbChanges, null, 'cash_in_txs') + - pgp.as.format(' where id=$1', [tx.id]) + ' returning *' - - return t.one(sql) - .then(toObj) -} - -function diff (oldTx, newTx) { - let updatedTx = {} - - if (!oldTx) throw new Error('oldTx must not be null') - if (!newTx) throw new Error('newTx must not be null') - - _.forEach(fieldKey => { - const oldField = oldTx[fieldKey] - const newField = newTx[fieldKey] - if (fieldKey === 'bills') return - if (_.isEqualWith(nilEqual, oldField, newField)) return - - if (!ensureRatchet(oldField, newField, fieldKey)) { - logger.warn('Value from lamassu-machine would violate ratchet [%s]', fieldKey) - logger.warn('Old tx: %j', oldTx) - logger.warn('New tx: %j', newTx) - throw new E.RatchetError('Value from lamassu-machine would violate ratchet') - } - - updatedTx[fieldKey] = newField - }, _.keys(newTx)) - - return updatedTx -} - -function ensureRatchet (oldField, newField, fieldKey) { - const monotonic = ['cryptoAtoms', 'fiat', 'send', 'sendConfirmed', 'operatorCompleted', 'timedout', 'txVersion', 'batched', 'discount'] - const free = ['sendPending', 'error', 'errorCode', 'customerId', 'discountSource'] - - if (_.isNil(oldField)) return true - if (_.includes(fieldKey, monotonic)) return isMonotonic(oldField, newField, fieldKey) - - if (_.includes(fieldKey, free)) { - if (_.isNil(newField)) return false - return true - } - - if (_.isNil(newField)) return false - if (BN.isBigNumber(oldField) && BN.isBigNumber(newField)) return new BN(oldField).eq(newField) - if (oldField.toString() === newField.toString()) return true - - return false -} - -function isMonotonic (oldField, newField, fieldKey) { - if (_.isNil(newField)) return false - if (_.isBoolean(oldField)) return oldField === newField || !oldField - if (BN.isBigNumber(oldField)) return oldField.lte(newField) - if (_.isNumber(oldField)) return oldField <= newField - - throw new Error(`Unexpected value [${fieldKey}]: ${oldField}, ${newField}`) -} - -function nilEqual (a, b) { - if (_.isNil(a) && _.isNil(b)) return true - - return undefined -} - -function isClearToSend (oldTx, newTx) { - const now = Date.now() - - return (newTx.send || newTx.batched) && - (!oldTx || (!oldTx.sendPending && !oldTx.sendConfirmed)) && - (newTx.created > now - PENDING_INTERVAL_MS) -} - -function isFinalTxStage (txChanges) { - return txChanges.send || txChanges.batched -} diff --git a/lib/cash-out/cash-out-actions.js b/lib/cash-out/cash-out-actions.js deleted file mode 100644 index 9c43e21a..00000000 --- a/lib/cash-out/cash-out-actions.js +++ /dev/null @@ -1,51 +0,0 @@ -const _ = require('lodash/fp') -const pgp = require('pg-promise')() - -module.exports = {logDispense, logActionById, logAction, logError} - -function logDispense (t, tx) { - const baseRec = {error: tx.error, error_code: tx.errorCode} - const rec = _.merge(mapDispense(tx), baseRec) - const action = _.isEmpty(tx.error) ? 'dispense' : 'dispenseError' - return logAction(t, action, rec, tx) -} - -function logActionById (t, action, _rec, txId) { - const rec = _.assign(_rec, {action, tx_id: txId, redeem: false}) - const sql = pgp.helpers.insert(rec, null, 'cash_out_actions') - - return t.none(sql) -} - -function logAction (t, action, _rec, tx) { - const rec = _.assign(_rec, {action, tx_id: tx.id, redeem: !!tx.redeem, device_id: tx.deviceId}) - const sql = pgp.helpers.insert(rec, null, 'cash_out_actions') - - return t.none(sql) - .then(_.constant(tx)) -} - -function logError (t, action, err, tx) { - return logAction(t, action, { - error: err.message, - error_code: err.name - }, tx) -} - -function mapDispense (tx) { - const bills = tx.bills - - if (_.isEmpty(bills)) return {} - - const res = {} - - _.forEach(it => { - const suffix = _.snakeCase(bills[it].name.replace(/cassette/gi, '')) - res[`provisioned_${suffix}`] = bills[it].provisioned - res[`denomination_${suffix}`] = bills[it].denomination - res[`dispensed_${suffix}`] = bills[it].dispensed - res[`rejected_${suffix}`] = bills[it].rejected - }, _.times(_.identity(), _.size(bills))) - - return res -} diff --git a/lib/cash-out/cash-out-atomic.js b/lib/cash-out/cash-out-atomic.js deleted file mode 100644 index ca5d2464..00000000 --- a/lib/cash-out/cash-out-atomic.js +++ /dev/null @@ -1,182 +0,0 @@ -const _ = require('lodash/fp') -const pgp = require('pg-promise')() - -const db = require('../db') -const E = require('../error') -const logger = require('../logger') - -const helper = require('./cash-out-helper') -const cashOutActions = require('./cash-out-actions') -const cashOutLow = require('./cash-out-low') - -const toObj = helper.toObj - -module.exports = { atomic } - -function atomic (tx, pi, fromClient) { - const TransactionMode = pgp.txMode.TransactionMode - const isolationLevel = pgp.txMode.isolationLevel - const mode = new TransactionMode({ tiLevel: isolationLevel.serializable }) - function transaction (t) { - const sql = 'SELECT * FROM cash_out_txs WHERE id=$1 FOR UPDATE' - - return t.oneOrNone(sql, [tx.id]) - .then(toObj) - .then(oldTx => { - const isStale = fromClient && oldTx && (oldTx.txVersion >= tx.txVersion) - if (isStale) throw new E.StaleTxError({ txId: tx.id }) - - // Server doesn't bump version, so we just prevent from version being older. - const isStaleFromServer = !fromClient && oldTx && (oldTx.txVersion > tx.txVersion) - if (isStaleFromServer) throw new Error('Stale Error: server triggered', tx.id) - - return preProcess(t, oldTx, tx, pi) - .then(preProcessedTx => cashOutLow.upsert(t, oldTx, preProcessedTx)) - }) - } - return db.tx({ mode }, transaction) -} - -function preProcess (t, oldTx, newTx, pi) { - if (!oldTx) { - return pi.isHd(newTx) - .then(isHd => nextHd(t, isHd, newTx)) - .then(newTxHd => { - return pi.newAddress(newTxHd) - .then(_.merge(newTxHd)) - }) - .then(addressedTx => { - const rec = { - to_address: addressedTx.toAddress, - layer_2_address: addressedTx.layer2Address - } - - return cashOutActions.logAction(t, 'provisionAddress', rec, addressedTx) - }) - .catch(err => { - pi.notifyOperator(newTx, { isRedemption: false, error: 'Error while provisioning address' }) - .catch((err) => logger.error('Failure sending transaction notification', err)) - return cashOutActions.logError(t, 'provisionAddress', err, newTx) - .then(() => { throw err }) - }) - } - - return Promise.resolve(updateStatus(oldTx, newTx)) - .then(updatedTx => { - if (updatedTx.status !== oldTx.status) { - const isZeroConf = pi.isZeroConf(updatedTx) - updatedTx.justAuthorized = wasJustAuthorized(oldTx, updatedTx, isZeroConf) - - const rec = { - to_address: updatedTx.toAddress, - tx_hash: updatedTx.txHash - } - - return cashOutActions.logAction(t, updatedTx.status, rec, updatedTx) - } - - const hasError = !oldTx.error && newTx.error - const hasDispenseOccurred = !oldTx.dispenseConfirmed && dispenseOccurred(newTx.bills) - - if (hasError || hasDispenseOccurred) { - return cashOutActions.logDispense(t, updatedTx) - .then(it => updateCassettes(t, updatedTx).then(() => it) ) - .then((t) => { - pi.notifyOperator(updatedTx, { isRedemption: true }) - .catch((err) => logger.error('Failure sending transaction notification', err)) - return t - }) - } - - if (!oldTx.phone && newTx.phone) { - return cashOutActions.logAction(t, 'addPhone', {}, updatedTx) - } - - if (!oldTx.redeem && newTx.redeem) { - return cashOutActions.logAction(t, 'redeemLater', {}, updatedTx) - } - - return updatedTx - }) -} - -function nextHd (t, isHd, tx) { - if (!isHd) return Promise.resolve(tx) - - return t.one("select nextval('hd_indices_seq') as hd_index") - .then(row => _.set('hdIndex', row.hd_index, tx)) -} - -function updateCassettes (t, tx) { - if (!dispenseOccurred(tx.bills)) return Promise.resolve() - - const billsStmt = _.join(', ')(_.map(it => `${tx.bills[it].name} = ${tx.bills[it].name} - $${it + 1}`)(_.range(0, _.size(tx.bills)))) - const returnStmt = _.join(', ')(_.map(bill => `${bill.name}`)(tx.bills)) - - const sql = `UPDATE devices SET ${billsStmt} WHERE device_id = $${_.size(tx.bills) + 1} RETURNING ${returnStmt}` - - const values = [] - - _.forEach(it => values.push( - tx.bills[it].dispensed + tx.bills[it].rejected - ), _.times(_.identity(), _.size(tx.bills))) - - values.push(tx.deviceId) - - return t.one(sql, values) -} - -function wasJustAuthorized (oldTx, newTx, isZeroConf) { - const isAuthorized = () => _.includes(oldTx.status, ['notSeen', 'published', 'rejected']) && - _.includes(newTx.status, ['authorized', 'instant', 'confirmed']) - - const isConfirmed = () => _.includes(oldTx.status, ['notSeen', 'published', 'authorized', 'rejected']) && - _.includes(newTx.status, ['instant', 'confirmed']) - - return isZeroConf ? isAuthorized() : isConfirmed() -} - -function isPublished (status) { - return _.includes(status, ['published', 'rejected', 'authorized', 'instant', 'confirmed']) -} - -function isConfirmed (status) { - return status === 'confirmed' -} - -function updateStatus (oldTx, newTx) { - const oldStatus = oldTx.status - const newStatus = ratchetStatus(oldStatus, newTx.status) - - const publishedAt = !oldTx.publishedAt && isPublished(newStatus) - ? 'now()^' - : undefined - - const confirmedAt = !oldTx.confirmedAt && isConfirmed(newStatus) - ? 'now()^' - : undefined - - const updateRec = { - publishedAt, - confirmedAt, - status: newStatus - } - - return _.merge(newTx, updateRec) -} - -function ratchetStatus (oldStatus, newStatus) { - const statusOrder = ['notSeen', 'published', 'rejected', - 'authorized', 'instant', 'confirmed'] - - if (oldStatus === newStatus) return oldStatus - if (newStatus === 'insufficientFunds') return newStatus - - const idx = Math.max(statusOrder.indexOf(oldStatus), statusOrder.indexOf(newStatus)) - return statusOrder[idx] -} - -function dispenseOccurred (bills) { - if (_.isEmpty(bills)) return false - return _.every(_.overEvery([_.has('dispensed'), _.has('rejected')]), bills) -} diff --git a/lib/compliance-triggers.js b/lib/compliance-triggers.js deleted file mode 100644 index dcbe6ab2..00000000 --- a/lib/compliance-triggers.js +++ /dev/null @@ -1,34 +0,0 @@ -const _ = require('lodash/fp') - -function getBackwardsCompatibleTriggers (triggers) { - const filtered = _.filter(_.matches({ triggerType: 'txVolume', direction: 'both', thresholdDays: 1 }))(triggers) - const grouped = _.groupBy(_.prop('requirement'))(filtered) - return _.mapValues(_.compose(_.get('threshold'), _.minBy('threshold')))(grouped) -} - -function hasSanctions (triggers) { - return _.some(_.matches({ requirement: 'sanctions' }))(triggers) -} - -function maxDaysThreshold (triggers) { - return _.max(_.map('thresholdDays')(triggers)) -} - -function getCashLimit (triggers) { - const withFiat = _.filter(({ triggerType }) => _.includes(triggerType, ['txVolume', 'txAmount'])) - const blocking = _.filter(({ requirement }) => _.includes(requirement, ['block', 'suspend'])) - return _.compose(_.minBy('threshold'), blocking, withFiat)(triggers) -} - -const hasRequirement = requirement => _.compose(_.negate(_.isEmpty), _.find(_.matches({ requirement }))) - -const hasPhone = hasRequirement('sms') -const hasFacephoto = hasRequirement('facephoto') -const hasIdScan = hasRequirement('idCardData') - -const AUTH_METHODS = { - SMS: 'SMS', - EMAIL: 'EMAIL' -} - -module.exports = { getBackwardsCompatibleTriggers, hasSanctions, maxDaysThreshold, getCashLimit, hasPhone, hasFacephoto, hasIdScan, AUTH_METHODS } \ No newline at end of file diff --git a/lib/compliance.js b/lib/compliance.js deleted file mode 100644 index becf9ee3..00000000 --- a/lib/compliance.js +++ /dev/null @@ -1,82 +0,0 @@ -const _ = require('lodash/fp') -const uuid = require('uuid') - -const logger = require('./logger') -const db = require('./db') -const ofac = require('./ofac/index') - -function logSanctionsMatch (deviceId, customer, sanctionsId, alias) { - const sql = `insert into sanctions_logs - (id, device_id, sanctioned_id, sanctioned_alias_id, sanctioned_alias_full_name, customer_id) - values - ($1, $2, $3, $4, $5, $6)` - - return db.none(sql, [uuid.v4(), deviceId, sanctionsId, alias.id, alias.fullName, customer.id]) -} - -function logSanctionsMatches (deviceId, customer, results) { - const logAlias = resultId => alias => logSanctionsMatch(deviceId, customer, resultId, alias) - const logResult = result => _.map(logAlias(result.id), result.aliases) - - return Promise.all(_.flatMap(logResult, results)) -} - -function matchOfac (deviceId, customer) { - return Promise.resolve() - .then(() => { - // Probably because we haven't asked for ID yet - if (!_.isPlainObject(customer.idCardData)) { - return true - } - - const nameParts = { - firstName: customer.idCardData.firstName, - lastName: customer.idCardData.lastName - } - - if (_.some(_.isNil, _.values(nameParts))) { - logger.error(new Error(`Insufficient idCardData while matching OFAC for: ${customer.id}`)) - return true - } - - const birthDate = customer.idCardData.dateOfBirth - - if (_.isNil(birthDate)) { - logger.error(new Error(`No birth date while matching OFAC for: ${customer.id}`)) - return true - } - - const options = { - threshold: 0.85, - fullNameThreshold: 0.95, - debug: false - } - - const results = ofac.match(nameParts, birthDate, options) - - return logSanctionsMatches(deviceId, customer, results) - .then(() => !_.isEmpty(results)) - }) -} - -// BACKWARDS_COMPATIBILITY 7.5 -// machines before 7.5 need to test sanctionsActive here -function validateOfac (deviceId, sanctionsActive, customer) { - if (!sanctionsActive) return Promise.resolve(true) - if (customer.sanctionsOverride === 'blocked') return Promise.resolve(false) - if (customer.sanctionsOverride === 'verified') return Promise.resolve(true) - - return matchOfac(deviceId, customer) - .then(didMatch => !didMatch) -} - -function validationPatch (deviceId, sanctionsActive, customer) { - return validateOfac(deviceId, sanctionsActive, customer) - .then(sanctions => - _.isNil(customer.sanctions) || customer.sanctions !== sanctions ? - { sanctions } : - {} - ) -} - -module.exports = {validationPatch} diff --git a/lib/email.js b/lib/email.js deleted file mode 100644 index 53367ca4..00000000 --- a/lib/email.js +++ /dev/null @@ -1,25 +0,0 @@ -const ph = require('./plugin-helper') - -function sendMessage (settings, rec) { - return Promise.resolve() - .then(() => { - const pluginCode = settings.config.notifications_thirdParty_email || 'mailgun' - const plugin = ph.load(ph.EMAIL, pluginCode) - const account = settings.accounts[pluginCode] - - return plugin.sendMessage(account, rec) - }) -} - -function sendCustomerMessage (settings, rec) { - return Promise.resolve() - .then(() => { - const pluginCode = settings.config.notifications_thirdParty_email || 'mailgun' - const plugin = ph.load(ph.EMAIL, pluginCode) - const account = settings.accounts[pluginCode] - - return plugin.sendMessage(account, rec) - }) -} - -module.exports = {sendMessage, sendCustomerMessage} diff --git a/lib/exchange.js b/lib/exchange.js deleted file mode 100644 index ee325b2f..00000000 --- a/lib/exchange.js +++ /dev/null @@ -1,81 +0,0 @@ -const _ = require('lodash/fp') -const { ALL_CRYPTOS } = require('@lamassu/coins') - -const configManager = require('./new-config-manager') -const ccxt = require('./plugins/exchange/ccxt') -const mockExchange = require('./plugins/exchange/mock-exchange') -const accounts = require('./new-admin/config/accounts') - -function lookupExchange (settings, cryptoCode) { - const exchange = configManager.getWalletSettings(cryptoCode, settings.config).exchange - if (exchange === 'no-exchange') return null - return exchange -} - -function fetchExchange (settings, cryptoCode) { - return Promise.resolve() - .then(() => { - const exchangeName = lookupExchange(settings, cryptoCode) - if (!exchangeName) throw new Error('No exchange set') - const account = settings.accounts[exchangeName] - - return { exchangeName, account } - }) -} - -function buy (settings, tradeEntry) { - const { cryptoAtoms, fiatCode, cryptoCode } = tradeEntry - return fetchExchange(settings, cryptoCode) - .then(r => { - if (r.exchangeName === 'mock-exchange') { - return mockExchange.buy(cryptoAtoms, fiatCode, cryptoCode) - } - return ccxt.trade('buy', r.account, tradeEntry, r.exchangeName) - }) -} - -function sell (settings, tradeEntry) { - const { cryptoAtoms, fiatCode, cryptoCode } = tradeEntry - return fetchExchange(settings, cryptoCode) - .then(r => { - if (r.exchangeName === 'mock-exchange') { - return mockExchange.sell(cryptoAtoms, fiatCode, cryptoCode) - } - return ccxt.trade('sell', r.account, tradeEntry, r.exchangeName) - }) -} - -function active (settings, cryptoCode) { - return !!lookupExchange(settings, cryptoCode) -} - -function getMarkets () { - const filterExchanges = _.filter(it => it.class === 'exchange' && !it.dev && it.code !== 'no-exchange') - const availableExchanges = _.map(it => it.code, filterExchanges(accounts.ACCOUNT_LIST)) - - const fetchMarketForExchange = exchange => - ccxt.getMarkets(exchange, ALL_CRYPTOS) - .then(markets => ({ exchange, markets })) - .catch(error => ({ - exchange, - markets: [], - error: error.message - })) - - const transformToObject = _.reduce((acc, { exchange, markets }) => ({ - ...acc, - [exchange]: markets - }), {}) - - const promises = _.map(fetchMarketForExchange, availableExchanges) - return Promise.all(promises) - .then(transformToObject) -} - -module.exports = { - fetchExchange, - buy, - sell, - active, - getMarkets -} diff --git a/lib/forex.js b/lib/forex.js deleted file mode 100644 index 011eb2e4..00000000 --- a/lib/forex.js +++ /dev/null @@ -1,62 +0,0 @@ -const _ = require('lodash/fp') -const axios = require('axios') -const BN = require('./bn') - -const MAX_ROTATIONS = 5 - -const getFiatRates = () => axios.get('https://bitpay.com/api/rates').then(response => response.data) - -const API_QUEUE = [ - { api: getBitPayFxRate, name: 'bitpay', fiatCodeProperty: 'code', rateProperty: 'rate' }, - { api: getCoinCapFxRate, name: 'coincap', fiatCodeProperty: 'symbol', rateProperty: 'rateUsd' } -] - -function getBitPayFxRate (fiatCode, fiatCodeProperty, rateProperty) { - return axios.get('https://bitpay.com/rates') - .then(response => { - const fxRates = response.data.data - const usdRate = findCurrencyRates(fxRates, 'USD', fiatCodeProperty, rateProperty) - const fxRate = findCurrencyRates(fxRates, fiatCode, fiatCodeProperty, rateProperty).div(usdRate) - return { - fxRate - } - }) -} - -function getCoinCapFxRate (fiatCode, fiatCodeProperty, rateProperty) { - return axios.get('https://api.coincap.io/v2/rates') - .then(response => { - const fxRates = response.data.data - const fxRate = new BN(1).div(findCurrencyRates(fxRates, fiatCode, fiatCodeProperty, rateProperty)) - return { - fxRate - } - }) -} - -function findCurrencyRates (fxRates, fiatCode, fiatCodeProperty, rateProperty) { - const rates = _.find(_.matchesProperty(fiatCodeProperty, fiatCode), fxRates) - if (!rates || !rates[rateProperty]) throw new Error(`Unsupported currency: ${fiatCode}`) - return new BN(rates[rateProperty].toString()) -} - -const getRate = (retries = 1, fiatCode) => { - const selected = _.first(API_QUEUE).name - const activeAPI = _.first(API_QUEUE).api - const fiatCodeProperty = _.first(API_QUEUE).fiatCodeProperty - const rateProperty = _.first(API_QUEUE).rateProperty - - if (!activeAPI) throw new Error(`FOREX api ${selected} does not exist.`) - - return activeAPI(fiatCode, fiatCodeProperty, rateProperty) - .catch(() => { - // Switch service - const erroredService = API_QUEUE.shift() - API_QUEUE.push(erroredService) - if (retries >= MAX_ROTATIONS) throw new Error(`FOREX API error from ${erroredService.name}`) - - return getRate(++retries, fiatCode) - }) -} - -module.exports = { getFiatRates, getRate } diff --git a/lib/graphql/types.js b/lib/graphql/types.js deleted file mode 100644 index a4dfa4c9..00000000 --- a/lib/graphql/types.js +++ /dev/null @@ -1,234 +0,0 @@ -const gql = require('graphql-tag') - -module.exports = gql` -type Coin { - cryptoCode: String! - cryptoCodeDisplay: String! - display: String! - minimumTx: String! - cashInFee: String! - cashOutFee: String! - cashInCommission: String! - cashOutCommission: String! - cryptoNetwork: String! - cryptoUnits: String! - batchable: Boolean! - isCashInOnly: Boolean! -} - -type LocaleInfo { - country: String! - fiatCode: String! - languages: [String!]! -} - -type OperatorInfo { - name: String! - phone: String! - email: String! - website: String! - companyNumber: String! -} - -type MachineInfo { - deviceId: String! @deprecated(reason: "unused by the machine") - deviceName: String - numberOfCassettes: Int - numberOfRecyclers: Int -} - -type ReceiptInfo { - paper: Boolean! - automaticPrint: Boolean! - sms: Boolean! - operatorWebsite: Boolean! - operatorEmail: Boolean! - operatorPhone: Boolean! - companyNumber: Boolean! - machineLocation: Boolean! - customerNameOrPhoneNumber: Boolean! - exchangeRate: Boolean! - addressQRCode: Boolean! -} - -type MachineScreenOptions { - rates: RateScreenOptions! -} - -type RateScreenOptions { - active: Boolean! -} - -type SpeedtestFile { - url: String! - size: Int! -} - -enum TriggerAutomationType { - Automatic - Manual -} - -type CustomTriggersAutomation { - id: ID! - type: TriggerAutomationType! -} - -type TriggersAutomation { - sanctions: TriggerAutomationType! - idCardPhoto: TriggerAutomationType! - idCardData: TriggerAutomationType! - facephoto: TriggerAutomationType! - usSsn: TriggerAutomationType! - custom: [CustomTriggersAutomation]! -} - -type CustomScreen { - text: String! - title: String! -} - -type CustomInput { - type: String! - constraintType: String! - label1: String - label2: String - choiceList: [String] -} - -type CustomRequest { - name: String! - input: CustomInput! - screen1: CustomScreen! - screen2: CustomScreen! -} - -type CustomInfoRequest { - id: String! - enabled: Boolean! - customRequest: CustomRequest! -} - -type Trigger { - id: String! - direction: String! - requirement: String! - triggerType: String! - - suspensionDays: Float - threshold: Int - thresholdDays: Int - customInfoRequestId: String @deprecated(reason: "use customInfoRequest.id") - customInfoRequest: CustomInfoRequest - externalService: String -} - -type TermsDetails { - tcPhoto: Boolean! - delay: Boolean! - title: String! - accept: String! - cancel: String! -} - -type Terms { - hash: String! - text: String - details: TermsDetails -} - -enum CustomerAuthentication { - EMAIL - SMS -} - -type StaticConfig { - configVersion: Int! - - coins: [Coin!]! - enablePaperWalletOnly: Boolean! - hasLightning: Boolean! - serverVersion: String! - timezone: Int! - twoWayMode: Boolean! - customerAuthentication: CustomerAuthentication! - - localeInfo: LocaleInfo! - operatorInfo: OperatorInfo - machineInfo: MachineInfo! - receiptInfo: ReceiptInfo - screenOptions: MachineScreenOptions - - speedtestFiles: [SpeedtestFile!]! - urlsToPing: [String!]! - - triggersAutomation: TriggersAutomation! - triggers: [Trigger!]! -} - -type DynamicCoinValues { - # NOTE: Doesn't seem to be used anywhere outside of lib/plugins.js. - # However, it can be used to generate the cache key, if we ever move to an - # actual caching mechanism. - #timestamp: String! - - cryptoCode: String! - balance: String! - - # Raw rates - ask: String! - bid: String! - - # Rates with commissions applied - cashIn: String! - cashOut: String! - - zeroConfLimit: Int! -} - -type PhysicalCassette { - name: String! - denomination: Int! - count: Int! -} - -type PhysicalRecycler { - name: String! - number: Int! - denomination: Int! - count: Int! -} - -type Cassettes { - physical: [PhysicalCassette!]! - virtual: [Int!]! -} - -type Recyclers { - physical: [PhysicalRecycler!]! - virtual: [Int!]! -} - -type DynamicConfig { - areThereAvailablePromoCodes: Boolean! - cassettes: Cassettes - recyclers: Recyclers - coins: [DynamicCoinValues!]! - reboot: Boolean! - shutdown: Boolean! - restartServices: Boolean! - emptyUnit: Boolean! - refillUnit: Boolean! - diagnostics: Boolean! -} - -type Configs { - static: StaticConfig - dynamic: DynamicConfig! -} - -type Query { - configs(currentConfigVersion: Int): Configs! - terms(currentHash: String, currentConfigVersion: Int): Terms -} -` diff --git a/lib/layer2.js b/lib/layer2.js deleted file mode 100644 index b77403da..00000000 --- a/lib/layer2.js +++ /dev/null @@ -1,53 +0,0 @@ -const configManager = require('./new-config-manager') -const ph = require('./plugin-helper') -const _ = require('lodash/fp') - -function fetch (settings, cryptoCode) { - const plugin = configManager.getWalletSettings(cryptoCode, settings.config).layer2 - - if (_.isEmpty(plugin) || plugin === 'no-layer2') return Promise.resolve() - - const layer2 = ph.load(ph.LAYER2, plugin) - const account = settings.accounts[plugin] - - return Promise.resolve({layer2, account}) -} - -function newAddress (settings, info) { - return fetch(settings, info.cryptoCode) - .then(r => { - if (!r) return - return r.layer2.newAddress(r.account, info) - }) -} - -function getStatus (settings, tx) { - const toAddress = tx.layer2Address - if (!toAddress) return Promise.resolve({status: 'notSeen'}) - - return fetch(settings, tx.cryptoCode) - .then(r => { - if (!r) return {status: 'notSeen'} - return r.layer2.getStatus(r.account, toAddress, tx.cryptoAtoms, tx.cryptoCode) - }) -} - -function cryptoNetwork (settings, cryptoCode) { - const plugin = configManager.getWalletSettings(cryptoCode, settings.config).layer2 - const layer2 = ph.load(ph.LAYER2, plugin) - const account = settings.accounts[plugin] - - if (!layer2.cryptoNetwork) return Promise.resolve(false) - return layer2.cryptoNetwork(account, cryptoCode) -} - -function isLayer2Address (address) { - return address.split(':').length >= 2 -} - -module.exports = { - isLayer2Address, - newAddress, - getStatus, - cryptoNetwork -} diff --git a/lib/machine-loader.js b/lib/machine-loader.js deleted file mode 100644 index 4276024f..00000000 --- a/lib/machine-loader.js +++ /dev/null @@ -1,534 +0,0 @@ -const fsPromises = require('fs').promises -const path = require('path') -const _ = require('lodash/fp') -const pgp = require('pg-promise')() -const uuid = require('uuid') -const makeDir = require('make-dir') - -const batching = require('./cashbox-batches') -const db = require('./db') -const pairing = require('./pairing') -const { checkPings, checkStuckScreen } = require('./notifier') -const dbm = require('./postgresql_interface') -const configManager = require('./new-config-manager') -const notifierUtils = require('./notifier/utils') -const notifierQueries = require('./notifier/queries') -const { GraphQLError } = require('graphql'); -const { loadLatestConfig } = require('./new-settings-loader') -const logger = require('./logger') - -const fullyFunctionalStatus = { label: 'Fully functional', type: 'success' } -const unresponsiveStatus = { label: 'Unresponsive', type: 'error' } -const stuckStatus = { label: 'Stuck', type: 'error' } -const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR - -const MACHINE_WITH_CALCULATED_FIELD_SQL = ` -select d.*, COALESCE(emptybills, 0) + COALESCE(regularbills, 0) as cashbox from devices d - left join ( - select count(*) as emptyBills, eub.device_id - from empty_unit_bills eub - where eub.cashbox_batch_id is null - group by eub.device_id - ) as nebills on nebills.device_id = d.device_id - left join ( - select count(*) as regularBills, cit.device_id from bills b - left join cash_in_txs cit on b.cash_in_txs_id = cit.id - where b.cashbox_batch_id is null and b.destination_unit = 'cashbox' - group by cit.device_id - ) as nbills on nbills.device_id = d.device_id` - -function toMachineObject (r) { - return { - deviceId: r.device_id, - cashUnits: { - cashbox: r.cashbox, - cassette1: r.cassette1, - cassette2: r.cassette2, - cassette3: r.cassette3, - cassette4: r.cassette4, - recycler1: r.recycler1, - recycler2: r.recycler2, - recycler3: r.recycler3, - recycler4: r.recycler4, - recycler5: r.recycler5, - recycler6: r.recycler6 - }, - numberOfCassettes: r.number_of_cassettes, - numberOfRecyclers: r.number_of_recyclers, - version: r.version, - model: r.model, - diagnostics: { - timestamp: r.diagnostics_timestamp? new Date(r.diagnostics_timestamp) : null, - scanTimestamp: r.diagnostics_scan_timestamp? new Date(r.diagnostics_scan_timestamp) : null, - frontTimestamp: r.diagnostics_front_timestamp? new Date(r.diagnostics_front_timestamp) : null - }, - pairedAt: new Date(r.created), - lastPing: new Date(r.last_online), - name: r.name, - paired: r.paired - // TODO: we shall start using this JSON field at some point - // location: r.location, - } -} - -function getMachineIds () { - const sql = 'select device_id from devices' - return db.any(sql) -} - -function getMachines () { - const sql = `${MACHINE_WITH_CALCULATED_FIELD_SQL} where display=TRUE ORDER BY created` - return db.any(sql) - .then(rr => rr.map(toMachineObject)) -} - -function getUnpairedMachines () { - return db.any('SELECT * FROM unpaired_devices') - .then(_.map(r => - _.flow( - _.set('deviceId', _.get('device_id', r)), - _.unset('device_id') - )(r) - )) -} - -function getConfig (defaultConfig) { - return defaultConfig ? Promise.resolve(defaultConfig) : loadLatestConfig() -} - -const getStatus = (ping, stuck) => { - if (ping && ping.age) return unresponsiveStatus - - if (stuck && stuck.age) return stuckStatus - - return fullyFunctionalStatus -} - -function addName (pings, events, config) { - return machine => { - const cashOutConfig = configManager.getCashOut(machine.deviceId, config) - - const cashOut = !!cashOutConfig.active - - const statuses = [ - getStatus( - _.first(pings[machine.deviceId]), - _.first(checkStuckScreen(events, machine)) - ) - ] - - return _.assign(machine, { cashOut, statuses }) - } -} - -function getMachineNames (config) { - return Promise.all([getMachines(), getConfig(config), getNetworkHeartbeat(), getNetworkPerformance()]) - .then(([rawMachines, config, heartbeat, performance]) => Promise.all( - [rawMachines, checkPings(rawMachines), dbm.machineEvents(), config, heartbeat, performance] - )) - .then(([rawMachines, pings, events, config, heartbeat, performance]) => { - const mergeByDeviceId = (x, y) => _.values(_.merge(_.keyBy('deviceId', x), _.keyBy('deviceId', y))) - const machines = mergeByDeviceId(mergeByDeviceId(rawMachines, heartbeat), performance) - - return machines.map(addName(pings, events, config)) - }) -} - -/** - * Given the machine id, get the machine name - * - * @name getMachineName - * @function - * @async - * - * @param {string} machineId machine id - * @returns {string} machine name - */ -function getMachineName (machineId) { - const sql = 'SELECT name FROM devices WHERE device_id=$1' - return db.oneOrNone(sql, [machineId]) - .then(it => it.name) -} - -function getMachine (machineId, config) { - const sql = `${MACHINE_WITH_CALCULATED_FIELD_SQL} WHERE d.device_id = $1` - - const queryMachine = db.oneOrNone(sql, [machineId]).then(r => { - if (r === null) throw new GraphQLError('Resource doesn\'t exist', { extensions: { code: 'NOT_FOUND' } }) - else return toMachineObject(r) - }) - - return Promise.all([queryMachine, dbm.machineEvents(), config, getNetworkHeartbeatByDevice(machineId), getNetworkPerformanceByDevice(machineId)]) - .then(([machine, events, config, heartbeat, performance]) => { - const pings = checkPings([machine]) - const mergedMachine = { - ...machine, - responseTime: _.get('responseTime', heartbeat), - packetLoss: _.get('packetLoss', heartbeat), - downloadSpeed: _.get('downloadSpeed', performance), - } - - return addName(pings, events, config)(mergedMachine) - }) -} - -function renameMachine (rec) { - const sql = 'UPDATE devices SET name=$1 WHERE device_id=$2' - return db.none(sql, [rec.newName, rec.deviceId]) -} - -function resetCashOutBills (rec) { - const detailB = notifierUtils.buildDetail({ deviceId: rec.deviceId }) - const { cassette1, cassette2, cassette3, cassette4, recycler1, recycler2, recycler3, recycler4, recycler5, recycler6 } = rec.cashUnits - const sql = `UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, recycler1=$5, recycler2=$6, recycler3=$7, recycler4=$8, recycler5=$9, recycler6=$10 WHERE device_id=$11;` - return db.none(sql, [cassette1, cassette2, cassette3, cassette4, recycler1, recycler2, recycler3, recycler4, recycler5, recycler6, rec.deviceId]).then(() => notifierQueries.invalidateNotification(detailB, 'fiatBalance')) -} - -function setCassetteBills (rec) { - const { cashbox, cassette1, cassette2, cassette3, cassette4, recycler1, recycler2, recycler3, recycler4, recycler5, recycler6 } = rec.cashUnits - return getMachine(rec.deviceId) - .then(machine => { - const oldCashboxCount = machine?.cashUnits?.cashbox - if (_.isNil(oldCashboxCount) || cashbox.toString() === oldCashboxCount.toString()) { - const sql = ` - UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, - recycler1=coalesce($5, recycler1), recycler2=coalesce($6, recycler2), recycler3=coalesce($7, recycler3), - recycler4=coalesce($8, recycler4), recycler5=coalesce($9, recycler5), recycler6=coalesce($10, recycler6) - WHERE device_id=$11` - return db.none(sql, [cassette1, cassette2, cassette3, cassette4, recycler1, recycler2, recycler3, recycler4, recycler5, recycler6, rec.deviceId]) - } - - return batching.updateMachineWithBatch({ ...rec, oldCashboxValue: oldCashboxCount }) - }) -} - -function emptyMachineUnits ({ deviceId, newUnits, fiatCode }) { - return loadLatestConfig() - .then(config => Promise.all([getMachine(deviceId), configManager.getCashOut(deviceId, config)])) - .then(([machine, cashoutSettings]) => { - const movedBills = _.reduce( - (acc, value) => ({ - ...acc, - [value]: { - operationName: `cash-${_.replace(/(cassette|recycler)/g, '$1-')(value)}-empty`, - delta: newUnits[value] - machine.cashUnits[value], - denomination: value !== 'cashbox' ? cashoutSettings[value] : null - } - }), - {}, - _.keys(newUnits) - ) - - const operationNames = _.mapValues(it => it.operationName)(_.filter(it => Math.abs(it.delta) > 0)(_.omit(['cashbox'], movedBills))) - const operationsToCreate = _.map(it => ({ - id: uuid.v4(), - device_id: deviceId, - operation_type: it - }))(operationNames) - - const billArr = _.reduce( - (acc, value) => { - const unit = movedBills[value] - return _.concat(acc, _.times(() => ({ - id: uuid.v4(), - fiat: unit.denomination, - fiat_code: fiatCode, - device_id: deviceId - // TODO: Uncomment this if we decide to keep track of bills across multiple operations. For now, we'll just create the emptying operations for each unit affected, but not relate these events with individual bills and just use the field for the cashbox batch event - // cash_unit_operation_id: _.find(it => it.operation_type === `cash-${_.replace(/(cassette|recycler)/g, '$1-')(value)}-empty`, operationsToCreate).id - }), Math.abs(unit.delta))) - }, - [], - _.keys(_.omit(['cashbox'], movedBills)) - ) - - // This occurs when an empty unit is called when the units are already empty, hence, no bills moved around - if (_.isEmpty(billArr) && _.isEmpty(operationsToCreate)) { - return Promise.resolve() - } - - return db.tx(t => { - const q1Cols = ['id', 'device_id', 'operation_type'] - const q1= t.none(pgp.helpers.insert(operationsToCreate, q1Cols, 'cash_unit_operation')) - const q2Cols = ['id', 'fiat', 'fiat_code', 'device_id'] - const q2 = t.none(pgp.helpers.insert(billArr, q2Cols, 'empty_unit_bills')) - const q3 = t.none(`UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, recycler1=$5, recycler2=$6, recycler3=$7, recycler4=$8, recycler5=$9, recycler6=$10 WHERE device_id=$11`, [ - _.defaultTo(machine.cashUnits.cassette1, newUnits.cassette1), - _.defaultTo(machine.cashUnits.cassette2, newUnits.cassette2), - _.defaultTo(machine.cashUnits.cassette3, newUnits.cassette3), - _.defaultTo(machine.cashUnits.cassette4, newUnits.cassette4), - _.defaultTo(machine.cashUnits.recycler1, newUnits.recycler1), - _.defaultTo(machine.cashUnits.recycler2, newUnits.recycler2), - _.defaultTo(machine.cashUnits.recycler3, newUnits.recycler3), - _.defaultTo(machine.cashUnits.recycler4, newUnits.recycler4), - _.defaultTo(machine.cashUnits.recycler5, newUnits.recycler5), - _.defaultTo(machine.cashUnits.recycler6, newUnits.recycler6), - deviceId - ]) - - return t.batch([q1, q2, q3]) - }) - }) -} - -function refillMachineUnits ({ deviceId, newUnits }) { - return getMachine(deviceId) - .then(machine => { - const movedBills = _.reduce( - (acc, value) => ({ - ...acc, - [value]: { - operationName: `cash-${_.replace(/(recycler)/g, '$1-')(value)}-refill`, - delta: newUnits[value] - machine.cashUnits[value] - } - }), - {}, - _.keys(newUnits) - ) - - const operationNames = _.mapValues(it => it.operationName)(_.filter(it => Math.abs(it.delta) > 0)(_.omit(['cassette1', 'cassette2', 'cassette3', 'cassette4'], movedBills))) - const operationsToCreate = _.map(it => ({ - id: uuid.v4(), - device_id: deviceId, - operation_type: it - }))(operationNames) - - // This occurs when a refill unit is called when the loading boxes are empty, hence, no bills moved around - if (_.isEmpty(operationsToCreate)) { - return Promise.resolve() - } - - return db.tx(t => { - const q1Cols = ['id', 'device_id', 'operation_type'] - const q1= t.none(pgp.helpers.insert(operationsToCreate, q1Cols, 'cash_unit_operation')) - const q2 = t.none(`UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, recycler1=$5, recycler2=$6, recycler3=$7, recycler4=$8, recycler5=$9, recycler6=$10 WHERE device_id=$11`, [ - _.defaultTo(machine.cashUnits.cassette1, newUnits.cassette1), - _.defaultTo(machine.cashUnits.cassette2, newUnits.cassette2), - _.defaultTo(machine.cashUnits.cassette3, newUnits.cassette3), - _.defaultTo(machine.cashUnits.cassette4, newUnits.cassette4), - _.defaultTo(machine.cashUnits.recycler1, newUnits.recycler1), - _.defaultTo(machine.cashUnits.recycler2, newUnits.recycler2), - _.defaultTo(machine.cashUnits.recycler3, newUnits.recycler3), - _.defaultTo(machine.cashUnits.recycler4, newUnits.recycler4), - _.defaultTo(machine.cashUnits.recycler5, newUnits.recycler5), - _.defaultTo(machine.cashUnits.recycler6, newUnits.recycler6), - deviceId - ]) - - return t.batch([q1, q2]) - }) - }) -} - -function unpair (rec) { - return pairing.unpair(rec.deviceId) -} - -function reboot (rec) { - return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify( - { - action: 'reboot', - value: _.pick(['deviceId', 'operatorId', 'action'], rec) - } - )]) -} - -function shutdown (rec) { - return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify( - { - action: 'shutdown', - value: _.pick(['deviceId', 'operatorId', 'action'], rec) - } - )]) -} - -function restartServices (rec) { - return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify( - { - action: 'restartServices', - value: _.pick(['deviceId', 'operatorId', 'action'], rec) - } - )]) -} - -function emptyUnit (rec) { - return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify( - { - action: 'emptyUnit', - value: _.pick(['deviceId', 'operatorId', 'action'], rec) - } - )]) -} - -function refillUnit (rec) { - return db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify( - { - action: 'refillUnit', - value: _.pick(['deviceId', 'operatorId', 'action'], rec) - } - )]) -} - -function diagnostics (rec) { - const directory = `${OPERATOR_DATA_DIR}/diagnostics/${rec.deviceId}/` - const sql = `UPDATE devices - SET diagnostics_timestamp = NULL, - diagnostics_scan_updated_at = NULL, - diagnostics_front_updated_at = NULL - WHERE device_id = $1` - - const scanPath = path.join(directory, 'scan.jpg') - const frontPath = path.join(directory, 'front.jpg') - - const removeFiles = [scanPath, frontPath].map(filePath => { - return fsPromises.unlink(filePath).catch(err => { - if (err.code !== 'ENOENT') { - throw err - } - // File doesn't exist, no problem - }) - }) - - return Promise.all(removeFiles) - .then(() => db.none(sql, [rec.deviceId])) - .then(() => db.none('NOTIFY $1:name, $2', ['machineAction', JSON.stringify( - { - action: 'diagnostics', - value: _.pick(['deviceId', 'operatorId', 'action'], rec) - } - )])) -} - -function setMachine (rec, operatorId) { - rec.operatorId = operatorId - switch (rec.action) { - case 'rename': return renameMachine(rec) - case 'resetCashOutBills': return resetCashOutBills(rec) - case 'setCassetteBills': return setCassetteBills(rec) - case 'unpair': return unpair(rec) - case 'reboot': return reboot(rec) - case 'shutdown': return shutdown(rec) - case 'restartServices': return restartServices(rec) - case 'emptyUnit': return emptyUnit(rec) - case 'refillUnit': return refillUnit(rec) - case 'diagnostics': return diagnostics(rec) - default: throw new Error('No such action: ' + rec.action) - } -} - -function updateNetworkPerformance (deviceId, data) { - if (_.isEmpty(data)) return Promise.resolve(true) - const downloadSpeed = _.head(data) - const dbData = { - device_id: deviceId, - download_speed: downloadSpeed.speed, - created: new Date() - } - const cs = new pgp.helpers.ColumnSet(['device_id', 'download_speed', 'created'], - { table: 'machine_network_performance' }) - const onConflict = ' ON CONFLICT (device_id) DO UPDATE SET ' + - cs.assignColumns({ from: 'EXCLUDED', skip: ['device_id'] }) - const upsert = pgp.helpers.insert(dbData, cs) + onConflict - return db.none(upsert) -} - -function updateNetworkHeartbeat (deviceId, data) { - if (_.isEmpty(data)) return Promise.resolve(true) - const avgResponseTime = _.meanBy(e => _.toNumber(e.averageResponseTime), data) - const avgPacketLoss = _.meanBy(e => _.toNumber(e.packetLoss), data) - const dbData = { - id: uuid.v4(), - device_id: deviceId, - average_response_time: avgResponseTime, - average_packet_loss: avgPacketLoss - } - const sql = pgp.helpers.insert(dbData, null, 'machine_network_heartbeat') - return db.none(sql) -} - -function getNetworkPerformance () { - const sql = `SELECT device_id, download_speed FROM machine_network_performance` - return db.manyOrNone(sql) - .then(res => _.map(_.mapKeys(_.camelCase))(res)) -} - -function getNetworkHeartbeat () { - const sql = `SELECT AVG(average_response_time) AS response_time, AVG(average_packet_loss) AS packet_loss, device_id - FROM machine_network_heartbeat - GROUP BY device_id` - return db.manyOrNone(sql) - .then(res => _.map(_.mapKeys(_.camelCase))(res)) -} - -function getNetworkPerformanceByDevice (deviceId) { - const sql = `SELECT device_id, download_speed FROM machine_network_performance WHERE device_id = $1` - return db.manyOrNone(sql, [deviceId]) - .then(res => _.mapKeys(_.camelCase, _.find(it => it.device_id === deviceId, res))) -} - -function getNetworkHeartbeatByDevice (deviceId) { - const sql = `SELECT AVG(average_response_time) AS response_time, AVG(average_packet_loss) AS packet_loss, device_id - FROM machine_network_heartbeat WHERE device_id = $1 - GROUP BY device_id` - return db.manyOrNone(sql, [deviceId]) - .then(res => _.mapKeys(_.camelCase, _.find(it => it.device_id === deviceId, res))) -} - -function updateDiagnostics (deviceId, images) { - const sql = `UPDATE devices - SET diagnostics_timestamp = NOW(), - diagnostics_scan_updated_at = CASE WHEN $2 THEN NOW() ELSE diagnostics_scan_updated_at END, - diagnostics_front_updated_at = CASE WHEN $3 THEN NOW() ELSE diagnostics_front_updated_at END - WHERE device_id = $1` - - const directory = `${OPERATOR_DATA_DIR}/diagnostics/${deviceId}/` - const { scan, front } = images - - return updatePhotos(directory, [['scan.jpg', scan], ['front.jpg', front]]) - .then(() => db.none(sql, [deviceId, !!scan, !!front])) - .catch(err => logger.error('while running machine diagnostics: ', err)) -} - -const updateFailedQRScans = (deviceId, frames) => { - const timestamp = (new Date()).toISOString() - const directory = `${OPERATOR_DATA_DIR}/failedQRScans/${deviceId}/` - const filenames = _.map(no => `${timestamp}-${no}.jpg`, _.range(0, _.size(frames))) - return updatePhotos(directory, _.zip(filenames, frames)) -} - -function createPhoto (name, data, dir) { - if (!data) { - logger.error(`Diagnostics error: No data to save for ${name} photo`) - return Promise.resolve() - } - - const decodedImageData = Buffer.from(data, 'base64') - const filename = path.join(dir, name) - return fsPromises.writeFile(filename, decodedImageData) -} - -function updatePhotos (dir, photoPairs) { - const dirname = path.join(dir) - _.attempt(() => makeDir.sync(dirname)) - return Promise.all(photoPairs.map( - ([filename, data]) => createPhoto(filename, data, dirname) - )) -} - -module.exports = { - getMachineName, - getMachines, - getUnpairedMachines, - getMachine, - getMachineNames, - setMachine, - updateNetworkPerformance, - updateNetworkHeartbeat, - getNetworkPerformance, - getNetworkHeartbeat, - getMachineIds, - emptyMachineUnits, - refillMachineUnits, - updateDiagnostics, - updateFailedQRScans -} diff --git a/lib/new-admin/config/accounts.js b/lib/new-admin/config/accounts.js deleted file mode 100644 index aed637d9..00000000 --- a/lib/new-admin/config/accounts.js +++ /dev/null @@ -1,74 +0,0 @@ -const { COINS, ALL_CRYPTOS } = require('@lamassu/coins') -const _ = require('lodash/fp') - -const { ALL } = require('../../plugins/common/ccxt') - -const { BTC, BCH, DASH, ETH, LTC, USDT, ZEC, XMR, LN, TRX, USDT_TRON, USDC } = COINS -const { bitpay, itbit, bitstamp, kraken, binanceus, cex, binance, bitfinex } = ALL - -const TICKER = 'ticker' -const WALLET = 'wallet' -const LAYER_2 = 'layer2' -const EXCHANGE = 'exchange' -const SMS = 'sms' -const ID_VERIFIER = 'idVerifier' -const EMAIL = 'email' -const ZERO_CONF = 'zeroConf' -const WALLET_SCORING = 'wallet_scoring' -const COMPLIANCE = 'compliance' - -const ALL_ACCOUNTS = [ - { code: 'bitfinex', display: 'Bitfinex', class: TICKER, cryptos: bitfinex.CRYPTO }, - { code: 'bitfinex', display: 'Bitfinex', class: EXCHANGE, cryptos: bitfinex.CRYPTO }, - { code: 'binance', display: 'Binance', class: TICKER, cryptos: binance.CRYPTO }, - { code: 'binanceus', display: 'Binance.us', class: TICKER, cryptos: binanceus.CRYPTO }, - { code: 'cex', display: 'CEX.IO', class: TICKER, cryptos: cex.CRYPTO }, - { code: 'bitpay', display: 'Bitpay', class: TICKER, cryptos: bitpay.CRYPTO }, - { code: 'kraken', display: 'Kraken', class: TICKER, cryptos: kraken.CRYPTO }, - { code: 'bitstamp', display: 'Bitstamp', class: TICKER, cryptos: bitstamp.CRYPTO }, - { code: 'itbit', display: 'itBit', class: TICKER, cryptos: itbit.CRYPTO }, - { code: 'mock-ticker', display: 'Mock (Caution!)', class: TICKER, cryptos: ALL_CRYPTOS, dev: true }, - { code: 'bitcoind', display: 'bitcoind', class: WALLET, cryptos: [BTC] }, - { code: 'no-layer2', display: 'No Layer 2', class: LAYER_2, cryptos: ALL_CRYPTOS }, - { code: 'infura', display: 'Infura/Alchemy', class: WALLET, cryptos: [ETH, USDT, USDC] }, - { code: 'trongrid', display: 'Trongrid', class: WALLET, cryptos: [TRX, USDT_TRON] }, - { code: 'geth', display: 'geth (deprecated)', class: WALLET, cryptos: [ETH, USDT, USDC] }, - { code: 'zcashd', display: 'zcashd', class: WALLET, cryptos: [ZEC] }, - { code: 'litecoind', display: 'litecoind', class: WALLET, cryptos: [LTC] }, - { code: 'dashd', display: 'dashd', class: WALLET, cryptos: [DASH] }, - { code: 'monerod', display: 'monerod', class: WALLET, cryptos: [XMR] }, - { code: 'bitcoincashd', display: 'bitcoincashd', class: WALLET, cryptos: [BCH] }, - { code: 'bitgo', display: 'BitGo', class: WALLET, cryptos: [BTC, ZEC, LTC, BCH, DASH] }, - { code: 'galoy', display: 'Galoy', class: WALLET, cryptos: [LN] }, - { code: 'bitstamp', display: 'Bitstamp', class: EXCHANGE, cryptos: bitstamp.CRYPTO }, - { code: 'itbit', display: 'itBit', class: EXCHANGE, cryptos: itbit.CRYPTO }, - { code: 'kraken', display: 'Kraken', class: EXCHANGE, cryptos: kraken.CRYPTO }, - { code: 'binance', display: 'Binance', class: EXCHANGE, cryptos: binance.CRYPTO }, - { code: 'binanceus', display: 'Binance.us', class: EXCHANGE, cryptos: binanceus.CRYPTO }, - { code: 'cex', display: 'CEX.IO', class: EXCHANGE, cryptos: cex.CRYPTO }, - { code: 'mock-wallet', display: 'Mock (Caution!)', class: WALLET, cryptos: ALL_CRYPTOS, dev: true }, - { code: 'no-exchange', display: 'No exchange', class: EXCHANGE, cryptos: ALL_CRYPTOS }, - { code: 'mock-exchange', display: 'Mock exchange', class: EXCHANGE, cryptos: ALL_CRYPTOS, dev: true }, - { code: 'mock-sms', display: 'Mock SMS', class: SMS, dev: true }, - { code: 'mock-id-verify', display: 'Mock ID verifier', class: ID_VERIFIER, dev: true }, - { code: 'twilio', display: 'Twilio', class: SMS }, - { code: 'telnyx', display: 'Telnyx', class: SMS }, - { code: 'vonage', display: 'Vonage', class: SMS }, - { code: 'inforu', display: 'InforU', class: SMS }, - { code: 'mailgun', display: 'Mailgun', class: EMAIL }, - { code: 'mock-email', display: 'Mock Email', class: EMAIL, dev: true }, - { code: 'none', display: 'None', class: ZERO_CONF, cryptos: ALL_CRYPTOS }, - { code: 'blockcypher', display: 'Blockcypher', class: ZERO_CONF, cryptos: [BTC] }, - { code: 'mock-zero-conf', display: 'Mock 0-conf', class: ZERO_CONF, cryptos: ALL_CRYPTOS, dev: true }, - { code: 'scorechain', display: 'Scorechain', class: WALLET_SCORING, cryptos: [BTC, ETH, LTC, BCH, DASH, USDT, USDC, USDT_TRON, TRX] }, - { code: 'elliptic', display: 'Elliptic', class: WALLET_SCORING, cryptos: [BTC, ETH, LTC, BCH, USDT, USDC, USDT_TRON, TRX, ZEC] }, - { code: 'mock-scoring', display: 'Mock scoring', class: WALLET_SCORING, cryptos: ALL_CRYPTOS, dev: true }, - { code: 'sumsub', display: 'Sumsub', class: COMPLIANCE }, - { code: 'mock-compliance', display: 'Mock Compliance', class: COMPLIANCE, dev: true }, -] - -const flags = require('minimist')(process.argv.slice(2)) -const devMode = flags.dev || flags.lamassuDev -const ACCOUNT_LIST = devMode ? ALL_ACCOUNTS : _.filter(it => !it.dev)(ALL_ACCOUNTS) - -module.exports = { ACCOUNT_LIST } diff --git a/lib/new-admin/config/data/countries.json b/lib/new-admin/config/data/countries.json deleted file mode 100644 index e4fa0c3d..00000000 --- a/lib/new-admin/config/data/countries.json +++ /dev/null @@ -1 +0,0 @@ -[{"code":"US","display":"United States"},{"code":"GB","display":"United Kingdom"},{"code":"CA","display":"Canada"},{"code":"AU","display":"Australia"},{"code":"AW","display":"Aruba"},{"code":"AF","display":"Afghanistan"},{"code":"AO","display":"Angola"},{"code":"AI","display":"Anguilla"},{"code":"AX","display":"Åland Islands"},{"code":"AL","display":"Albania"},{"code":"AD","display":"Andorra"},{"code":"AE","display":"United Arab Emirates"},{"code":"AR","display":"Argentina"},{"code":"AM","display":"Armenia"},{"code":"AS","display":"American Samoa"},{"code":"AQ","display":"Antarctica"},{"code":"TF","display":"French Southern and Antarctic Lands"},{"code":"AG","display":"Antigua and Barbuda"},{"code":"AT","display":"Austria"},{"code":"AZ","display":"Azerbaijan"},{"code":"BI","display":"Burundi"},{"code":"BE","display":"Belgium"},{"code":"BJ","display":"Benin"},{"code":"BF","display":"Burkina Faso"},{"code":"BD","display":"Bangladesh"},{"code":"BG","display":"Bulgaria"},{"code":"BH","display":"Bahrain"},{"code":"BS","display":"Bahamas"},{"code":"BA","display":"Bosnia and Herzegovina"},{"code":"BL","display":"Saint Barthélemy"},{"code":"BY","display":"Belarus"},{"code":"BZ","display":"Belize"},{"code":"BM","display":"Bermuda"},{"code":"BO","display":"Bolivia"},{"code":"BR","display":"Brazil"},{"code":"BB","display":"Barbados"},{"code":"BN","display":"Brunei"},{"code":"BT","display":"Bhutan"},{"code":"BV","display":"Bouvet Island"},{"code":"BW","display":"Botswana"},{"code":"CF","display":"Central African Republic"},{"code":"CC","display":"Cocos (Keeling) Islands"},{"code":"CH","display":"Switzerland"},{"code":"CL","display":"Chile"},{"code":"CN","display":"China"},{"code":"CI","display":"Ivory Coast"},{"code":"CM","display":"Cameroon"},{"code":"CD","display":"DR Congo"},{"code":"CG","display":"Republic of the Congo"},{"code":"CK","display":"Cook Islands"},{"code":"CO","display":"Colombia"},{"code":"KM","display":"Comoros"},{"code":"CV","display":"Cape Verde"},{"code":"CR","display":"Costa Rica"},{"code":"CU","display":"Cuba"},{"code":"CW","display":"Curaçao"},{"code":"CX","display":"Christmas Island"},{"code":"KY","display":"Cayman Islands"},{"code":"CY","display":"Cyprus"},{"code":"CZ","display":"Czech Republic"},{"code":"DE","display":"Germany"},{"code":"DJ","display":"Djibouti"},{"code":"DM","display":"Dominica"},{"code":"DK","display":"Denmark"},{"code":"DO","display":"Dominican Republic"},{"code":"DZ","display":"Algeria"},{"code":"EC","display":"Ecuador"},{"code":"EG","display":"Egypt"},{"code":"ER","display":"Eritrea"},{"code":"EH","display":"Western Sahara"},{"code":"ES","display":"Spain"},{"code":"EE","display":"Estonia"},{"code":"ET","display":"Ethiopia"},{"code":"FI","display":"Finland"},{"code":"FJ","display":"Fiji"},{"code":"FK","display":"Falkland Islands"},{"code":"FR","display":"France"},{"code":"FO","display":"Faroe Islands"},{"code":"FM","display":"Micronesia"},{"code":"GA","display":"Gabon"},{"code":"GE","display":"Georgia"},{"code":"GG","display":"Guernsey"},{"code":"GH","display":"Ghana"},{"code":"GI","display":"Gibraltar"},{"code":"GN","display":"Guinea"},{"code":"GP","display":"Guadeloupe"},{"code":"GM","display":"Gambia"},{"code":"GW","display":"Guinea-Bissau"},{"code":"GQ","display":"Equatorial Guinea"},{"code":"GR","display":"Greece"},{"code":"GD","display":"Grenada"},{"code":"GL","display":"Greenland"},{"code":"GT","display":"Guatemala"},{"code":"GF","display":"French Guiana"},{"code":"GU","display":"Guam"},{"code":"GY","display":"Guyana"},{"code":"HK","display":"Hong Kong"},{"code":"HM","display":"Heard Island and McDonald Islands"},{"code":"HN","display":"Honduras"},{"code":"HR","display":"Croatia"},{"code":"HT","display":"Haiti"},{"code":"HU","display":"Hungary"},{"code":"ID","display":"Indonesia"},{"code":"IM","display":"Isle of Man"},{"code":"IN","display":"India"},{"code":"IO","display":"British Indian Ocean Territory"},{"code":"IE","display":"Ireland"},{"code":"IR","display":"Iran"},{"code":"IQ","display":"Iraq"},{"code":"IS","display":"Iceland"},{"code":"IL","display":"Israel"},{"code":"IT","display":"Italy"},{"code":"JM","display":"Jamaica"},{"code":"JE","display":"Jersey"},{"code":"JO","display":"Jordan"},{"code":"JP","display":"Japan"},{"code":"KZ","display":"Kazakhstan"},{"code":"KE","display":"Kenya"},{"code":"KG","display":"Kyrgyzstan"},{"code":"KH","display":"Cambodia"},{"code":"KI","display":"Kiribati"},{"code":"KN","display":"Saint Kitts and Nevis"},{"code":"KR","display":"South Korea"},{"code":"XK","display":"Kosovo"},{"code":"KW","display":"Kuwait"},{"code":"LA","display":"Laos"},{"code":"LB","display":"Lebanon"},{"code":"LR","display":"Liberia"},{"code":"LY","display":"Libya"},{"code":"LC","display":"Saint Lucia"},{"code":"LI","display":"Liechtenstein"},{"code":"LK","display":"Sri Lanka"},{"code":"LS","display":"Lesotho"},{"code":"LT","display":"Lithuania"},{"code":"LU","display":"Luxembourg"},{"code":"LV","display":"Latvia"},{"code":"MO","display":"Macau"},{"code":"MF","display":"Saint Martin"},{"code":"MA","display":"Morocco"},{"code":"MC","display":"Monaco"},{"code":"MD","display":"Moldova"},{"code":"MG","display":"Madagascar"},{"code":"MV","display":"Maldives"},{"code":"MX","display":"Mexico"},{"code":"MH","display":"Marshall Islands"},{"code":"MK","display":"Macedonia"},{"code":"ML","display":"Mali"},{"code":"MT","display":"Malta"},{"code":"MM","display":"Myanmar"},{"code":"ME","display":"Montenegro"},{"code":"MN","display":"Mongolia"},{"code":"MP","display":"Northern Mariana Islands"},{"code":"MZ","display":"Mozambique"},{"code":"MR","display":"Mauritania"},{"code":"MS","display":"Montserrat"},{"code":"MQ","display":"Martinique"},{"code":"MU","display":"Mauritius"},{"code":"MW","display":"Malawi"},{"code":"MY","display":"Malaysia"},{"code":"YT","display":"Mayotte"},{"code":"NA","display":"Namibia"},{"code":"NC","display":"New Caledonia"},{"code":"NE","display":"Niger"},{"code":"NF","display":"Norfolk Island"},{"code":"NG","display":"Nigeria"},{"code":"NI","display":"Nicaragua"},{"code":"NU","display":"Niue"},{"code":"NL","display":"Netherlands"},{"code":"NO","display":"Norway"},{"code":"NP","display":"Nepal"},{"code":"NR","display":"Nauru"},{"code":"NZ","display":"New Zealand"},{"code":"OM","display":"Oman"},{"code":"PK","display":"Pakistan"},{"code":"PA","display":"Panama"},{"code":"PN","display":"Pitcairn Islands"},{"code":"PE","display":"Peru"},{"code":"PH","display":"Philippines"},{"code":"PW","display":"Palau"},{"code":"PG","display":"Papua New Guinea"},{"code":"PL","display":"Poland"},{"code":"PR","display":"Puerto Rico"},{"code":"KP","display":"North Korea"},{"code":"PT","display":"Portugal"},{"code":"PY","display":"Paraguay"},{"code":"PS","display":"Palestine"},{"code":"PF","display":"French Polynesia"},{"code":"QA","display":"Qatar"},{"code":"RE","display":"Réunion"},{"code":"RO","display":"Romania"},{"code":"RU","display":"Russia"},{"code":"RW","display":"Rwanda"},{"code":"SA","display":"Saudi Arabia"},{"code":"SD","display":"Sudan"},{"code":"SN","display":"Senegal"},{"code":"SG","display":"Singapore"},{"code":"GS","display":"South Georgia"},{"code":"SJ","display":"Svalbard and Jan Mayen"},{"code":"SB","display":"Solomon Islands"},{"code":"SL","display":"Sierra Leone"},{"code":"SV","display":"El Salvador"},{"code":"SM","display":"San Marino"},{"code":"SO","display":"Somalia"},{"code":"PM","display":"Saint Pierre and Miquelon"},{"code":"RS","display":"Serbia"},{"code":"SS","display":"South Sudan"},{"code":"ST","display":"São Tomé and Príncipe"},{"code":"SR","display":"Suriname"},{"code":"SK","display":"Slovakia"},{"code":"SI","display":"Slovenia"},{"code":"SE","display":"Sweden"},{"code":"SZ","display":"Swaziland"},{"code":"SX","display":"Sint Maarten"},{"code":"SC","display":"Seychelles"},{"code":"SY","display":"Syria"},{"code":"TC","display":"Turks and Caicos Islands"},{"code":"TD","display":"Chad"},{"code":"TG","display":"Togo"},{"code":"TH","display":"Thailand"},{"code":"TJ","display":"Tajikistan"},{"code":"TK","display":"Tokelau"},{"code":"TM","display":"Turkmenistan"},{"code":"TL","display":"Timor-Leste"},{"code":"TO","display":"Tonga"},{"code":"TT","display":"Trinidad and Tobago"},{"code":"TN","display":"Tunisia"},{"code":"TR","display":"Turkey"},{"code":"TV","display":"Tuvalu"},{"code":"TW","display":"Taiwan"},{"code":"TZ","display":"Tanzania"},{"code":"UG","display":"Uganda"},{"code":"UA","display":"Ukraine"},{"code":"UM","display":"United States Minor Outlying Islands"},{"code":"UY","display":"Uruguay"},{"code":"UZ","display":"Uzbekistan"},{"code":"VA","display":"Vatican City"},{"code":"VC","display":"Saint Vincent and the Grenadines"},{"code":"VE","display":"Venezuela"},{"code":"VG","display":"British Virgin Islands"},{"code":"VI","display":"United States Virgin Islands"},{"code":"VN","display":"Vietnam"},{"code":"VU","display":"Vanuatu"},{"code":"WF","display":"Wallis and Futuna"},{"code":"WS","display":"Samoa"},{"code":"YE","display":"Yemen"},{"code":"ZA","display":"South Africa"},{"code":"ZM","display":"Zambia"},{"code":"ZW","display":"Zimbabwe"}] \ No newline at end of file diff --git a/lib/new-admin/config/data/languages.json b/lib/new-admin/config/data/languages.json deleted file mode 100644 index b61a3758..00000000 --- a/lib/new-admin/config/data/languages.json +++ /dev/null @@ -1,255 +0,0 @@ -{ -"attribute": {"name":0, "nativeName":1}, -"rtl": {"ar":1,"dv":1,"fa":1,"ha":1,"he":1,"ks":1,"ku":1,"ps":1,"ur":1,"yi":1}, -"lang": { -"aa":["Afar","Afar"], -"ab":["Abkhazian","Аҧсуа"], -"af":["Afrikaans","Afrikaans"], -"ak":["Akan","Akana"], -"am":["Amharic","አማርኛ"], -"an":["Aragonese","Aragonés"], -"ar":["Arabic","العربية"], -"as":["Assamese","অসমীয়া"], -"av":["Avar","Авар"], -"ay":["Aymara","Aymar"], -"az":["Azerbaijani","Azərbaycanca / آذربايجان"], -"ba":["Bashkir","Башҡорт"], -"be":["Belarusian","Беларуская"], -"bg":["Bulgarian","Български"], -"bh":["Bihari","भोजपुरी"], -"bi":["Bislama","Bislama"], -"bm":["Bambara","Bamanankan"], -"bn":["Bengali","বাংলা"], -"bo":["Tibetan","བོད་ཡིག / Bod skad"], -"br":["Breton","Brezhoneg"], -"bs":["Bosnian","Bosanski"], -"ca":["Catalan","Català"], -"ce":["Chechen","Нохчийн"], -"ch":["Chamorro","Chamoru"], -"co":["Corsican","Corsu"], -"cr":["Cree","Nehiyaw"], -"cs":["Czech","Česky"], -"cu":["Old Church Slavonic / Old Bulgarian","словѣньскъ / slověnĭskŭ"], -"cv":["Chuvash","Чăваш"], -"cy":["Welsh","Cymraeg"], -"da":["Danish","Dansk"], -"de":["German","Deutsch"], -"dv":["Divehi","ދިވެހިބަސް"], -"dz":["Dzongkha","ཇོང་ཁ"], -"ee":["Ewe","Ɛʋɛ"], -"el":["Greek","Ελληνικά"], -"en":["English","English"], -"eo":["Esperanto","Esperanto"], -"es":["Spanish","Español"], -"et":["Estonian","Eesti"], -"eu":["Basque","Euskara"], -"fa":["Persian","فارسی"], -"ff":["Peul","Fulfulde"], -"fi":["Finnish","Suomi"], -"fj":["Fijian","Na Vosa Vakaviti"], -"fo":["Faroese","Føroyskt"], -"fr":["French","Français"], -"fy":["West Frisian","Frysk"], -"ga":["Irish","Gaeilge"], -"gd":["Scottish Gaelic","Gàidhlig"], -"gl":["Galician","Galego"], -"gn":["Guarani","Avañe'ẽ"], -"gu":["Gujarati","ગુજરાતી"], -"gv":["Manx","Gaelg"], -"ha":["Hausa","هَوُسَ"], -"he":["Hebrew","עברית"], -"hi":["Hindi","हिन्दी"], -"ho":["Hiri Motu","Hiri Motu"], -"hr":["Croatian","Hrvatski"], -"ht":["Haitian","Krèyol ayisyen"], -"hu":["Hungarian","Magyar"], -"hy":["Armenian","Հայերեն"], -"hz":["Herero","Otsiherero"], -"ia":["Interlingua","Interlingua"], -"id":["Indonesian","Bahasa Indonesia"], -"ie":["Interlingue","Interlingue"], -"ig":["Igbo","Igbo"], -"ii":["Sichuan Yi","ꆇꉙ / 四川彝语"], -"ik":["Inupiak","Iñupiak"], -"io":["Ido","Ido"], -"is":["Icelandic","Íslenska"], -"it":["Italian","Italiano"], -"iu":["Inuktitut","ᐃᓄᒃᑎᑐᑦ"], -"ja":["Japanese","日本語"], -"jv":["Javanese","Basa Jawa"], -"ka":["Georgian","ქართული"], -"kg":["Kongo","KiKongo"], -"ki":["Kikuyu","Gĩkũyũ"], -"kj":["Kuanyama","Kuanyama"], -"kk":["Kazakh","Қазақша"], -"kl":["Greenlandic","Kalaallisut"], -"km":["Cambodian","ភាសាខ្មែរ"], -"kn":["Kannada","ಕನ್ನಡ"], -"ko":["Korean","한국어"], -"kr":["Kanuri","Kanuri"], -"ks":["Kashmiri","कश्मीरी / كشميري"], -"ku":["Kurdish","Kurdî / كوردی"], -"kv":["Komi","Коми"], -"kw":["Cornish","Kernewek"], -"ky":["Kirghiz","Kırgızca / Кыргызча"], -"la":["Latin","Latina"], -"lb":["Luxembourgish","Lëtzebuergesch"], -"lg":["Ganda","Luganda"], -"li":["Limburgian","Limburgs"], -"ln":["Lingala","Lingála"], -"lo":["Laotian","ລາວ / Pha xa lao"], -"lt":["Lithuanian","Lietuvių"], -"lv":["Latvian","Latviešu"], -"mg":["Malagasy","Malagasy"], -"mh":["Marshallese","Kajin Majel / Ebon"], -"mi":["Maori","Māori"], -"mk":["Macedonian","Македонски"], -"ml":["Malayalam","മലയാളം"], -"mn":["Mongolian","Монгол"], -"mo":["Moldovan","Moldovenească"], -"mr":["Marathi","मराठी"], -"ms":["Malay","Bahasa Melayu"], -"mt":["Maltese","bil-Malti"], -"my":["Burmese","Myanmasa"], -"na":["Nauruan","Dorerin Naoero"], -"nd":["North Ndebele","Sindebele"], -"ne":["Nepali","नेपाली"], -"ng":["Ndonga","Oshiwambo"], -"nl":["Dutch","Nederlands"], -"nn":["Norwegian Nynorsk","Norsk (nynorsk)"], -"no":["Norwegian","Norsk (bokmål / riksmål)"], -"nr":["South Ndebele","isiNdebele"], -"nv":["Navajo","Diné bizaad"], -"ny":["Chichewa","Chi-Chewa"], -"oc":["Occitan","Occitan"], -"oj":["Ojibwa","ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin"], -"om":["Oromo","Oromoo"], -"or":["Oriya","ଓଡ଼ିଆ"], -"os":["Ossetian / Ossetic","Иронау"], -"pa":["Panjabi / Punjabi","ਪੰਜਾਬੀ / पंजाबी / پنجابي"], -"pi":["Pali","Pāli / पाऴि"], -"pl":["Polish","Polski"], -"ps":["Pashto","پښتو"], -"pt":["Portuguese","Português"], -"qu":["Quechua","Runa Simi"], -"rm":["Raeto Romance","Rumantsch"], -"rn":["Kirundi","Kirundi"], -"ro":["Romanian","Română"], -"ru":["Russian","Русский"], -"rw":["Rwandi","Kinyarwandi"], -"sa":["Sanskrit","संस्कृतम्"], -"sc":["Sardinian","Sardu"], -"sd":["Sindhi","सिनधि"], -"se":["Northern Sami","Sámegiella"], -"sg":["Sango","Sängö"], -"sh":["Serbo-Croatian","Srpskohrvatski / Српскохрватски"], -"si":["Sinhalese","සිංහල"], -"sk":["Slovak","Slovenčina"], -"sl":["Slovenian","Slovenščina"], -"sm":["Samoan","Gagana Samoa"], -"sn":["Shona","chiShona"], -"so":["Somalia","Soomaaliga"], -"sq":["Albanian","Shqip"], -"sr":["Serbian","Српски"], -"ss":["Swati","SiSwati"], -"st":["Southern Sotho","Sesotho"], -"su":["Sundanese","Basa Sunda"], -"sv":["Swedish","Svenska"], -"sw":["Swahili","Kiswahili"], -"ta":["Tamil","தமிழ்"], -"te":["Telugu","తెలుగు"], -"tg":["Tajik","Тоҷикӣ"], -"th":["Thai","ไทย / Phasa Thai"], -"ti":["Tigrinya","ትግርኛ"], -"tk":["Turkmen","Туркмен / تركمن"], -"tl":["Tagalog / Filipino","Tagalog"], -"tn":["Tswana","Setswana"], -"to":["Tonga","Lea Faka-Tonga"], -"tr":["Turkish","Türkçe"], -"ts":["Tsonga","Xitsonga"], -"tt":["Tatar","Tatarça"], -"tw":["Twi","Twi"], -"ty":["Tahitian","Reo Mā`ohi"], -"ug":["Uyghur","Uyƣurqə / ئۇيغۇرچە"], -"uk":["Ukrainian","Українська"], -"ur":["Urdu","اردو"], -"uz":["Uzbek","Ўзбек"], -"ve":["Venda","Tshivenḓa"], -"vi":["Vietnamese","Tiếng Việt"], -"vo":["Volapük","Volapük"], -"wa":["Walloon","Walon"], -"wo":["Wolof","Wollof"], -"xh":["Xhosa","isiXhosa"], -"yi":["Yiddish","ייִדיש"], -"yo":["Yoruba","Yorùbá"], -"za":["Zhuang","Cuengh / Tôô / 壮语"], -"zh":["Chinese","中文"], -"zu":["Zulu","isiZulu"] -}, -"supported": [ - "en-US", - "en-CA", - "fr-QC", - "ach-UG", - "af-ZA", - "ar-SA", - "bg-BG", - "ca-ES", - "cs-CZ", - "cy-GB", - "de-DE", - "de-AT", - "de-CH", - "da-DK", - "el-GR", - "en-GB", - "en-AU", - "en-HK", - "en-IE", - "en-NZ", - "en-PR", - "es-ES", - "es-MX", - "et-EE", - "fi-FI", - "fr-FR", - "fr-CH", - "fur-IT", - "ga-IE", - "gd-GB", - "he-IL", - "hr-HR", - "hu-HU", - "hy-AM", - "id-ID", - "it-CH", - "it-IT", - "ja-JP", - "ka-GE", - "ko-KR", - "ky-KG", - "lt-LT", - "nb-NO", - "nl-BE", - "nl-NL", - "pt-PT", - "pt-BR", - "pl-PL", - "ro-RO", - "ru-RU", - "sco-GB", - "sh-HR", - "sk-SK", - "sl-SI", - "sr-SP", - "sv-SE", - "th-TH", - "tr-TR", - "uk-UA", - "vi-VN", - "zh-CN", - "zh-HK", - "zh-SG", - "zh-TW" -] -} diff --git a/lib/new-admin/graphql/modules/authentication/FIDO2FAStrategy.js b/lib/new-admin/graphql/modules/authentication/FIDO2FAStrategy.js deleted file mode 100644 index b8ab9d74..00000000 --- a/lib/new-admin/graphql/modules/authentication/FIDO2FAStrategy.js +++ /dev/null @@ -1,175 +0,0 @@ -const simpleWebauthn = require('@simplewebauthn/server') -const base64url = require('base64url') -const _ = require('lodash/fp') - -const userManagement = require('../userManagement') -const credentials = require('../../../../hardware-credentials') -const T = require('../../../../time') -const users = require('../../../../users') - -const devMode = require('minimist')(process.argv.slice(2)).dev - -const REMEMBER_ME_AGE = 90 * T.day - -const generateAttestationOptions = (session, options) => { - return users.getUserById(options.userId).then(user => { - return Promise.all([credentials.getHardwareCredentialsByUserId(user.id), user]) - }).then(([userDevices, user]) => { - const opts = simpleWebauthn.generateAttestationOptions({ - rpName: 'Lamassu', - rpID: options.domain, - userName: user.username, - userID: user.id, - timeout: 60000, - attestationType: 'indirect', - excludeCredentials: userDevices.map(dev => ({ - id: dev.data.credentialID, - type: 'public-key', - transports: ['usb', 'ble', 'nfc', 'internal'] - })), - authenticatorSelection: { - userVerification: 'discouraged', - requireResidentKey: false - } - }) - - session.webauthn = { - attestation: { - challenge: opts.challenge - } - } - - return opts - }) -} - -const generateAssertionOptions = (session, options) => { - return userManagement.authenticateUser(options.username, options.password).then(user => { - return credentials.getHardwareCredentialsByUserId(user.id).then(devices => { - const opts = simpleWebauthn.generateAssertionOptions({ - timeout: 60000, - allowCredentials: devices.map(dev => ({ - id: dev.data.credentialID, - type: 'public-key', - transports: ['usb', 'ble', 'nfc', 'internal'] - })), - userVerification: 'discouraged', - rpID: options.domain - }) - - session.webauthn = { - assertion: { - challenge: opts.challenge - } - } - - return opts - }) - }) -} - -const validateAttestation = (session, options) => { - const webauthnData = session.webauthn.attestation - const expectedChallenge = webauthnData.challenge - - return Promise.all([ - users.getUserById(options.userId), - simpleWebauthn.verifyAttestationResponse({ - credential: options.attestationResponse, - expectedChallenge: `${expectedChallenge}`, - expectedOrigin: `https://${options.domain}${devMode ? `:3001` : ``}`, - expectedRPID: options.domain - }) - ]) - .then(([user, verification]) => { - const { verified, attestationInfo } = verification - - if (!(verified || attestationInfo)) { - session.webauthn = null - return false - } - - const { - counter, - credentialPublicKey, - credentialID - } = attestationInfo - - return credentials.getHardwareCredentialsByUserId(user.id) - .then(userDevices => { - const existingDevice = userDevices.find(device => device.data.credentialID === credentialID) - - if (!existingDevice) { - const newDevice = { - counter, - credentialPublicKey, - credentialID - } - credentials.createHardwareCredential(user.id, newDevice) - } - - session.webauthn = null - return verified - }) - }) -} - -const validateAssertion = (session, options) => { - return userManagement.authenticateUser(options.username, options.password).then(user => { - const expectedChallenge = session.webauthn.assertion.challenge - - return credentials.getHardwareCredentialsByUserId(user.id).then(devices => { - const dbAuthenticator = _.find(dev => { - return Buffer.from(dev.data.credentialID).compare(base64url.toBuffer(options.assertionResponse.rawId)) === 0 - }, devices) - - if (!dbAuthenticator.data) { - throw new Error(`Could not find authenticator matching ${options.assertionResponse.id}`) - } - - const convertedAuthenticator = _.merge( - dbAuthenticator.data, - { credentialPublicKey: Buffer.from(dbAuthenticator.data.credentialPublicKey) } - ) - - let verification - try { - verification = simpleWebauthn.verifyAssertionResponse({ - credential: options.assertionResponse, - expectedChallenge: `${expectedChallenge}`, - expectedOrigin: `https://${options.domain}${devMode ? `:3001` : ``}`, - expectedRPID: options.domain, - authenticator: convertedAuthenticator - }) - } catch (err) { - console.error(err) - return false - } - - const { verified, assertionInfo } = verification - - if (!verified) { - session.webauthn = null - return false - } - - dbAuthenticator.data.counter = assertionInfo.newCounter - return credentials.updateHardwareCredential(dbAuthenticator) - .then(() => { - const finalUser = { id: user.id, username: user.username, role: user.role } - session.user = finalUser - if (options.rememberMe) session.cookie.maxAge = REMEMBER_ME_AGE - - session.webauthn = null - return verified - }) - }) - }) -} - -module.exports = { - generateAttestationOptions, - generateAssertionOptions, - validateAttestation, - validateAssertion -} diff --git a/lib/new-admin/graphql/resolvers/cashbox.resolver.js b/lib/new-admin/graphql/resolvers/cashbox.resolver.js deleted file mode 100644 index 193666c5..00000000 --- a/lib/new-admin/graphql/resolvers/cashbox.resolver.js +++ /dev/null @@ -1,17 +0,0 @@ -const { parseAsync } = require('json2csv') -const cashbox = require('../../../cashbox-batches') -const logDateFormat = require('../../../logs').logDateFormat - -const resolvers = { - Query: { - cashboxBatches: () => cashbox.getBatches(), - cashboxBatchesCsv: (...[, { from, until, timezone }]) => cashbox.getBatches(from, until) - .then(data => parseAsync(logDateFormat(timezone, cashbox.logFormatter(data), ['created']))) - }, - Mutation: { - createBatch: (...[, { deviceId, cashboxCount }]) => cashbox.createCashboxBatch(deviceId, cashboxCount), - editBatch: (...[, { id, performedBy }]) => cashbox.editBatchById(id, performedBy) - } -} - -module.exports = resolvers diff --git a/lib/new-admin/graphql/resolvers/config.resolver.js b/lib/new-admin/graphql/resolvers/config.resolver.js deleted file mode 100644 index 6bb38a22..00000000 --- a/lib/new-admin/graphql/resolvers/config.resolver.js +++ /dev/null @@ -1,11 +0,0 @@ -const { accounts: accountsConfig, countries, languages } = require('../../config') - -const resolver = { - Query: { - countries: () => countries, - languages: () => languages, - accountsConfig: () => accountsConfig - } -} - -module.exports = resolver diff --git a/lib/new-admin/graphql/resolvers/customInfoRequests.resolver.js b/lib/new-admin/graphql/resolvers/customInfoRequests.resolver.js deleted file mode 100644 index fefdcf6b..00000000 --- a/lib/new-admin/graphql/resolvers/customInfoRequests.resolver.js +++ /dev/null @@ -1,33 +0,0 @@ -const authentication = require('../modules/userManagement') -const queries = require('../../services/customInfoRequests') -const DataLoader = require('dataloader') - -const customerCustomInfoRequestsLoader = new DataLoader(ids => queries.batchGetAllCustomInfoRequestsForCustomer(ids), { cache: false }) - -const customInfoRequestLoader = new DataLoader(ids => queries.batchGetCustomInfoRequest(ids), { cache: false }) - -const resolvers = { - Customer: { - customInfoRequests: parent => customerCustomInfoRequestsLoader.load(parent.id) - }, - CustomRequestData: { - customInfoRequest: parent => customInfoRequestLoader.load(parent.infoRequestId) - }, - Query: { - customInfoRequests: (...[, { onlyEnabled }]) => queries.getCustomInfoRequests(onlyEnabled), - customerCustomInfoRequests: (...[, { customerId }]) => queries.getAllCustomInfoRequestsForCustomer(customerId), - customerCustomInfoRequest: (...[, { customerId, infoRequestId }]) => queries.getCustomInfoRequestForCustomer(customerId, infoRequestId) - }, - Mutation: { - insertCustomInfoRequest: (...[, { customRequest }]) => queries.addCustomInfoRequest(customRequest), - removeCustomInfoRequest: (...[, { id }]) => queries.removeCustomInfoRequest(id), - editCustomInfoRequest: (...[, { id, customRequest }]) => queries.editCustomInfoRequest(id, customRequest), - setAuthorizedCustomRequest: (...[, { customerId, infoRequestId, override }, context]) => { - const token = authentication.getToken(context) - return queries.setAuthorizedCustomRequest(customerId, infoRequestId, override, token) - }, - setCustomerCustomInfoRequest: (...[, { customerId, infoRequestId, data }]) => queries.setCustomerData(customerId, infoRequestId, data) - } -} - -module.exports = resolvers diff --git a/lib/new-admin/graphql/resolvers/loyalty.resolver.js b/lib/new-admin/graphql/resolvers/loyalty.resolver.js deleted file mode 100644 index 9a12a89e..00000000 --- a/lib/new-admin/graphql/resolvers/loyalty.resolver.js +++ /dev/null @@ -1,16 +0,0 @@ -const loyalty = require('../../../loyalty') - -const resolvers = { - Query: { - promoCodes: () => loyalty.getAvailablePromoCodes(), - individualDiscounts: () => loyalty.getAvailableIndividualDiscounts() - }, - Mutation: { - createPromoCode: (...[, { code, discount }]) => loyalty.createPromoCode(code, discount), - deletePromoCode: (...[, { codeId }]) => loyalty.deletePromoCode(codeId), - createIndividualDiscount: (...[, { customerId, discount }]) => loyalty.createIndividualDiscount(customerId, discount), - deleteIndividualDiscount: (...[, { discountId }]) => loyalty.deleteIndividualDiscount(discountId) - } -} - -module.exports = resolvers diff --git a/lib/new-admin/graphql/resolvers/scalar.resolver.js b/lib/new-admin/graphql/resolvers/scalar.resolver.js deleted file mode 100644 index ddfc12ac..00000000 --- a/lib/new-admin/graphql/resolvers/scalar.resolver.js +++ /dev/null @@ -1,9 +0,0 @@ -const { DateTimeISOResolver, JSONResolver, JSONObjectResolver } = require('graphql-scalars') - -const resolvers = { - JSON: JSONResolver, - JSONObject: JSONObjectResolver, - DateTimeISO: DateTimeISOResolver -} - -module.exports = resolvers diff --git a/lib/new-admin/graphql/resolvers/transaction.resolver.js b/lib/new-admin/graphql/resolvers/transaction.resolver.js deleted file mode 100644 index f262517a..00000000 --- a/lib/new-admin/graphql/resolvers/transaction.resolver.js +++ /dev/null @@ -1,43 +0,0 @@ -const DataLoader = require('dataloader') -const { parseAsync } = require('json2csv') -const _ = require('lodash/fp') - -const filters = require('../../filters') -const cashOutTx = require('../../../cash-out/cash-out-tx') -const cashInTx = require('../../../cash-in/cash-in-tx') -const transactions = require('../../services/transactions') -const anonymous = require('../../../constants').anonymousCustomer -const logDateFormat = require('../../../logs').logDateFormat - -const transactionsLoader = new DataLoader(ids => transactions.getCustomerTransactionsBatch(ids), { cache: false }) - -const resolvers = { - Customer: { - transactions: parent => transactionsLoader.load(parent.id) - }, - Transaction: { - isAnonymous: parent => (parent.customerId === anonymous.uuid) - }, - Query: { - transactions: (...[, { from, until, limit, offset, txClass, deviceId, customerName, fiatCode, cryptoCode, toAddress, status, swept, excludeTestingCustomers }]) => - transactions.batch(from, until, limit, offset, txClass, deviceId, customerName, fiatCode, cryptoCode, toAddress, status, swept, excludeTestingCustomers), - transactionsCsv: (...[, { from, until, limit, offset, txClass, deviceId, customerName, fiatCode, cryptoCode, toAddress, status, swept, timezone, excludeTestingCustomers, simplified }]) => - transactions.batch(from, until, limit, offset, null, txClass, deviceId, customerName, fiatCode, cryptoCode, toAddress, status, swept, excludeTestingCustomers, simplified) - .then(data => parseAsync(logDateFormat(timezone, data, ['created', 'sendTime', 'publishedAt']))), - transactionCsv: (...[, { id, txClass, timezone }]) => - transactions.getTx(id, txClass).then(data => - parseAsync(logDateFormat(timezone, [data], ['created', 'sendTime', 'publishedAt'])) - ), - txAssociatedDataCsv: (...[, { id, txClass, timezone }]) => - transactions.getTxAssociatedData(id, txClass).then(data => - parseAsync(logDateFormat(timezone, data, ['created'])) - ), - transactionFilters: () => filters.transaction() - }, - Mutation: { - cancelCashOutTransaction: (...[, { id }]) => cashOutTx.cancel(id), - cancelCashInTransaction: (...[, { id }]) => cashInTx.cancel(id) - } -} - -module.exports = resolvers diff --git a/lib/new-admin/graphql/resolvers/users.resolver.js b/lib/new-admin/graphql/resolvers/users.resolver.js deleted file mode 100644 index c62bc8e0..00000000 --- a/lib/new-admin/graphql/resolvers/users.resolver.js +++ /dev/null @@ -1,92 +0,0 @@ -const authentication = require('../modules/authentication') -const userManagement = require('../modules/userManagement') -const users = require('../../../users') -const sessionManager = require('../../../session-manager') - -const getAttestationQueryOptions = variables => { - switch (authentication.CHOSEN_STRATEGY) { - case 'FIDO2FA': - return { userId: variables.userID, domain: variables.domain } - case 'FIDOPasswordless': - return { userId: variables.userID, domain: variables.domain } - case 'FIDOUsernameless': - return { userId: variables.userID, domain: variables.domain } - default: - return {} - } -} - -const getAssertionQueryOptions = variables => { - switch (authentication.CHOSEN_STRATEGY) { - case 'FIDO2FA': - return { username: variables.username, password: variables.password, domain: variables.domain } - case 'FIDOPasswordless': - return { username: variables.username, domain: variables.domain } - case 'FIDOUsernameless': - return { domain: variables.domain } - default: - return {} - } -} - -const getAttestationMutationOptions = variables => { - switch (authentication.CHOSEN_STRATEGY) { - case 'FIDO2FA': - return { userId: variables.userID, attestationResponse: variables.attestationResponse, domain: variables.domain } - case 'FIDOPasswordless': - return { userId: variables.userID, attestationResponse: variables.attestationResponse, domain: variables.domain } - case 'FIDOUsernameless': - return { userId: variables.userID, attestationResponse: variables.attestationResponse, domain: variables.domain } - default: - return {} - } -} - -const getAssertionMutationOptions = variables => { - switch (authentication.CHOSEN_STRATEGY) { - case 'FIDO2FA': - return { username: variables.username, password: variables.password, rememberMe: variables.rememberMe, assertionResponse: variables.assertionResponse, domain: variables.domain } - case 'FIDOPasswordless': - return { username: variables.username, rememberMe: variables.rememberMe, assertionResponse: variables.assertionResponse, domain: variables.domain } - case 'FIDOUsernameless': - return { assertionResponse: variables.assertionResponse, domain: variables.domain } - default: - return {} - } -} - -const resolver = { - Query: { - users: () => users.getUsers(), - sessions: () => sessionManager.getSessions(), - userSessions: (...[, { username }]) => sessionManager.getSessionsByUsername(username), - userData: (...[, {}, context]) => userManagement.getUserData(context), - get2FASecret: (...[, { username, password }]) => userManagement.get2FASecret(username, password), - confirm2FA: (...[, { code }, context]) => userManagement.confirm2FA(code, context), - validateRegisterLink: (...[, { token }]) => userManagement.validateRegisterLink(token), - validateResetPasswordLink: (...[, { token }]) => userManagement.validateResetPasswordLink(token), - validateReset2FALink: (...[, { token }]) => userManagement.validateReset2FALink(token), - generateAttestationOptions: (...[, variables, context]) => authentication.strategy.generateAttestationOptions(context.req.session, getAttestationQueryOptions(variables)), - generateAssertionOptions: (...[, variables, context]) => authentication.strategy.generateAssertionOptions(context.req.session, getAssertionQueryOptions(variables)) - }, - Mutation: { - enableUser: (...[, { confirmationCode, id }, context]) => userManagement.enableUser(confirmationCode, id, context), - disableUser: (...[, { confirmationCode, id }, context]) => userManagement.disableUser(confirmationCode, id, context), - deleteSession: (...[, { sid }, context]) => userManagement.deleteSession(sid, context), - deleteUserSessions: (...[, { username }]) => sessionManager.deleteSessionsByUsername(username), - changeUserRole: (...[, { confirmationCode, id, newRole }, context]) => userManagement.changeUserRole(confirmationCode, id, newRole, context), - login: (...[, { username, password }]) => userManagement.login(username, password), - input2FA: (...[, { username, password, rememberMe, code }, context]) => userManagement.input2FA(username, password, rememberMe, code, context), - setup2FA: (...[, { username, password, rememberMe, codeConfirmation }, context]) => userManagement.setup2FA(username, password, rememberMe, codeConfirmation, context), - createResetPasswordToken: (...[, { confirmationCode, userID }, context]) => userManagement.createResetPasswordToken(confirmationCode, userID, context), - createReset2FAToken: (...[, { confirmationCode, userID }, context]) => userManagement.createReset2FAToken(confirmationCode, userID, context), - createRegisterToken: (...[, { username, role }]) => userManagement.createRegisterToken(username, role), - register: (...[, { token, username, password, role }]) => userManagement.register(token, username, password, role), - resetPassword: (...[, { token, userID, newPassword }, context]) => userManagement.resetPassword(token, userID, newPassword, context), - reset2FA: (...[, { token, userID, code }, context]) => userManagement.reset2FA(token, userID, code, context), - validateAttestation: (...[, variables, context]) => authentication.strategy.validateAttestation(context.req.session, getAttestationMutationOptions(variables)), - validateAssertion: (...[, variables, context]) => authentication.strategy.validateAssertion(context.req.session, getAssertionMutationOptions(variables)) - } -} - -module.exports = resolver diff --git a/lib/new-admin/graphql/types/log.type.js b/lib/new-admin/graphql/types/log.type.js deleted file mode 100644 index de7aee38..00000000 --- a/lib/new-admin/graphql/types/log.type.js +++ /dev/null @@ -1,26 +0,0 @@ -const gql = require('graphql-tag') - -const typeDef = gql` - type MachineLog { - id: ID! - logLevel: String! - timestamp: DateTimeISO! - message: String! - } - - type ServerLog { - id: ID! - logLevel: String! - timestamp: DateTimeISO! - message: String - } - - type Query { - machineLogs(deviceId: ID!, from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int): [MachineLog] @auth - machineLogsCsv(deviceId: ID!, from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int, timezone: String): String @auth - serverLogs(from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int): [ServerLog] @auth - serverLogsCsv(from: DateTimeISO, until: DateTimeISO, limit: Int, offset: Int, timezone: String): String @auth - } -` - -module.exports = typeDef diff --git a/lib/new-admin/middlewares/session.js b/lib/new-admin/middlewares/session.js deleted file mode 100644 index 2c0400af..00000000 --- a/lib/new-admin/middlewares/session.js +++ /dev/null @@ -1,26 +0,0 @@ -const express = require('express') -const router = express.Router() -const session = require('express-session') -const PgSession = require('connect-pg-simple')(session) -const db = require('../../db') -const { USER_SESSIONS_TABLE_NAME } = require('../../constants') -const { getOperatorId } = require('../../operator') - -router.use('*', async (req, res, next) => getOperatorId('authentication').then(operatorId => session({ - store: new PgSession({ - pgPromise: db, - tableName: USER_SESSIONS_TABLE_NAME - }), - name: 'lamassu_sid', - secret: operatorId, - resave: false, - saveUninitialized: false, - cookie: { - httpOnly: true, - secure: true, - sameSite: true - } -})(req, res, next)) -) - -module.exports = router diff --git a/lib/new-admin/services/funding.js b/lib/new-admin/services/funding.js deleted file mode 100644 index 5b425d82..00000000 --- a/lib/new-admin/services/funding.js +++ /dev/null @@ -1,75 +0,0 @@ -const _ = require('lodash/fp') -const BN = require('../../bn') -const settingsLoader = require('../../new-settings-loader') -const configManager = require('../../new-config-manager') -const wallet = require('../../wallet') -const ticker = require('../../ticker') -const txBatching = require('../../tx-batching') -const { utils: coinUtils } = require('@lamassu/coins') - -function computeCrypto (cryptoCode, _balance) { - const cryptoRec = coinUtils.getCryptoCurrency(cryptoCode) - const unitScale = cryptoRec.unitScale - - return new BN(_balance).shiftedBy(-unitScale).decimalPlaces(5) -} - -function computeFiat (rate, cryptoCode, _balance) { - const cryptoRec = coinUtils.getCryptoCurrency(cryptoCode) - const unitScale = cryptoRec.unitScale - - return new BN(_balance).shiftedBy(-unitScale).times(rate).decimalPlaces(5) -} - -function getSingleCoinFunding (settings, fiatCode, cryptoCode) { - const promises = [ - wallet.newFunding(settings, cryptoCode), - ticker.getRates(settings, fiatCode, cryptoCode), - txBatching.getOpenBatchCryptoValue(cryptoCode) - ] - - return Promise.all(promises) - .then(([fundingRec, ratesRec, batchRec]) => { - const rates = ratesRec.rates - const rate = (rates.ask.plus(rates.bid)).div(2) - const fundingConfirmedBalance = fundingRec.fundingConfirmedBalance - const fiatConfirmedBalance = computeFiat(rate, cryptoCode, fundingConfirmedBalance) - const pending = fundingRec.fundingPendingBalance.minus(batchRec) - const fiatPending = computeFiat(rate, cryptoCode, pending) - const fundingAddress = fundingRec.fundingAddress - const fundingAddressUrl = coinUtils.buildUrl(cryptoCode, fundingAddress) - - return { - cryptoCode, - fundingAddress, - fundingAddressUrl, - confirmedBalance: computeCrypto(cryptoCode, fundingConfirmedBalance).toFormat(5), - pending: computeCrypto(cryptoCode, pending).toFormat(5), - fiatConfirmedBalance: fiatConfirmedBalance, - fiatPending: fiatPending, - fiatCode - } - }) -} - -// Promise.allSettled not running on current version of node -const reflect = p => p.then(value => ({ value, status: 'fulfilled' }), error => ({ error: error.toString(), status: 'rejected' })) - -function getFunding () { - return settingsLoader.loadLatest().then(settings => { - const cryptoCodes = configManager.getAllCryptoCurrencies(settings.config) - const fiatCode = configManager.getGlobalLocale(settings.config).fiatCurrency - const pareCoins = c => _.includes(c.cryptoCode, cryptoCodes) - const cryptoCurrencies = coinUtils.cryptoCurrencies() - const cryptoDisplays = _.filter(pareCoins, cryptoCurrencies) - - const promises = cryptoDisplays.map(it => getSingleCoinFunding(settings, fiatCode, it.cryptoCode)) - return Promise.all(promises.map(reflect)) - .then((response) => { - const mapped = response.map(it => _.merge({ errorMsg: it.error }, it.value)) - return _.toArray(_.merge(mapped, cryptoDisplays)) - }) - }) -} - -module.exports = { getFunding } diff --git a/lib/new-admin/services/login.js b/lib/new-admin/services/login.js deleted file mode 100644 index 8eb19c53..00000000 --- a/lib/new-admin/services/login.js +++ /dev/null @@ -1,16 +0,0 @@ -const db = require('../../db') - -function validateUser (username, password) { - return db.tx(t => { - const q1 = t.one('SELECT * FROM users WHERE username=$1 AND password=$2', [username, password]) - const q2 = t.none('UPDATE users SET last_accessed = now() WHERE username=$1', [username]) - - return t.batch([q1, q2]) - .then(([user]) => user) - .catch(() => false) - }) -} - -module.exports = { - validateUser -} diff --git a/lib/new-admin/services/pairing.js b/lib/new-admin/services/pairing.js deleted file mode 100644 index d267c1a9..00000000 --- a/lib/new-admin/services/pairing.js +++ /dev/null @@ -1,34 +0,0 @@ -const fs = require('fs') -const pify = require('pify') -const readFile = pify(fs.readFile) -const crypto = require('crypto') -const baseX = require('base-x') -const { parse, NIL } = require('uuid') - -const db = require('../../db') -const pairing = require('../../pairing') - -const ALPHA_BASE = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:' -const bsAlpha = baseX(ALPHA_BASE) - -const CA_PATH = process.env.CA_PATH -const HOSTNAME = process.env.HOSTNAME - -const unpair = pairing.unpair - -function totem (name) { - return readFile(CA_PATH) - .then(data => { - const caHash = crypto.createHash('sha256').update(data).digest() - const token = crypto.randomBytes(32) - const hexToken = token.toString('hex') - const caHexToken = crypto.createHash('sha256').update(hexToken).digest('hex') - const buf = Buffer.concat([caHash, token, Buffer.from(HOSTNAME)]) - const sql = 'insert into pairing_tokens (token, name) values ($1, $3), ($2, $3)' - - return db.none(sql, [hexToken, caHexToken, name]) - .then(() => bsAlpha.encode(buf)) - }) -} - -module.exports = { totem, unpair } diff --git a/lib/notifier/index.js b/lib/notifier/index.js deleted file mode 100644 index 8e61f162..00000000 --- a/lib/notifier/index.js +++ /dev/null @@ -1,328 +0,0 @@ -const _ = require('lodash/fp') - -const configManager = require('../new-config-manager') -const logger = require('../logger') -const queries = require('./queries') -const settingsLoader = require('../new-settings-loader') -const customers = require('../customers') - -const notificationCenter = require('./notificationCenter') -const utils = require('./utils') -const emailFuncs = require('./email') -const smsFuncs = require('./sms') -const webhookFuncs = require('./webhook') -const { STALE, STALE_STATE } = require('./codes') - -function buildMessage (alerts, notifications) { - const smsEnabled = utils.isActive(notifications.sms) - const emailEnabled = utils.isActive(notifications.email) - - let rec = {} - if (smsEnabled) { - rec = _.set(['sms', 'body'])( - smsFuncs.printSmsAlerts(alerts, notifications.sms) - )(rec) - } - if (emailEnabled) { - rec = _.set(['email', 'subject'])( - emailFuncs.alertSubject(alerts, notifications.email) - )(rec) - rec = _.set(['email', 'body'])( - emailFuncs.printEmailAlerts(alerts, notifications.email) - )(rec) - } - - return rec -} - -function checkNotification (plugins) { - const notifications = plugins.getNotificationConfig() - const smsEnabled = utils.isActive(notifications.sms) - const emailEnabled = utils.isActive(notifications.email) - const notificationCenterEnabled = utils.isActive(notifications.notificationCenter) - - if (!(notificationCenterEnabled || smsEnabled || emailEnabled)) return Promise.resolve() - - return getAlerts(plugins) - .then(alerts => { - notifyIfActive('errors', 'errorAlertsNotify', alerts) - const currentAlertFingerprint = utils.buildAlertFingerprint( - alerts, - notifications - ) - if (!currentAlertFingerprint) { - const inAlert = !!utils.getAlertFingerprint() - // variables for setAlertFingerprint: (fingerprint = null, lastAlertTime = null) - utils.setAlertFingerprint(null, null) - if (inAlert) return utils.sendNoAlerts(plugins, smsEnabled, emailEnabled) - } - if (utils.shouldNotAlert(currentAlertFingerprint)) return - - const message = buildMessage(alerts, notifications) - utils.setAlertFingerprint(currentAlertFingerprint, Date.now()) - return plugins.sendMessage(message) - }) - .then(results => { - if (results && results.length > 0) { - logger.debug('Successfully sent alerts') - } - }) - .catch(logger.error) -} - -function getAlerts (plugins) { - return Promise.all([ - plugins.checkBalances(), - queries.machineEvents(), - plugins.getMachineNames() - ]).then(([balances, events, devices]) => { - notifyIfActive('balance', 'balancesNotify', balances) - return buildAlerts(checkPings(devices), balances, events, devices) - }) -} - -function buildAlerts (pings, balances, events, devices) { - const alerts = { devices: {}, deviceNames: {} } - alerts.general = _.filter(r => !r.deviceId, balances) - _.forEach(device => { - const deviceId = device.deviceId - const ping = pings[deviceId] || [] - const stuckScreen = checkStuckScreen(events, device) - - alerts.devices = _.set([deviceId, 'balanceAlerts'], _.filter( - ['deviceId', deviceId], - balances - ), alerts.devices) - alerts.devices[deviceId].deviceAlerts = _.isEmpty(ping) ? stuckScreen : ping - - alerts.deviceNames[deviceId] = device.name - }, devices) - - return alerts -} - -function checkPings (devices) { - const deviceIds = _.map('deviceId', devices) - const pings = _.map(utils.checkPing, devices) - return _.zipObject(deviceIds)(pings) -} - -function checkStuckScreen (deviceEvents, machine) { - const lastEvent = _.pipe( - _.filter(e => e.device_id === machine.deviceId), - _.sortBy(utils.getDeviceTime), - _.map(utils.parseEventNote), - _.last - )(deviceEvents) - - if (!lastEvent) return [] - - const state = lastEvent.note.state - const isIdle = lastEvent.note.isIdle - - if (isIdle) return [] - - const age = Math.floor(lastEvent.age) - const machineName = machine.name - if (age > STALE_STATE) return [{ code: STALE, state, age, machineName }] - - return [] -} - -function transactionNotify (tx, rec) { - return settingsLoader.loadLatestConfig().then(config => { - const notifSettings = configManager.getGlobalNotifications(config) - const highValueTx = tx.fiat.gt(notifSettings.highValueTransaction || Infinity) - const isCashOut = tx.direction === 'cashOut' - - // for notification center - const directionDisplay = isCashOut ? 'cash-out' : 'cash-in' - const readyToNotify = !isCashOut || (tx.direction === 'cashOut' && rec.isRedemption) - // awaiting for redesign. notification should not be sent if toggle in the settings table is disabled, - // but currently we're sending notifications of high value tx even with the toggle disabled - if (readyToNotify && !highValueTx) { - notifyIfActive('transactions', 'notifCenterTransactionNotify', highValueTx, directionDisplay, tx.fiat, tx.fiatCode, tx.deviceId, tx.toAddress) - } else if (readyToNotify && highValueTx) { - notificationCenter.notifCenterTransactionNotify(highValueTx, directionDisplay, tx.fiat, tx.fiatCode, tx.deviceId, tx.toAddress) - } - - // alert through sms or email any transaction or high value transaction, if SMS || email alerts are enabled - const walletSettings = configManager.getWalletSettings(tx.cryptoCode, config) - const zeroConfLimit = walletSettings.zeroConfLimit || 0 - const zeroConf = isCashOut && tx.fiat.lte(zeroConfLimit) - const notificationsEnabled = notifSettings.sms.transactions || notifSettings.email.transactions - const customerPromise = tx.customerId ? customers.getById(tx.customerId) : Promise.resolve({}) - - if (!notificationsEnabled && !highValueTx) return Promise.resolve() - if (zeroConf && isCashOut && !rec.isRedemption && !rec.error) return Promise.resolve() - if (!zeroConf && rec.isRedemption) return sendRedemptionMessage(tx.id, rec.error) - - return Promise.all([ - queries.getMachineName(tx.deviceId), - customerPromise - ]).then(([machineName, customer]) => { - return utils.buildTransactionMessage(tx, rec, highValueTx, machineName, customer) - }).then(([msg, highValueTx]) => sendTransactionMessage(msg, highValueTx)) - }) -} - -function complianceNotify (settings, customer, deviceId, action, period) { - const timestamp = (new Date()).toLocaleString() - return queries.getMachineName(deviceId) - .then(machineName => { - const notifications = configManager.getGlobalNotifications(settings.config) - - const msgCore = { - BLOCKED: `was blocked`, - SUSPENDED: `was suspended for ${!!period && period} days`, - PENDING_COMPLIANCE: `is waiting for your manual approval`, - } - - const rec = { - sms: { - body: `Customer ${customer.phone} ${msgCore[action]} - ${machineName}. ${timestamp}` - }, - email: { - subject: `Customer compliance`, - body: `Customer ${customer.phone} ${msgCore[action]} in machine ${machineName}. ${timestamp}` - }, - webhook: { - topic: `Customer compliance`, - content: `Customer ${customer.phone} ${msgCore[action]} in machine ${machineName}. ${timestamp}` - } - } - - const promises = [] - - const emailActive = - notifications.email.active && - notifications.email.compliance - - const smsActive = - notifications.sms.active && - notifications.sms.compliance - - const webhookActive = true - - if (emailActive) promises.push(emailFuncs.sendMessage(settings, rec)) - if (smsActive) promises.push(smsFuncs.sendMessage(settings, rec)) - if (webhookActive) promises.push(webhookFuncs.sendMessage(settings, rec)) - - notifyIfActive('compliance', 'customerComplianceNotify', customer, deviceId, action, machineName, period) - - return Promise.all(promises) - .catch(err => console.error(`An error occurred when sending a notification. Please check your notification preferences and 3rd party account configuration: ${err.stack}`)) - }) -} - -function sendRedemptionMessage (txId, error) { - const subject = `Here's an update on transaction ${txId}` - const body = error - ? `Error: ${error}` - : 'It was just dispensed successfully' - - const rec = { - sms: { - body: `${subject} - ${body}` - }, - email: { - subject, - body - }, - webhook: { - topic: `Transaction update`, - content: body - } - } - return sendTransactionMessage(rec) -} - -function sendTransactionMessage (rec, isHighValueTx) { - return settingsLoader.loadLatest().then(settings => { - const notifications = configManager.getGlobalNotifications(settings.config) - - const promises = [] - - const emailActive = - notifications.email.active && - (notifications.email.transactions || isHighValueTx) - if (emailActive) promises.push(emailFuncs.sendMessage(settings, rec)) - - const smsActive = - notifications.sms.active && - (notifications.sms.transactions || isHighValueTx) - if (smsActive) promises.push(smsFuncs.sendMessage(settings, rec)) - - // TODO: Webhook transaction notifications are dependent on notification settings, due to how transactionNotify() is programmed - // As changing it would require structural change to that function and the current behavior is temporary (webhooks will eventually have settings tied to them), it's not worth those changes right now - const webhookActive = true - if (webhookActive) promises.push(webhookFuncs.sendMessage(settings, rec)) - - return Promise.all(promises) - .catch(err => console.error(`An error occurred when sending a notification. Please check your notification preferences and 3rd party account configuration: ${err.stack}`)) - }) -} - -function cashboxNotify (deviceId) { - return Promise.all([ - settingsLoader.loadLatest(), - queries.getMachineName(deviceId) - ]) - .then(([settings, machineName]) => { - const notifications = configManager.getGlobalNotifications(settings.config) - const rec = { - sms: { - body: `Cashbox removed - ${machineName}` - }, - email: { - subject: `Cashbox removal`, - body: `Cashbox removed in machine ${machineName}` - }, - webhook: { - topic: `Cashbox removal`, - content: `Cashbox removed in machine ${machineName}` - } - } - - const promises = [] - - const emailActive = - notifications.email.active && - notifications.email.security - - const smsActive = - notifications.sms.active && - notifications.sms.security - - const webhookActive = true - - if (emailActive) promises.push(emailFuncs.sendMessage(settings, rec)) - if (smsActive) promises.push(smsFuncs.sendMessage(settings, rec)) - if (webhookActive) promises.push(webhookFuncs.sendMessage(settings, rec)) - notifyIfActive('security', 'cashboxNotify', deviceId) - - return Promise.all(promises) - .catch(err => console.error(`An error occurred when sending a notification. Please check your notification preferences and 3rd party account configuration: ${err.stack}`)) - }) -} - -// for notification center, check if type of notification is active before calling the respective notify function -const notifyIfActive = (type, fnName, ...args) => { - return settingsLoader.loadLatestConfig().then(config => { - const notificationSettings = configManager.getGlobalNotifications(config).notificationCenter - if (!notificationCenter[fnName]) return Promise.reject(new Error(`Notification function ${fnName} for type ${type} does not exist`)) - if (!(notificationSettings.active && notificationSettings[type])) return Promise.resolve() - return notificationCenter[fnName](...args) - }).catch(logger.error) -} - -module.exports = { - transactionNotify, - complianceNotify, - checkNotification, - checkPings, - checkStuckScreen, - sendRedemptionMessage, - cashboxNotify, - notifyIfActive -} diff --git a/lib/notifier/notificationCenter.js b/lib/notifier/notificationCenter.js deleted file mode 100644 index 7f3480b0..00000000 --- a/lib/notifier/notificationCenter.js +++ /dev/null @@ -1,215 +0,0 @@ -const _ = require('lodash/fp') - -const queries = require('./queries') -const utils = require('./utils') -const customers = require('../customers') -const { - NOTIFICATION_TYPES: { - SECURITY, - COMPLIANCE, - CRYPTO_BALANCE, - FIAT_BALANCE, - ERROR, - HIGH_VALUE_TX, - NORMAL_VALUE_TX - }, - - STALE, - PING, - - HIGH_CRYPTO_BALANCE, - LOW_CRYPTO_BALANCE, - CASH_BOX_FULL, - LOW_CASH_OUT, - LOW_RECYCLER_STACKER, -} = require('./codes') - -const sanctionsNotify = (customer, phone) => { - const code = 'SANCTIONS' - const detailB = utils.buildDetail({ customerId: customer.id, code }) - const addNotif = phone => - queries.addNotification(COMPLIANCE, `Blocked customer with phone ${phone} for being on the OFAC sanctions list`, detailB) - // if it's a new customer then phone comes as undefined - return phone ? addNotif(phone) : customers.getById(customer.id).then(c => addNotif(c.phone)) -} - -const clearOldCustomerSuspendedNotifications = (customerId, deviceId) => { - const detailB = utils.buildDetail({ code: 'SUSPENDED', customerId, deviceId }) - return queries.invalidateNotification(detailB, 'compliance') -} - -const customerComplianceNotify = (customer, deviceId, code, machineName, days = null) => { - // code for now can be "BLOCKED", "SUSPENDED" - const detailB = utils.buildDetail({ customerId: customer.id, code, deviceId }) - const date = new Date() - if (days) { - date.setDate(date.getDate() + days) - } - const message = code === 'SUSPENDED' ? `Customer ${customer.phone} suspended until ${date.toLocaleString()}` : - code === 'BLOCKED' ? `Customer ${customer.phone} blocked` : - `Customer ${customer.phone} has pending compliance in machine ${machineName}` - - return clearOldCustomerSuspendedNotifications(customer.id, deviceId) - .then(() => queries.getValidNotifications(COMPLIANCE, detailB)) - .then(res => { - if (res.length > 0) return Promise.resolve() - return queries.addNotification(COMPLIANCE, message, detailB) - }) -} - -const clearOldFiatNotifications = (balances) => { - return queries.getAllValidNotifications(FIAT_BALANCE).then(notifications => { - const filterByBalance = _.filter(notification => { - const { cassette, deviceId } = notification.detail - return !_.find(balance => balance.cassette === cassette && balance.deviceId === deviceId)(balances) - }) - const indexesToInvalidate = _.compose(_.map('id'), filterByBalance)(notifications) - const notInvalidated = _.filter(notification => { - return !_.find(id => notification.id === id)(indexesToInvalidate) - }, notifications) - return (indexesToInvalidate.length ? queries.batchInvalidate(indexesToInvalidate) : Promise.resolve()).then(() => notInvalidated) - }) -} - -const fiatBalancesNotify = (fiatWarnings) => { - return clearOldFiatNotifications(fiatWarnings).then(notInvalidated => { - return fiatWarnings.forEach(balance => { - if (_.find(o => { - const { cassette, deviceId } = o.detail - return cassette === balance.cassette && deviceId === balance.deviceId - }, notInvalidated)) return - const message = balance.code === LOW_CASH_OUT ? - `Cash-out cassette ${balance.cassette} low or empty!` : - balance.code === LOW_RECYCLER_STACKER ? - `Recycler ${balance.cassette} low or empty!` : - balance.code === CASH_BOX_FULL ? - `Cash box full or almost full!` : - `Cash box full or almost full!` /* Shouldn't happen */ - const detailB = utils.buildDetail({ deviceId: balance.deviceId, cassette: balance.cassette }) - return queries.addNotification(FIAT_BALANCE, message, detailB) - }) - }) -} - -const clearOldCryptoNotifications = balances => { - return queries.getAllValidNotifications(CRYPTO_BALANCE).then(res => { - const filterByBalance = _.filter(notification => { - const { cryptoCode, code } = notification.detail - return !_.find(balance => balance.cryptoCode === cryptoCode && balance.code === code)(balances) - }) - const indexesToInvalidate = _.compose(_.map('id'), filterByBalance)(res) - - const notInvalidated = _.filter(notification => { - return !_.find(id => notification.id === id)(indexesToInvalidate) - }, res) - return (indexesToInvalidate.length ? queries.batchInvalidate(indexesToInvalidate) : Promise.resolve()).then(() => notInvalidated) - }) -} - -const cryptoBalancesNotify = (cryptoWarnings) => { - return clearOldCryptoNotifications(cryptoWarnings).then(notInvalidated => { - return cryptoWarnings.forEach(balance => { - // if notification exists in DB and wasnt invalidated then don't add a duplicate - if (_.find(o => { - const { code, cryptoCode } = o.detail - return code === balance.code && cryptoCode === balance.cryptoCode - }, notInvalidated)) return - - const fiat = utils.formatCurrency(balance.fiatBalance.balance, balance.fiatCode) - const message = `${balance.code === HIGH_CRYPTO_BALANCE ? 'High' : 'Low'} balance in ${balance.cryptoCode} [${fiat}]` - const detailB = utils.buildDetail({ cryptoCode: balance.cryptoCode, code: balance.code }) - return queries.addNotification(CRYPTO_BALANCE, message, detailB) - }) - }) -} - -const balancesNotify = (balances) => { - const isCryptoCode = c => _.includes(c, [HIGH_CRYPTO_BALANCE, LOW_CRYPTO_BALANCE]) - const isFiatCode = c => _.includes(c, [LOW_CASH_OUT, CASH_BOX_FULL, LOW_RECYCLER_STACKER]) - const by = o => - isCryptoCode(o) ? 'crypto' : - isFiatCode(o) ? 'fiat' : - undefined - const warnings = _.flow( - _.groupBy(_.flow(_.get(['code']), by)), - _.update('crypto', _.defaultTo([])), - _.update('fiat', _.defaultTo([])), - )(balances) - return Promise.all([cryptoBalancesNotify(warnings.crypto), fiatBalancesNotify(warnings.fiat)]) -} - -const clearOldErrorNotifications = alerts => { - return queries.getAllValidNotifications(ERROR) - .then(res => { - // for each valid notification in DB see if it exists in alerts - // if the notification doesn't exist in alerts, it is not valid anymore - const filterByAlert = _.filter(notification => { - const { code, deviceId } = notification.detail - return !_.find(alert => alert.code === code && alert.deviceId === deviceId)(alerts) - }) - const indexesToInvalidate = _.compose(_.map('id'), filterByAlert)(res) - if (!indexesToInvalidate.length) return Promise.resolve() - return queries.batchInvalidate(indexesToInvalidate) - }) -} - -const errorAlertsNotify = (alertRec) => { - const embedDeviceId = deviceId => _.assign({ deviceId }) - const mapToAlerts = _.map(it => _.map(embedDeviceId(it), alertRec.devices[it].deviceAlerts)) - const alerts = _.compose(_.flatten, mapToAlerts, _.keys)(alertRec.devices) - - return clearOldErrorNotifications(alerts).then(() => { - _.forEach(alert => { - switch (alert.code) { - case PING: { - const detailB = utils.buildDetail({ code: PING, age: alert.age ? alert.age : -1, deviceId: alert.deviceId }) - return queries.getValidNotifications(ERROR, _.omit(['age'], detailB)).then(res => { - if (res.length > 0) return Promise.resolve() - const message = `Machine down` - return queries.addNotification(ERROR, message, detailB) - }) - } - case STALE: { - const detailB = utils.buildDetail({ code: STALE, deviceId: alert.deviceId }) - return queries.getValidNotifications(ERROR, detailB).then(res => { - if (res.length > 0) return Promise.resolve() - const message = `Machine is stuck on ${alert.state} screen` - return queries.addNotification(ERROR, message, detailB) - }) - } - } - }, alerts) - }) -} - -function notifCenterTransactionNotify (isHighValue, direction, fiat, fiatCode, deviceId, cryptoAddress) { - const messageSuffix = isHighValue ? 'High value' : '' - const message = `${messageSuffix} ${fiat} ${fiatCode} ${direction} transaction` - const detailB = utils.buildDetail({ deviceId: deviceId, direction, fiat, fiatCode, cryptoAddress }) - return queries.addNotification(isHighValue ? HIGH_VALUE_TX : NORMAL_VALUE_TX, message, detailB) -} - -const blacklistNotify = (tx, isAddressReuse) => { - const code = isAddressReuse ? 'REUSED' : 'BLOCKED' - const name = isAddressReuse ? 'reused' : 'blacklisted' - - const detailB = utils.buildDetail({ cryptoCode: tx.cryptoCode, code, cryptoAddress: tx.toAddress }) - const message = `Blocked ${name} address: ${tx.cryptoCode} ${tx.toAddress.substr(0, 10)}...` - return queries.addNotification(COMPLIANCE, message, detailB) -} - -const cashboxNotify = deviceId => { - const detailB = utils.buildDetail({ deviceId: deviceId }) - const message = `Cashbox removed` - return queries.addNotification(SECURITY, message, detailB) -} - -module.exports = { - sanctionsNotify, - customerComplianceNotify, - balancesNotify, - errorAlertsNotify, - notifCenterTransactionNotify, - blacklistNotify, - cashboxNotify -} diff --git a/lib/plugins.js b/lib/plugins.js deleted file mode 100644 index 3bdf0181..00000000 --- a/lib/plugins.js +++ /dev/null @@ -1,950 +0,0 @@ -const _ = require('lodash/fp') -const crypto = require('crypto') -const pgp = require('pg-promise')() -const { getTimezoneOffset } = require('date-fns-tz') -const { millisecondsToMinutes } = require('date-fns/fp') - -const BN = require('./bn') -const dbm = require('./postgresql_interface') -const db = require('./db') -const logger = require('./logger') -const logs = require('./logs') -const T = require('./time') -const configManager = require('./new-config-manager') -const settingsLoader = require('./new-settings-loader') -const ticker = require('./ticker') -const wallet = require('./wallet') -const walletScoring = require('./wallet-scoring') -const exchange = require('./exchange') -const sms = require('./sms') -const email = require('./email') -const cashOutHelper = require('./cash-out/cash-out-helper') -const machineLoader = require('./machine-loader') -const commissionMath = require('./commission-math') -const loyalty = require('./loyalty') -const transactionBatching = require('./tx-batching') - -const { - CASH_OUT_DISPENSE_READY, - CASH_OUT_MAXIMUM_AMOUNT_OF_CASSETTES, - CASH_OUT_MAXIMUM_AMOUNT_OF_RECYCLERS, - CASH_UNIT_CAPACITY, - CONFIRMATION_CODE, -} = require('./constants') - -const notifier = require('./notifier') - -const { utils: coinUtils } = require('@lamassu/coins') - -const mapValuesWithKey = _.mapValues.convert({ - cap: false -}) - -const TRADE_TTL = 2 * T.minutes -const STALE_TICKER = 3 * T.minutes -const STALE_BALANCE = 3 * T.minutes -const tradesQueues = {} - -function plugins (settings, deviceId) { - - function internalBuildRates (tickers, withCommission = true) { - const localeConfig = configManager.getLocale(deviceId, settings.config) - const cryptoCodes = localeConfig.cryptoCurrencies - - const rates = {} - - cryptoCodes.forEach((cryptoCode, i) => { - const rateRec = tickers[i] - const commissions = configManager.getCommissions(cryptoCode, deviceId, settings.config) - - if (!rateRec) return - - const cashInCommission = new BN(1).plus(new BN(commissions.cashIn).div(100)) - - const cashOutCommission = _.isNil(commissions.cashOut) - ? undefined - : new BN(1).plus(new BN(commissions.cashOut).div(100)) - - if (Date.now() - rateRec.timestamp > STALE_TICKER) return logger.warn('Stale rate for ' + cryptoCode) - const rate = rateRec.rates - - withCommission ? rates[cryptoCode] = { - cashIn: rate.ask.times(cashInCommission).decimalPlaces(5), - cashOut: cashOutCommission && rate.bid.div(cashOutCommission).decimalPlaces(5) - } : rates[cryptoCode] = { - cashIn: rate.ask.decimalPlaces(5), - cashOut: rate.bid.decimalPlaces(5) - } - }) - return rates - } - - function buildRatesNoCommission (tickers) { - return internalBuildRates(tickers, false) - } - - function buildRates (tickers) { - return internalBuildRates(tickers, true) - } - - function getNotificationConfig () { - return configManager.getGlobalNotifications(settings.config) - } - - function buildBalances (balanceRecs) { - const localeConfig = configManager.getLocale(deviceId, settings.config) - const cryptoCodes = localeConfig.cryptoCurrencies - - const balances = {} - - cryptoCodes.forEach((cryptoCode, i) => { - const balanceRec = balanceRecs[i] - if (!balanceRec) return logger.warn('No balance for ' + cryptoCode + ' yet') - if (Date.now() - balanceRec.timestamp > STALE_BALANCE) return logger.warn('Stale balance for ' + cryptoCode) - - balances[cryptoCode] = balanceRec.balance - }) - - return balances - } - - function isZeroConf (tx) { - const walletSettings = configManager.getWalletSettings(tx.cryptoCode, settings.config) - const zeroConfLimit = walletSettings.zeroConfLimit || 0 - return tx.fiat.lte(zeroConfLimit) - } - - const accountProvisioned = (cashUnitType, cashUnits, redeemableTxs) => { - const kons = (cashUnits, tx) => { - // cash-out-helper sends 0 as fallback value, need to filter it out as there are no '0' denominations - const cashUnitsBills = _.flow( - _.get(['bills']), - _.filter(it => _.includes(cashUnitType, it.name) && it.denomination > 0), - _.zip(cashUnits), - )(tx) - - const sameDenominations = ([cashUnit, bill]) => cashUnit?.denomination === bill?.denomination - if (!_.every(sameDenominations, cashUnitsBills)) - throw new Error(`Denominations don't add up, ${cashUnitType}s were changed.`) - - return _.map( - ([cashUnit, { provisioned }]) => _.set('count', cashUnit.count - provisioned, cashUnit), - cashUnitsBills - ) - } - - return _.reduce(kons, cashUnits, redeemableTxs) - } - - function computeAvailableCassettes (cassettes, redeemableTxs) { - if (_.isEmpty(redeemableTxs)) return cassettes - cassettes = accountProvisioned('cassette', cassettes, redeemableTxs) - if (_.some(({ count }) => count < 0, cassettes)) - throw new Error('Negative note count: %j', counts) - return cassettes - } - - function computeAvailableRecyclers (recyclers, redeemableTxs) { - if (_.isEmpty(redeemableTxs)) return recyclers - recyclers = accountProvisioned('recycler', recyclers, redeemableTxs) - if (_.some(({ count }) => count < 0, recyclers)) - throw new Error('Negative note count: %j', counts) - return recyclers - } - - function buildAvailableCassettes (excludeTxId) { - const cashOutConfig = configManager.getCashOut(deviceId, settings.config) - - if (!cashOutConfig.active) return Promise.resolve() - - return Promise.all([dbm.cassetteCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)]) - .then(([{ counts, numberOfCassettes }, redeemableTxs]) => { - redeemableTxs = _.reject(_.matchesProperty('id', excludeTxId), redeemableTxs) - - const denominations = _.map( - it => cashOutConfig[`cassette${it}`], - _.range(1, numberOfCassettes+1) - ) - - if (counts.length !== denominations.length) - throw new Error('Denominations and respective counts do not match!') - - const cassettes = _.map( - it => ({ - name: `cassette${it + 1}`, - denomination: parseInt(denominations[it], 10), - count: parseInt(counts[it], 10) - }), - _.range(0, numberOfCassettes) - ) - - const virtualCassettes = denominations.length ? [Math.max(...denominations) * 2] : [] - - try { - return { - cassettes: computeAvailableCassettes(cassettes, redeemableTxs), - virtualCassettes - } - } catch (err) { - logger.error(err) - return { - cassettes, - virtualCassettes - } - } - }) - } - - function buildAvailableRecyclers (excludeTxId) { - const cashOutConfig = configManager.getCashOut(deviceId, settings.config) - - if (!cashOutConfig.active) return Promise.resolve() - - return Promise.all([dbm.recyclerCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)]) - .then(([{ counts, numberOfRecyclers }, redeemableTxs]) => { - redeemableTxs = _.reject(_.matchesProperty('id', excludeTxId), redeemableTxs) - - const denominations = _.map( - it => cashOutConfig[`recycler${it}`], - _.range(1, numberOfRecyclers+1) - ) - - if (counts.length !== denominations.length) - throw new Error('Denominations and respective counts do not match!') - - const recyclers = _.map( - it => ({ - number: it + 1, - name: `recycler${it + 1}`, - denomination: parseInt(denominations[it], 10), - count: parseInt(counts[it], 10) - }), - _.range(0, numberOfRecyclers) - ) - - const virtualRecyclers = denominations.length ? [Math.max(..._.flatten(denominations)) * 2] : [] - - try { - return { - recyclers: computeAvailableRecyclers(recyclers, redeemableTxs), - virtualRecyclers - } - } catch (err) { - logger.error(err) - return { - recyclers, - virtualRecyclers - } - } - }) - } - - function buildAvailableUnits (excludeTxId) { - return Promise.all([buildAvailableCassettes(excludeTxId), buildAvailableRecyclers(excludeTxId)]) - .then(([cassettes, recyclers]) => ({ cassettes: cassettes.cassettes, recyclers: recyclers.recyclers })) - } - - function mapCoinSettings (coinParams) { - const [ cryptoCode, cryptoNetwork ] = coinParams - const commissions = configManager.getCommissions(cryptoCode, deviceId, settings.config) - const minimumTx = new BN(commissions.minimumTx) - const cashInFee = new BN(commissions.fixedFee) - const cashOutFee = new BN(commissions.cashOutFixedFee) - const cashInCommission = new BN(commissions.cashIn) - const cashOutCommission = _.isNumber(commissions.cashOut) ? new BN(commissions.cashOut) : null - const cryptoRec = coinUtils.getCryptoCurrency(cryptoCode) - const cryptoUnits = configManager.getCryptoUnits(cryptoCode, settings.config) - - return { - cryptoCode, - cryptoCodeDisplay: cryptoRec.cryptoCodeDisplay ?? cryptoCode, - display: cryptoRec.display, - isCashInOnly: Boolean(cryptoRec.isCashinOnly), - minimumTx: BN.max(minimumTx, cashInFee), - cashInFee, - cashOutFee, - cashInCommission, - cashOutCommission, - cryptoNetwork, - cryptoUnits - } - } - - function getTickerRates (fiatCode, cryptoCode) { - return ticker.getRates(settings, fiatCode, cryptoCode) - } - - function pollQueries () { - const localeConfig = configManager.getLocale(deviceId, settings.config) - const fiatCode = localeConfig.fiatCurrency - const cryptoCodes = localeConfig.cryptoCurrencies - const machineScreenOpts = configManager.getAllMachineScreenOpts(settings.config) - - const tickerPromises = cryptoCodes.map(c => getTickerRates(fiatCode, c)) - const balancePromises = cryptoCodes.map(c => fiatBalance(fiatCode, c)) - const networkPromises = cryptoCodes.map(c => wallet.cryptoNetwork(settings, c)) - const supportsBatchingPromise = cryptoCodes.map(c => wallet.supportsBatching(settings, c)) - - return Promise.all([ - buildAvailableCassettes(), - buildAvailableRecyclers(), - settingsLoader.fetchCurrentConfigVersion(), - millisecondsToMinutes(getTimezoneOffset(localeConfig.timezone)), - loyalty.getNumberOfAvailablePromoCodes(), - Promise.all(supportsBatchingPromise), - Promise.all(tickerPromises), - Promise.all(balancePromises), - Promise.all(networkPromises) - ]) - .then(([ - cassettes, - recyclers, - configVersion, - timezone, - numberOfAvailablePromoCodes, - batchableCoins, - tickers, - balances, - networks - ]) => { - const coinsWithoutRate = _.flow( - _.zip(cryptoCodes), - _.map(mapCoinSettings) - )(networks) - - const coins = _.flow( - _.map(it => ({ batchable: it })), - _.zipWith( - _.assign, - _.zipWith(_.assign, coinsWithoutRate, tickers) - ) - )(batchableCoins) - - return { - cassettes, - recyclers: recyclers, - rates: buildRates(tickers), - balances: buildBalances(balances), - coins, - configVersion, - areThereAvailablePromoCodes: numberOfAvailablePromoCodes > 0, - timezone, - screenOptions: machineScreenOpts - } - }) - } - - function sendCoins (tx) { - return wallet.supportsBatching(settings, tx.cryptoCode) - .then(supportsBatching => { - if (supportsBatching) { - return transactionBatching.addTransactionToBatch(tx) - .then(() => ({ - batched: true, - sendPending: false, - error: null, - errorCode: null - })) - } - return wallet.sendCoins(settings, tx) - }) - } - - function recordPing (deviceTime, version, model) { - const devices = { - version, - model, - last_online: deviceTime - } - - return Promise.all([ - db.none(`insert into machine_pings(device_id, device_time) values($1, $2) - ON CONFLICT (device_id) DO UPDATE SET device_time = $2, updated = now()`, [deviceId, deviceTime]), - db.none(pgp.helpers.update(devices, null, 'devices') + 'WHERE device_id = ${deviceId}', { - deviceId - }) - ]) - } - - function pruneMachinesHeartbeat () { - const sql = `DELETE FROM machine_network_heartbeat h - USING (SELECT device_id, max(created) as lastEntry FROM machine_network_heartbeat GROUP BY device_id) d - WHERE d.device_id = h.device_id AND h.created < d.lastEntry` - db.none(sql) - } - - function isHd (tx) { - return wallet.isHd(settings, tx) - } - - function getStatus (tx) { - return wallet.getStatus(settings, tx, deviceId) - } - - function newAddress (tx) { - const info = { - cryptoCode: tx.cryptoCode, - label: 'TX ' + Date.now(), - account: 'deposit', - hdIndex: tx.hdIndex, - cryptoAtoms: tx.cryptoAtoms, - isLightning: tx.isLightning - } - return wallet.newAddress(settings, info, tx) - } - - function fiatBalance (fiatCode, cryptoCode) { - const commissions = configManager.getCommissions(cryptoCode, deviceId, settings.config) - return Promise.all([ - getTickerRates(fiatCode, cryptoCode), - wallet.balance(settings, cryptoCode) - ]) - .then(([rates, balanceRec]) => { - if (!rates || !balanceRec) return null - - const rawRate = rates.rates.ask - const cashInCommission = new BN(1).minus(new BN(commissions.cashIn).div(100)) - const balance = balanceRec.balance - - if (!rawRate || !balance) return null - - const rate = rawRate.div(cashInCommission) - - const lowBalanceMargin = new BN(0.95) - - const cryptoRec = coinUtils.getCryptoCurrency(cryptoCode) - const unitScale = cryptoRec.unitScale - const shiftedRate = rate.shiftedBy(-unitScale) - const fiatTransferBalance = balance.times(shiftedRate).times(lowBalanceMargin) - - return { - timestamp: balanceRec.timestamp, - balance: fiatTransferBalance.integerValue(BN.ROUND_DOWN).toString() - } - }) - } - - function notifyConfirmation (tx) { - logger.debug('notifyConfirmation') - - const phone = tx.phone - - const timestamp = `${(new Date()).toISOString().substring(11, 19)} UTC` - return sms.getSms(CASH_OUT_DISPENSE_READY, phone, { timestamp }) - .then(smsObj => { - const rec = { - sms: smsObj - } - - return sms.sendMessage(settings, rec) - .then(() => { - const sql = 'UPDATE cash_out_txs SET notified=$1 WHERE id=$2' - const values = [true, tx.id] - - return db.none(sql, values) - }) - }) - } - - function notifyOperator (tx, rec) { - // notify operator about new transaction and add high volume txs to database - return notifier.transactionNotify(tx, rec) - } - - function clearOldLogs () { - return logs.clearOldLogs() - .catch(logger.error) - } - - /* - * Trader functions - */ - - function buy (rec, tx) { - return buyAndSell(rec, true, tx) - } - - function sell (rec) { - return buyAndSell(rec, false) - } - - function buyAndSell (rec, doBuy, tx) { - const cryptoCode = rec.cryptoCode - return exchange.fetchExchange(settings, cryptoCode) - .then(_exchange => { - const fiatCode = _exchange.account.currencyMarket - const cryptoAtoms = doBuy ? commissionMath.fiatToCrypto(tx, rec, deviceId, settings.config) : rec.cryptoAtoms.negated() - - const market = [fiatCode, cryptoCode].join('') - - if (!exchange.active(settings, cryptoCode)) return - - const direction = doBuy ? 'cashIn' : 'cashOut' - const internalTxId = tx ? tx.id : rec.id - logger.debug('[%s] Pushing trade: %d', market, cryptoAtoms) - if (!tradesQueues[market]) tradesQueues[market] = [] - tradesQueues[market].push({ - direction, - internalTxId, - fiatCode, - cryptoAtoms, - cryptoCode, - timestamp: Date.now() - }) - }) - } - - function consolidateTrades (cryptoCode, fiatCode) { - const market = [fiatCode, cryptoCode].join('') - - const marketTradesQueues = tradesQueues[market] - if (!marketTradesQueues || marketTradesQueues.length === 0) return null - - logger.debug('[%s] tradesQueues size: %d', market, marketTradesQueues.length) - logger.debug('[%s] tradesQueues head: %j', market, marketTradesQueues[0]) - - const t1 = Date.now() - - const filtered = marketTradesQueues - .filter(tradeEntry => { - return t1 - tradeEntry.timestamp < TRADE_TTL - }) - - const filteredCount = marketTradesQueues.length - filtered.length - - if (filteredCount > 0) { - tradesQueues[market] = filtered - logger.debug('[%s] expired %d trades', market, filteredCount) - } - - if (filtered.length === 0) return null - - const partitionByDirection = _.partition(({ direction }) => direction === 'cashIn') - const [cashInTxs, cashOutTxs] = _.compose(partitionByDirection, _.uniqBy('internalTxId'))(filtered) - - const cryptoAtoms = filtered - .reduce((prev, current) => prev.plus(current.cryptoAtoms), new BN(0)) - - const timestamp = filtered.map(r => r.timestamp).reduce((acc, r) => Math.max(acc, r), 0) - - const consolidatedTrade = { - cashInTxs, - cashOutTxs, - fiatCode, - cryptoAtoms, - cryptoCode, - timestamp - } - - tradesQueues[market] = [] - - logger.debug('[%s] consolidated: %j', market, consolidatedTrade) - return consolidatedTrade - } - - function executeTrades () { - return machineLoader.getMachines() - .then(devices => { - const deviceIds = devices.map(device => device.deviceId) - const lists = deviceIds.map(deviceId => { - const localeConfig = configManager.getLocale(deviceId, settings.config) - const cryptoCodes = localeConfig.cryptoCurrencies - - return Promise.all(cryptoCodes.map(cryptoCode => { - return exchange.fetchExchange(settings, cryptoCode) - .then(exchange => ({ - fiatCode: exchange.account.currencyMarket, - cryptoCode - })) - })) - }) - - return Promise.all(lists) - }) - .then(lists => { - return Promise.all(_.uniq(_.flatten(lists)) - .map(r => executeTradesForMarket(settings, r.fiatCode, r.cryptoCode))) - }) - .catch(logger.error) - } - - function executeTradesForMarket (settings, fiatCode, cryptoCode) { - if (!exchange.active(settings, cryptoCode)) return - - const market = [fiatCode, cryptoCode].join('') - const tradeEntry = consolidateTrades(cryptoCode, fiatCode) - - if (tradeEntry === null || tradeEntry.cryptoAtoms.eq(0)) return - - return executeTradeForType(tradeEntry) - .catch(err => { - tradesQueues[market].push(tradeEntry) - if (err.name === 'orderTooSmall') return logger.debug(err.message) - logger.error(err) - }) - } - - function executeTradeForType (_tradeEntry) { - const expand = te => _.assign(te, { - cryptoAtoms: te.cryptoAtoms.abs(), - type: te.cryptoAtoms.gte(0) ? 'buy' : 'sell' - }) - - const tradeEntry = expand(_tradeEntry) - const execute = tradeEntry.type === 'buy' ? exchange.buy : exchange.sell - - return recordTrade(tradeEntry) - .then(newEntry => { - tradeEntry.tradeId = newEntry.id - return execute(settings, tradeEntry) - .catch(err => { - updateTradeEntry(tradeEntry, newEntry, err) - .then(() => { - logger.error(err) - throw err - }) - }) - }) - } - - function updateTradeEntry (tradeEntry, newEntry, err) { - const data = mergeTradeEntryAndError(tradeEntry, err) - const sql = pgp.helpers.update(data, ['error'], 'trades') + ` WHERE id = ${newEntry.id}` - return db.none(sql) - } - - function recordTradeAndTx (tradeId, { cashInTxs, cashOutTxs }, dbTx) { - const columnSetCashIn = new pgp.helpers.ColumnSet(['tx_id', 'trade_id'], { table: 'cashin_tx_trades' }) - const columnSetCashOut = new pgp.helpers.ColumnSet(['tx_id', 'trade_id'], { table: 'cashout_tx_trades' }) - const mapToEntry = _.map(tx => ({ tx_id: tx.internalTxId, trade_id: tradeId })) - const queries = [] - - if (!_.isEmpty(cashInTxs)) { - const query = pgp.helpers.insert(mapToEntry(cashInTxs), columnSetCashIn) - queries.push(dbTx.none(query)) - } - if (!_.isEmpty(cashOutTxs)) { - const query = pgp.helpers.insert(mapToEntry(cashOutTxs), columnSetCashOut) - queries.push(dbTx.none(query)) - } - return Promise.all(queries) - } - - function convertBigNumFields (obj) { - const convert = (value, key) => _.includes(key, ['cryptoAtoms', 'fiat']) - ? value.toString() - : value - - const convertKey = key => _.includes(key, ['cryptoAtoms', 'fiat']) - ? key + '#' - : key - - return _.mapKeys(convertKey, mapValuesWithKey(convert, obj)) - } - - function mergeTradeEntryAndError (tradeEntry, error) { - if (error && error.message) { - return Object.assign({}, tradeEntry, { - error: error.message.slice(0, 200) - }) - } - return tradeEntry - } - - function recordTrade (_tradeEntry, error) { - const massage = _.flow( - mergeTradeEntryAndError, - _.pick(['cryptoCode', 'cryptoAtoms', 'fiatCode', 'type', 'error']), - convertBigNumFields, - _.mapKeys(_.snakeCase) - ) - const tradeEntry = massage(_tradeEntry, error) - const sql = pgp.helpers.insert(tradeEntry, null, 'trades') + 'RETURNING *' - return db.tx(t => { - return t.oneOrNone(sql) - .then(newTrade => { - return recordTradeAndTx(newTrade.id, _tradeEntry, t) - .then(() => newTrade) - }) - }) - } - - function sendMessage (rec) { - const notifications = configManager.getGlobalNotifications(settings.config) - - let promises = [] - if (notifications.email.active && rec.email) promises.push(email.sendMessage(settings, rec)) - if (notifications.sms.active && rec.sms) promises.push(sms.sendMessage(settings, rec)) - - return Promise.all(promises) - } - - function checkDevicesCashBalances (fiatCode, devices) { - return _.map(device => checkDeviceCashBalances(fiatCode, device), devices) - } - - function getCashUnitCapacity (model, device) { - if (!CASH_UNIT_CAPACITY[model]) { - return CASH_UNIT_CAPACITY.default[device] - } - return CASH_UNIT_CAPACITY[model][device] - } - - function checkDeviceCashBalances (fiatCode, device) { - const deviceId = device.deviceId - const machineName = device.name - const notifications = configManager.getNotifications(null, deviceId, settings.config) - - const cashInAlerts = device.cashUnits.cashbox > notifications.cashInAlertThreshold - ? [{ - code: 'CASH_BOX_FULL', - machineName, - deviceId, - notes: device.cashUnits.cashbox - }] - : [] - - const cashOutConfig = configManager.getCashOut(deviceId, settings.config) - const cashOutEnabled = cashOutConfig.active - const isUnitLow = (have, max, limit) => ((have / max) * 100) < limit - - if (!cashOutEnabled) - return cashInAlerts - - const cassetteCapacity = getCashUnitCapacity(device.model, 'cassette') - const cassetteAlerts = Array(Math.min(device.numberOfCassettes ?? 0, CASH_OUT_MAXIMUM_AMOUNT_OF_CASSETTES)) - .fill(null) - .flatMap((_elem, idx) => { - const nth = idx + 1 - const cassetteField = `cassette${nth}` - const notes = device.cashUnits[cassetteField] - const denomination = cashOutConfig[cassetteField] - - const limit = notifications[`fillingPercentageCassette${nth}`] - return isUnitLow(notes, cassetteCapacity, limit) ? - [{ - code: 'LOW_CASH_OUT', - cassette: nth, - machineName, - deviceId, - notes, - denomination, - fiatCode - }] : - [] - }) - - const recyclerCapacity = getCashUnitCapacity(device.model, 'recycler') - const recyclerAlerts = Array(Math.min(device.numberOfRecyclers ?? 0, CASH_OUT_MAXIMUM_AMOUNT_OF_RECYCLERS)) - .fill(null) - .flatMap((_elem, idx) => { - const nth = idx + 1 - const recyclerField = `recycler${nth}` - const notes = device.cashUnits[recyclerField] - const denomination = cashOutConfig[recyclerField] - - const limit = notifications[`fillingPercentageRecycler${nth}`] - return isUnitLow(notes, recyclerCapacity, limit) ? - [{ - code: 'LOW_RECYCLER_STACKER', - cassette: nth, // @see DETAIL_TEMPLATE in /lib/notifier/utils.js - machineName, - deviceId, - notes, - denomination, - fiatCode - }] : - [] - }) - - return [].concat(cashInAlerts, cassetteAlerts, recyclerAlerts) - } - - function checkCryptoBalances (fiatCode, devices) { - const fiatBalancePromises = cryptoCodes => _.map(c => fiatBalance(fiatCode, c), cryptoCodes) - - const fetchCryptoCodes = _deviceId => { - const localeConfig = configManager.getLocale(_deviceId, settings.config) - return localeConfig.cryptoCurrencies - } - - const union = _.flow(_.map(fetchCryptoCodes), _.flatten, _.uniq) - const cryptoCodes = union(devices) - const checkCryptoBalanceWithFiat = _.partial(checkCryptoBalance, [fiatCode]) - - return Promise.all(fiatBalancePromises(cryptoCodes)) - .then(balances => _.map(checkCryptoBalanceWithFiat, _.zip(cryptoCodes, balances))) - } - - function checkCryptoBalance (fiatCode, rec) { - const [cryptoCode, fiatBalance] = rec - if (!fiatBalance) return null - - const notifications = configManager.getNotifications(cryptoCode, null, settings.config) - const lowAlertThreshold = notifications.cryptoLowBalance - const highAlertThreshold = notifications.cryptoHighBalance - - const req = { - cryptoCode, - fiatBalance, - fiatCode - } - - if (_.isFinite(lowAlertThreshold) && new BN(fiatBalance.balance).lt(lowAlertThreshold)) { - return _.set('code')('LOW_CRYPTO_BALANCE')(req) - } - - if (_.isFinite(highAlertThreshold) && new BN(fiatBalance.balance).gt(highAlertThreshold)) { - return _.set('code')('HIGH_CRYPTO_BALANCE')(req) - } - - return null - } - - function checkBalances () { - const localeConfig = configManager.getGlobalLocale(settings.config) - const fiatCode = localeConfig.fiatCurrency - - return machineLoader.getMachines() - .then(devices => Promise.all([ - checkCryptoBalances(fiatCode, devices), - checkDevicesCashBalances(fiatCode, devices) - ])) - .then(_.flow(_.flattenDeep, _.compact)) - } - - function randomCode () { - return new BN(crypto.randomBytes(3).toString('hex'), 16).shiftedBy(-6).toFixed(6).slice(-6) - } - - function getPhoneCode (phone) { - const code = settings.config.notifications_thirdParty_sms === 'mock-sms' - ? '123' - : randomCode() - - const timestamp = `${(new Date()).toISOString().substring(11, 19)} UTC` - return sms.getSms(CONFIRMATION_CODE, phone, { code, timestamp }) - .then(smsObj => { - const rec = { - sms: smsObj - } - - return sms.sendMessage(settings, rec) - .then(() => code) - }) - } - - function getEmailCode (toEmail) { - const code = settings.config.notifications_thirdParty_email === 'mock-email' - ? '123' - : randomCode() - - const rec = { - email: { - toEmail, - subject: 'Your cryptomat code', - body: `Your cryptomat code: ${code}` - } - } - - return email.sendCustomerMessage(settings, rec) - .then(() => code) - } - - function sweepHdRow (row) { - const txId = row.id - const cryptoCode = row.crypto_code - - return wallet.sweep(settings, txId, cryptoCode, row.hd_index) - .then(txHash => { - if (txHash) { - logger.debug('[%s] Swept address with tx: %s', cryptoCode, txHash) - - const sql = `update cash_out_txs set swept='t' - where id=$1` - - return db.none(sql, row.id) - } - }) - .catch(err => logger.error('[%s] [Session ID: %s] Sweep error: %s', cryptoCode, row.id, err.message)) - } - - function sweepHd () { - const sql = `SELECT id, crypto_code, hd_index FROM cash_out_txs - WHERE hd_index IS NOT NULL AND NOT swept AND status IN ('confirmed', 'instant') AND created > now() - interval '1 week'` - - return db.any(sql) - .then(rows => Promise.all(rows.map(sweepHdRow))) - .catch(logger.error) - } - - function getMachineNames () { - return machineLoader.getMachineNames(settings.config) - } - - function getRawRates () { - const localeConfig = configManager.getGlobalLocale(settings.config) - const fiatCode = localeConfig.fiatCurrency - - const cryptoCodes = configManager.getAllCryptoCurrencies(settings.config) - const tickerPromises = cryptoCodes.map(c => getTickerRates(fiatCode, c)) - - return Promise.all(tickerPromises) - } - - function getRates () { - return getRawRates() - .then(buildRates) - } - - function rateAddress (cryptoCode, address) { - return walletScoring.rateAddress(settings, cryptoCode, address) - } - - function rateTransaction (cryptoCode, address) { - return walletScoring.rateTransaction(settings, cryptoCode, address) - } - - function isWalletScoringEnabled (tx) { - return walletScoring.isWalletScoringEnabled(settings, tx.cryptoCode) - } - - function probeLN (cryptoCode, address) { - return wallet.probeLN(settings, cryptoCode, address) - } - - return { - getRates, - recordPing, - buildRates, - getRawRates, - buildRatesNoCommission, - pollQueries, - sendCoins, - newAddress, - isHd, - isZeroConf, - getStatus, - getPhoneCode, - getEmailCode, - executeTrades, - clearOldLogs, - notifyConfirmation, - sweepHd, - sendMessage, - checkBalances, - getMachineNames, - buy, - sell, - getNotificationConfig, - notifyOperator, - pruneMachinesHeartbeat, - rateAddress, - rateTransaction, - isWalletScoringEnabled, - probeLN, - buildAvailableUnits - } -} - -module.exports = plugins diff --git a/lib/plugins/compliance/sumsub/sumsub.js b/lib/plugins/compliance/sumsub/sumsub.js deleted file mode 100644 index b295f7c3..00000000 --- a/lib/plugins/compliance/sumsub/sumsub.js +++ /dev/null @@ -1,53 +0,0 @@ -const _ = require('lodash/fp') - -const sumsubApi = require('./sumsub.api') -const { PENDING, RETRY, APPROVED, REJECTED } = require('../consts') - -const CODE = 'sumsub' - -const getApplicantByExternalId = (account, userId) => { - return sumsubApi.getApplicantByExternalId(account, userId) - .then(r => r.data) -} - -const createApplicant = (account, userId, level) => { - return sumsubApi.createApplicant(account, userId, level) - .then(r => r.data) - .catch(err => { - if (err.response.status === 409) return getApplicantByExternalId(account, userId) - throw err - }) -} - -const createLink = (account, userId, level) => { - return sumsubApi.createLink(account, userId, level) - .then(r => r.data.url) -} - -const getApplicantStatus = (account, userId) => { - return sumsubApi.getApplicantByExternalId(account, userId) - .then(r => { - const levelName = _.get('data.review.levelName', r) - const reviewStatus = _.get('data.review.reviewStatus', r) - const reviewAnswer = _.get('data.review.reviewResult.reviewAnswer', r) - const reviewRejectType = _.get('data.review.reviewResult.reviewRejectType', r) - - // if last review was from a different level, return the current level and RETRY - if (levelName !== account.applicantLevel) return { level: account.applicantLevel, answer: RETRY } - - let answer = PENDING - if (reviewStatus === 'init') answer = RETRY - if (reviewAnswer === 'GREEN' && reviewStatus === 'completed') answer = APPROVED - if (reviewAnswer === 'RED' && reviewRejectType === 'RETRY') answer = RETRY - if (reviewAnswer === 'RED' && reviewRejectType === 'FINAL') answer = REJECTED - - return { level: levelName, answer } - }) -} - -module.exports = { - CODE, - createApplicant, - getApplicantStatus, - createLink -} \ No newline at end of file diff --git a/lib/plugins/exchange/ccxt.js b/lib/plugins/exchange/ccxt.js deleted file mode 100644 index a69021ba..00000000 --- a/lib/plugins/exchange/ccxt.js +++ /dev/null @@ -1,92 +0,0 @@ -const { utils: coinUtils } = require('@lamassu/coins') -const _ = require('lodash/fp') -const ccxt = require('ccxt') -const mem = require('mem') - -const { buildMarket, ALL, isConfigValid } = require('../common/ccxt') -const { ORDER_TYPES } = require('./consts') -const logger = require('../../logger') -const { currencies } = require('../../new-admin/config') -const T = require('../../time') - -const DEFAULT_PRICE_PRECISION = 2 -const DEFAULT_AMOUNT_PRECISION = 8 - -function trade (side, account, tradeEntry, exchangeName) { - const { cryptoAtoms, fiatCode, cryptoCode: _cryptoCode, tradeId } = tradeEntry - try { - const cryptoCode = coinUtils.getEquivalentCode(_cryptoCode) - const exchangeConfig = ALL[exchangeName] - if (!exchangeConfig) throw Error('Exchange configuration not found') - - const { USER_REF, loadOptions, loadConfig = _.noop, REQUIRED_CONFIG_FIELDS, ORDER_TYPE, AMOUNT_PRECISION } = exchangeConfig - if (!isConfigValid(account, REQUIRED_CONFIG_FIELDS)) throw Error('Invalid config') - - const selectedFiatMarket = account.currencyMarket - const symbol = buildMarket(selectedFiatMarket, cryptoCode, exchangeName) - const precision = _.defaultTo(DEFAULT_AMOUNT_PRECISION, AMOUNT_PRECISION) - const amount = coinUtils.toUnit(cryptoAtoms, cryptoCode).toFixed(precision) - const accountOptions = _.isFunction(loadOptions) ? loadOptions(account) : {} - const withCustomKey = USER_REF ? { [USER_REF]: tradeId } : {} - const options = _.assign(accountOptions, withCustomKey) - const exchange = new ccxt[exchangeName](loadConfig(account)) - - if (ORDER_TYPE === ORDER_TYPES.MARKET) { - return exchange.createOrder(symbol, ORDER_TYPES.MARKET, side, amount, null, options) - } - - return exchange.fetchOrderBook(symbol) - .then(orderBook => { - const price = calculatePrice(side, amount, orderBook).toFixed(DEFAULT_PRICE_PRECISION) - return exchange.createOrder(symbol, ORDER_TYPES.LIMIT, side, amount, price, options) - }) - } catch (e) { - return Promise.reject(e) - } -} - -function calculatePrice (side, amount, orderBook) { - const book = side === 'buy' ? 'asks' : 'bids' - let collected = 0.0 - for (const entry of orderBook[book]) { - collected += parseFloat(entry[1]) - if (collected >= amount) return parseFloat(entry[0]) - } - throw new Error('Insufficient market depth') -} - -function _getMarkets (exchangeName, availableCryptos) { - const prunedCryptos = _.compose(_.uniq, _.map(coinUtils.getEquivalentCode))(availableCryptos) - - try { - const exchange = new ccxt[exchangeName]() - const cryptosToQuoteAgainst = ['USDT'] - const currencyCodes = _.concat(_.map(it => it.code, currencies), cryptosToQuoteAgainst) - - return exchange.fetchMarkets() - .then(_.filter(it => (it.type === 'spot' || it.spot))) - .then(res => - _.reduce((acc, value) => { - if (_.includes(value.base, prunedCryptos) && _.includes(value.quote, currencyCodes)) { - if (value.quote === value.base) return acc - - if (_.isNil(acc[value.quote])) { - return { ...acc, [value.quote]: [value.base] } - } - - acc[value.quote].push(value.base) - } - return acc - }, {}, res) - ) - } catch (e) { - logger.debug(`No CCXT exchange found for ${exchangeName}`) - } -} - -const getMarkets = mem(_getMarkets, { - maxAge: T.week, - cacheKey: (exchangeName, availableCryptos) => exchangeName -}) - -module.exports = { trade, getMarkets } diff --git a/lib/plugins/exchange/itbit.js b/lib/plugins/exchange/itbit.js deleted file mode 100644 index d80268e1..00000000 --- a/lib/plugins/exchange/itbit.js +++ /dev/null @@ -1,25 +0,0 @@ -const _ = require('lodash/fp') - -const { ORDER_TYPES } = require('./consts') -const { COINS } = require('@lamassu/coins') - -const ORDER_TYPE = ORDER_TYPES.LIMIT -const { BTC, ETH, USDT, LN } = COINS -const CRYPTO = [BTC, ETH, USDT, LN] -const FIAT = ['USD'] -const DEFAULT_FIAT_MARKET = 'USD' -const AMOUNT_PRECISION = 4 -const REQUIRED_CONFIG_FIELDS = ['clientKey', 'clientSecret', 'userId', 'walletId', 'currencyMarket'] - -const loadConfig = (account) => { - const mapper = { - 'clientKey': 'apiKey', - 'clientSecret': 'secret', - 'userId': 'uid' - } - const mapped = _.mapKeys(key => mapper[key] ? mapper[key] : key)(_.omit(['walletId'], account)) - return { ...mapped, timeout: 3000 } -} -const loadOptions = ({ walletId }) => ({ walletId }) - -module.exports = { loadOptions, loadConfig, DEFAULT_FIAT_MARKET, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION } diff --git a/lib/plugins/exchange/mock-exchange.js b/lib/plugins/exchange/mock-exchange.js deleted file mode 100644 index bdf287da..00000000 --- a/lib/plugins/exchange/mock-exchange.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - buy, - sell -} - -function buy (cryptoAtoms, fiatCode, cryptoCode) { - console.log('[mock] buying %s %s for %s', cryptoAtoms.toString(), cryptoCode, fiatCode) - return Promise.resolve() -} - -function sell (cryptoAtoms, fiatCode, cryptoCode) { - console.log('[mock] selling %s %s for %s', cryptoAtoms.toString(), cryptoCode, fiatCode) - return Promise.resolve() -} diff --git a/lib/plugins/sms/telnyx/telnyx.js b/lib/plugins/sms/telnyx/telnyx.js deleted file mode 100644 index 10253e82..00000000 --- a/lib/plugins/sms/telnyx/telnyx.js +++ /dev/null @@ -1,27 +0,0 @@ -const Telnyx = require('telnyx') - -const NAME = 'Telnyx' - -function sendMessage (account, rec) { - const telnyx = Telnyx(account.apiKey) - - const from = account.fromNumber - const text = rec.sms.body - const to = rec.sms.toNumber || account.toNumber - - return telnyx.messages.create({ from, to, text }) - .catch(err => { - throw new Error(`Telnyx error: ${err.message}`) - }) -} - -function getLookup () { - throw new Error('Telnyx error: lookup not supported') -} - - -module.exports = { - NAME, - sendMessage, - getLookup -} diff --git a/lib/plugins/sms/twilio/twilio.js b/lib/plugins/sms/twilio/twilio.js deleted file mode 100644 index bdfc3843..00000000 --- a/lib/plugins/sms/twilio/twilio.js +++ /dev/null @@ -1,69 +0,0 @@ -const twilio = require('twilio') -const _ = require('lodash/fp') - -const NAME = 'Twilio' - -const BAD_NUMBER_CODES = [21201, 21202, 21211, 21214, 21216, 21217, 21219, 21408, - 21610, 21612, 21614, 21608] - -function sendMessage (account, rec) { - return Promise.resolve() - .then(() => { - // to catch configuration errors like - // "Error: username is required" - const client = twilio(account.accountSid, account.authToken) - const body = rec.sms.body - const _toNumber = rec.sms.toNumber || account.toNumber - const from = (_.startsWith('+')(account.fromNumber) - || !_.isNumber(String(account.fromNumber).replace(/\s/g,''))) - ? account.fromNumber : `+${account.fromNumber}` - - const opts = { - body: body, - to: _toNumber, - from - } - - return client.messages.create(opts) - }) - .catch(err => { - if (_.includes(err.code, BAD_NUMBER_CODES)) { - const badNumberError = new Error(err.message) - badNumberError.name = 'BadNumberError' - throw badNumberError - } - - throw new Error(`Twilio error: ${err.message}`) - }) -} - -function getLookup (account, number) { - return Promise.resolve() - .then(() => { - const client = twilio(account.accountSid, account.authToken) - return client.lookups.v1.phoneNumbers(number) - .fetch({ addOns: ['lamassu_ekata'] }) - }) - .then(info => info.addOns.results['lamassu_ekata']) - .then(info => { - if (info.status !== 'successful') { - throw new Error(`Twilio error: ${info.message}`) - } - return info - }) - .catch(err => { - if (_.includes(err.code, BAD_NUMBER_CODES)) { - const badNumberError = new Error(err.message) - badNumberError.name = 'BadNumberError' - throw badNumberError - } - - throw new Error(`Twilio error: ${err.message}`) - }) -} - -module.exports = { - NAME, - sendMessage, - getLookup -} diff --git a/lib/plugins/ticker/pazuz-ticker/pazuz-ticker.js b/lib/plugins/ticker/pazuz-ticker/pazuz-ticker.js deleted file mode 100644 index 34daf691..00000000 --- a/lib/plugins/ticker/pazuz-ticker/pazuz-ticker.js +++ /dev/null @@ -1,28 +0,0 @@ -const https = require('https') -const axios = require('axios').create({ - // TODO: get rejectUnauthorized true to work - baseURL: `${process.env.TICKER_URL}/api/rates/`, - httpsAgent: new https.Agent({ - rejectUnauthorized: false - }) -}) - -const BN = require('../../../bn') - -function ticker (account, fiatCode, cryptoCode) { - return axios.get(`${cryptoCode}/${fiatCode}`) - .then(({ data }) => { - if (data.error) throw new Error(JSON.stringify(data.error)) - return { - rates: { - ask: BN(data.ask), - bid: BN(data.bid), - signature: data.signature - } - } - }) -} - -module.exports = { - ticker -} diff --git a/lib/plugins/tokens/erc20.abi.json b/lib/plugins/tokens/erc20.abi.json deleted file mode 100644 index b66cb33f..00000000 --- a/lib/plugins/tokens/erc20.abi.json +++ /dev/null @@ -1,282 +0,0 @@ -[ - { - "constant":true, - "inputs":[ - - ], - "name":"name", - "outputs":[ - { - "name":"", - "type":"string" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":false, - "inputs":[ - { - "name":"_spender", - "type":"address" - }, - { - "name":"_value", - "type":"uint256" - } - ], - "name":"approve", - "outputs":[ - { - "name":"success", - "type":"bool" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":true, - "inputs":[ - - ], - "name":"totalSupply", - "outputs":[ - { - "name":"", - "type":"uint256" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":false, - "inputs":[ - { - "name":"_from", - "type":"address" - }, - { - "name":"_to", - "type":"address" - }, - { - "name":"_value", - "type":"uint256" - } - ], - "name":"transferFrom", - "outputs":[ - { - "name":"success", - "type":"bool" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":true, - "inputs":[ - - ], - "name":"decimals", - "outputs":[ - { - "name":"", - "type":"uint256" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":true, - "inputs":[ - - ], - "name":"version", - "outputs":[ - { - "name":"", - "type":"string" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":true, - "inputs":[ - { - "name":"_owner", - "type":"address" - } - ], - "name":"balanceOf", - "outputs":[ - { - "name":"balance", - "type":"uint256" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":true, - "inputs":[ - - ], - "name":"symbol", - "outputs":[ - { - "name":"", - "type":"string" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":false, - "inputs":[ - { - "name":"_to", - "type":"address" - }, - { - "name":"_value", - "type":"uint256" - } - ], - "name":"transfer", - "outputs":[ - { - "name":"success", - "type":"bool" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":false, - "inputs":[ - { - "name":"_spender", - "type":"address" - }, - { - "name":"_value", - "type":"uint256" - }, - { - "name":"_extraData", - "type":"bytes" - } - ], - "name":"approveAndCall", - "outputs":[ - { - "name":"success", - "type":"bool" - } - ], - "payable":false, - "type":"function" - }, - { - "constant":true, - "inputs":[ - { - "name":"_owner", - "type":"address" - }, - { - "name":"_spender", - "type":"address" - } - ], - "name":"allowance", - "outputs":[ - { - "name":"remaining", - "type":"uint256" - } - ], - "payable":false, - "type":"function" - }, - { - "inputs":[ - { - "name":"_initialAmount", - "type":"uint256" - }, - { - "name":"_tokenName", - "type":"string" - }, - { - "name":"_decimalUnits", - "type":"uint8" - }, - { - "name":"_tokenSymbol", - "type":"string" - } - ], - "type":"constructor" - }, - { - "payable":false, - "type":"fallback" - }, - { - "anonymous":false, - "inputs":[ - { - "indexed":true, - "name":"_from", - "type":"address" - }, - { - "indexed":true, - "name":"_to", - "type":"address" - }, - { - "indexed":false, - "name":"_value", - "type":"uint256" - } - ], - "name":"Transfer", - "type":"event" - }, - { - "anonymous":false, - "inputs":[ - { - "indexed":true, - "name":"_owner", - "type":"address" - }, - { - "indexed":true, - "name":"_spender", - "type":"address" - }, - { - "indexed":false, - "name":"_value", - "type":"uint256" - } - ], - "name":"Approval", - "type":"event" - } -] \ No newline at end of file diff --git a/lib/plugins/wallet-scoring/mock-scoring/mock-scoring.js b/lib/plugins/wallet-scoring/mock-scoring/mock-scoring.js deleted file mode 100644 index 0f154ffc..00000000 --- a/lib/plugins/wallet-scoring/mock-scoring/mock-scoring.js +++ /dev/null @@ -1,28 +0,0 @@ -const NAME = 'FakeScoring' - -const { WALLET_SCORE_THRESHOLD } = require('../../../constants') - -function rateAddress (account, cryptoCode, address) { - return new Promise((resolve, _) => { - setTimeout(() => { - console.log('[WALLET-SCORING] DEBUG: Mock scoring rating wallet address %s', address) - return Promise.resolve(2) - .then(score => resolve({ address, score, isValid: score < WALLET_SCORE_THRESHOLD })) - }, 100) - }) -} - -function isWalletScoringEnabled (account, cryptoCode) { - return new Promise((resolve, _) => { - setTimeout(() => { - return resolve(true) - }, 100) - }) -} - -module.exports = { - NAME, - rateAddress, - rateTransaction:rateAddress, - isWalletScoringEnabled -} diff --git a/lib/plugins/wallet/bitcoincashd/bitcoincashd.js b/lib/plugins/wallet/bitcoincashd/bitcoincashd.js deleted file mode 100644 index 1208a19e..00000000 --- a/lib/plugins/wallet/bitcoincashd/bitcoincashd.js +++ /dev/null @@ -1,148 +0,0 @@ -const _ = require('lodash/fp') -const jsonRpc = require('../../common/json-rpc') - -const BN = require('../../../bn') -const E = require('../../../error') -const { utils: coinUtils } = require('@lamassu/coins') - -const cryptoRec = coinUtils.getCryptoCurrency('BCH') -const unitScale = cryptoRec.unitScale - -const rpcConfig = jsonRpc.rpcConfig(cryptoRec) - -function fetch (method, params) { - return jsonRpc.fetch(rpcConfig, method, params) -} - -function errorHandle (e) { - const err = JSON.parse(e.message) - switch (err.code) { - case -6: - throw new E.InsufficientFundsError() - default: - throw e - } -} - -function checkCryptoCode (cryptoCode) { - if (cryptoCode !== 'BCH') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - return Promise.resolve() -} - -function accountBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getwalletinfo')) - .then(({ balance }) => new BN(balance).shiftedBy(unitScale).decimalPlaces(0)) -} - -function accountUnconfirmedBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getwalletinfo')) - .then(({ unconfirmed_balance: balance }) => new BN(balance).shiftedBy(unitScale).decimalPlaces(0)) -} - -// We want a balance that includes all spends (0 conf) but only deposits that -// have at least 1 confirmation. getbalance does this for us automatically. -function balance (account, cryptoCode, settings, operatorId) { - return accountBalance(cryptoCode) -} - -function sendCoins (account, tx, settings, operatorId) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - const coins = cryptoAtoms.shiftedBy(-unitScale).toFixed(8) - return checkCryptoCode(cryptoCode) - .then(() => fetch('sendtoaddress', [toAddress, coins])) - .then((txId) => fetch('gettransaction', [txId])) - .then((res) => _.pick(['fee', 'txid'], res)) - .then((pickedObj) => { - return { - fee: new BN(pickedObj.fee).abs().shiftedBy(unitScale).decimalPlaces(0), - txid: pickedObj.txid - } - }) - .catch(errorHandle) -} - -function newAddress (account, info, tx, settings, operatorId) { - return checkCryptoCode(info.cryptoCode) - .then(() => fetch('getnewaddress')) -} - -function addressBalance (address, confs) { - return fetch('getreceivedbyaddress', [address, confs]) - .then(r => new BN(r).shiftedBy(unitScale).decimalPlaces(0)) -} - -function confirmedBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 1)) -} - -function pendingBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 0)) -} - -function getStatus (account, tx, requested, settings, operatorId) { - const { toAddress, cryptoCode } = tx - - return checkCryptoCode(cryptoCode) - .then(() => confirmedBalance(toAddress, cryptoCode)) - .then(confirmed => { - if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } - - return pendingBalance(toAddress, cryptoCode) - .then(pending => { - if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' } - if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' } - return { receivedCryptoAtoms: pending, status: 'notSeen' } - }) - }) -} - -function newFunding (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => { - const promises = [ - accountUnconfirmedBalance(cryptoCode), - accountBalance(cryptoCode), - newAddress(account, { cryptoCode }) - ] - - return Promise.all(promises) - }) - .then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({ - fundingPendingBalance, - fundingConfirmedBalance, - fundingAddress - })) -} - -function cryptoNetwork (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => parseInt(rpcConfig.port, 10) === 18332 ? 'test' : 'main') -} - -function checkBlockchainStatus (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getblockchaininfo')) - .then(res => !!res['initialblockdownload'] ? 'syncing' : 'ready') -} - -function getTxHashesByAddress (cryptoCode, address) { - checkCryptoCode(cryptoCode) - .then(() => fetch('listreceivedbyaddress', [0, true, true, address])) - .then(txsByAddress => Promise.all(_.map(id => fetch('getrawtransaction', [id]), _.flatMap(it => it.txids, txsByAddress)))) - .then(_.map(({ hash }) => hash)) -} - -module.exports = { - balance, - sendCoins, - newAddress, - getStatus, - newFunding, - cryptoNetwork, - checkBlockchainStatus, - getTxHashesByAddress -} diff --git a/lib/plugins/wallet/bitcoind/bitcoind.js b/lib/plugins/wallet/bitcoind/bitcoind.js deleted file mode 100644 index ba5d17ae..00000000 --- a/lib/plugins/wallet/bitcoind/bitcoind.js +++ /dev/null @@ -1,224 +0,0 @@ -const _ = require('lodash/fp') -const jsonRpc = require('../../common/json-rpc') -const { getSatBEstimateFee } = require('../../../blockexplorers/mempool.space') - -const BN = require('../../../bn') -const E = require('../../../error') -const logger = require('../../../logger') -const { utils: coinUtils } = require('@lamassu/coins') -const { isDevMode } = require('../../../environment-helper') - -const cryptoRec = coinUtils.getCryptoCurrency('BTC') -const unitScale = cryptoRec.unitScale - -const rpcConfig = jsonRpc.rpcConfig(cryptoRec) - -const SUPPORTS_BATCHING = true - -function fetch (method, params) { - return jsonRpc.fetch(rpcConfig, method, params) -} - -function errorHandle (e) { - const err = JSON.parse(e.message) - switch (err.code) { - case -5: - return logger.error(`${err}`) - case -6: - throw new E.InsufficientFundsError() - default: - throw e - } -} - -function checkCryptoCode (cryptoCode) { - if (cryptoCode !== 'BTC') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - return Promise.resolve() -} - -function accountBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getbalances')) - .then(({ mine }) => new BN(mine.trusted).shiftedBy(unitScale).decimalPlaces(0)) - .catch(errorHandle) -} - -function accountUnconfirmedBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getbalances')) - .then(({ mine }) => new BN(mine.untrusted_pending).plus(mine.immature).shiftedBy(unitScale).decimalPlaces(0)) - .catch(errorHandle) -} - -// We want a balance that includes all spends (0 conf) but only deposits that -// have at least 1 confirmation. getbalance does this for us automatically. -function balance (account, cryptoCode, settings, operatorId) { - return accountBalance(cryptoCode) -} - -function estimateFee () { - return getSatBEstimateFee() - .then(result => BN(result)) - .catch(err => { - logger.error('failure estimating fes', err) - }) -} - -function calculateFeeDiscount (feeMultiplier = 1, unitScale) { - // 0 makes bitcoind do automatic fee selection - const AUTOMATIC_FEE = 0 - return estimateFee() - .then(estimatedFee => { - if (!estimatedFee) { - logger.info('failure estimating fee, using bitcoind automatic fee selection') - return AUTOMATIC_FEE - } - // transform from sat/vB to BTC/kvB and apply the multipler - const newFee = estimatedFee.shiftedBy(-unitScale+3).times(feeMultiplier) - if (newFee.lt(0.00001) || newFee.gt(0.1)) { - logger.info('fee outside safety parameters, defaulting to automatic fee selection') - return AUTOMATIC_FEE - } - return newFee.toFixed(8) - }) -} - -function sendCoins (account, tx, settings, operatorId, feeMultiplier) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - const coins = cryptoAtoms.shiftedBy(-unitScale).toFixed(8) - - return checkCryptoCode(cryptoCode) - .then(() => calculateFeeDiscount(feeMultiplier, unitScale)) - .then(newFee => fetch('settxfee', [newFee])) - .then(() => fetch('sendtoaddress', [toAddress, coins])) - .then((txId) => fetch('gettransaction', [txId])) - .then((res) => _.pick(['fee', 'txid'], res)) - .then((pickedObj) => { - return { - fee: new BN(pickedObj.fee).abs().shiftedBy(unitScale).decimalPlaces(0), - txid: pickedObj.txid - } - }) - .catch(errorHandle) -} - -function sendCoinsBatch (account, txs, cryptoCode, feeMultiplier) { - return checkCryptoCode(cryptoCode) - .then(() => calculateFeeDiscount(feeMultiplier, unitScale)) - .then(newFee => fetch('settxfee', [newFee])) - .then(() => _.reduce((acc, value) => ({ - ...acc, - [value.toAddress]: _.isNil(acc[value.toAddress]) - ? BN(value.cryptoAtoms).shiftedBy(-unitScale).toFixed(8) - : BN(acc[value.toAddress]).plus(BN(value.cryptoAtoms).shiftedBy(-unitScale).toFixed(8)) - }), {}, txs)) - .then((obj) => fetch('sendmany', ['', obj])) - .then((txId) => fetch('gettransaction', [txId])) - .then((res) => _.pick(['fee', 'txid'], res)) - .then((pickedObj) => ({ - fee: new BN(pickedObj.fee).abs().shiftedBy(unitScale).decimalPlaces(0), - txid: pickedObj.txid - })) - .catch(errorHandle) -} - -function newAddress (account, info, tx, settings, operatorId) { - return checkCryptoCode(info.cryptoCode) - .then(() => fetch('getnewaddress')) - .catch(errorHandle) -} - -function addressBalance (address, confs) { - return fetch('getreceivedbyaddress', [address, confs]) - .then(r => new BN(r).shiftedBy(unitScale).decimalPlaces(0)) - .catch(errorHandle) -} - -function confirmedBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 1)) -} - -function pendingBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 0)) -} - -function getStatus (account, tx, requested, settings, operatorId) { - const { toAddress, cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => confirmedBalance(toAddress, cryptoCode)) - .then(confirmed => { - if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } - - return pendingBalance(toAddress, cryptoCode) - .then(pending => { - if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' } - if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' } - return { receivedCryptoAtoms: pending, status: 'notSeen' } - }) - }) -} - -function newFunding (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => { - const promises = [ - accountUnconfirmedBalance(cryptoCode), - accountBalance(cryptoCode), - newAddress(account, { cryptoCode }) - ] - - return Promise.all(promises) - }) - .then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({ - fundingPendingBalance, - fundingConfirmedBalance, - fundingAddress - })) - .catch(errorHandle) -} - -function cryptoNetwork (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => parseInt(rpcConfig.port, 10) === 18332 ? 'test' : 'main') -} - -function fetchRBF (txId) { - return fetch('getmempoolentry', [txId]) - .then((res) => { - return [txId, res['bip125-replaceable']] - }) - .catch(err => { - errorHandle(err) - return [txId, true] - }) -} - -function checkBlockchainStatus (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getblockchaininfo')) - .then(res => !!res['initialblockdownload'] ? 'syncing' : 'ready') -} - -function getTxHashesByAddress (cryptoCode, address) { - checkCryptoCode(cryptoCode) - .then(() => fetch('listreceivedbyaddress', [0, true, true, address])) - .then(txsByAddress => Promise.all(_.map(id => fetch('getrawtransaction', [id]), _.flatMap(it => it.txids, txsByAddress)))) - .then(_.map(({ hash }) => hash)) -} - -module.exports = { - balance, - sendCoins, - newAddress, - getStatus, - newFunding, - cryptoNetwork, - fetchRBF, - sendCoinsBatch, - checkBlockchainStatus, - getTxHashesByAddress, - fetch, - SUPPORTS_BATCHING -} diff --git a/lib/plugins/wallet/dashd/dashd.js b/lib/plugins/wallet/dashd/dashd.js deleted file mode 100644 index e5167332..00000000 --- a/lib/plugins/wallet/dashd/dashd.js +++ /dev/null @@ -1,143 +0,0 @@ -const _ = require('lodash/fp') -const jsonRpc = require('../../common/json-rpc') - -const { utils: coinUtils } = require('@lamassu/coins') - -const BN = require('../../../bn') -const E = require('../../../error') - -const cryptoRec = coinUtils.getCryptoCurrency('DASH') -const unitScale = cryptoRec.unitScale - -const rpcConfig = jsonRpc.rpcConfig(cryptoRec) - -function fetch (method, params) { - return jsonRpc.fetch(rpcConfig, method, params) -} - -function errorHandle (e) { - const err = JSON.parse(e.message) - switch (err.code) { - case -6: - throw new E.InsufficientFundsError() - default: - throw e - } -} - -function checkCryptoCode (cryptoCode) { - if (cryptoCode !== 'DASH') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - return Promise.resolve() -} - -function accountBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getwalletinfo')) - .then(({ balance }) => new BN(balance).shiftedBy(unitScale).decimalPlaces(0)) -} - -function accountUnconfirmedBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getwalletinfo')) - .then(({ unconfirmed_balance: balance }) => new BN(balance).shiftedBy(unitScale).decimalPlaces(0)) -} - -// We want a balance that includes all spends (0 conf) but only deposits that -// have at least 1 confirmation. getbalance does this for us automatically. -function balance (account, cryptoCode, settings, operatorId) { - return accountBalance(cryptoCode) -} - -function sendCoins (account, tx, settings, operatorId) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - const coins = cryptoAtoms.shiftedBy(-unitScale).toFixed(8) - - return checkCryptoCode(cryptoCode) - .then(() => fetch('sendtoaddress', [toAddress, coins])) - .then((txId) => fetch('gettransaction', [txId])) - .then((res) => _.pick(['fee', 'txid'], res)) - .then((pickedObj) => { - return { - fee: new BN(pickedObj.fee).abs().shiftedBy(unitScale).decimalPlaces(0), - txid: pickedObj.txid - } - }) - .catch(errorHandle) -} - -function newAddress (account, info, tx, settings, operatorId) { - return checkCryptoCode(info.cryptoCode) - .then(() => fetch('getnewaddress')) -} - -function addressBalance (address, confs) { - return fetch('getreceivedbyaddress', [address, confs]) - .then(r => new BN(r).shiftedBy(unitScale).decimalPlaces(0)) -} - -function confirmedBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 1)) -} - -function pendingBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 0)) -} - -function getStatus (account, tx, requested, settings, operatorId) { - const { toAddress, cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => confirmedBalance(toAddress, cryptoCode)) - .then(confirmed => { - if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } - - return pendingBalance(toAddress, cryptoCode) - .then(pending => { - if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' } - if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' } - return { receivedCryptoAtoms: pending, status: 'notSeen' } - }) - }) -} - -function newFunding (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => { - const promises = [ - accountUnconfirmedBalance(cryptoCode), - accountBalance(cryptoCode), - newAddress(account, { cryptoCode }) - ] - - return Promise.all(promises) - }) - .then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({ - fundingPendingBalance, - fundingConfirmedBalance, - fundingAddress - })) -} - -function checkBlockchainStatus (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getblockchaininfo')) - .then(res => !!res['initialblockdownload'] ? 'syncing' : 'ready') -} - -function getTxHashesByAddress (cryptoCode, address) { - checkCryptoCode(cryptoCode) - .then(() => fetch('listreceivedbyaddress', [0, true, true, true, address])) - .then(txsByAddress => Promise.all(_.map(id => fetch('getrawtransaction', [id]), _.flatMap(it => it.txids, txsByAddress)))) - .then(_.map(({ hash }) => hash)) -} - -module.exports = { - balance, - sendCoins, - newAddress, - getStatus, - newFunding, - checkBlockchainStatus, - getTxHashesByAddress -} diff --git a/lib/plugins/wallet/galoy/galoy.js b/lib/plugins/wallet/galoy/galoy.js deleted file mode 100644 index a2e57906..00000000 --- a/lib/plugins/wallet/galoy/galoy.js +++ /dev/null @@ -1,377 +0,0 @@ -const _ = require('lodash/fp') -const axios = require('axios') -const { utils: coinUtils } = require('@lamassu/coins') - -const NAME = 'LN' -const SUPPORTED_COINS = ['LN'] - -const BN = require('../../../bn') - -function request (graphqlQuery, token, endpoint) { - const headers = { - 'content-type': 'application/json', - 'X-API-KEY': token - } - return axios({ - method: 'post', - url: endpoint, - headers: headers, - data: graphqlQuery - }) - .then(r => { - if (r.error) throw r.error - return r.data - }) - .catch(err => { - throw new Error(err) - }) -} - -function checkCryptoCode (cryptoCode) { - if (!SUPPORTED_COINS.includes(cryptoCode)) { - return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - } - - return Promise.resolve() -} - -function getTransactionsByAddress (token, endpoint, walletId, address) { - const accountInfo = { - 'operationName': 'me', - 'query': `query me($walletId: WalletId!, , $address: OnChainAddress!) { - me { - defaultAccount { - walletById(walletId: $walletId) { - transactionsByAddress (address: $address) { - edges { - node { - direction - settlementAmount - status - } - } - } - } - } - } - }`, - 'variables': { walletId, address } - } - return request(accountInfo, token, endpoint) - .then(r => { - return r.data.me.defaultAccount.walletById.transactionsByAddress - }) - .catch(err => { - throw new Error(err) - }) -} - -function getGaloyWallet (token, endpoint, walletId) { - const accountInfo = { - 'operationName': 'me', - 'query': `query me($walletId: WalletId!) { - me { - defaultAccount { - walletById(walletId: $walletId) { - id - walletCurrency - balance - } - } - } - }`, - 'variables': { walletId } - } - return request(accountInfo, token, endpoint) - .then(r => { - return r.data.me.defaultAccount.walletById - }) - .catch(err => { - throw new Error(err) - }) -} - -function isLnInvoice (address) { - return address.toLowerCase().startsWith('lnbc') -} - -function isLnurl (address) { - return address.toLowerCase().startsWith('lnurl') -} - -function sendFundsOnChain (walletId, address, cryptoAtoms, token, endpoint) { - const sendOnChain = { - 'operationName': 'onChainPaymentSend', - 'query': `mutation onChainPaymentSend($input: OnChainPaymentSendInput!) { - onChainPaymentSend(input: $input) { - errors { - message - path - } - status - } - }`, - 'variables': { 'input': { address, amount: cryptoAtoms.toString(), walletId } } - } - return request(sendOnChain, token, endpoint) - .then(result => { - return result.data.onChainPaymentSend - }) -} - -function sendFundsLNURL (walletId, lnurl, cryptoAtoms, token, endpoint) { - const sendLnNoAmount = { - 'operationName': 'lnurlPaymentSend', - 'query': `mutation lnurlPaymentSend($input: LnurlPaymentSendInput!) { - lnurlPaymentSend(input: $input) { - errors { - message - path - } - status - } - }`, - 'variables': { 'input': { 'lnurl': `${lnurl}`, 'walletId': `${walletId}`, 'amount': `${cryptoAtoms}` } } - } - return request(sendLnNoAmount, token, endpoint).then(result => result.data.lnurlPaymentSend) -} - -function sendFundsLN (walletId, invoice, cryptoAtoms, token, endpoint) { - const sendLnNoAmount = { - 'operationName': 'lnNoAmountInvoicePaymentSend', - 'query': `mutation lnNoAmountInvoicePaymentSend($input: LnNoAmountInvoicePaymentInput!) { - lnNoAmountInvoicePaymentSend(input: $input) { - errors { - message - path - } - status - } - }`, - 'variables': { 'input': { 'paymentRequest': invoice, walletId, amount: cryptoAtoms.toString() } } - } - return request(sendLnNoAmount, token, endpoint).then(result => result.data.lnNoAmountInvoicePaymentSend) -} - -function sendProbeRequest (walletId, invoice, cryptoAtoms, token, endpoint) { - const sendProbeNoAmount = { - 'operationName': 'lnNoAmountInvoiceFeeProbe', - 'query': `mutation lnNoAmountInvoiceFeeProbe($input: LnNoAmountInvoiceFeeProbeInput!) { - lnNoAmountInvoiceFeeProbe(input: $input) { - amount - errors { - message - path - } - } - }`, - 'variables': { 'input': { paymentRequest: invoice, walletId, amount: cryptoAtoms.toString() } } - } - return request(sendProbeNoAmount, token, endpoint).then(result => result.data.lnNoAmountInvoiceFeeProbe) -} - -function sendCoins (account, tx, settings, operatorId) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => { - if (isLnInvoice(toAddress)) { - return sendFundsLN(account.walletId, toAddress, cryptoAtoms, account.apiSecret, account.endpoint) - } - if (isLnurl(toAddress)) { - return sendFundsLNURL(account.walletId, toAddress, cryptoAtoms, account.apiSecret, account.endpoint) - } - return sendFundsOnChain(account.walletId, toAddress, cryptoAtoms, account.apiSecret, account.endpoint) - }) - .then(result => { - switch (result.status) { - case 'ALREADY_PAID': - throw new Error('Transaction already exists!') - case 'FAILURE': - throw new Error('Transaction failed!', JSON.stringify(result.errors)) - case 'SUCCESS': - return '' - case 'PENDING': - return '' - default: - throw new Error(`Transaction failed: ${_.head(result.errors).message}`) - } - }) -} - -function probeLN (account, cryptoCode, invoice) { - const probeHardLimits = [200000, 1000000, 2000000] - const promises = probeHardLimits.map(limit => { - return sendProbeRequest(account.walletId, invoice, limit, account.apiSecret, account.endpoint) - .then(r => _.isEmpty(r.errors)) - }) - return Promise.all(promises) - .then(results => _.zipObject(probeHardLimits, results)) -} - -function newOnChainAddress (walletId, token, endpoint) { - const createOnChainAddress = { - 'operationName': 'onChainAddressCreate', - 'query': `mutation onChainAddressCreate($input: OnChainAddressCreateInput!) { - onChainAddressCreate(input: $input) { - address - errors { - message - path - } - } - }`, - 'variables': { 'input': { walletId } } - } - return request(createOnChainAddress, token, endpoint) - .then(result => { - return result.data.onChainAddressCreate.address - }) -} - -function newNoAmountInvoice (walletId, token, endpoint) { - const createInvoice = { - 'operationName': 'lnNoAmountInvoiceCreate', - 'query': `mutation lnNoAmountInvoiceCreate($input: LnNoAmountInvoiceCreateInput!) { - lnNoAmountInvoiceCreate(input: $input) { - errors { - message - path - } - invoice { - paymentRequest - } - } - }`, - 'variables': { 'input': { walletId } } - } - return request(createInvoice, token, endpoint) - .then(result => { - return result.data.lnNoAmountInvoiceCreate.invoice.paymentRequest - }) - -} - -function newInvoice (walletId, cryptoAtoms, token, endpoint) { - const createInvoice = { - 'operationName': 'lnInvoiceCreate', - 'query': `mutation lnInvoiceCreate($input: LnInvoiceCreateInput!) { - lnInvoiceCreate(input: $input) { - errors { - message - path - } - invoice { - paymentRequest - } - } - }`, - 'variables': { 'input': { walletId, amount: cryptoAtoms.toString() } } - } - return request(createInvoice, token, endpoint) - .then(result => { - return result.data.lnInvoiceCreate.invoice.paymentRequest - }) -} - -function balance (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => getGaloyWallet(account.apiSecret, account.endpoint, account.walletId)) - .then(wallet => { - return new BN(wallet.balance || 0) - }) -} - -function newAddress (account, info, tx, settings, operatorId) { - const { cryptoAtoms, cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => newInvoice(account.walletId, cryptoAtoms, account.apiSecret, account.endpoint)) -} - -function getInvoiceStatus (token, endpoint, address) { - const query = { - 'operationName': 'lnInvoicePaymentStatus', - 'query': `query lnInvoicePaymentStatus($input: LnInvoicePaymentStatusInput!) { - lnInvoicePaymentStatus(input: $input) { - status - } - }`, - 'variables': { input: { paymentRequest: address } } - } - return request(query, token, endpoint) - .then(r => { - return r?.data?.lnInvoicePaymentStatus?.status - }) - .catch(err => { - throw new Error(err) - }) -} - -function getStatus (account, tx, requested, settings, operatorId) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - const getBalance = _.reduce((acc, value) => { - acc[value.node.status] = acc[value.node.status].plus(new BN(value.node.settlementAmount)) - return acc - }, { SUCCESS: new BN(0), PENDING: new BN(0), FAILURE: new BN(0) }) - - return checkCryptoCode(cryptoCode) - .then(() => { - const address = coinUtils.parseUrl(cryptoCode, account.environment, toAddress, false) - if (isLnInvoice(address)) { - return getInvoiceStatus(account.apiSecret, account.endpoint, address) - .then(it => { - const isPaid = it === 'PAID' - if (isPaid) return { receivedCryptoAtoms: cryptoAtoms, status: 'confirmed' } - return { receivedCryptoAtoms: BN(0), status: 'notSeen' } - }) - } - // On-chain and intra-ledger transactions - return getTransactionsByAddress(account.apiSecret, account.endpoint, account.walletId, address) - .then(transactions => { - const { SUCCESS: confirmed, PENDING: pending } = getBalance(transactions.edges) - if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } - if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' } - if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' } - return { receivedCryptoAtoms: pending, status: 'notSeen' } - }) - }) -} - -function newFunding (account, cryptoCode, settings, operatorId) { - // Regular BTC address - return checkCryptoCode(cryptoCode) - .then(() => getGaloyWallet(account.apiSecret, account.endpoint, account.walletId)) - .then(wallet => { - return newOnChainAddress(account.walletId, account.apiSecret, account.endpoint) - .then(onChainAddress => [onChainAddress, wallet.balance]) - }) - .then(([onChainAddress, balance]) => { - return { - // with the old api is not possible to get pending balance - fundingPendingBalance: new BN(0), - fundingConfirmedBalance: new BN(balance), - fundingAddress: onChainAddress - } - }) -} - -function cryptoNetwork (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => account.environment === 'test' ? 'test' : 'main') -} - -function checkBlockchainStatus (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => Promise.resolve('ready')) -} - -module.exports = { - NAME, - balance, - sendCoins, - newAddress, - getStatus, - newFunding, - cryptoNetwork, - checkBlockchainStatus, - probeLN -} diff --git a/lib/plugins/wallet/infura/infura.js b/lib/plugins/wallet/infura/infura.js deleted file mode 100644 index 5732bc2c..00000000 --- a/lib/plugins/wallet/infura/infura.js +++ /dev/null @@ -1,60 +0,0 @@ -const _ = require('lodash/fp') -const NodeCache = require('node-cache') -const base = require('../geth/base') -const T = require('../../../time') -const { BALANCE_FETCH_SPEED_MULTIPLIER } = require('../../../constants') - -const NAME = 'infura' - -function run (account) { - if (!account.endpoint) throw new Error('Need to configure API endpoint for Infura') - - const endpoint = _.startsWith('https://')(account.endpoint) - ? account.endpoint : `https://${account.endpoint}` - - base.connect(endpoint) -} - -const txsCache = new NodeCache({ - stdTTL: T.hour / 1000, - checkperiod: T.minute / 1000, - deleteOnExpire: true -}) - -function shouldGetStatus (tx) { - const timePassedSinceTx = Date.now() - new Date(tx.created) - const timePassedSinceReq = Date.now() - new Date(txsCache.get(tx.id).lastReqTime) - - if (timePassedSinceTx < 3 * T.minutes) return _.isNil(txsCache.get(tx.id).res) || timePassedSinceReq > 10 * T.seconds - if (timePassedSinceTx < 5 * T.minutes) return _.isNil(txsCache.get(tx.id).res) || timePassedSinceReq > 20 * T.seconds - if (timePassedSinceTx < 30 * T.minutes) return _.isNil(txsCache.get(tx.id).res) || timePassedSinceReq > T.minute - if (timePassedSinceTx < 1 * T.hour) return _.isNil(txsCache.get(tx.id).res) || timePassedSinceReq > 2 * T.minute - if (timePassedSinceTx < 3 * T.hours) return _.isNil(txsCache.get(tx.id).res) || timePassedSinceReq > 5 * T.minute - if (timePassedSinceTx < 1 * T.day) return _.isNil(txsCache.get(tx.id).res) || timePassedSinceReq > T.hour - return _.isNil(txsCache.get(tx.id).res) || timePassedSinceReq > T.hour -} - -// Override geth's getStatus function to allow for different polling timing -function getStatus (account, tx, requested, settings, operatorId) { - if (_.isNil(txsCache.get(tx.id))) { - txsCache.set(tx.id, { lastReqTime: Date.now() }) - } - - // return last available response - if (!shouldGetStatus(tx)) { - return Promise.resolve(txsCache.get(tx.id).res) - } - - return base.getStatus(account, tx, requested, settings, operatorId) - .then(res => { - if (res.status === 'confirmed') { - txsCache.del(tx.id) // Transaction reached final status, can trim it from the caching obj - } else { - txsCache.set(tx.id, { lastReqTime: Date.now(), res }) - txsCache.ttl(tx.id, T.hour / 1000) - } - return res - }) -} - -module.exports = _.merge(base, { NAME, run, getStatus, fetchSpeed: BALANCE_FETCH_SPEED_MULTIPLIER.SLOW }) diff --git a/lib/plugins/wallet/litecoind/litecoind.js b/lib/plugins/wallet/litecoind/litecoind.js deleted file mode 100644 index 61dc1f9e..00000000 --- a/lib/plugins/wallet/litecoind/litecoind.js +++ /dev/null @@ -1,140 +0,0 @@ -const _ = require('lodash/fp') -const jsonRpc = require('../../common/json-rpc') - -const { utils: coinUtils } = require('@lamassu/coins') - -const BN = require('../../../bn') -const E = require('../../../error') - -const cryptoRec = coinUtils.getCryptoCurrency('LTC') -const unitScale = cryptoRec.unitScale - -const rpcConfig = jsonRpc.rpcConfig(cryptoRec) - -function fetch (method, params) { - return jsonRpc.fetch(rpcConfig, method, params) -} - -function errorHandle (e) { - const err = JSON.parse(e.message) - switch (err.code) { - case -6: - throw new E.InsufficientFundsError() - default: - throw e - } -} - -function checkCryptoCode (cryptoCode) { - if (cryptoCode !== 'LTC') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - return Promise.resolve() -} - -function accountBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getwalletinfo')) - .then(({ balance }) => new BN(balance).shiftedBy(unitScale).decimalPlaces(0)) -} - -function accountUnconfirmedBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getwalletinfo')) - .then(({ unconfirmed_balance: balance }) => new BN(balance).shiftedBy(unitScale).decimalPlaces(0)) -} - -// We want a balance that includes all spends (0 conf) but only deposits that -// have at least 1 confirmation. getbalance does this for us automatically. -function balance (account, cryptoCode, settings, operatorId) { - return accountBalance(cryptoCode) -} - -function sendCoins (account, tx, settings, operatorId) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - const coins = cryptoAtoms.shiftedBy(-unitScale).toFixed(8) - - return checkCryptoCode(cryptoCode) - .then(() => fetch('sendtoaddress', [toAddress, coins])) - .then((txId) => fetch('gettransaction', [txId])) - .then((res) => _.pick(['fee', 'txid'], res)) - .then((pickedObj) => { - return { - fee: new BN(pickedObj.fee).abs().shiftedBy(unitScale).decimalPlaces(0), - txid: pickedObj.txid - } - }) - .catch(errorHandle) -} - -function newAddress (account, info, tx, settings, operatorId) { - return checkCryptoCode(info.cryptoCode) - .then(() => fetch('getnewaddress')) -} - -function addressBalance (address, confs) { - return fetch('getreceivedbyaddress', [address, confs]) - .then(r => new BN(r).shiftedBy(unitScale).decimalPlaces(0)) -} - -function confirmedBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 1)) -} - -function pendingBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 0)) -} - -function getStatus (account, tx, requested, settings, operatorId) { - const { toAddress, cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => confirmedBalance(toAddress, cryptoCode)) - .then(confirmed => { - if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } - - return pendingBalance(toAddress, cryptoCode) - .then(pending => { - if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' } - if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' } - return { receivedCryptoAtoms: pending, status: 'notSeen' } - }) - }) -} - -function newFunding (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => { - const promises = [ - accountUnconfirmedBalance(cryptoCode), - accountBalance(cryptoCode), - newAddress(account, { cryptoCode }) - ] - - return Promise.all(promises) - }) - .then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({ - fundingPendingBalance, - fundingConfirmedBalance, - fundingAddress - })) -} - -function checkBlockchainStatus (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getblockchaininfo')) - .then(res => !!res['initialblockdownload'] ? 'syncing' : 'ready') -} - -function getTxHashesByAddress (cryptoCode, address) { - throw new Error(`Transactions hash retrieval not implemented for this coin!`) -} - -module.exports = { - balance, - sendCoins, - newAddress, - getStatus, - newFunding, - checkBlockchainStatus, - getTxHashesByAddress -} diff --git a/lib/plugins/wallet/mock-wallet/mock-wallet.js b/lib/plugins/wallet/mock-wallet/mock-wallet.js deleted file mode 100644 index 4e359287..00000000 --- a/lib/plugins/wallet/mock-wallet/mock-wallet.js +++ /dev/null @@ -1,141 +0,0 @@ -const _ = require('lodash/fp') - -const BN = require('../../../bn') -const E = require('../../../error') -const { utils: coinUtils } = require('@lamassu/coins') - -const NAME = 'FakeWallet' - -const SECONDS = 1000 -const PUBLISH_TIME = 3 * SECONDS -const AUTHORIZE_TIME = PUBLISH_TIME + 5 * SECONDS -const CONFIRM_TIME = AUTHORIZE_TIME + 10 * SECONDS -const SUPPORTED_COINS = coinUtils.cryptoCurrencies() - -let t0 - -const checkCryptoCode = (cryptoCode) => !_.includes(cryptoCode, SUPPORTED_COINS) - ? Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - : Promise.resolve() - -function _balance (cryptoCode) { - const cryptoRec = coinUtils.getCryptoCurrency(cryptoCode) - const unitScale = cryptoRec.unitScale - return new BN(10).shiftedBy(unitScale).decimalPlaces(0) -} - -function balance (account, cryptoCode, settings, operatorId) { - return Promise.resolve() - .then(() => _balance(cryptoCode)) -} - -function pendingBalance (account, cryptoCode) { - return balance(account, cryptoCode) - .then(b => b.times(1.1)) -} - -function confirmedBalance (account, cryptoCode) { - return balance(account, cryptoCode) -} - -// Note: This makes it easier to test insufficient funds errors -let sendCount = 100 - -function isInsufficient (cryptoAtoms, cryptoCode) { - const b = _balance(cryptoCode) - return cryptoAtoms.gt(b.div(1000).times(sendCount)) -} - -function sendCoins (account, tx, settings, operatorId) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - sendCount++ - return new Promise((resolve, reject) => { - setTimeout(() => { - if (isInsufficient(cryptoAtoms, cryptoCode)) { - console.log('[%s] DEBUG: Mock wallet insufficient funds: %s', - cryptoCode, cryptoAtoms.toString()) - return reject(new E.InsufficientFundsError()) - } - - console.log('[%s] DEBUG: Mock wallet sending %s cryptoAtoms to %s', - cryptoCode, cryptoAtoms.toString(), toAddress) - return resolve({ txid: '', fee: new BN(0) }) - }, 2000) - }) -} - -function sendCoinsBatch (account, txs, cryptoCode) { - sendCount = sendCount + txs.length - return new Promise((resolve, reject) => { - setTimeout(() => { - const cryptoSum = _.reduce((acc, value) => acc.plus(value.crypto_atoms), BN(0), txs) - if (isInsufficient(cryptoSum, cryptoCode)) { - console.log('[%s] DEBUG: Mock wallet insufficient funds: %s', - cryptoCode, cryptoSum.toString()) - return reject(new E.InsufficientFundsError()) - } - - console.log('[%s] DEBUG: Mock wallet sending %s cryptoAtoms in a batch', - cryptoCode, cryptoSum.toString()) - return resolve({ txid: '', fee: BN(0) }) - }, 2000) - }) -} - -function newAddress () { - t0 = Date.now() - return Promise.resolve('') -} - -function newFunding (account, cryptoCode, settings, operatorId) { - const promises = [ - pendingBalance(account, cryptoCode), - confirmedBalance(account, cryptoCode), - newAddress(account, { cryptoCode }) - ] - - return Promise.all(promises) - .then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({ - fundingPendingBalance, - fundingConfirmedBalance, - fundingAddress - })) -} - -function getStatus (account, tx, requested, settings, operatorId) { - const { toAddress, cryptoCode } = tx - const elapsed = Date.now() - t0 - - if (elapsed < PUBLISH_TIME) return Promise.resolve({ receivedCryptoAtoms: new BN(0), status: 'notSeen' }) - if (elapsed < AUTHORIZE_TIME) return Promise.resolve({ receivedCryptoAtoms: requested, status: 'published' }) - if (elapsed < CONFIRM_TIME) return Promise.resolve({ receivedCryptoAtoms: requested, status: 'authorized' }) - - console.log('[%s] DEBUG: Mock wallet has confirmed transaction [%s]', cryptoCode, toAddress.slice(0, 5)) - - return Promise.resolve({ status: 'confirmed' }) -} - -function getTxHashesByAddress (cryptoCode, address) { - return new Promise((resolve, reject) => { - setTimeout(() => { - return resolve([]) // TODO: should return something other than empty list? - }, 100) - }) -} - -function checkBlockchainStatus (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => Promise.resolve('ready')) -} - -module.exports = { - NAME, - balance, - sendCoinsBatch, - sendCoins, - newAddress, - getStatus, - newFunding, - checkBlockchainStatus, - getTxHashesByAddress -} diff --git a/lib/plugins/wallet/monerod/monerod.js b/lib/plugins/wallet/monerod/monerod.js deleted file mode 100644 index d5aa5098..00000000 --- a/lib/plugins/wallet/monerod/monerod.js +++ /dev/null @@ -1,254 +0,0 @@ -const fs = require('fs') -const path = require('path') -const _ = require('lodash/fp') -const { COINS, utils } = require('@lamassu/coins') -const { default: PQueue } = require('p-queue') - -const BN = require('../../../bn') -const E = require('../../../error') -const logger = require('../../../logger') -const jsonRpc = require('../../common/json-rpc') - -const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR - -const cryptoRec = utils.getCryptoCurrency(COINS.XMR) -const configPath = utils.configPath(cryptoRec, BLOCKCHAIN_DIR) -const walletDir = path.resolve(utils.cryptoDir(cryptoRec, BLOCKCHAIN_DIR), 'wallets') - -const DIGEST_QUEUE = new PQueue({ - concurrency: 1, - interval: 150, -}) - -function createDigestRequest (account = {}, method, params = []) { - return DIGEST_QUEUE.add(() => jsonRpc.fetchDigest(account, method, params) - .then(res => { - const r = JSON.parse(res) - if (r.error) throw r.error - return r.result - }) - ) -} - -function rpcConfig () { - try { - const config = jsonRpc.parseConf(configPath) - return { - username: config['rpc-login'].split(':')[0], - password: config['rpc-login'].split(':')[1], - port: cryptoRec.walletPort || cryptoRec.defaultPort - } - } catch (err) { - logger.error('Wallet is currently not installed!') - return { - username: '', - password: '', - port: cryptoRec.walletPort || cryptoRec.defaultPort - } - } -} - -function fetch (method, params) { - return createDigestRequest(rpcConfig(), method, params) -} - -function handleError (error, method) { - switch(error.code) { - case -13: - { - if ( - fs.existsSync(path.resolve(walletDir, 'Wallet')) && - fs.existsSync(path.resolve(walletDir, 'Wallet.keys')) - ) { - logger.debug('Found wallet! Opening wallet...') - return openWallet() - } - logger.debug('Couldn\'t find wallet! Creating...') - return createWallet() - } - case -21: - throw new Error('Wallet already exists!') - case -22: - try { - return openWalletWithPassword() - } catch { - throw new Error('Invalid wallet password!') - } - case -17: - throw new E.InsufficientFundsError() - case -37: - throw new E.InsufficientFundsError() - default: - throw new Error( - _.join(' ', [ - `json-rpc::${method} error:`, - JSON.stringify(_.get('message', error, '')), - JSON.stringify(_.get('response.data.error', error, '')) - ]) - ) - } -} - -function openWallet () { - return fetch('open_wallet', { filename: 'Wallet' }) - .catch(() => openWalletWithPassword()) -} - -function openWalletWithPassword () { - return fetch('open_wallet', { filename: 'Wallet', password: rpcConfig().password }) -} - -function createWallet () { - return fetch('create_wallet', { filename: 'Wallet', language: 'English' }) - .then(() => new Promise(() => setTimeout(() => openWallet(), 3000))) - .then(() => fetch('auto_refresh')) -} - -function checkCryptoCode (cryptoCode) { - if (cryptoCode !== 'XMR') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - return Promise.resolve() -} - -function refreshWallet () { - return fetch('refresh') - .catch(err => handleError(err, 'refreshWallet')) -} - -function accountBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => refreshWallet()) - .then(() => fetch('get_balance', { account_index: 0, address_indices: [0] })) - .then(res => { - return BN(res.unlocked_balance).decimalPlaces(0) - }) - .catch(err => handleError(err, 'accountBalance')) -} - -function balance (account, cryptoCode, settings, operatorId) { - return accountBalance(cryptoCode) -} - -function sendCoins (account, tx, settings, operatorId, feeMultiplier) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => refreshWallet()) - .then(() => fetch('transfer_split', { - destinations: [{ amount: cryptoAtoms, address: toAddress }], - account_index: 0, - subaddr_indices: [], - priority: 0, - mixin: 6, - ring_size: 7, - unlock_time: 0, - get_tx_hex: false, - new_algorithm: false, - get_tx_metadata: false - })) - .then(res => ({ - fee: BN(res.fee_list[0]).abs(), - txid: res.tx_hash_list[0] - })) - .catch(err => handleError(err, 'sendCoins')) -} - -function newAddress (account, info, tx, settings, operatorId) { - return checkCryptoCode(info.cryptoCode) - .then(() => fetch('create_address', { account_index: 0 })) - .then(res => res.address) - .catch(err => handleError(err, 'newAddress')) -} - -function getStatus (account, tx, requested, settings, operatorId) { - const { toAddress, cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => refreshWallet()) - .then(() => fetch('get_address_index', { address: toAddress })) - .then(addressRes => fetch('get_transfers', { in: true, pool: true, account_index: addressRes.index.major, subaddr_indices: [addressRes.index.minor] })) - .then(transferRes => { - const confirmedToAddress = _.filter(it => it.address === toAddress, transferRes.in ?? []) - const pendingToAddress = _.filter(it => it.address === toAddress, transferRes.pool ?? []) - const confirmed = _.reduce((acc, value) => acc.plus(value.amount), BN(0), confirmedToAddress) - const pending = _.reduce((acc, value) => acc.plus(value.amount), BN(0), pendingToAddress) - - if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } - if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' } - if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' } - return { receivedCryptoAtoms: pending, status: 'notSeen' } - }) - .catch(err => handleError(err, 'getStatus')) -} - -function newFunding (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => refreshWallet()) - .then(() => Promise.all([ - fetch('get_balance', { account_index: 0, address_indices: [0] }), - fetch('create_address', { account_index: 0 }), - fetch('get_transfers', { pool: true, account_index: 0 }) - ])) - .then(([balanceRes, addressRes, transferRes]) => { - const memPoolBalance = _.reduce((acc, value) => acc.plus(value.amount), BN(0), transferRes.pool) - return { - fundingPendingBalance: BN(balanceRes.balance).minus(balanceRes.unlocked_balance).plus(memPoolBalance), - fundingConfirmedBalance: BN(balanceRes.unlocked_balance), - fundingAddress: addressRes.address - } - }) - .catch(err => handleError(err, 'newFunding')) -} - -function cryptoNetwork (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => { - switch(parseInt(rpcConfig().port, 10)) { - case 18082: - return 'main' - case 28082: - return 'test' - case 38083: - return 'stage' - default: - return '' - } - }) -} - -function checkBlockchainStatus (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => { - try { - const config = jsonRpc.parseConf(configPath) - - // Daemon uses a different connection of the wallet - const rpcConfig = { - username: config['rpc-login'].split(':')[0], - password: config['rpc-login'].split(':')[1], - port: cryptoRec.defaultPort - } - - return jsonRpc.fetchDigest(rpcConfig, 'get_info') - .then(res => !!res.synchronized ? 'ready' : 'syncing') - } catch (err) { - throw new Error('XMR daemon is currently not installed') - } - }) -} - -function getTxHashesByAddress (cryptoCode, address) { - checkCryptoCode(cryptoCode) - .then(() => refreshWallet()) - .then(() => fetch('get_address_index', { address: address })) - .then(addressRes => fetch('get_transfers', { in: true, pool: true, pending: true, account_index: addressRes.index.major, subaddr_indices: [addressRes.index.minor] })) - .then(_.map(({ txid }) => txid)) -} - -module.exports = { - balance, - sendCoins, - newAddress, - getStatus, - newFunding, - cryptoNetwork, - checkBlockchainStatus, - getTxHashesByAddress -} diff --git a/lib/plugins/wallet/pazuz-wallet/pazuz-wallet.js b/lib/plugins/wallet/pazuz-wallet/pazuz-wallet.js deleted file mode 100644 index afb0aa74..00000000 --- a/lib/plugins/wallet/pazuz-wallet/pazuz-wallet.js +++ /dev/null @@ -1,98 +0,0 @@ -const https = require('https') -const BN = require('../../../bn') -const E = require('../../../error') -const _ = require('lodash/fp') - -const SUPPORTED_COINS = ['BTC'] - -const axios = require('axios').create({ - // TODO: get rejectUnauthorized true to work - baseURL: `${process.env.WALLET_URL}/api`, - httpsAgent: new https.Agent({ - rejectUnauthorized: false - }) -}) - -const checkCryptoCode = (cryptoCode) => !_.includes(cryptoCode, SUPPORTED_COINS) - ? Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - : Promise.resolve() - -function balance (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => { - return axios.post('/balance', { - cryptoCode, - config: settings.config, - operatorId - }) - }) - .then(({ data }) => { - if (data.error) throw new Error(JSON.stringify(data.error)) - return new BN(data.balance) - }) -} - -function sendCoins (account, tx, settings, operatorId) { - const { cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => { - return axios.post('/sendCoins', { - tx, - config: settings.config, - operatorId - }) - }) - .then(({ data }) => { - if (data.error && data.error.errorCode === 'sc-001') throw new E.InsufficientFundsError() - else if (data.error) throw new Error(JSON.stringify(data.error)) - const fee = new BN(data.fee).decimalPlaces(0) - const txid = data.txid - return { txid, fee } - }) -} - -function newAddress (account, info, tx, settings, operatorId) { - return checkCryptoCode(info.cryptoCode) - .then(() => axios.post('/newAddress', { - info, - tx, - config: settings.config, - operatorId - })) - .then(({ data }) => { - if(data.error) throw new Error(JSON.stringify(data.error)) - return data.newAddress - }) -} - -function getStatus (account, tx, requested, settings, operatorId) { - return checkCryptoCode(tx.cryptoCode) - .then(() => axios.get(`/balance/${tx.toAddress}?cryptoCode=${tx.cryptoCode}`)) - .then(({ data }) => { - if (data.error) throw new Error(JSON.stringify(data.error)) - const confirmed = new BN(data.confirmedBalance) - const pending = new BN(data.pendingBalance) - if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } - if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' } - if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' } - return { receivedCryptoAtoms: pending, status: 'notSeen' } - }) -} - -function newFunding (account, cryptoCode, settings, operatorId) { - throw new E.NotImplementedError() -} - -function sweep (account, txId, cryptoCode, hdIndex, settings, operatorId) { - throw new E.NotImplementedError() -} - -module.exports = { - balance, - sendCoins, - newAddress, - newFunding, - getStatus, - sweep, - supportsHd: true, -} diff --git a/lib/plugins/wallet/zcashd/zcashd.js b/lib/plugins/wallet/zcashd/zcashd.js deleted file mode 100644 index 1122bf18..00000000 --- a/lib/plugins/wallet/zcashd/zcashd.js +++ /dev/null @@ -1,167 +0,0 @@ -const _ = require('lodash/fp') -const pRetry = require('p-retry') -const jsonRpc = require('../../common/json-rpc') - -const { utils: coinUtils } = require('@lamassu/coins') - -const BN = require('../../../bn') -const E = require('../../../error') - -const cryptoRec = coinUtils.getCryptoCurrency('ZEC') -const unitScale = cryptoRec.unitScale - -const rpcConfig = jsonRpc.rpcConfig(cryptoRec) - -function fetch (method, params) { - return jsonRpc.fetch(rpcConfig, method, params) -} - -function errorHandle (e) { - const err = JSON.parse(e.message) - switch (err.code) { - case -6: - throw new E.InsufficientFundsError() - default: - throw e - } -} - -function checkCryptoCode (cryptoCode) { - if (cryptoCode !== 'ZEC') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) - return Promise.resolve() -} - -function accountBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getwalletinfo')) - .then(({ balance }) => new BN(balance).shiftedBy(unitScale).decimalPlaces(0)) -} - -function accountUnconfirmedBalance (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getwalletinfo')) - .then(({ unconfirmed_balance: balance }) => new BN(balance).shiftedBy(unitScale).decimalPlaces(0)) -} - -// We want a balance that includes all spends (0 conf) but only deposits that -// have at least 1 confirmation. getbalance does this for us automatically. -function balance (account, cryptoCode, settings, operatorId) { - return accountBalance(cryptoCode) -} - -function sendCoins (account, tx, settings, operatorId) { - const { toAddress, cryptoAtoms, cryptoCode } = tx - const coins = cryptoAtoms.shiftedBy(-unitScale).toFixed(8) - const checkSendStatus = function (opid) { - return new Promise((resolve, reject) => { - fetch('z_getoperationstatus', [[opid]]) - .then(res => { - const status = _.get('status', res[0]) - switch (status) { - case 'success': - resolve(res[0]) - break - case 'failed': - throw new pRetry.AbortError(res[0].error) - case 'executing': - reject(new Error('operation still executing')) - break - } - }) - }) - } - - const checker = opid => pRetry(() => checkSendStatus(opid), { retries: 20, minTimeout: 300, factor: 1.05 }) - - return checkCryptoCode(cryptoCode) - .then(() => fetch('z_sendmany', ['ANY_TADDR', [{ address: toAddress, amount: coins }], null, null, 'NoPrivacy'])) - .then(checker) - .then((res) => { - return { - fee: _.get('params.fee', res), - txid: _.get('result.txid', res) - } - }) - .then((pickedObj) => { - return { - fee: new BN(pickedObj.fee).abs().shiftedBy(unitScale).decimalPlaces(0), - txid: pickedObj.txid - } - }) - .catch(errorHandle) -} - -function newAddress (account, info, tx, settings, operatorId) { - return checkCryptoCode(info.cryptoCode) - .then(() => fetch('getnewaddress')) -} - -function addressBalance (address, confs) { - return fetch('getreceivedbyaddress', [address, confs]) - .then(r => new BN(r).shiftedBy(unitScale).decimalPlaces(0)) -} - -function confirmedBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 1)) -} - -function pendingBalance (address, cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => addressBalance(address, 0)) -} - -function getStatus (account, tx, requested, settings, operatorId) { - const { toAddress, cryptoCode } = tx - return checkCryptoCode(cryptoCode) - .then(() => confirmedBalance(toAddress, cryptoCode)) - .then(confirmed => { - if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } - - return pendingBalance(toAddress, cryptoCode) - .then(pending => { - if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' } - if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' } - return { receivedCryptoAtoms: pending, status: 'notSeen' } - }) - }) -} - -function newFunding (account, cryptoCode, settings, operatorId) { - return checkCryptoCode(cryptoCode) - .then(() => { - const promises = [ - accountUnconfirmedBalance(cryptoCode), - accountBalance(cryptoCode), - newAddress(account, { cryptoCode }) - ] - - return Promise.all(promises) - }) - .then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({ - fundingPendingBalance, - fundingConfirmedBalance, - fundingAddress - })) -} - -function checkBlockchainStatus (cryptoCode) { - return checkCryptoCode(cryptoCode) - .then(() => fetch('getblockchaininfo')) - .then(res => !!res['initial_block_download_complete'] ? 'ready' : 'syncing') -} - -function getTxHashesByAddress (cryptoCode, address) { - checkCryptoCode(cryptoCode) - .then(() => fetch('getaddresstxids', [address])) -} - -module.exports = { - balance, - sendCoins, - newAddress, - getStatus, - newFunding, - checkBlockchainStatus, - getTxHashesByAddress -} diff --git a/lib/plugins/zero-conf/blockcypher/blockcypher.js b/lib/plugins/zero-conf/blockcypher/blockcypher.js deleted file mode 100644 index ef48e61f..00000000 --- a/lib/plugins/zero-conf/blockcypher/blockcypher.js +++ /dev/null @@ -1,48 +0,0 @@ -const qs = require('querystring') -const axios = require('axios') -const _ = require('lodash/fp') - -const { fetchRBF } = require('../../wallet/bitcoind/bitcoind') -module.exports = { authorize } - -function highConfidence (confidence, txref, txRBF) { - if (txref.double_spend) return 0 - if (txRBF) return 0 - if (txref.confirmations > 0 || txref.confidence * 100 >= confidence) return txref.value - return 0 -} - -function authorize (account, toAddress, cryptoAtoms, cryptoCode, isBitcoindAvailable) { - return Promise.resolve() - .then(() => { - if (cryptoCode !== 'BTC') throw new Error('Unsupported crypto: ' + cryptoCode) - - const query = qs.stringify({ - token: account.token, - includeConfidence: true - }) - - const confidence = account.confidenceFactor - const isRBFEnabled = account.rbf - const url = `https://api.blockcypher.com/v1/btc/main/addrs/${toAddress}?${query}` - - return axios.get(url) - .then(r => { - const data = r.data - if (isBitcoindAvailable && isRBFEnabled && data.unconfirmed_txrefs) { - const promises = _.map(unconfirmedTxref => fetchRBF(unconfirmedTxref.tx_hash), data.unconfirmed_txrefs) - return Promise.all(promises) - .then(values => { - const unconfirmedTxsRBF = _.fromPairs(values) - const sumTxRefs = txrefs => _.sumBy(txref => highConfidence(confidence, txref, unconfirmedTxsRBF[txref.tx_hash]), txrefs) - const authorizedValue = sumTxRefs(data.txrefs) + sumTxRefs(data.unconfirmed_txrefs) - return cryptoAtoms.lte(authorizedValue) - }) - } - - const sumTxRefs = txrefs => _.sumBy(txref => highConfidence(confidence, txref), txrefs) - const authorizedValue = sumTxRefs(data.txrefs) + sumTxRefs(data.unconfirmed_txrefs) - return cryptoAtoms.lte(authorizedValue) - }) - }) -} diff --git a/lib/plugins/zero-conf/mock-zero-conf/mock-zero-conf.js b/lib/plugins/zero-conf/mock-zero-conf/mock-zero-conf.js deleted file mode 100644 index d2276170..00000000 --- a/lib/plugins/zero-conf/mock-zero-conf/mock-zero-conf.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = {authorize} - -function authorize (account, toAddress, cryptoAtoms, cryptoCode) { - return Promise.resolve() - .then(() => { - if (cryptoCode !== 'BTC') throw new Error('Unsupported crypto: ' + cryptoCode) - - const isAuthorized = false - return isAuthorized - }) -} diff --git a/lib/postgresql_interface.js b/lib/postgresql_interface.js deleted file mode 100644 index 014d52fa..00000000 --- a/lib/postgresql_interface.js +++ /dev/null @@ -1,86 +0,0 @@ -const _ = require('lodash/fp') -const db = require('./db') -const pgp = require('pg-promise')() - -function getInsertQuery (tableName, fields) { - // outputs string like: '$1, $2, $3...' with proper No of items - const placeholders = fields.map(function (_, i) { - return '$' + (i + 1) - }).join(', ') - - const query = 'INSERT INTO ' + tableName + - ' (' + fields.join(', ') + ')' + - ' VALUES' + - ' (' + placeholders + ')' - - return query -} - -exports.recordDeviceEvent = function recordDeviceEvent (deviceId, event) { - const sql = 'INSERT INTO device_events (device_id, event_type, ' + - 'note, device_time) VALUES ($1, $2, $3, $4)' - const values = [deviceId, event.eventType, event.note, - event.deviceTime] - - return db.none(sql, values) -} - -exports.cassetteCounts = function cassetteCounts (deviceId) { - const sql = 'SELECT cassette1, cassette2, cassette3, cassette4, number_of_cassettes FROM devices ' + - 'WHERE device_id=$1' - - return db.one(sql, [deviceId]) - .then(row => { - const counts = [] - _.forEach(it => { - counts.push(row[`cassette${it + 1}`]) - }, _.times(_.identity(), row.number_of_cassettes)) - - return { numberOfCassettes: row.number_of_cassettes, counts } - }) -} - -exports.recyclerCounts = function recyclerCounts (deviceId) { - const sql = 'SELECT recycler1, recycler2, recycler3, recycler4, recycler5, recycler6, number_of_recyclers FROM devices ' + - 'WHERE device_id=$1' - - return db.one(sql, [deviceId]) - .then(row => { - const counts = [] - _.forEach(it => { - counts.push(row[`recycler${it + 1}`]) - }, _.times(_.identity(), row.number_of_recyclers)) - - return { numberOfRecyclers: row.number_of_recyclers, counts } - }) -} - -// Note: since we only prune on insert, we'll always have -// last known state. -exports.machineEvent = function machineEvent (rec) { - const fields = ['id', 'device_id', 'event_type', 'note', 'device_time'] - const sql = getInsertQuery('machine_events', fields) - const values = [rec.id, rec.deviceId, rec.eventType, rec.note, rec.deviceTime] - - const deleteSql = `delete from machine_events - where created < now() - interval '1 days'` - - return db.none(sql, values) - .then(() => db.none(deleteSql)) -} - -exports.machineEventsByIdBatch = function machineEventsByIdBatch (machineIds) { - const formattedIds = _.map(pgp.as.text, machineIds).join(',') - const sql = `SELECT *, (EXTRACT(EPOCH FROM (now() - created))) * 1000 AS age FROM machine_events WHERE device_id IN ($1^) ORDER BY age ASC LIMIT 1` - return db.any(sql, [formattedIds]).then(res => { - const events = _.map(_.mapKeys(_.camelCase))(res) - const eventMap = _.groupBy('deviceId', events) - return machineIds.map(id => _.prop([0], eventMap[id])) - }) -} - -exports.machineEvents = function machineEvents () { - const sql = 'SELECT *, (EXTRACT(EPOCH FROM (now() - created))) * 1000 AS age FROM machine_events' - - return db.any(sql, []) -} diff --git a/lib/routes/phoneCodeRoutes.js b/lib/routes/phoneCodeRoutes.js deleted file mode 100644 index 25fa3795..00000000 --- a/lib/routes/phoneCodeRoutes.js +++ /dev/null @@ -1,74 +0,0 @@ -const express = require('express') -const router = express.Router() -const semver = require('semver') -const _ = require('lodash/fp') - -const compliance = require('../compliance') -const complianceTriggers = require('../compliance-triggers') -const configManager = require('../new-config-manager') -const { get, add, getById, update } = require('../customers') -const httpError = require('../route-helpers').httpError -const plugins = require('../plugins') -const Tx = require('../tx') -const respond = require('../respond') -const loyalty = require('../loyalty') - -function addOrUpdateCustomer (req) { - const customerData = req.body - const machineVersion = req.query.version - const triggers = configManager.getTriggers(req.settings.config) - const compatTriggers = complianceTriggers.getBackwardsCompatibleTriggers(triggers) - const maxDaysThreshold = complianceTriggers.maxDaysThreshold(triggers) - - return get(customerData.phone) - .then(customer => { - if (customer) return customer - - return add(req.body) - }) - .then(customer => getById(customer.id)) - .then(customer => { - // BACKWARDS_COMPATIBILITY 7.5 - // machines before 7.5 expect customer with sanctions result - const isOlderMachineVersion = !machineVersion || semver.lt(machineVersion, '7.5.0-beta.0') - const shouldRunOfacCompat = !compatTriggers.sanctions && isOlderMachineVersion - if (!shouldRunOfacCompat) return customer - - return compliance.validationPatch(req.deviceId, !!compatTriggers.sanctions, customer) - .then(patch => { - if (_.isEmpty(patch)) return customer - return update(customer.id, patch) - }) - }) - .then(customer => { - return Tx.customerHistory(customer.id, maxDaysThreshold) - .then(result => { - customer.txHistory = result - return customer - }) - }) - .then(customer => { - return loyalty.getCustomerActiveIndividualDiscount(customer.id) - .then(discount => ({ ...customer, discount })) - }) -} - -function getCustomerWithPhoneCode (req, res, next) { - const pi = plugins(req.settings, req.deviceId) - const phone = req.body.phone - - return pi.getPhoneCode(phone) - .then(code => { - return addOrUpdateCustomer(req) - .then(customer => respond(req, res, { code, customer })) - }) - .catch(err => { - if (err.name === 'BadNumberError') throw httpError('Bad number', 401) - throw err - }) - .catch(next) -} - -router.post('/', getCustomerWithPhoneCode) - -module.exports = router diff --git a/lib/routes/pollingRoutes.js b/lib/routes/pollingRoutes.js deleted file mode 100644 index 96ce9135..00000000 --- a/lib/routes/pollingRoutes.js +++ /dev/null @@ -1,171 +0,0 @@ -const express = require('express') -const nmd = require('nano-markdown') -const _ = require('lodash/fp') - -const router = express.Router() - -const complianceTriggers = require('../compliance-triggers') -const configManager = require('../new-config-manager') -const plugins = require('../plugins') -const semver = require('semver') -const state = require('../middlewares/state') -const version = require('../../package.json').version -const { batchGetCustomInfoRequest, getCustomInfoRequests } = require('../new-admin/services/customInfoRequests') - -const urlsToPing = [ - `us.archive.ubuntu.com`, - `uk.archive.ubuntu.com`, - `za.archive.ubuntu.com`, - `cn.archive.ubuntu.com` -] - -const speedtestFiles = [ - { - url: 'https://github.com/lamassu/speed-test-assets/raw/main/python-defaults_2.7.18-3.tar.gz', - size: 44668 - } -] - -function checkHasLightning (settings) { - return configManager.getWalletSettings('BTC', settings.config).layer2 !== 'no-layer2' -} - -const createTerms = terms => (terms.active && terms.text) ? ({ - active: terms.active, - title: terms.title, - text: nmd(terms.text), - accept: terms.acceptButtonText, - cancel: terms.cancelButtonText -}) : null - -const buildTriggers = (allTriggers) => { - const normalTriggers = [] - const customTriggers = _.filter(o => { - if (_.isEmpty(o.customInfoRequestId) || _.isNil(o.customInfoRequestId)) normalTriggers.push(o) - return !_.isNil(o.customInfoRequestId) && !_.isEmpty(o.customInfoRequestId) - }, allTriggers) - - return _.flow([_.map(_.get('customInfoRequestId')), batchGetCustomInfoRequest])(customTriggers) - .then(res => { - res.forEach((details, index) => { - // make sure we aren't attaching the details to the wrong trigger - if (customTriggers[index].customInfoRequestId !== details.id) return - customTriggers[index] = { ...customTriggers[index], customInfoRequest: details } - }) - return [...normalTriggers, ...customTriggers] - }) -} - -function poll (req, res, next) { - const machineVersion = req.query.version - const machineModel = req.query.model - const deviceId = req.deviceId - const deviceTime = req.deviceTime - const pid = req.query.pid - const settings = req.settings - const operatorId = res.locals.operatorId - const localeConfig = configManager.getLocale(deviceId, settings.config) - const zeroConfLimits = _.reduce((acc, cryptoCode) => { - acc[cryptoCode] = configManager.getWalletSettings(cryptoCode, settings.config).zeroConfLimit - return acc - }, {}, localeConfig.cryptoCurrencies) - const pi = plugins(settings, deviceId) - const hasLightning = checkHasLightning(settings) - - const operatorInfo = configManager.getOperatorInfo(settings.config) - const machineInfo = { deviceId: req.deviceId, deviceName: req.deviceName } - const cashOutConfig = configManager.getCashOut(deviceId, settings.config) - const receipt = configManager.getReceipt(settings.config) - const terms = configManager.getTermsConditions(settings.config) - const enablePaperWalletOnly = configManager.getCompliance(settings.config).enablePaperWalletOnly - - state.pids = _.update(operatorId, _.set(deviceId, { pid, ts: Date.now() }), state.pids) - - // BACKWARDS_COMPATIBILITY 8.1 - // Machines after 8.1 only need the server version from the initial polling request. - if (semver.gte(machineVersion, '8.1.0-beta.0')) - return res.json({ version }) - - return Promise.all([ - pi.recordPing(deviceTime, machineVersion, machineModel), - pi.pollQueries(), - buildTriggers(configManager.getTriggers(settings.config)), - configManager.getTriggersAutomation(getCustomInfoRequests(true), settings.config, true), - ]) - .then(([_pingRes, results, triggers, triggersAutomation]) => { - const reboot = pid && state.reboots?.[operatorId]?.[deviceId] === pid - const shutdown = pid && state.shutdowns?.[operatorId]?.[deviceId] === pid - const restartServices = pid && state.restartServicesMap?.[operatorId]?.[deviceId] === pid - const emptyUnit = pid && state.emptyUnit?.[operatorId]?.[deviceId] === pid - const refillUnit = pid && state.refillUnit?.[operatorId]?.[deviceId] === pid - const langs = localeConfig.languages - - const locale = { - fiatCode: localeConfig.fiatCurrency, - localeInfo: { - primaryLocale: langs[0], - primaryLocales: langs, - country: localeConfig.country - } - } - - const response = { - error: null, - locale, - version, - receiptPrintingActive: receipt.active, - automaticReceiptPrint: receipt.automaticPrint, - smsReceiptActive: receipt.sms, - enablePaperWalletOnly, - twoWayMode: cashOutConfig.active, - zeroConfLimits, - reboot, - shutdown, - restartServices, - emptyUnit, - refillUnit, - hasLightning, - receipt, - operatorInfo, - machineInfo, - triggers, - triggersAutomation, - speedtestFiles, - urlsToPing - } - - // BACKWARDS_COMPATIBILITY 7.6 - // Machines before 7.6 expect a single zeroConfLimit value per machine. - if (!semver.gte(machineVersion, '7.6.0-beta.0')) - response.zeroConfLimit = _.min(_.values(zeroConfLimits)) - - // BACKWARDS_COMPATIBILITY 7.5 - // machines before 7.5 expect old compliance - if (!machineVersion || semver.lt(machineVersion, '7.5.0-beta.0')) { - const compatTriggers = complianceTriggers.getBackwardsCompatibleTriggers(triggers) - response.smsVerificationActive = !!compatTriggers.sms - response.smsVerificationThreshold = compatTriggers.sms - response.idCardDataVerificationActive = !!compatTriggers.idCardData - response.idCardDataVerificationThreshold = compatTriggers.idCardData - response.idCardPhotoVerificationActive = !!compatTriggers.idCardPhoto - response.idCardPhotoVerificationThreshold = compatTriggers.idCardPhoto - response.sanctionsVerificationActive = !!compatTriggers.sanctions - response.sanctionsVerificationThreshold = compatTriggers.sanctions - response.frontCameraVerificationActive = !!compatTriggers.facephoto - response.frontCameraVerificationThreshold = compatTriggers.facephoto - } - - // BACKWARDS_COMPATIBILITY 7.4.9 - // machines before 7.4.9 expect t&c on poll - if (!machineVersion || semver.lt(machineVersion, '7.4.9')) { - response.terms = createTerms(terms) - } - - return res.json(_.assign(response, results)) - }) - .catch(next) -} - -router.get('/', poll) - -module.exports = router diff --git a/lib/routes/probeLnRoutes.js b/lib/routes/probeLnRoutes.js deleted file mode 100644 index 62cf127e..00000000 --- a/lib/routes/probeLnRoutes.js +++ /dev/null @@ -1,20 +0,0 @@ -const express = require('express') -const router = express.Router() - -const plugins = require('../plugins') -const settingsLoader = require('../new-settings-loader') - -function probe (req, res, next) { - // TODO: why req.settings is undefined? - settingsLoader.loadLatest() - .then(settings => { - const pi = plugins(settings, req.deviceId) - return pi.probeLN('LN', req.body.address) - .then(r => res.status(200).send({ hardLimits: r })) - .catch(next) - }) -} - -router.get('/', probe) - -module.exports = router \ No newline at end of file diff --git a/lib/sanctions.js b/lib/sanctions.js deleted file mode 100644 index 33900835..00000000 --- a/lib/sanctions.js +++ /dev/null @@ -1,44 +0,0 @@ -const _ = require('lodash/fp') -const ofac = require('./ofac') -const T = require('./time') -const logger = require('./logger') -const customers = require('./customers') - -const sanctionStatus = { - loaded: false, - timestamp: null -} - -const loadOrUpdateSanctions = () => { - if (!sanctionStatus.loaded || (sanctionStatus.timestamp && Date.now() > sanctionStatus.timestamp + T.day)) { - logger.info('No sanction lists loaded. Loading sanctions...') - return ofac.load() - .then(() => { - logger.info('OFAC sanction list loaded!') - sanctionStatus.loaded = true - sanctionStatus.timestamp = Date.now() - }) - .catch(e => { - logger.error('Couldn\'t load OFAC sanction list!', e) - }) - } - - return Promise.resolve() -} - -const checkByUser = (customerId, userToken) => { - return Promise.all([loadOrUpdateSanctions(), customers.getCustomerById(customerId)]) - .then(([, customer]) => { - const { firstName, lastName, dateOfBirth } = customer?.idCardData - const birthdate = _.replace(/-/g, '')(dateOfBirth) - const ofacMatches = ofac.match({ firstName, lastName }, birthdate, { threshold: 0.85, fullNameThreshold: 0.95, debug: false }) - const isOfacSanctioned = _.size(ofacMatches) > 0 - customers.updateCustomer(customerId, { sanctions: !isOfacSanctioned }, userToken) - - return { ofacSanctioned: isOfacSanctioned } - }) -} - -module.exports = { - checkByUser -} diff --git a/lib/tx-batching-processing.js b/lib/tx-batching-processing.js deleted file mode 100644 index 94f4791d..00000000 --- a/lib/tx-batching-processing.js +++ /dev/null @@ -1,30 +0,0 @@ -const _ = require('lodash/fp') - -const txBatching = require('./tx-batching') -const wallet = require('./wallet') - -function submitBatch (settings, batch) { - txBatching.getBatchTransactions(batch) - .then(txs => { - if (_.isEmpty(txs)) return Promise.resolve() - return wallet.sendCoinsBatch(settings, txs, batch.crypto_code) - .then(res => txBatching.confirmSentBatch(batch, res)) - .catch(err => txBatching.setErroredBatch(batch, err.message)) - }) -} - -function processBatches (settings, lifecycle) { - return txBatching.getBatchesByStatus(['open']) - .then(batches => { - _.each(batch => { - const elapsedMS = batch.time_elapsed * 1000 - - if (elapsedMS >= lifecycle) { - return txBatching.closeTransactionBatch(batch) - .then(() => submitBatch(settings, batch)) - } - }, batches) - }) -} - -module.exports = processBatches diff --git a/lib/wallet-scoring.js b/lib/wallet-scoring.js deleted file mode 100644 index 9b426faf..00000000 --- a/lib/wallet-scoring.js +++ /dev/null @@ -1,54 +0,0 @@ -const ph = require('./plugin-helper') -const argv = require('minimist')(process.argv.slice(2)) - -// TODO - This function should be rolled back after UI is created for this feature -function loadWalletScoring (settings) { - if (argv.mockScoring) { - const mock = ph.load(ph.WALLET_SCORING, 'mock-scoring') - return { plugin: mock, account: {} } - } - - const scorechainAccount = settings.accounts['scorechain'] - if (scorechainAccount?.enabled) { - const scorechain = ph.load(ph.WALLET_SCORING, 'scorechain') - return { plugin: scorechain, account: scorechainAccount} - } - - const ellipticAccount = settings.accounts['elliptic'] - const elliptic = ph.load(ph.WALLET_SCORING, 'elliptic') - - return { plugin: elliptic, account: ellipticAccount } -} - -function rateTransaction (settings, cryptoCode, address) { - return Promise.resolve() - .then(() => { - const { plugin, account } = loadWalletScoring(settings) - - return plugin.rateAddress(account, cryptoCode, address) - }) -} - -function rateAddress (settings, cryptoCode, address) { - return Promise.resolve() - .then(() => { - const { plugin, account } = loadWalletScoring(settings) - - return plugin.rateAddress(account, cryptoCode, address) - }) -} - -function isWalletScoringEnabled (settings, cryptoCode) { - return Promise.resolve() - .then(() => { - const { plugin, account } = loadWalletScoring(settings) - - return plugin.isWalletScoringEnabled(account, cryptoCode) - }) -} - -module.exports = { - rateAddress, - rateTransaction, - isWalletScoringEnabled -} diff --git a/lib/wallet.js b/lib/wallet.js deleted file mode 100644 index 0597b3ed..00000000 --- a/lib/wallet.js +++ /dev/null @@ -1,311 +0,0 @@ -const _ = require('lodash/fp') -const mem = require('mem') -const hkdf = require('futoin-hkdf') - -const configManager = require('./new-config-manager') -const pify = require('pify') -const fs = pify(require('fs')) - -const mnemonicHelpers = require('./mnemonic-helpers') -const ph = require('./plugin-helper') -const layer2 = require('./layer2') -const httpError = require('./route-helpers').httpError -const logger = require('./logger') -const { getOpenBatchCryptoValue } = require('./tx-batching') -const BN = require('./bn') -const { BALANCE_FETCH_SPEED_MULTIPLIER } = require('./constants') - -const FETCH_INTERVAL = 5000 -const INSUFFICIENT_FUNDS_CODE = 570 -const INSUFFICIENT_FUNDS_NAME = 'InsufficientFunds' -const ZERO_CONF_EXPIRATION = 60000 - -const MNEMONIC_PATH = process.env.MNEMONIC_PATH - -function computeSeed (masterSeed) { - return hkdf(masterSeed, 32, { salt: 'lamassu-server-salt', info: 'wallet-seed' }) -} - -function computeOperatorId (masterSeed) { - return hkdf(masterSeed, 16, { salt: 'lamassu-server-salt', info: 'operator-id' }).toString('hex') -} - -function fetchWallet (settings, cryptoCode) { - return fs.readFile(MNEMONIC_PATH, 'utf8') - .then(mnemonic => { - const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic) - const plugin = configManager.getWalletSettings(cryptoCode, settings.config).wallet - const wallet = ph.load(ph.WALLET, plugin) - const rawAccount = settings.accounts[plugin] - const account = _.set('seed', computeSeed(masterSeed), rawAccount) - const accountWithMnemonic = _.set('mnemonic', mnemonic, account) - if (_.isFunction(wallet.run)) wallet.run(accountWithMnemonic) - const operatorId = computeOperatorId(masterSeed) - return { wallet, account: accountWithMnemonic, operatorId } - }) -} - -const lastBalance = {} - -function _balance (settings, cryptoCode) { - return fetchWallet(settings, cryptoCode) - .then(r => r.wallet.balance(r.account, cryptoCode, settings, r.operatorId)) - .then(balance => Promise.all([balance, getOpenBatchCryptoValue(cryptoCode)])) - .then(([balance, reservedBalance]) => ({ balance: BN(balance).minus(reservedBalance), reservedBalance, timestamp: Date.now() })) - .then(r => { - lastBalance[cryptoCode] = r - return r - }) - .catch(err => { - logger.error(err) - return lastBalance[cryptoCode] - }) -} - -function probeLN (settings, cryptoCode, address) { - return fetchWallet(settings, cryptoCode).then(r => { - if (!r.wallet.probeLN) return null - return r.wallet.probeLN(r.account, cryptoCode, address) - }) -} - -function sendCoins (settings, tx) { - return fetchWallet(settings, tx.cryptoCode) - .then(r => { - const feeMultiplier = new BN(configManager.getWalletSettings(tx.cryptoCode, settings.config).feeMultiplier) - return r.wallet.sendCoins(r.account, tx, settings, r.operatorId, feeMultiplier) - .then(res => { - mem.clear(module.exports.balance) - return res - }) - }) - .catch(err => { - if (err.name === INSUFFICIENT_FUNDS_NAME) { - throw httpError(INSUFFICIENT_FUNDS_NAME, INSUFFICIENT_FUNDS_CODE) - } - throw err - }) -} - -function sendCoinsBatch (settings, txs, cryptoCode) { - return fetchWallet(settings, cryptoCode) - .then(r => { - const feeMultiplier = new BN(configManager.getWalletSettings(cryptoCode, settings.config).feeMultiplier) - return r.wallet.sendCoinsBatch(r.account, txs, cryptoCode, feeMultiplier) - .then(res => { - mem.clear(module.exports.balance) - return res - }) - }) - .catch(err => { - if (err.name === INSUFFICIENT_FUNDS_NAME) { - throw httpError(INSUFFICIENT_FUNDS_NAME, INSUFFICIENT_FUNDS_CODE) - } - - throw err - }) -} - -function newAddress (settings, info, tx) { - const walletAddressPromise = fetchWallet(settings, info.cryptoCode) - .then(r => r.wallet.newAddress(r.account, info, tx, settings, r.operatorId)) - - return Promise.all([ - walletAddressPromise, - layer2.newAddress(settings, info) - ]) - .then(([toAddress, layer2Address]) => ({ - toAddress, - layer2Address - })) -} - -function newFunding (settings, cryptoCode, address) { - return fetchWallet(settings, cryptoCode) - .then(r => { - const wallet = r.wallet - const account = r.account - - return wallet.newFunding(account, cryptoCode, settings, r.operatorId) - }) -} - -function mergeStatus (a, b) { - if (!a) return b - if (!b) return a - - return { receivedCryptoAtoms: a.receivedCryptoAtoms, status: mergeStatusMode(a.status, b.status) } -} - -function mergeStatusMode (a, b) { - const cleared = ['authorized', 'confirmed', 'instant'] - if (_.includes(a, cleared)) return a - if (_.includes(b, cleared)) return b - - if (a === 'published') return a - if (b === 'published') return b - - if (a === 'rejected') return a - if (b === 'rejected') return b - - return 'notSeen' -} - -function getWalletStatus (settings, tx) { - const fudgeFactorEnabled = configManager.getGlobalCashOut(settings.config).fudgeFactorActive - const fudgeFactor = fudgeFactorEnabled ? 100 : 0 - const requested = tx.cryptoAtoms.minus(fudgeFactor) - - const walletStatusPromise = fetchWallet(settings, tx.cryptoCode) - .then(r => r.wallet.getStatus(r.account, tx, requested, settings, r.operatorId)) - - return Promise.all([ - walletStatusPromise, - layer2.getStatus(settings, tx) - ]) - .then(([walletStatus, layer2Status]) => { - return mergeStatus(walletStatus, layer2Status) - }) -} - -function authorizeZeroConf (settings, tx, machineId) { - const walletSettings = configManager.getWalletSettings(tx.cryptoCode, settings.config) - const isBitcoindAvailable = walletSettings.wallet === 'bitcoind' - const plugin = walletSettings.zeroConf - const zeroConfLimit = walletSettings.zeroConfLimit || 0 - - if (!_.isObject(tx.fiat)) { - return Promise.reject(new Error('tx.fiat is undefined!')) - } - - // TODO: confirm if this treatment is needed for ERC-20 tokens, once their cash-out transactions are enabled - if (tx.cryptoCode === 'ETH') { - return Promise.resolve(false) - } - - if (tx.fiat.gt(zeroConfLimit)) { - return Promise.resolve(false) - } - - if (plugin === 'none') return Promise.resolve(true) - - const zeroConf = ph.load(ph.ZERO_CONF, plugin) - const account = settings.accounts[plugin] - - return zeroConf.authorize(account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode, isBitcoindAvailable) -} - -function getStatus (settings, tx, machineId) { - return getWalletStatus(settings, tx) - .then((statusRec) => { - if (statusRec.status === 'authorized') { - return authorizeZeroConf(settings, tx, machineId) - .then(isAuthorized => { - const publishAge = Date.now() - tx.publishedAt - - const unauthorizedStatus = publishAge < ZERO_CONF_EXPIRATION - ? 'published' - : 'rejected' - - // Sanity check to confirm if there's any cryptoatoms for which to dispense bills - const authorizedStatus = isAuthorized ? 'authorized' : unauthorizedStatus - const status = BN(tx.cryptoAtoms).gt(0) ? authorizedStatus : 'rejected' - - return { receivedCryptoAtoms: statusRec.receivedCryptoAtoms, status } - }) - } - - return statusRec - }) -} - -function sweep (settings, txId, cryptoCode, hdIndex) { - return fetchWallet(settings, cryptoCode) - .then(r => r.wallet.sweep(r.account, txId, cryptoCode, hdIndex, settings, r.operatorId)) -} - -function isHd (settings, tx) { - return fetchWallet(settings, tx.cryptoCode) - .then(r => r.wallet.supportsHd) -} - -function cryptoNetwork (settings, cryptoCode) { - const plugin = configManager.getWalletSettings(cryptoCode, settings.config).wallet - const account = settings.accounts[plugin] - return fetchWallet(settings, cryptoCode).then(r => { - if (!r.wallet.cryptoNetwork) return Promise.resolve(false) - return r.wallet.cryptoNetwork(account, cryptoCode, settings, r.operatorId) - }) -} - -function isStrictAddress (settings, cryptoCode, toAddress) { - // Note: For now, only for wallets that specifically check for this. - - return fetchWallet(settings, cryptoCode) - .then(r => { - if (!r.wallet.isStrictAddress) return true - return r.wallet.isStrictAddress(cryptoCode, toAddress, settings, r.operatorId) - }) -} - -function supportsBatching (settings, cryptoCode) { - return fetchWallet(settings, cryptoCode).then(r => { - return Promise.resolve(!!r.wallet.SUPPORTS_BATCHING && !!configManager.getWalletSettings(cryptoCode, settings.config).allowTransactionBatching) - }) -} - -function checkBlockchainStatus (settings, cryptoCode) { - const walletDaemons = { - BTC: './plugins/wallet/bitcoind/bitcoind.js', - BCH: './plugins/wallet/bitcoincashd/bitcoincashd.js', - DASH: './plugins/wallet/dashd/dashd.js', - ETH: './plugins/wallet/geth/base.js', - LTC: './plugins/wallet/litecoind/litecoind.js', - XMR: './plugins/wallet/monerod/monerod.js', - ZEC: './plugins/wallet/zcashd/zcashd.js' - } - - return Promise.resolve(require(walletDaemons[cryptoCode])) - .then(({ checkBlockchainStatus }) => checkBlockchainStatus(cryptoCode)) -} - -const balance = (settings, cryptoCode) => { - return fetchWallet(settings, cryptoCode) - .then(r => r.wallet.fetchSpeed ?? BALANCE_FETCH_SPEED_MULTIPLIER.NORMAL) - .then(multiplier => { - switch (multiplier) { - case BALANCE_FETCH_SPEED_MULTIPLIER.NORMAL: - return balanceNormal(settings, cryptoCode) - case BALANCE_FETCH_SPEED_MULTIPLIER.SLOW: - return balanceSlow(settings, cryptoCode) - default: - throw new Error() - } - }) -} - -const balanceNormal = mem(_balance, { - maxAge: BALANCE_FETCH_SPEED_MULTIPLIER.NORMAL * FETCH_INTERVAL, - cacheKey: (settings, cryptoCode) => cryptoCode -}) - -const balanceSlow = mem(_balance, { - maxAge: BALANCE_FETCH_SPEED_MULTIPLIER.SLOW * FETCH_INTERVAL, - cacheKey: (settings, cryptoCode) => cryptoCode -}) - -module.exports = { - balance, - sendCoins, - sendCoinsBatch, - newAddress, - getStatus, - isStrictAddress, - sweep, - isHd, - newFunding, - cryptoNetwork, - supportsBatching, - checkBlockchainStatus, - probeLN -} diff --git a/migrations/001-initial.js b/migrations/001-initial.js deleted file mode 100644 index c4ac59ce..00000000 --- a/migrations/001-initial.js +++ /dev/null @@ -1,38 +0,0 @@ -const db = require('./db') - -exports.up = function (next) { - var sqls = [ - 'CREATE TABLE IF NOT EXISTS user_config ( ' + - 'id serial PRIMARY KEY, ' + - 'type text NOT NULL, ' + - 'data json NOT NULL ' + - ')', - - 'CREATE TABLE IF NOT EXISTS devices ( ' + - 'id serial PRIMARY KEY, ' + - 'fingerprint text NOT NULL UNIQUE, ' + - 'name text, ' + - 'authorized boolean, ' + - 'unpair boolean NOT NULL DEFAULT false' + - ')', - - 'CREATE TABLE IF NOT EXISTS pairing_tokens (' + - 'id serial PRIMARY KEY, ' + - 'token text, ' + - 'created timestamp NOT NULL DEFAULT now() ' + - ')', - - 'CREATE TABLE IF NOT EXISTS users ( ' + - 'id serial PRIMARY KEY, ' + - 'userName text NOT NULL UNIQUE, ' + - 'salt text NOT NULL, ' + - 'pwdHash text NOT NULL ' + - ')' - ] - - db.multi(sqls, next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/002-bills.js b/migrations/002-bills.js deleted file mode 100644 index a75f9dcb..00000000 --- a/migrations/002-bills.js +++ /dev/null @@ -1,21 +0,0 @@ -var db = require('./db') - -exports.up = function (next) { - const sql = - ['CREATE TABLE bills ( ' + - 'id uuid PRIMARY KEY, ' + - 'device_fingerprint text NOT NULL, ' + - 'denomination integer NOT NULL, ' + - 'currency_code text NOT NULL, ' + - 'satoshis integer NOT NULL, ' + - 'to_address text NOT NULL, ' + - 'session_id uuid NOT NULL, ' + - 'device_time bigint NOT NULL, ' + - 'created timestamp NOT NULL DEFAULT now() )'] - - db.multi(sql, next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/003-device-events.js b/migrations/003-device-events.js deleted file mode 100644 index 21c666ef..00000000 --- a/migrations/003-device-events.js +++ /dev/null @@ -1,15 +0,0 @@ -var db = require('./db') - -exports.up = function (next) { - db.multi(['CREATE TABLE IF NOT EXISTS machine_events ( ' + - 'id uuid PRIMARY KEY, ' + - 'device_fingerprint text NOT NULL, ' + - 'event_type text NOT NULL, ' + - 'note text, ' + - 'device_time bigint NOT NULL, ' + - 'created timestamp NOT NULL DEFAULT now() )'], next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/004-transactions-reload.js b/migrations/004-transactions-reload.js deleted file mode 100644 index fb5aba8b..00000000 --- a/migrations/004-transactions-reload.js +++ /dev/null @@ -1,69 +0,0 @@ -var db = require('./db') - -function singleQuotify (item) { return '\'' + item + '\'' } - -exports.up = function (next) { - var stages = ['initial_request', 'partial_request', 'final_request', - 'partial_send', 'deposit', 'dispense_request', 'dispense'] - .map(singleQuotify).join(',') - - var authorizations = ['timeout', 'machine', 'pending', 'rejected', - 'published', 'authorized', 'confirmed'].map(singleQuotify).join(',') - - var sqls = [ - 'CREATE TYPE transaction_stage AS ENUM (' + stages + ')', - 'CREATE TYPE transaction_authority AS ENUM (' + authorizations + ')', - - 'CREATE TABLE transactions ( ' + - 'id serial PRIMARY KEY, ' + - 'session_id uuid NOT NULL, ' + - 'device_fingerprint text, ' + - 'to_address text NOT NULL, ' + - 'satoshis integer NOT NULL DEFAULT 0, ' + - 'fiat integer NOT NULL DEFAULT 0, ' + - 'currency_code text NOT NULL, ' + - 'fee integer NOT NULL DEFAULT 0, ' + - 'incoming boolean NOT NULL, ' + - 'stage transaction_stage NOT NULL, ' + - 'authority transaction_authority NOT NULL, ' + - 'tx_hash text, ' + - 'error text, ' + - 'created timestamp NOT NULL DEFAULT now(), ' + - 'UNIQUE (session_id, to_address, stage, authority) ' + - ')', - 'CREATE INDEX ON transactions (session_id)', - - 'CREATE TABLE pending_transactions ( ' + - 'id serial PRIMARY KEY, ' + - 'device_fingerprint text NOT NULL, ' + - 'session_id uuid UNIQUE NOT NULL, ' + - 'incoming boolean NOT NULL, ' + - 'currency_code text NOT NULL, ' + - 'to_address text NOT NULL, ' + - 'satoshis integer NOT NULL, ' + - 'updated timestamp NOT NULL DEFAULT now() ' + - ')', - - 'CREATE TABLE dispenses ( ' + - 'id serial PRIMARY KEY, ' + - 'device_fingerprint text NOT NULL, ' + - 'transaction_id integer UNIQUE REFERENCES transactions(id), ' + - 'dispense1 integer NOT NULL, ' + - 'reject1 integer NOT NULL, ' + - 'count1 integer NOT NULL, ' + - 'dispense2 integer NOT NULL, ' + - 'reject2 integer NOT NULL, ' + - 'count2 integer NOT NULL, ' + - 'refill boolean NOT NULL, ' + - 'error text, ' + - 'created timestamp NOT NULL DEFAULT now() ' + - ')', - 'CREATE INDEX ON dispenses (device_fingerprint)' - ] - - db.multi(sqls, next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/006-add-machine-config.js b/migrations/006-add-machine-config.js deleted file mode 100644 index effa5b58..00000000 --- a/migrations/006-add-machine-config.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -var db = require('./db') - -exports.up = function (next) { - db.multi(['CREATE TABLE IF NOT EXISTS machine_configs ( ' + - 'id serial PRIMARY KEY, ' + - 'device_fingerprint text NOT NULL, ' + - 'data json NOT NULL )'], next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/010-cached-requests.js b/migrations/010-cached-requests.js deleted file mode 100644 index 01ca6779..00000000 --- a/migrations/010-cached-requests.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -var db = require('./db') - -exports.up = function (next) { - db.multi(['CREATE TABLE IF NOT EXISTS cached_responses ( ' + - 'id serial PRIMARY KEY, ' + - 'device_fingerprint text NOT NULL, ' + - 'session_id uuid NOT NULL, ' + - 'path text NOT NULL, ' + - 'method text NOT NULL, ' + - 'body json NOT NULL, ' + - 'created timestamptz NOT NULL DEFAULT now(), ' + - 'UNIQUE (device_fingerprint, session_id, path, method) ' + - ')'], next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1557800959028-machine-pings-rename.js b/migrations/1557800959028-machine-pings-rename.js deleted file mode 100644 index 9475b96f..00000000 --- a/migrations/1557800959028-machine-pings-rename.js +++ /dev/null @@ -1,13 +0,0 @@ -const db = require('./db') - -exports.up = function (next) { - var sql = [ - 'ALTER TABLE machine_pings RENAME COLUMN created to updated' - ] - - db.multi(sql, next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1601649726488-user-suspend.js b/migrations/1601649726488-user-suspend.js deleted file mode 100644 index 01313ed6..00000000 --- a/migrations/1601649726488-user-suspend.js +++ /dev/null @@ -1,13 +0,0 @@ -const db = require('./db') - -exports.up = function (next) { - var sql = [ - "ALTER TABLE customers ADD COLUMN suspended_until timestamptz" - ] - - db.multi(sql, next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1603804834628-add-last-accessed-tokens.js b/migrations/1603804834628-add-last-accessed-tokens.js deleted file mode 100644 index 8ce76bcf..00000000 --- a/migrations/1603804834628-add-last-accessed-tokens.js +++ /dev/null @@ -1,13 +0,0 @@ -const db = require('./db') - -exports.up = function (next) { - var sql = [ - 'ALTER TABLE user_tokens ADD COLUMN last_accessed timestamptz', - ] - - db.multi(sql, next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1617742522808-zeroConfLimit-migrate.js b/migrations/1617742522808-zeroConfLimit-migrate.js deleted file mode 100644 index 4aa746a9..00000000 --- a/migrations/1617742522808-zeroConfLimit-migrate.js +++ /dev/null @@ -1,44 +0,0 @@ -const _ = require('lodash/fp') -var db = require('../lib/db') -const settingsLoader = require('../lib/new-settings-loader') -const configManager = require('../lib/new-config-manager') - -exports.up = function (next) { - return db.tx(async t => { - const settingsPromise = settingsLoader.loadLatestConfig() - const machinesPromise = t.any('SELECT device_id FROM devices') - const [config, machines] = await Promise.all([settingsPromise, machinesPromise]) - const cryptoCodes = configManager.getCryptosFromWalletNamespace(config) - - const deviceIds = _.map(_.get('device_id'))(machines) - const getZeroConfLimit = _.compose(_.get('zeroConfLimit'), it => configManager.getCashOut(it, config)) - const zeroConfLimits = _.map(getZeroConfLimit)(deviceIds) - - const configMin = _.min(zeroConfLimits) - const smallerZeroConf = _.isFinite(configMin) ? Number(configMin) : 0 - - _.forEach(cryptoCode => { - const walletConfig = configManager.getWalletSettings(cryptoCode, config) - const zeroConfLimit = _.get('zeroConfLimit', walletConfig) - - if (_.isNil(zeroConfLimit)) { - config[`wallets_${cryptoCode}_zeroConfLimit`] = smallerZeroConf - } - }, cryptoCodes) - - _.forEach(deviceId => { - const key = `cashOut_${deviceId}_zeroConfLimit` - if (_.has(key, config)) { - config[key] = null - } - })(deviceIds) - - return settingsLoader.migrationSaveConfig(config) - }) - .then(() => next()) - .catch(err => next(err)) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1620680439585-add-cashbox-reset-settings.js b/migrations/1620680439585-add-cashbox-reset-settings.js deleted file mode 100644 index 582cb047..00000000 --- a/migrations/1620680439585-add-cashbox-reset-settings.js +++ /dev/null @@ -1,23 +0,0 @@ -const { migrationSaveConfig, loadLatest } = require('../lib/new-settings-loader') - -exports.up = function (next) { - const newConfig = { - cashIn_cashboxReset: 'Manual' - } - return loadLatest() - .then(config => { - return migrationSaveConfig(newConfig) - .then(() => next()) - .catch(err => { - if (err.message === 'lamassu-server is not configured') { - return next() - } - console.log(err.message) - return next(err) - }) - }) -} - -module.exports.down = function (next) { - next() -} diff --git a/migrations/1623413776161-create-operator-ids.js b/migrations/1623413776161-create-operator-ids.js deleted file mode 100644 index c9157f0f..00000000 --- a/migrations/1623413776161-create-operator-ids.js +++ /dev/null @@ -1,49 +0,0 @@ -var db = require('./db') -const pify = require('pify') -const fs = pify(require('fs')) -const hkdf = require('futoin-hkdf') - -const state = require('../lib/middlewares/state') -const mnemonicHelpers = require('../lib/mnemonic-helpers') - -function computeOperatorId (masterSeed) { - return hkdf(masterSeed, 16, { salt: 'lamassu-server-salt', info: 'operator-id' }).toString('hex') -} - -function getMnemonic () { - if (state.mnemonic) return Promise.resolve(state.mnemonic) - return fs.readFile(process.env.MNEMONIC_PATH, 'utf8').then(mnemonic => { - state.mnemonic = mnemonic - return mnemonic - }) -} - -function generateOperatorId () { - return getMnemonic().then(mnemonic => { - return computeOperatorId(mnemonicHelpers.toEntropyBuffer(mnemonic)) - }).catch(e => { - console.error('Error while computing operator id\n' + e) - throw e - }) -} - -exports.up = function (next) { - return generateOperatorId() - .then(operatorId => { - const sql = [ - `CREATE TABLE operator_ids ( - id serial PRIMARY KEY, - operator_id TEXT NOT NULL, - service TEXT NOT NULL - )`, - `INSERT INTO operator_ids (operator_id, service) VALUES ('${operatorId}','middleware')`, - `INSERT INTO operator_ids (operator_id, service) VALUES ('${operatorId}','coinatmradar')`, - `INSERT INTO operator_ids (operator_id, service) VALUES ('${operatorId}','authentication')` - ] - db.multi(sql, next) - }) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1716969535424-customer-last-auth-attempt.js b/migrations/1716969535424-customer-last-auth-attempt.js deleted file mode 100644 index 56086cac..00000000 --- a/migrations/1716969535424-customer-last-auth-attempt.js +++ /dev/null @@ -1,13 +0,0 @@ -const db = require('./db') - -exports.up = function (next) { - let sql = [ - 'ALTER TABLE customers ADD COLUMN last_auth_attempt timestamptz' - ] - - db.multi(sql, next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1721313145136-customer-last-used-machine.js b/migrations/1721313145136-customer-last-used-machine.js deleted file mode 100644 index 119f0bf8..00000000 --- a/migrations/1721313145136-customer-last-used-machine.js +++ /dev/null @@ -1,9 +0,0 @@ -const db = require('./db') - -exports.up = function (next) { - db.multi(['ALTER TABLE customers ADD COLUMN last_used_machine TEXT REFERENCES devices (device_id)'], next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1724242113482-drop-last-used-fkey.js b/migrations/1724242113482-drop-last-used-fkey.js deleted file mode 100644 index 9459ac51..00000000 --- a/migrations/1724242113482-drop-last-used-fkey.js +++ /dev/null @@ -1,9 +0,0 @@ -const db = require('./db') - -exports.up = function (next) { - db.multi(['ALTER TABLE customers DROP CONSTRAINT customers_last_used_machine_fkey;'], next) -} - -exports.down = function (next) { - next() -} diff --git a/migrations/1732790112740-add-cashout-fee-to-cash_out_txs.js b/migrations/1732790112740-add-cashout-fee-to-cash_out_txs.js deleted file mode 100644 index ad5df91b..00000000 --- a/migrations/1732790112740-add-cashout-fee-to-cash_out_txs.js +++ /dev/null @@ -1,7 +0,0 @@ -const db = require('./db') - -exports.up = next => db.multi([ - 'ALTER TABLE cash_out_txs ADD COLUMN fixed_fee numeric(14, 5) NOT NULL DEFAULT 0;' -], next) - -exports.down = next => next() diff --git a/migrations/1732790112741-add-cashout-fee-to-user_config.js b/migrations/1732790112741-add-cashout-fee-to-user_config.js deleted file mode 100644 index 92296e38..00000000 --- a/migrations/1732790112741-add-cashout-fee-to-user_config.js +++ /dev/null @@ -1,7 +0,0 @@ -const { saveConfig } = require('../lib/new-settings-loader') - -exports.up = next => saveConfig({ 'commissions_cashOutFixedFee': 0 }) - .then(next) - .catch(next) - -exports.down = next => next() diff --git a/migrations/1743526540370-deprecate-tables.js b/migrations/1743526540370-deprecate-tables.js deleted file mode 100644 index c478442f..00000000 --- a/migrations/1743526540370-deprecate-tables.js +++ /dev/null @@ -1,12 +0,0 @@ -const db = require('./db') - -exports.up = next => db.multi([ - 'DROP TABLE aggregated_machine_pings;', - 'DROP TABLE cash_in_refills;', - 'DROP TABLE cash_out_refills;', - 'DROP TABLE customer_compliance_persistence;', - 'DROP TABLE compliance_overrides_persistence;', - 'DROP TABLE server_events;', -], next) - -exports.down = next => next() diff --git a/migrations/1744294267662-bills-performance.js b/migrations/1744294267662-bills-performance.js deleted file mode 100644 index dbeb9479..00000000 --- a/migrations/1744294267662-bills-performance.js +++ /dev/null @@ -1,10 +0,0 @@ -const db = require('./db') - -exports.up = next => db.multi([ - 'ALTER TABLE bills ADD CONSTRAINT cash_in_txs_id FOREIGN KEY (cash_in_txs_id) REFERENCES cash_in_txs(id);', - 'CREATE INDEX bills_cash_in_txs_id_idx ON bills USING btree (cash_in_txs_id);', - `CREATE INDEX bills_null_cashbox_batch_id_idx ON bills (cash_in_txs_id) WHERE cashbox_batch_id IS NULL AND destination_unit = 'cashbox';`, - 'CREATE INDEX cash_in_txs_device_id_idx ON cash_in_txs USING btree (device_id);' -], next) - -exports.down = next => next() diff --git a/migrations/1744294267663-blacklist-normalization.js b/migrations/1744294267663-blacklist-normalization.js deleted file mode 100644 index ff8ed9c9..00000000 --- a/migrations/1744294267663-blacklist-normalization.js +++ /dev/null @@ -1,11 +0,0 @@ -const db = require('./db') - -exports.up = next => db.multi([ - 'ALTER TABLE public.blacklist DROP CONSTRAINT IF EXISTS blacklist_pkey;', - 'ALTER TABLE public.blacklist ADD PRIMARY KEY (address);', - 'DROP INDEX IF EXISTS blacklist_temp_address_key;', - 'CREATE UNIQUE INDEX blacklist_address_idx ON public.blacklist USING btree (address);', - -], next) - -exports.down = next => next() diff --git a/new-lamassu-admin/.env b/new-lamassu-admin/.env deleted file mode 100644 index e666d42d..00000000 --- a/new-lamassu-admin/.env +++ /dev/null @@ -1,4 +0,0 @@ -SKIP_PREFLIGHT_CHECK=true -HTTPS=true -REACT_APP_TYPE_CHECK_SANCTUARY=false -PORT=3001 diff --git a/new-lamassu-admin/.vscode/settings.json b/new-lamassu-admin/.vscode/settings.json deleted file mode 100644 index dc8891d5..00000000 --- a/new-lamassu-admin/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "editor.codeActionsOnSave": { - "source.fixAll.eslint": true - } -} \ No newline at end of file diff --git a/new-lamassu-admin/eslint.config.js b/new-lamassu-admin/eslint.config.js deleted file mode 100644 index 48fe2205..00000000 --- a/new-lamassu-admin/eslint.config.js +++ /dev/null @@ -1,39 +0,0 @@ -import globals from 'globals' -import pluginJs from '@eslint/js' -import pluginReact from 'eslint-plugin-react' -import reactCompiler from 'eslint-plugin-react-compiler' -import eslintConfigPrettier from 'eslint-config-prettier' - -/** @type {import('eslint').Linter.Config[]} */ -export default [ - { - files: ['**/*.{js,mjs,cjs,jsx}'], - languageOptions: { - ...pluginReact.configs.flat.recommended.languageOptions, - globals: { - ...globals.browser, - process: 'readonly' - } - }, - settings: { - react: { - version: '16' - } - }, - plugins: { - 'react-compiler': reactCompiler - } - }, - pluginJs.configs.recommended, - pluginReact.configs.flat.recommended, - { - rules: { - 'no-unused-vars': 'off', - 'react/prop-types': 'off', - 'react/display-name': 'off', - 'react/no-unescaped-entities': 'off', - 'react-compiler/react-compiler': 'warn' - } - }, - eslintConfigPrettier -] diff --git a/new-lamassu-admin/jsconfig.json b/new-lamassu-admin/jsconfig.json deleted file mode 100644 index 30b25afe..00000000 --- a/new-lamassu-admin/jsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "." - }, - "include": ["src"] -} diff --git a/new-lamassu-admin/nginx/nginx.conf b/new-lamassu-admin/nginx/nginx.conf deleted file mode 100644 index 13ac5c80..00000000 --- a/new-lamassu-admin/nginx/nginx.conf +++ /dev/null @@ -1,28 +0,0 @@ -server { - listen 80; - - location / { - root /usr/share/nginx/html; - index index.html index.htm; - - try_files $uri /index.html; - } - - location /graphql { - proxy_pass https://lamassu-admin-server/graphql; - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 300; - proxy_connect_timeout 300; - proxy_send_timeout 300; - } - - error_page 500 502 503 504 /50x.html; - - location = /50x.html { - root /usr/share/nginx/html; - } - -} \ No newline at end of file diff --git a/new-lamassu-admin/package-lock.json b/new-lamassu-admin/package-lock.json deleted file mode 100644 index ba65fec1..00000000 --- a/new-lamassu-admin/package-lock.json +++ /dev/null @@ -1,8372 +0,0 @@ -{ - "name": "lamassu-admin", - "version": "0.2.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "lamassu-admin", - "version": "0.2.1", - "license": "../LICENSE", - "dependencies": { - "@apollo/react-hooks": "^3.1.3", - "@lamassu/coins": "v1.6.1", - "@material-ui/core": "4.12.4", - "@material-ui/icons": "4.11.2", - "@material-ui/lab": "^4.0.0-alpha.61", - "@simplewebauthn/browser": "^3.0.0", - "@use-hooks/axios": "1.3.0", - "apollo-cache-inmemory": "^1.6.6", - "apollo-client": "^2.6.10", - "apollo-link": "^1.2.14", - "apollo-link-error": "^1.1.13", - "apollo-link-http": "^1.5.17", - "apollo-upload-client": "^13.0.0", - "axios": "0.21.1", - "bignumber.js": "9.0.0", - "classnames": "2.2.6", - "countries-and-timezones": "^2.4.0", - "d3": "^6.2.0", - "date-fns": "^2.26.0", - "date-fns-tz": "^1.1.6", - "downshift": "3.3.4", - "file-saver": "2.0.2", - "formik": "2.2.0", - "graphql": "^14.5.8", - "graphql-tag": "^2.12.6", - "jss-plugin-extend": "^10.0.0", - "jszip": "^3.6.0", - "libphonenumber-js": "^1.11.15", - "match-sorter": "^4.2.0", - "pretty-ms": "^2.1.0", - "qrcode.react": "0.9.3", - "ramda": "^0.26.1", - "react": "^16.12.0", - "react-copy-to-clipboard": "^5.0.2", - "react-dom": "^16.10.2", - "react-dropzone": "^11.4.2", - "react-material-ui-carousel": "^2.3.11", - "react-number-format": "^4.4.1", - "react-otp-input": "^2.3.0", - "react-router-dom": "5.1.2", - "react-use": "15.3.2", - "react-virtualized": "^9.21.2", - "ua-parser-js": "^1.0.2", - "uuid": "^8.3.2", - "yup": "1.4.0" - }, - "devDependencies": { - "@eslint/js": "^9.16.0", - "@vitejs/plugin-react-swc": "^3.7.2", - "esbuild-plugin-react-virtualized": "^1.0.4", - "eslint": "^9.16.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-react": "^7.37.2", - "eslint-plugin-react-compiler": "^19.0.0-beta-df7b47d-20241124", - "globals": "^15.13.0", - "lint-staged": "^15.2.10", - "prettier": "3.4.1", - "vite": "^6.0.1", - "vite-plugin-svgr": "^4.3.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@apollo/react-common": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@apollo/react-common/-/react-common-3.1.4.tgz", - "integrity": "sha512-X5Kyro73bthWSCBJUC5XYQqMnG0dLWuDZmVkzog9dynovhfiVCV4kPSdgSIkqnb++cwCzOVuQ4rDKVwo2XRzQA==", - "dependencies": { - "ts-invariant": "^0.4.4", - "tslib": "^1.10.0" - }, - "peerDependencies": { - "@types/react": "^16.8.0", - "apollo-client": "^2.6.4", - "apollo-utilities": "^1.3.2", - "graphql": "^14.3.1", - "react": "^16.8.0" - } - }, - "node_modules/@apollo/react-hooks": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@apollo/react-hooks/-/react-hooks-3.1.5.tgz", - "integrity": "sha512-y0CJ393DLxIIkksRup4nt+vSjxalbZBXnnXxYbviq/woj+zKa431zy0yT4LqyRKpFy9ahMIwxBnBwfwIoupqLQ==", - "dependencies": { - "@apollo/react-common": "^3.1.4", - "@wry/equality": "^0.1.9", - "ts-invariant": "^0.4.4", - "tslib": "^1.10.0" - }, - "peerDependencies": { - "@types/react": "^16.8.0", - "apollo-client": "^2.6.4", - "graphql": "^14.3.1", - "react": "^16.8.0", - "react-dom": "^16.8.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "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.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", - "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", - "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.5", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.7", - "@babel/parser": "^7.26.7", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.26.7", - "@babel/types": "^7.26.7", - "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": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/@babel/generator": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", - "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.26.5", - "@babel/types": "^7.26.5", - "@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-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.26.5", - "@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-create-class-features-plugin": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", - "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.25.9", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": 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": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": 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-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", - "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", - "dev": true, - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/traverse": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz", - "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==", - "dev": true, - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", - "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.26.7" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", - "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", - "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.7", - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.7", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/traverse/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/@babel/types": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", - "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", - "dev": true, - "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/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", - "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/config-array/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "9.19.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", - "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", - "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", - "dev": true, - "dependencies": { - "@eslint/core": "^0.10.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", - "dev": true, - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", - "dev": true, - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "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": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@lamassu/bolt11": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@lamassu/bolt11/-/bolt11-1.5.1.tgz", - "integrity": "sha512-uP1FyG2cGUveX4tpcbpfs+px0aty0/cJ0O+v+yro24sSYOUvWT/N89yhZBOo/dOGEW+S3J45vzBoeH/OnK6jgA==", - "dependencies": { - "bech32": "^1.1.2", - "bitcoinjs-lib": "4.0.3", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "lodash": "^4.17.11", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/@lamassu/bolt11/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/@lamassu/coins": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@lamassu/coins/-/coins-1.6.1.tgz", - "integrity": "sha512-UC3+YmlEWsyVv2ydCD2fUhNHPZ7GoOTulgB4dumMDT60hVv8l1F9fxJE/1UG9ZQg8We4+eW7nOGEeKoS5V6Xiw==", - "dependencies": { - "@lamassu/bolt11": "1.5.1", - "bech32": "2.0.0", - "big-integer": "^1.6.48", - "bignumber.js": "^9.0.0", - "bitcoinjs-lib": "4.0.3", - "bitcore-lib-cash": "^8.25.25", - "blakejs": "^1.2.1", - "bs58check": "^2.0.2", - "cashaddrjs": "^0.4.4", - "crypto-js": "^3.1.9-1", - "ethereumjs-icap": "^0.3.2", - "keccak256": "^1.0.2", - "lodash": "^4.17.10" - } - }, - "node_modules/@material-ui/core": { - "version": "4.12.4", - "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz", - "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==", - "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", - "dependencies": { - "@babel/runtime": "^7.4.4", - "@material-ui/styles": "^4.11.5", - "@material-ui/system": "^4.12.2", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.3", - "@types/react-transition-group": "^4.2.0", - "clsx": "^1.0.4", - "hoist-non-react-statics": "^3.3.2", - "popper.js": "1.16.1-lts", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0", - "react-transition-group": "^4.4.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/material-ui" - }, - "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@material-ui/icons": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz", - "integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==", - "deprecated": "You can now upgrade to @mui/icons. See the guide: https://mui.com/guides/migration-v4/", - "dependencies": { - "@babel/runtime": "^7.4.4" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "@material-ui/core": "^4.0.0", - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@material-ui/lab": { - "version": "4.0.0-alpha.61", - "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.61.tgz", - "integrity": "sha512-rSzm+XKiNUjKegj8bzt5+pygZeckNLOr+IjykH8sYdVk7dE9y2ZuUSofiMV2bJk3qU+JHwexmw+q0RyNZB9ugg==", - "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", - "dependencies": { - "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.11.3", - "clsx": "^1.0.4", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "@material-ui/core": "^4.12.1", - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@material-ui/styles": { - "version": "4.11.5", - "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz", - "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==", - "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", - "dependencies": { - "@babel/runtime": "^7.4.4", - "@emotion/hash": "^0.8.0", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.3", - "clsx": "^1.0.4", - "csstype": "^2.5.2", - "hoist-non-react-statics": "^3.3.2", - "jss": "^10.5.1", - "jss-plugin-camel-case": "^10.5.1", - "jss-plugin-default-unit": "^10.5.1", - "jss-plugin-global": "^10.5.1", - "jss-plugin-nested": "^10.5.1", - "jss-plugin-props-sort": "^10.5.1", - "jss-plugin-rule-value-function": "^10.5.1", - "jss-plugin-vendor-prefixer": "^10.5.1", - "prop-types": "^15.7.2" - }, - "engines": { - "node": ">=8.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/material-ui" - }, - "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@material-ui/system": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz", - "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==", - "dependencies": { - "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.11.3", - "csstype": "^2.5.2", - "prop-types": "^15.7.2" - }, - "engines": { - "node": ">=8.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/material-ui" - }, - "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@material-ui/types": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", - "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", - "peerDependencies": { - "@types/react": "*" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@material-ui/utils": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz", - "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==", - "dependencies": { - "@babel/runtime": "^7.4.4", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - } - }, - "node_modules/@reach/auto-id": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@reach/auto-id/-/auto-id-0.2.0.tgz", - "integrity": "sha512-lVK/svL2HuQdp7jgvlrLkFsUx50Az9chAhxpiPwBqcS83I2pVWvXp98FOcSCCJCV++l115QmzHhFd+ycw1zLBg==", - "peerDependencies": { - "react": "^16.8.0", - "react-dom": "^16.8.0" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", - "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.0.tgz", - "integrity": "sha512-Eeao7ewDq79jVEsrtWIj5RNqB8p2knlm9fhR6uJ2gqP7UfbLrTrxevudVrEPDM7Wkpn/HpRC2QfazH7MXLz3vQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.0.tgz", - "integrity": "sha512-yVh0Kf1f0Fq4tWNf6mWcbQBCLDpDrDEl88lzPgKhrgTcDrTtlmun92ywEF9dCjmYO3EFiSuJeeo9cYRxl2FswA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.0.tgz", - "integrity": "sha512-gCs0ErAZ9s0Osejpc3qahTsqIPUDjSKIyxK/0BGKvL+Tn0n3Kwvj8BrCv7Y5sR1Ypz1K2qz9Ny0VvkVyoXBVUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.0.tgz", - "integrity": "sha512-aIB5Anc8hngk15t3GUkiO4pv42ykXHfmpXGS+CzM9CTyiWyT8HIS5ygRAy7KcFb/wiw4Br+vh1byqcHRTfq2tQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.0.tgz", - "integrity": "sha512-kpdsUdMlVJMRMaOf/tIvxk8TQdzHhY47imwmASOuMajg/GXpw8GKNd8LNwIHE5Yd1onehNpcUB9jHY6wgw9nHQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.0.tgz", - "integrity": "sha512-D0RDyHygOBCQiqookcPevrvgEarN0CttBecG4chOeIYCNtlKHmf5oi5kAVpXV7qs0Xh/WO2RnxeicZPtT50V0g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.0.tgz", - "integrity": "sha512-mCIw8j5LPDXmCOW8mfMZwT6F/Kza03EnSr4wGYEswrEfjTfVsFOxvgYfuRMxTuUF/XmRb9WSMD5GhCWDe2iNrg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.0.tgz", - "integrity": "sha512-AwwldAu4aCJPob7zmjuDUMvvuatgs8B/QiVB0KwkUarAcPB3W+ToOT+18TQwY4z09Al7G0BvCcmLRop5zBLTag==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.0.tgz", - "integrity": "sha512-e7kDUGVP+xw05pV65ZKb0zulRploU3gTu6qH1qL58PrULDGxULIS0OSDQJLH7WiFnpd3ZKUU4VM3u/Z7Zw+e7Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.0.tgz", - "integrity": "sha512-SXYJw3zpwHgaBqTXeAZ31qfW/v50wq4HhNVvKFhRr5MnptRX2Af4KebLWR1wpxGJtLgfS2hEPuALRIY3LPAAcA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.0.tgz", - "integrity": "sha512-e5XiCinINCI4RdyU3sFyBH4zzz7LiQRvHqDtRe9Dt8o/8hTBaYpdPimayF00eY2qy5j4PaaWK0azRgUench6WQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.0.tgz", - "integrity": "sha512-3SWN3e0bAsm9ToprLFBSro8nJe6YN+5xmB11N4FfNf92wvLye/+Rh5JGQtKOpwLKt6e61R1RBc9g+luLJsc23A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.0.tgz", - "integrity": "sha512-B1Oqt3GLh7qmhvfnc2WQla4NuHlcxAD5LyueUi5WtMc76ZWY+6qDtQYqnxARx9r+7mDGfamD+8kTJO0pKUJeJA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.0.tgz", - "integrity": "sha512-UfUCo0h/uj48Jq2lnhX0AOhZPSTAq3Eostas+XZ+GGk22pI+Op1Y6cxQ1JkUuKYu2iU+mXj1QjPrZm9nNWV9rg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.0.tgz", - "integrity": "sha512-chZLTUIPbgcpm+Z7ALmomXW8Zh+wE2icrG+K6nt/HenPLmtwCajhQC5flNSk1Xy5EDMt/QAOz2MhzfOfJOLSiA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.0.tgz", - "integrity": "sha512-jo0UolK70O28BifvEsFD/8r25shFezl0aUk2t0VJzREWHkq19e+pcLu4kX5HiVXNz5qqkD+aAq04Ct8rkxgbyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.0.tgz", - "integrity": "sha512-Vmg0NhAap2S54JojJchiu5An54qa6t/oKT7LmDaWggpIcaiL8WcWHEN6OQrfTdL6mQ2GFyH7j2T5/3YPEDOOGA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.0.tgz", - "integrity": "sha512-CV2aqhDDOsABKHKhNcs1SZFryffQf8vK2XrxP6lxC99ELZAdvsDgPklIBfd65R8R+qvOm1SmLaZ/Fdq961+m7A==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.0.tgz", - "integrity": "sha512-g2ASy1QwHP88y5KWvblUolJz9rN+i4ZOsYzkEwcNfaNooxNUXG+ON6F5xFo0NIItpHqxcdAyls05VXpBnludGw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@simplewebauthn/browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-3.1.0.tgz", - "integrity": "sha512-ocg23JXTFXKQ7flisTyIeQJA/KzAer1XC77rWVhz8H85/Y3d40fJRQPU5HpkTp9G4JUq4tpO5w7eHn8Dpdr+5w==" - }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", - "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", - "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-preset": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", - "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", - "dev": true, - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", - "@svgr/babel-plugin-transform-svg-component": "8.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", - "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3", - "snake-case": "^3.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", - "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/plugin-jsx": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", - "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "@svgr/hast-util-to-babel-ast": "8.0.0", - "svg-parser": "^2.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" - } - }, - "node_modules/@swc/core": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.12.tgz", - "integrity": "sha512-+iUL0PYpPm6N9AdV1wvafakvCqFegQus1aoEDxgFsv3/uNVNIyRaupf/v/Zkp5hbep2EzhtoJR0aiJIzDbXWHg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.17" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.10.12", - "@swc/core-darwin-x64": "1.10.12", - "@swc/core-linux-arm-gnueabihf": "1.10.12", - "@swc/core-linux-arm64-gnu": "1.10.12", - "@swc/core-linux-arm64-musl": "1.10.12", - "@swc/core-linux-x64-gnu": "1.10.12", - "@swc/core-linux-x64-musl": "1.10.12", - "@swc/core-win32-arm64-msvc": "1.10.12", - "@swc/core-win32-ia32-msvc": "1.10.12", - "@swc/core-win32-x64-msvc": "1.10.12" - }, - "peerDependencies": { - "@swc/helpers": "*" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.12.tgz", - "integrity": "sha512-pOANQegUTAriW7jq3SSMZGM5l89yLVMs48R0F2UG6UZsH04SiViCnDctOGlA/Sa++25C+rL9MGMYM1jDLylBbg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.12.tgz", - "integrity": "sha512-m4kbpIDDsN1FrwfNQMU+FTrss356xsXvatLbearwR+V0lqOkjLBP0VmRvQfHEg+uy13VPyrT9gj4HLoztlci7w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.12.tgz", - "integrity": "sha512-OY9LcupgqEu8zVK+rJPes6LDJJwPDmwaShU96beTaxX2K6VrXbpwm5WbPS/8FfQTsmpnuA7dCcMPUKhNgmzTrQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.12.tgz", - "integrity": "sha512-nJD587rO0N4y4VZszz3xzVr7JIiCzSMhEMWnPjuh+xmPxDBz0Qccpr8xCr1cSxpl1uY7ERkqAGlKr6CwoV5kVg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.12.tgz", - "integrity": "sha512-oqhSmV+XauSf0C//MoQnVErNUB/5OzmSiUzuazyLsD5pwqKNN+leC3JtRQ/QVzaCpr65jv9bKexT9+I2Tt3xDw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.12.tgz", - "integrity": "sha512-XldSIHyjD7m1Gh+/8rxV3Ok711ENLI420CU2EGEqSe3VSGZ7pHJvJn9ZFbYpWhsLxPqBYMFjp3Qw+J6OXCPXCA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.12.tgz", - "integrity": "sha512-wvPXzJxzPgTqhyp1UskOx1hRTtdWxlyFD1cGWOxgLsMik0V9xKRgqKnMPv16Nk7L9xl6quQ6DuUHj9ID7L3oVw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.12.tgz", - "integrity": "sha512-TUYzWuu1O7uyIcRfxdm6Wh1u+gNnrW5M1DUgDOGZLsyQzgc2Zjwfh2llLhuAIilvCVg5QiGbJlpibRYJ/8QGsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.12.tgz", - "integrity": "sha512-4Qrw+0Xt+Fe2rz4OJ/dEPMeUf/rtuFWWAj/e0vL7J5laUHirzxawLRE5DCJLQTarOiYR6mWnmadt9o3EKzV6Xg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.12.tgz", - "integrity": "sha512-YiloZXLW7rUxJpALwHXaGjVaAEn+ChoblG7/3esque+Y7QCyheoBUJp2DVM1EeVA43jBfZ8tvYF0liWd9Tpz1A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true - }, - "node_modules/@swc/types": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz", - "integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==", - "dev": true, - "dependencies": { - "@swc/counter": "^0.1.3" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@types/js-cookie": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.6.tgz", - "integrity": "sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw==" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "22.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz", - "integrity": "sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.14", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", - "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" - }, - "node_modules/@types/react": { - "version": "16.14.62", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.62.tgz", - "integrity": "sha512-BWf7hqninZav6nerxXj+NeZT/mTpDeG6Lk2zREHAy63CrnXoOGPGtNqTFYFN/sqpSaREDP5otVV88axIXmKfGA==", - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "^0.16", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-transition-group": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", - "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", - "peerDependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react/node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" - }, - "node_modules/@types/zen-observable": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.7.tgz", - "integrity": "sha512-LKzNTjj+2j09wAo/vvVjzgw5qckJJzhdGgWHW7j69QIGdq/KnZrMAMIHQiWGl3Ccflh5/CudBAntTPYdprPltA==" - }, - "node_modules/@use-hooks/axios": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@use-hooks/axios/-/axios-1.3.0.tgz", - "integrity": "sha512-utvbuLjhgzWU2hU6XkLHIzzNEUYOgqwlSO8mhmUb+a1LIkdQPCoBh6RPWvD7GiOI7AM36JbUPyKv/2vC/e86Tg==", - "dependencies": { - "axios": "^0.19.0", - "react": "^16.8.1", - "react-dom": "^16.8.1" - }, - "peerDependencies": { - "react": "^16.8.1", - "react-dom": "^16.8.1" - } - }, - "node_modules/@use-hooks/axios/node_modules/axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410", - "dependencies": { - "follow-redirects": "1.5.10" - } - }, - "node_modules/@vitejs/plugin-react-swc": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.7.2.tgz", - "integrity": "sha512-y0byko2b2tSVVf5Gpng1eEhX1OvPC7x8yns1Fx8jDzlJp4LS6CMkCPfLw47cjyoMrshQDoQw4qcgjsU9VvlCew==", - "dev": true, - "dependencies": { - "@swc/core": "^1.7.26" - }, - "peerDependencies": { - "vite": "^4 || ^5 || ^6" - } - }, - "node_modules/@wry/context": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.4.4.tgz", - "integrity": "sha512-LrKVLove/zw6h2Md/KZyWxIkFM6AoyKp71OqpH9Hiip1csjPVoD3tPxlbQUNxEnHENks3UGgNpSBCAfq9KWuag==", - "dependencies": { - "@types/node": ">=6", - "tslib": "^1.9.3" - } - }, - "node_modules/@wry/equality": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz", - "integrity": "sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA==", - "dependencies": { - "tslib": "^1.9.3" - } - }, - "node_modules/@xobotyi/scrollbar-width": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", - "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==" - }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", - "dev": true, - "dependencies": { - "environment": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/apollo-cache": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.3.5.tgz", - "integrity": "sha512-1XoDy8kJnyWY/i/+gLTEbYLnoiVtS8y7ikBr/IfmML4Qb+CM7dEEbIUOjnY716WqmZ/UpXIxTfJsY7rMcqiCXA==", - "dependencies": { - "apollo-utilities": "^1.3.4", - "tslib": "^1.10.0" - }, - "peerDependencies": { - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/apollo-cache-inmemory": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.6.tgz", - "integrity": "sha512-L8pToTW/+Xru2FFAhkZ1OA9q4V4nuvfoPecBM34DecAugUZEBhI2Hmpgnzq2hTKZ60LAMrlqiASm0aqAY6F8/A==", - "dependencies": { - "apollo-cache": "^1.3.5", - "apollo-utilities": "^1.3.4", - "optimism": "^0.10.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.10.0" - }, - "peerDependencies": { - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/apollo-client": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.6.10.tgz", - "integrity": "sha512-jiPlMTN6/5CjZpJOkGeUV0mb4zxx33uXWdj/xQCfAMkuNAC3HN7CvYDyMHHEzmcQ5GV12LszWoQ/VlxET24CtA==", - "dependencies": { - "@types/zen-observable": "^0.8.0", - "apollo-cache": "1.3.5", - "apollo-link": "^1.0.0", - "apollo-utilities": "1.3.4", - "symbol-observable": "^1.0.2", - "ts-invariant": "^0.4.0", - "tslib": "^1.10.0", - "zen-observable": "^0.8.0" - }, - "peerDependencies": { - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/apollo-link": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz", - "integrity": "sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg==", - "dependencies": { - "apollo-utilities": "^1.3.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.9.3", - "zen-observable-ts": "^0.8.21" - }, - "peerDependencies": { - "graphql": "^0.11.3 || ^0.12.3 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/apollo-link-error": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/apollo-link-error/-/apollo-link-error-1.1.13.tgz", - "integrity": "sha512-jAZOOahJU6bwSqb2ZyskEK1XdgUY9nkmeclCrW7Gddh1uasHVqmoYc4CKdb0/H0Y1J9lvaXKle2Wsw/Zx1AyUg==", - "dependencies": { - "apollo-link": "^1.2.14", - "apollo-link-http-common": "^0.2.16", - "tslib": "^1.9.3" - } - }, - "node_modules/apollo-link-http": { - "version": "1.5.17", - "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.17.tgz", - "integrity": "sha512-uWcqAotbwDEU/9+Dm9e1/clO7hTB2kQ/94JYcGouBVLjoKmTeJTUPQKcJGpPwUjZcSqgYicbFqQSoJIW0yrFvg==", - "dependencies": { - "apollo-link": "^1.2.14", - "apollo-link-http-common": "^0.2.16", - "tslib": "^1.9.3" - }, - "peerDependencies": { - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/apollo-link-http-common": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.16.tgz", - "integrity": "sha512-2tIhOIrnaF4UbQHf7kjeQA/EmSorB7+HyJIIrUjJOKBgnXwuexi8aMecRlqTIDWcyVXCeqLhUnztMa6bOH/jTg==", - "dependencies": { - "apollo-link": "^1.2.14", - "ts-invariant": "^0.4.0", - "tslib": "^1.9.3" - }, - "peerDependencies": { - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/apollo-upload-client": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-13.0.0.tgz", - "integrity": "sha512-lJ9/bk1BH1lD15WhWRha2J3+LrXrPIX5LP5EwiOUHv8PCORp4EUrcujrA3rI5hZeZygrTX8bshcuMdpqpSrvtA==", - "dependencies": { - "@babel/runtime": "^7.9.2", - "apollo-link": "^1.2.12", - "apollo-link-http-common": "^0.2.14", - "extract-files": "^8.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/jaydenseric" - } - }, - "node_modules/apollo-utilities": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz", - "integrity": "sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig==", - "dependencies": { - "@wry/equality": "^0.1.2", - "fast-json-stable-stringify": "^2.0.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.10.0" - }, - "peerDependencies": { - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "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.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "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.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "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.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/attr-accept": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", - "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/auto-bind": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-2.1.1.tgz", - "integrity": "sha512-NUwV1i9D3vxxY1KnfZgSZ716d6ovY7o8LfOwLhGIPFBowIb6Ln6DBW64+jCqPzUznel2hRSkQnYQqvh7/ldw8A==", - "dependencies": { - "@types/react": "^16.8.12" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "dependencies": { - "follow-redirects": "^1.10.0" - } - }, - "node_modules/axios/node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base-x": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" - }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bigi": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", - "integrity": "sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==" - }, - "node_modules/bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", - "engines": { - "node": "*" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip-schnorr": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/bip-schnorr/-/bip-schnorr-0.6.4.tgz", - "integrity": "sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg==", - "dependencies": { - "bigi": "^1.4.2", - "ecurve": "^1.0.6", - "js-sha256": "^0.9.0", - "randombytes": "^2.1.0", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/bip32": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-1.0.4.tgz", - "integrity": "sha512-8T21eLWylZETolyqCPgia+MNp+kY37zFr7PTFDTPObHeNi9JlfG4qGIh8WzerIJidtwoK+NsWq2I5i66YfHoIw==", - "dependencies": { - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.0.0", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bitcoin-ops": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz", - "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==" - }, - "node_modules/bitcoinjs-lib": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-4.0.3.tgz", - "integrity": "sha512-cb5t55MYUpwQi095J+u6eyltgIU7lbhZfC6+annstncDhfH4cyctW5jmU/tac7NonZZFYH7DktWnDxUm9AWWDQ==", - "dependencies": { - "bech32": "^1.1.2", - "bip32": "^1.0.0", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.4.0", - "bs58check": "^2.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.1", - "tiny-secp256k1": "^1.0.0", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", - "wif": "^2.0.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/bitcoinjs-lib/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/bitcore-lib": { - "version": "8.25.47", - "resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.25.47.tgz", - "integrity": "sha512-qDZr42HuP4P02I8kMGZUx/vvwuDsz8X3rQxXLfM0BtKzlQBcbSM7ycDkDN99Xc5jzpd4fxNQyyFXOmc6owUsrQ==", - "dependencies": { - "bech32": "=2.0.0", - "bip-schnorr": "=0.6.4", - "bn.js": "=4.11.8", - "bs58": "^4.0.1", - "buffer-compare": "=1.1.1", - "elliptic": "^6.5.3", - "inherits": "=2.0.1", - "lodash": "^4.17.20" - } - }, - "node_modules/bitcore-lib-cash": { - "version": "8.25.47", - "resolved": "https://registry.npmjs.org/bitcore-lib-cash/-/bitcore-lib-cash-8.25.47.tgz", - "integrity": "sha512-Qk8L0zLJPv34vSd3pbOOvjpgIi/gU6SHSmX1lJY+lwL9S16KF8fi1Lc9/RNm2tWLGiuMxrg2vKV/9U0yCuQBlQ==", - "dependencies": { - "bitcore-lib": "^8.25.47", - "bn.js": "=4.11.8", - "bs58": "^4.0.1", - "buffer-compare": "=1.1.1", - "elliptic": "^6.5.3", - "inherits": "=2.0.1", - "lodash": "^4.17.20" - } - }, - "node_modules/bitcore-lib-cash/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" - }, - "node_modules/bitcore-lib-cash/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==" - }, - "node_modules/bitcore-lib/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" - }, - "node_modules/bitcore-lib/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==" - }, - "node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" - }, - "node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "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": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-compare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz", - "integrity": "sha512-O6NvNiHZMd3mlIeMDjP6t/gPG75OqGPeiRZXoMQZJ6iy9GofCls4Ijs5YkPZZwoysizLiedhticmdyx/GyHghA==" - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001696", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz", - "integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/cashaddrjs": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cashaddrjs/-/cashaddrjs-0.4.4.tgz", - "integrity": "sha512-xZkuWdNOh0uq/mxJIng6vYWfTowZLd9F4GMAlp2DwFHlcCqCm91NtuAc47RuV4L7r4PYcY5p6Cr2OKNb4hnkWA==", - "dependencies": { - "big-integer": "1.6.36" - } - }, - "node_modules/cashaddrjs/node_modules/big-integer": { - "version": "1.6.36", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz", - "integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "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/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/classnames": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" - }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/compute-scroll-into-view": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", - "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", - "dependencies": { - "toggle-selection": "^1.0.6" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/countries-and-timezones": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/countries-and-timezones/-/countries-and-timezones-2.5.0.tgz", - "integrity": "sha512-bleDLu9/Bgs/eT+ZJcXGAIu+S7QDosYbmViKtYdhT7IDTNqyQoAO5vmjKwVdalTDyqXE8TOR1hKbpbnK5f0COQ==", - "engines": { - "node": ">=8.x", - "npm": ">=5.x" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "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": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "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": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-js": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz", - "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==" - }, - "node_modules/css-in-js-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", - "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", - "dependencies": { - "hyphenate-style-name": "^1.0.3" - } - }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-vendor": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", - "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", - "dependencies": { - "@babel/runtime": "^7.8.3", - "is-in-browser": "^1.0.2" - } - }, - "node_modules/csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" - }, - "node_modules/d3": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-6.7.0.tgz", - "integrity": "sha512-hNHRhe+yCDLUG6Q2LwvR/WdNFPOJQ5VWqsJcwIYVeI401+d2/rrCjxSXkiAdIlpx7/73eApFB4Olsmh3YN7a6g==", - "dependencies": { - "d3-array": "2", - "d3-axis": "2", - "d3-brush": "2", - "d3-chord": "2", - "d3-color": "2", - "d3-contour": "2", - "d3-delaunay": "5", - "d3-dispatch": "2", - "d3-drag": "2", - "d3-dsv": "2", - "d3-ease": "2", - "d3-fetch": "2", - "d3-force": "2", - "d3-format": "2", - "d3-geo": "2", - "d3-hierarchy": "2", - "d3-interpolate": "2", - "d3-path": "2", - "d3-polygon": "2", - "d3-quadtree": "2", - "d3-random": "2", - "d3-scale": "3", - "d3-scale-chromatic": "2", - "d3-selection": "2", - "d3-shape": "2", - "d3-time": "2", - "d3-time-format": "3", - "d3-timer": "2", - "d3-transition": "2", - "d3-zoom": "2" - } - }, - "node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "dependencies": { - "internmap": "^1.0.0" - } - }, - "node_modules/d3-axis": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-2.1.0.tgz", - "integrity": "sha512-z/G2TQMyuf0X3qP+Mh+2PimoJD41VOCjViJzT0BHeL/+JQAofkiWZbWxlwFGb1N8EN+Cl/CW+MUKbVzr1689Cw==" - }, - "node_modules/d3-brush": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-2.1.0.tgz", - "integrity": "sha512-cHLLAFatBATyIKqZOkk/mDHUbzne2B3ZwxkzMHvFTCZCmLaXDpZRihQSn8UNXTkGD/3lb/W2sQz0etAftmHMJQ==", - "dependencies": { - "d3-dispatch": "1 - 2", - "d3-drag": "2", - "d3-interpolate": "1 - 2", - "d3-selection": "2", - "d3-transition": "2" - } - }, - "node_modules/d3-chord": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-2.0.0.tgz", - "integrity": "sha512-D5PZb7EDsRNdGU4SsjQyKhja8Zgu+SHZfUSO5Ls8Wsn+jsAKUUGkcshLxMg9HDFxG3KqavGWaWkJ8EpU8ojuig==", - "dependencies": { - "d3-path": "1 - 2" - } - }, - "node_modules/d3-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz", - "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==" - }, - "node_modules/d3-contour": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-2.0.0.tgz", - "integrity": "sha512-9unAtvIaNk06UwqBmvsdHX7CZ+NPDZnn8TtNH1myW93pWJkhsV25JcgnYAu0Ck5Veb1DHiCv++Ic5uvJ+h50JA==", - "dependencies": { - "d3-array": "2" - } - }, - "node_modules/d3-delaunay": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-5.3.0.tgz", - "integrity": "sha512-amALSrOllWVLaHTnDLHwMIiz0d1bBu9gZXd1FiLfXf8sHcX9jrcj81TVZOqD4UX7MgBZZ07c8GxzEgBpJqc74w==", - "dependencies": { - "delaunator": "4" - } - }, - "node_modules/d3-dispatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz", - "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==" - }, - "node_modules/d3-drag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz", - "integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==", - "dependencies": { - "d3-dispatch": "1 - 2", - "d3-selection": "2" - } - }, - "node_modules/d3-dsv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-2.0.0.tgz", - "integrity": "sha512-E+Pn8UJYx9mViuIUkoc93gJGGYut6mSDKy2+XaPwccwkRGlR+LO97L2VCCRjQivTwLHkSnAJG7yo00BWY6QM+w==", - "dependencies": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - }, - "bin": { - "csv2json": "bin/dsv2json", - "csv2tsv": "bin/dsv2dsv", - "dsv2dsv": "bin/dsv2dsv", - "dsv2json": "bin/dsv2json", - "json2csv": "bin/json2dsv", - "json2dsv": "bin/json2dsv", - "json2tsv": "bin/json2dsv", - "tsv2csv": "bin/dsv2dsv", - "tsv2json": "bin/dsv2json" - } - }, - "node_modules/d3-ease": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz", - "integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ==" - }, - "node_modules/d3-fetch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-2.0.0.tgz", - "integrity": "sha512-TkYv/hjXgCryBeNKiclrwqZH7Nb+GaOwo3Neg24ZVWA3MKB+Rd+BY84Nh6tmNEMcjUik1CSUWjXYndmeO6F7sw==", - "dependencies": { - "d3-dsv": "1 - 2" - } - }, - "node_modules/d3-force": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz", - "integrity": "sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==", - "dependencies": { - "d3-dispatch": "1 - 2", - "d3-quadtree": "1 - 2", - "d3-timer": "1 - 2" - } - }, - "node_modules/d3-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz", - "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==" - }, - "node_modules/d3-geo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.2.tgz", - "integrity": "sha512-8pM1WGMLGFuhq9S+FpPURxic+gKzjluCD/CHTuUF3mXMeiCo0i6R0tO1s4+GArRFde96SLcW/kOFRjoAosPsFA==", - "dependencies": { - "d3-array": "^2.5.0" - } - }, - "node_modules/d3-hierarchy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz", - "integrity": "sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw==" - }, - "node_modules/d3-interpolate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz", - "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==", - "dependencies": { - "d3-color": "1 - 2" - } - }, - "node_modules/d3-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz", - "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA==" - }, - "node_modules/d3-polygon": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-2.0.0.tgz", - "integrity": "sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==" - }, - "node_modules/d3-quadtree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz", - "integrity": "sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw==" - }, - "node_modules/d3-random": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-2.2.2.tgz", - "integrity": "sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw==" - }, - "node_modules/d3-scale": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz", - "integrity": "sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==", - "dependencies": { - "d3-array": "^2.3.0", - "d3-format": "1 - 2", - "d3-interpolate": "1.2.0 - 2", - "d3-time": "^2.1.1", - "d3-time-format": "2 - 3" - } - }, - "node_modules/d3-scale-chromatic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz", - "integrity": "sha512-LLqy7dJSL8yDy7NRmf6xSlsFZ6zYvJ4BcWFE4zBrOPnQERv9zj24ohnXKRbyi9YHnYV+HN1oEO3iFK971/gkzA==", - "dependencies": { - "d3-color": "1 - 2", - "d3-interpolate": "1 - 2" - } - }, - "node_modules/d3-selection": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz", - "integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA==" - }, - "node_modules/d3-shape": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz", - "integrity": "sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==", - "dependencies": { - "d3-path": "1 - 2" - } - }, - "node_modules/d3-time": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", - "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", - "dependencies": { - "d3-array": "2" - } - }, - "node_modules/d3-time-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", - "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", - "dependencies": { - "d3-time": "1 - 2" - } - }, - "node_modules/d3-timer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz", - "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==" - }, - "node_modules/d3-transition": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz", - "integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==", - "dependencies": { - "d3-color": "1 - 2", - "d3-dispatch": "1 - 2", - "d3-ease": "1 - 2", - "d3-interpolate": "1 - 2", - "d3-timer": "1 - 2" - }, - "peerDependencies": { - "d3-selection": "2" - } - }, - "node_modules/d3-zoom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz", - "integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==", - "dependencies": { - "d3-dispatch": "1 - 2", - "d3-drag": "2", - "d3-interpolate": "1 - 2", - "d3-selection": "2", - "d3-transition": "2" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/date-fns-tz": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-1.3.8.tgz", - "integrity": "sha512-qwNXUFtMHTTU6CFSFjoJ80W8Fzzp24LntbjFFBgL/faqds4e5mo9mftoRLgr3Vi1trISsg4awSpYVsOQCRnapQ==", - "peerDependencies": { - "date-fns": ">=2.0.0" - } - }, - "node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "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/delaunator": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz", - "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==" - }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, - "node_modules/dom-helpers/node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dot-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "node_modules/downshift": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/downshift/-/downshift-3.3.4.tgz", - "integrity": "sha512-3bM11S3p78p/moyJqDPc1j357dm/C+dN+54HKuc526k5etNXvnXyxsb+Ufd2yLL6qK4QZA62DysAgtMCIsKCNA==", - "dependencies": { - "@babel/runtime": "^7.4.5", - "@reach/auto-id": "^0.2.0", - "compute-scroll-into-view": "^1.0.9", - "prop-types": "^15.7.2", - "react-is": "^16.9.0" - }, - "peerDependencies": { - "react": ">=0.14.9" - } - }, - "node_modules/downshift/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ecurve": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/ecurve/-/ecurve-1.0.6.tgz", - "integrity": "sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==", - "dependencies": { - "bigi": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.90", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz", - "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==", - "dev": true - }, - "node_modules/elliptic": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "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/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "dependencies": { - "stackframe": "^1.3.4" - } - }, - "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", - "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.6", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.4", - "safe-array-concat": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dev": true, - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" - } - }, - "node_modules/esbuild-plugin-react-virtualized": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esbuild-plugin-react-virtualized/-/esbuild-plugin-react-virtualized-1.0.4.tgz", - "integrity": "sha512-/Y+82TBduHox0/uhJlTgUqi3ZWN+qZPF0xy9crkHQE2AOOdm76l6VY2F0Mdfvue9hqXz2FOlKHlHUVXNalHLzA==", - "dev": true, - "peerDependencies": { - "esbuild": "*" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", - "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.10.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.19.0", - "@eslint/plugin-kit": "^0.2.5", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", - "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", - "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.1", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-compiler": { - "version": "19.0.0-beta-e552027-20250112", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-e552027-20250112.tgz", - "integrity": "sha512-VjkIXHouCYyJHgk5HmZ1LH+fAK5CX+ULRX9iNYtwYJ+ljbivFhIT+JJyxNT/USQpCeS2Dt5ahjFeeMv0RRwTww==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "hermes-parser": "^0.25.1", - "zod": "^3.22.4", - "zod-validation-error": "^3.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" - }, - "peerDependencies": { - "eslint": ">=7" - } - }, - "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", - "dev": true, - "dependencies": { - "acorn": "^8.14.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ethereumjs-icap": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/ethereumjs-icap/-/ethereumjs-icap-0.3.2.tgz", - "integrity": "sha512-7F8M8iKTFMOLTKCRHdm5dWjS0J1r/cgTlZ5zwgSCDy4hSAh6aLBrhYj0vAVRtUThs0ba3imfSlwtQ0Bit+VqRA==", - "deprecated": "This library has been deprecated and is not maintained.", - "dependencies": { - "base-x": "^3.0.0" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true - }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/extract-files": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-8.1.0.tgz", - "integrity": "sha512-PTGtfthZK79WUMk+avLmwx3NGdU8+iVFXC2NMGxKsn0MnihOG2lvumj+AZo8CTwTrwjXDgZ5tztbRlEdRjBonQ==", - "engines": { - "node": "10 - 12 || >= 13.7" - }, - "funding": { - "url": "https://github.com/sponsors/jaydenseric" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-shallow-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", - "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" - }, - "node_modules/fastest-stable-stringify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", - "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==" - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/file-saver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", - "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" - }, - "node_modules/file-selector": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.4.0.tgz", - "integrity": "sha512-iACCiXeMYOvZqlF1kTiYINzgepRBymz1wwjiuup9u9nayhb6g4fSwiyJ/6adli+EPwrWtpgQAh2PoS7HukEGEg==", - "dependencies": { - "tslib": "^2.0.3" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/file-selector/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dependencies": { - "debug": "=3.1.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/for-each": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.4.tgz", - "integrity": "sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==", - "dev": true, - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/formik": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.0.tgz", - "integrity": "sha512-l47RfvejhfHNh8rTRVaCaPfx8nyeYDSTLaEqRvLX4qkWnrrq9ByGVCWggVR+0TVtzc5Ub1gLUuVu9UKuGwfhjA==", - "dependencies": { - "deepmerge": "^2.1.1", - "hoist-non-react-statics": "^3.3.0", - "lodash": "^4.17.14", - "lodash-es": "^4.17.14", - "react-fast-compare": "^2.0.1", - "scheduler": "^0.18.0", - "tiny-warning": "^1.0.2", - "tslib": "^1.10.0" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/formik/node_modules/scheduler": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", - "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "function-bind": "^1.1.2", - "get-proto": "^1.0.0", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "15.14.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", - "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graphql": { - "version": "14.7.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.7.0.tgz", - "integrity": "sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==", - "dependencies": { - "iterall": "^1.2.2" - }, - "engines": { - "node": ">= 6.x" - } - }, - "node_modules/graphql-tag": { - "version": "2.12.6", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", - "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/graphql-tag/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dev": true, - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "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": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true - }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, - "dependencies": { - "hermes-estree": "0.25.1" - } - }, - "node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/hyphenate-style-name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", - "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==" - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/inline-style-prefixer": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", - "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", - "dependencies": { - "css-in-js-utils": "^3.1.0" - } - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dev": true, - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", - "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-in-browser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", - "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==" - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", - "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/iterall": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", - "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" - }, - "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/js-cookie": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", - "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" - }, - "node_modules/js-sha256": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", - "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jss": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", - "integrity": "sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" - } - }, - "node_modules/jss-plugin-camel-case": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz", - "integrity": "sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "hyphenate-style-name": "^1.0.3", - "jss": "10.10.0" - } - }, - "node_modules/jss-plugin-default-unit": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz", - "integrity": "sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0" - } - }, - "node_modules/jss-plugin-extend": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-extend/-/jss-plugin-extend-10.10.0.tgz", - "integrity": "sha512-sKYrcMfr4xxigmIwqTjxNcHwXJIfvhvjTNxF+Tbc1NmNdyspGW47Ey6sGH8BcQ4FFQhLXctpWCQSpDwdNmXSwg==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0", - "tiny-warning": "^1.0.2" - } - }, - "node_modules/jss-plugin-global": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz", - "integrity": "sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0" - } - }, - "node_modules/jss-plugin-nested": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz", - "integrity": "sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0", - "tiny-warning": "^1.0.2" - } - }, - "node_modules/jss-plugin-props-sort": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz", - "integrity": "sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0" - } - }, - "node_modules/jss-plugin-rule-value-function": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz", - "integrity": "sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0", - "tiny-warning": "^1.0.2" - } - }, - "node_modules/jss-plugin-vendor-prefixer": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz", - "integrity": "sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "css-vendor": "^2.0.8", - "jss": "10.10.0" - } - }, - "node_modules/jss/node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "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/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/jszip/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "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/jszip/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/jszip/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/keccak": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", - "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", - "hasInstallScript": true, - "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/keccak256": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/keccak256/-/keccak256-1.0.6.tgz", - "integrity": "sha512-8GLiM01PkdJVGUhR1e6M/AvWnSqYS0HaERI+K/QtStGDGlSTx2B1zTqZk4Zlqu5TxHJNTxWAdP9Y+WI50OApUw==", - "dependencies": { - "bn.js": "^5.2.0", - "buffer": "^6.0.3", - "keccak": "^3.0.2" - } - }, - "node_modules/keccak256/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libphonenumber-js": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.19.tgz", - "integrity": "sha512-bW/Yp/9dod6fmyR+XqSUL1N5JE7QRxQ3KrBIbYS1FTv32e5i3SEtQVX+71CYNv8maWNSOgnlCoNp9X78f/cKiA==" - }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/lint-staged": { - "version": "15.4.3", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.3.tgz", - "integrity": "sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==", - "dev": true, - "dependencies": { - "chalk": "^5.4.1", - "commander": "^13.1.0", - "debug": "^4.4.0", - "execa": "^8.0.1", - "lilconfig": "^3.1.3", - "listr2": "^8.2.5", - "micromatch": "^4.0.8", - "pidtree": "^0.6.0", - "string-argv": "^0.3.2", - "yaml": "^2.7.0" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": ">=18.12.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/lint-staged/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/lint-staged/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "dev": true, - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "dev": true, - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", - "dev": true, - "dependencies": { - "get-east-asian-width": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lower-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/match-sorter": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-4.2.1.tgz", - "integrity": "sha512-s+3h9TiZU9U1pWhIERHf8/f4LmBN6IXaRgo2CI17+XGByGS1GvG5VvXK9pcGyCjGe3WM3mSYRC3ipGrd5UEVgw==", - "dependencies": { - "@babel/runtime": "^7.10.5", - "remove-accents": "0.4.2" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merkle-lib": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/merkle-lib/-/merkle-lib-2.0.10.tgz", - "integrity": "sha512-XrNQvUbn1DL5hKNe46Ccs+Tu3/PYOlrcZILuGUhb95oKBPjc/nmIC8D462PQkipVDGKRvwhn+QFg2cCdIvmDJA==" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mini-create-react-context": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.3.3.tgz", - "integrity": "sha512-TtF6hZE59SGmS4U8529qB+jJFeW6asTLDIpPgvPLSCsooAwJS7QprHIFTqv9/Qh3NdLwQxFYgiHX5lqb6jqzPA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dependencies": { - "@babel/runtime": "^7.12.1", - "tiny-warning": "^1.0.3" - }, - "peerDependencies": { - "prop-types": "^15.0.0", - "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/nan": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", - "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==" - }, - "node_modules/nano-css": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", - "integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15", - "css-tree": "^1.1.2", - "csstype": "^3.1.2", - "fastest-stable-stringify": "^2.0.2", - "inline-style-prefixer": "^7.0.1", - "rtl-css-js": "^1.16.1", - "stacktrace-js": "^2.0.2", - "stylis": "^4.3.0" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/nano-css/node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/no-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "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": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dev": true, - "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": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "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.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optimism": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.10.3.tgz", - "integrity": "sha512-9A5pqGoQk49H6Vhjb9kPgAeeECfUDF6aIICbMDL23kDLStBn1MWk3YvcZ4xWF9CsSf6XEgvRLkXy4xof/56vVw==", - "dependencies": { - "@wry/context": "^0.4.0" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "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/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-ms": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-1.0.1.tgz", - "integrity": "sha512-LpH1Cf5EYuVjkBvCDBYvkUPh+iv2bk3FHflxHkpCYT0/FZ1d3N3uJaLiHr4yGuMcFUhv6eAivitTvWZI4B/chg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/path-to-regexp/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/plur": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-1.0.0.tgz", - "integrity": "sha512-qSnKBSZeDY8ApxwhfVIwKwF36KVJqb1/9nzYYq3j3vdwocULCXT8f8fQGkiw1Nk9BGfxiDagEe/pwakA+bOBqw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/popper.js": { - "version": "1.16.1-lts", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", - "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", - "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", - "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pretty-ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-2.1.0.tgz", - "integrity": "sha512-H2enpsxzDhuzRl3zeSQpQMirn8dB0Z/gxW96j06tMfTviUWvX14gjKb7qd1gtkUyYhDPuoNe00K5PqNvy2oQNg==", - "dependencies": { - "is-finite": "^1.0.1", - "parse-ms": "^1.0.0", - "plur": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "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": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/property-expr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", - "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pushdata-bitcoin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz", - "integrity": "sha512-hw7rcYTJRAl4olM8Owe8x0fBuJJ+WGbMhQuLWOXEMN3PxPCKQHRkhfL+XG0+iXUmSHjkMmb3Ba55Mt21cZc9kQ==", - "dependencies": { - "bitcoin-ops": "^1.3.0" - } - }, - "node_modules/qr.js": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", - "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" - }, - "node_modules/qrcode.react": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-0.9.3.tgz", - "integrity": "sha512-gGd30Ez7cmrKxyN2M3nueaNLk/f9J7NDRgaD5fVgxGpPLsYGWMn9UQ+XnDpv95cfszTQTdaf4QGLNMf3xU0hmw==", - "dependencies": { - "prop-types": "^15.6.0", - "qr.js": "0.0.0" - }, - "peerDependencies": { - "react": "^15.5.3 || ^16.0.0" - } - }, - "node_modules/ramda": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", - "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-copy-to-clipboard": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", - "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", - "dependencies": { - "copy-to-clipboard": "^3.3.1", - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "react": "^15.3.0 || 16 || 17 || 18" - } - }, - "node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/react-dropzone": { - "version": "11.7.1", - "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.7.1.tgz", - "integrity": "sha512-zxCMwhfPy1olUEbw3FLNPLhAm/HnaYH5aELIEglRbqabizKAdHs0h+WuyOpmA+v1JXn0++fpQDdNfUagWt5hJQ==", - "dependencies": { - "attr-accept": "^2.2.2", - "file-selector": "^0.4.0", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">= 10.13" - }, - "peerDependencies": { - "react": ">= 16.8" - } - }, - "node_modules/react-fast-compare": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", - "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" - }, - "node_modules/react-material-ui-carousel": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/react-material-ui-carousel/-/react-material-ui-carousel-2.3.11.tgz", - "integrity": "sha512-rsD9D2JLDBTfinaPy1+hcb7gunfdX7jmga7xESfRCCtLXzokOrkhmx4qMd8dZmYY42zc/HbYqLqg9E/d187lbw==", - "dependencies": { - "auto-bind": "^2.1.1", - "react-swipeable": "^6.1.0" - }, - "peerDependencies": { - "@material-ui/core": "^4.11.3", - "@material-ui/icons": "^4.11.2", - "react": "^16.13.1 || ^17.0.1", - "react-dom": "^16.13.1 || ^17.0.1" - } - }, - "node_modules/react-number-format": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-4.9.4.tgz", - "integrity": "sha512-Gq20Z3ugqPLFgeaidnx5on9cNpbQZntPN3QgNAL/WJrNNlQnNznY0LCx7g8xtssmRBw0/hw+SCqw6zAcajooiA==", - "dependencies": { - "prop-types": "^15.7.2" - }, - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-otp-input": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/react-otp-input/-/react-otp-input-2.4.0.tgz", - "integrity": "sha512-AIgl7u4sS9BTNCxX1xlaS5fPWay/Zml8Ho5LszXZKXrH1C/TiFsTQGmtl13UecQYO3mSF3HUzG2rrDf0sjEFmg==", - "peerDependencies": { - "react": "^16.2.0", - "react-dom": "^16.2.0" - } - }, - "node_modules/react-router": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz", - "integrity": "sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.3.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, - "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/react-router-dom": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.1.2.tgz", - "integrity": "sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.1.2", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, - "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/react-router/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-swipeable": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/react-swipeable/-/react-swipeable-6.2.2.tgz", - "integrity": "sha512-Oz7nSFrssvq2yvy05aNL3F+yBUqSvLsK6x1mu+rQFOpMdQVnt4izKt1vyjvvTb70q6GQOaSpaB6qniROW2MAzQ==", - "peerDependencies": { - "react": "^16.8.3 || ^17 || ^18" - } - }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, - "node_modules/react-universal-interface": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", - "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==", - "peerDependencies": { - "react": "*", - "tslib": "*" - } - }, - "node_modules/react-use": { - "version": "15.3.2", - "resolved": "https://registry.npmjs.org/react-use/-/react-use-15.3.2.tgz", - "integrity": "sha512-DAbc+pVedZC4P5rLBKdIvTTB03+4T/pR6jZ2pKQPgqfq4UC1Oymmbehon5z8XXSUgZs0tgIvbBzVEdiWMS9k+g==", - "dependencies": { - "@types/js-cookie": "2.2.6", - "@xobotyi/scrollbar-width": "1.9.5", - "copy-to-clipboard": "^3.2.0", - "fast-deep-equal": "^3.1.3", - "fast-shallow-equal": "^1.0.0", - "js-cookie": "^2.2.1", - "nano-css": "^5.2.1", - "react-universal-interface": "^0.6.2", - "resize-observer-polyfill": "^1.5.1", - "screenfull": "^5.0.0", - "set-harmonic-interval": "^1.0.1", - "throttle-debounce": "^2.1.0", - "ts-easing": "^0.2.0", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": "^16.8.0", - "react-dom": "^16.8.0" - } - }, - "node_modules/react-use/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/react-virtualized": { - "version": "9.22.6", - "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.6.tgz", - "integrity": "sha512-U5j7KuUQt3AaMatlMJ0UJddqSiX+Km0YJxSqbAzIiGw5EmNz0khMyqP2hzgu4+QUtm+QPIrxzUX4raJxmVJnHg==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "clsx": "^1.0.4", - "dom-helpers": "^5.1.3", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-lifecycles-compat": "^3.0.4" - }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" - }, - "node_modules/resize-observer-polyfill": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", - "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" - }, - "node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rollup": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.0.tgz", - "integrity": "sha512-+4C/cgJ9w6sudisA0nZz0+O7lTP9a3CzNLsoDwaRumM8QHwghUsu6tqHXiTmNUp/rqNiM14++7dkzHDyCRs0Jg==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.0", - "@rollup/rollup-android-arm64": "4.34.0", - "@rollup/rollup-darwin-arm64": "4.34.0", - "@rollup/rollup-darwin-x64": "4.34.0", - "@rollup/rollup-freebsd-arm64": "4.34.0", - "@rollup/rollup-freebsd-x64": "4.34.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.0", - "@rollup/rollup-linux-arm-musleabihf": "4.34.0", - "@rollup/rollup-linux-arm64-gnu": "4.34.0", - "@rollup/rollup-linux-arm64-musl": "4.34.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.0", - "@rollup/rollup-linux-riscv64-gnu": "4.34.0", - "@rollup/rollup-linux-s390x-gnu": "4.34.0", - "@rollup/rollup-linux-x64-gnu": "4.34.0", - "@rollup/rollup-linux-x64-musl": "4.34.0", - "@rollup/rollup-win32-arm64-msvc": "4.34.0", - "@rollup/rollup-win32-ia32-msvc": "4.34.0", - "@rollup/rollup-win32-x64-msvc": "4.34.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/rtl-css-js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", - "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", - "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" - }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-push-apply/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/screenfull": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", - "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "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": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "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/set-harmonic-interval": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", - "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==", - "engines": { - "node": ">=6.9" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dev": true, - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/snake-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stack-generator": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", - "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", - "dependencies": { - "stackframe": "^1.3.4" - } - }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" - }, - "node_modules/stacktrace-gps": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz", - "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==", - "dependencies": { - "source-map": "0.5.6", - "stackframe": "^1.3.4" - } - }, - "node_modules/stacktrace-gps/node_modules/source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stacktrace-js": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", - "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", - "dependencies": { - "error-stack-parser": "^2.0.6", - "stack-generator": "^2.0.5", - "stacktrace-gps": "^3.0.4" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "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/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stylis": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.5.tgz", - "integrity": "sha512-K7npNOKGRYuhAFFzkzMGfxFDpN6gDwf8hcMiE+uveTVbBgm93HrNP3ZDUpKqzZ4pG7TP6fmb+EMAQPjq9FqqvA==" - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true - }, - "node_modules/symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/throttle-debounce": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", - "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/tiny-case": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", - "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==" - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - }, - "node_modules/tiny-secp256k1": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.7.tgz", - "integrity": "sha512-eb+F6NabSnjbLwNoC+2o5ItbmP1kg7HliWue71JgLegQt6A5mTN8YbvTLCazdlg6e5SV6A+r8OGvZYskdlmhqQ==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" - }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" - }, - "node_modules/ts-easing": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz", - "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==" - }, - "node_modules/ts-invariant": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", - "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==", - "dependencies": { - "tslib": "^1.9.3" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" - }, - "node_modules/ua-parser-js": { - "version": "1.0.40", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", - "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], - "bin": { - "ua-parser-js": "script/cli.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" - }, - "node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, - "node_modules/varuint-bitcoin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", - "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, - "node_modules/vite": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", - "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", - "dev": true, - "dependencies": { - "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite-plugin-svgr": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.3.0.tgz", - "integrity": "sha512-Jy9qLB2/PyWklpYy0xk0UU3TlU0t2UMpJXZvf+hWII1lAmRHrOUKi11Uw8N3rxoNk7atZNYO3pR3vI1f7oi+6w==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.1.3", - "@svgr/core": "^8.1.0", - "@svgr/plugin-jsx": "^8.1.0" - }, - "peerDependencies": { - "vite": ">=2.6.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dev": true, - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "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-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", - "dependencies": { - "bs58check": "<3.0.0" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", - "dev": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yup": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", - "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", - "dependencies": { - "property-expr": "^2.0.5", - "tiny-case": "^1.0.3", - "toposort": "^2.0.2", - "type-fest": "^2.19.0" - } - }, - "node_modules/zen-observable": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" - }, - "node_modules/zen-observable-ts": { - "version": "0.8.21", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz", - "integrity": "sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg==", - "dependencies": { - "tslib": "^1.9.3", - "zen-observable": "^0.8.0" - } - }, - "node_modules/zod": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-validation-error": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz", - "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", - "dev": true, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "zod": "^3.18.0" - } - } - } -} diff --git a/new-lamassu-admin/patches/react-scripts+4.0.0.patch b/new-lamassu-admin/patches/react-scripts+4.0.0.patch deleted file mode 100644 index 916c3ecd..00000000 --- a/new-lamassu-admin/patches/react-scripts+4.0.0.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/node_modules/react-scripts/config/webpack.config.js b/node_modules/react-scripts/config/webpack.config.js -index 80c6ac2..3420936 100644 ---- a/node_modules/react-scripts/config/webpack.config.js -+++ b/node_modules/react-scripts/config/webpack.config.js -@@ -752,6 +752,7 @@ module.exports = function (webpackEnv) { - formatter: require.resolve('react-dev-utils/eslintFormatter'), - eslintPath: require.resolve('eslint'), - context: paths.appSrc, -+ cache: true, - // ESLint class options - cwd: paths.appPath, - resolvePluginsRelativeTo: __dirname, diff --git a/new-lamassu-admin/src/App.jsx b/new-lamassu-admin/src/App.jsx deleted file mode 100644 index 83d8e3cf..00000000 --- a/new-lamassu-admin/src/App.jsx +++ /dev/null @@ -1,168 +0,0 @@ -import { useQuery } from '@apollo/react-hooks' -import CssBaseline from '@material-ui/core/CssBaseline' -import Grid from '@material-ui/core/Grid' -import Slide from '@material-ui/core/Slide' -import { - StylesProvider, - jssPreset, - MuiThemeProvider, - makeStyles -} from '@material-ui/core/styles' -import gql from 'graphql-tag' -import { create } from 'jss' -import extendJss from 'jss-plugin-extend' -import React, { useContext, useState } from 'react' -import { - useLocation, - useHistory, - BrowserRouter as Router -} from 'react-router-dom' -import Header from 'src/components/layout/Header' -import Sidebar from 'src/components/layout/Sidebar' -import TitleSection from 'src/components/layout/TitleSection' -import { tree, hasSidebar, Routes, getParent } from 'src/routing/routes' -import ApolloProvider from 'src/utils/apollo' - -import AppContext from 'src/AppContext' -import global from 'src/styling/global' -import theme from 'src/styling/theme' -import { backgroundColor, mainWidth } from 'src/styling/variables' - -const jss = create({ - plugins: [extendJss(), ...jssPreset().plugins] -}) - -const fill = '100%' -const flexDirection = 'column' - -const useStyles = makeStyles({ - ...global, - root: { - backgroundColor, - width: fill, - minHeight: fill, - display: 'flex', - flexDirection - }, - wrapper: { - width: mainWidth, - height: fill, - margin: '0 auto', - flex: 1, - display: 'flex', - flexDirection - }, - grid: { - flex: 1, - height: '100%' - }, - contentWithSidebar: { - flex: 1, - marginLeft: 48, - paddingTop: 15 - }, - contentWithoutSidebar: { - width: mainWidth - } -}) - -const GET_USER_DATA = gql` - query userData { - userData { - id - username - role - enabled - last_accessed - last_accessed_from - last_accessed_address - } - } -` - -const Main = () => { - const classes = useStyles() - const location = useLocation() - const history = useHistory() - const { wizardTested, userData, setUserData } = useContext(AppContext) - - const { loading } = useQuery(GET_USER_DATA, { - onCompleted: userResponse => { - if (!userData && userResponse?.userData) - setUserData(userResponse.userData) - } - }) - - const route = location.pathname - - const sidebar = hasSidebar(route) - const parent = sidebar ? getParent(route) : {} - - const is404 = location.pathname === '/404' - - const isSelected = it => location.pathname === it.route - - const onClick = it => history.push(it.route) - - const contentClassName = sidebar - ? classes.contentWithSidebar - : classes.contentWithoutSidebar - - return ( -
- {!is404 && wizardTested && userData && ( -
- )} -
- {sidebar && !is404 && wizardTested && ( - -
- -
-
- )} - - - {sidebar && !is404 && wizardTested && ( - it.label} - onClick={onClick} - /> - )} -
{!loading && }
-
-
-
- ) -} - -const App = () => { - const [wizardTested, setWizardTested] = useState(false) - const [userData, setUserData] = useState(null) - - const setRole = role => { - if (userData && role && userData.role !== role) { - setUserData({ ...userData, role }) - } - } - - return ( - - - - - - -
- - - - - - ) -} - -export default App diff --git a/new-lamassu-admin/src/components/Carousel.jsx b/new-lamassu-admin/src/components/Carousel.jsx deleted file mode 100644 index a16fad95..00000000 --- a/new-lamassu-admin/src/components/Carousel.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import React, { memo } from 'react' -import ReactCarousel from 'react-material-ui-carousel' -import LeftArrow from 'src/styling/icons/arrow/carousel-left-arrow.svg?react' -import RightArrow from 'src/styling/icons/arrow/carousel-right-arrow.svg?react' - -const useStyles = makeStyles({ - imgWrapper: { - alignItems: 'center', - justifyContent: 'center', - display: 'flex' - }, - imgInner: { - objectFit: 'contain', - objectPosition: 'center', - width: 500, - height: 400, - marginBottom: 40 - } -}) - -export const Carousel = memo(({ photosData, slidePhoto }) => { - const classes = useStyles() - - return ( - <> - } - NextIcon={} - navButtonsProps={{ - style: { - backgroundColor: 'transparent', - borderRadius: 0, - color: 'transparent', - opacity: 1 - } - }} - navButtonsWrapperProps={{ - style: { - marginLeft: -22, - marginRight: -22 - } - }} - autoPlay={false} - indicators={false} - navButtonsAlwaysVisible={true} - next={activeIndex => slidePhoto(activeIndex)} - prev={activeIndex => slidePhoto(activeIndex)}> - {photosData.map((item, i) => ( -
-
- -
-
- ))} -
- - ) -}) diff --git a/new-lamassu-admin/src/components/Chip.jsx b/new-lamassu-admin/src/components/Chip.jsx deleted file mode 100644 index 2f876c40..00000000 --- a/new-lamassu-admin/src/components/Chip.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import Chip from '@material-ui/core/Chip' -import { withStyles } from '@material-ui/core/styles' -import React, { memo } from 'react' - -import { - fontColor, - inputFontWeight, - subheaderColor, - smallestFontSize, - inputFontFamily -} from 'src/styling/variables' - -const styles = theme => ({ - root: { - backgroundColor: subheaderColor, - borderRadius: 4, - margin: theme.spacing(0.5, 0.25), - height: 18 - }, - label: { - fontSize: smallestFontSize, - color: fontColor, - fontWeight: inputFontWeight, - fontFamily: inputFontFamily, - paddingRight: 4, - paddingLeft: 4 - } -}) - -const LsChip = memo(({ classes, ...props }) => ( - -)) - -export default withStyles(styles)(LsChip) diff --git a/new-lamassu-admin/src/components/CollapsibleCard.jsx b/new-lamassu-admin/src/components/CollapsibleCard.jsx deleted file mode 100644 index 574340a1..00000000 --- a/new-lamassu-admin/src/components/CollapsibleCard.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import Grid from '@material-ui/core/Grid' -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React from 'react' - -import { white } from 'src/styling/variables' - -const cardState = Object.freeze({ - DEFAULT: 'default', - SHRUNK: 'shrunk', - EXPANDED: 'expanded' -}) - -const styles = { - card: { - wordWrap: 'break-word', - boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)', - borderRadius: 12, - padding: 24, - backgroundColor: white - } -} - -const useStyles = makeStyles(styles) - -const CollapsibleCard = ({ className, state, shrunkComponent, children }) => { - const classes = useStyles() - return ( - - {state === cardState.SHRUNK ? shrunkComponent : children} - - ) -} - -CollapsibleCard.propTypes = { - shrunkComponent: PropTypes.node.isRequired -} - -export default CollapsibleCard -export { cardState } diff --git a/new-lamassu-admin/src/components/DeleteDialog.jsx b/new-lamassu-admin/src/components/DeleteDialog.jsx deleted file mode 100644 index 256c0f27..00000000 --- a/new-lamassu-admin/src/components/DeleteDialog.jsx +++ /dev/null @@ -1,98 +0,0 @@ -import { - Dialog, - DialogActions, - DialogContent, - makeStyles -} from '@material-ui/core' -import React from 'react' -import { H4, P } from 'src/components/typography' -import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' - -import { Button, IconButton } from 'src/components/buttons' -import { spacer } from 'src/styling/variables' - -import ErrorMessage from './ErrorMessage' - -const useStyles = makeStyles({ - content: { - width: 434, - padding: spacer * 2, - paddingRight: spacer * 3.5 - }, - titleSection: { - padding: spacer * 2, - paddingRight: spacer * 1.5, - display: 'flex', - justifyContent: 'space-between', - margin: 0 - }, - actions: { - padding: spacer * 4, - paddingTop: spacer * 2 - }, - title: { - margin: 0 - }, - closeButton: { - padding: 0, - marginTop: -(spacer / 2) - } -}) - -export const DialogTitle = ({ children, close }) => { - const classes = useStyles() - return ( -
- {children} - {close && ( - - - - )} -
- ) -} - -export const DeleteDialog = ({ - title = 'Confirm Delete', - open = false, - onConfirmed, - onDismissed, - item = 'item', - confirmationMessage = `Are you sure you want to delete this ${item}?`, - extraMessage, - errorMessage = '' -}) => { - const classes = useStyles() - - return ( - - onDismissed()}> -

{title}

-
- {errorMessage && ( - - - {errorMessage.split(':').map(error => ( - <> - {error} -
- - ))} -
-
- )} - - {confirmationMessage &&

{confirmationMessage}

} - {extraMessage} -
- - - -
- ) -} diff --git a/new-lamassu-admin/src/components/ErrorMessage.jsx b/new-lamassu-admin/src/components/ErrorMessage.jsx deleted file mode 100644 index 7433a70b..00000000 --- a/new-lamassu-admin/src/components/ErrorMessage.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import classnames from 'classnames' -import React from 'react' -import ErrorIcon from 'src/styling/icons/warning-icon/tomato.svg?react' - -import { errorColor } from 'src/styling/variables' - -import { Info3 } from './typography' - -const styles = { - wrapper: { - display: 'flex', - alignItems: 'center', - '& > svg': { - marginRight: 10 - } - }, - message: { - display: 'flex', - alignItems: 'center', - color: errorColor, - margin: 0, - whiteSpace: 'break-spaces' - } -} - -const useStyles = makeStyles(styles) - -const ErrorMessage = ({ className, children, ...props }) => { - const classes = useStyles() - - return ( -
- - {children} -
- ) -} - -export default ErrorMessage diff --git a/new-lamassu-admin/src/components/ImagePopper.styles.js b/new-lamassu-admin/src/components/ImagePopper.styles.js deleted file mode 100644 index f30c8f3e..00000000 --- a/new-lamassu-admin/src/components/ImagePopper.styles.js +++ /dev/null @@ -1,25 +0,0 @@ -export default { - row: { - display: 'flex', - flexDirection: 'row' - }, - image: ({ width, height }) => ({ - objectFit: 'cover', - borderRadius: '8px 0px 0px 8px', - width, - height - }), - popupImage: ({ popupWidth, popupHeight }) => ({ - objectFit: 'cover', - width: popupWidth, - height: popupHeight - }), - button: ({ height }) => ({ - borderRadius: '0px 8px 8px 0px', - height - }), - popoverContent: { - display: 'block', - padding: [[10, 15]] - } -} diff --git a/new-lamassu-admin/src/components/InfoMessage.jsx b/new-lamassu-admin/src/components/InfoMessage.jsx deleted file mode 100644 index e0baa4fa..00000000 --- a/new-lamassu-admin/src/components/InfoMessage.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Box, makeStyles } from '@material-ui/core' -import React from 'react' -import { Label1 } from 'src/components/typography' -import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react' - -const useStyles = makeStyles({ - message: ({ width }) => ({ - width, - marginTop: 4, - marginLeft: 16 - }) -}) - -const InfoMessage = ({ children, width = 330, className }) => { - const classes = useStyles({ width }) - - return ( - - - {children} - - ) -} - -export default InfoMessage diff --git a/new-lamassu-admin/src/components/InformativeDialog.jsx b/new-lamassu-admin/src/components/InformativeDialog.jsx deleted file mode 100644 index 47959cff..00000000 --- a/new-lamassu-admin/src/components/InformativeDialog.jsx +++ /dev/null @@ -1,64 +0,0 @@ -import { Dialog, DialogContent, makeStyles } from '@material-ui/core' -import React, { memo } from 'react' -import { H1 } from 'src/components/typography' -import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' - -import { IconButton } from 'src/components/buttons' -import { spacer } from 'src/styling/variables' - -const useStyles = makeStyles({ - closeButton: { - display: 'flex', - padding: [[spacer * 2, spacer * 2, 0, spacer * 2]], - paddingRight: spacer * 1.5, - justifyContent: 'end' - }, - title: { - margin: [[0, spacer * 2, spacer, spacer * 2 + 4]] - } -}) - -export const DialogTitle = ({ children, onClose }) => { - const classes = useStyles() - return ( -
- {children} - {onClose && ( - - - - )} -
- ) -} - -export const InformativeDialog = memo( - ({ title = '', open, onDissmised, disabled = false, data, ...props }) => { - const classes = useStyles() - - const innerOnClose = () => { - onDissmised() - } - - return ( - -
- - - -
-

{title}

- {data} -
- ) - } -) diff --git a/new-lamassu-admin/src/components/Modal.jsx b/new-lamassu-admin/src/components/Modal.jsx deleted file mode 100644 index aba40236..00000000 --- a/new-lamassu-admin/src/components/Modal.jsx +++ /dev/null @@ -1,122 +0,0 @@ -import { makeStyles, Modal as MaterialModal, Paper } from '@material-ui/core' -import classnames from 'classnames' -import React from 'react' -import { H1, H4 } from 'src/components/typography' -import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' - -import { IconButton } from 'src/components/buttons' - -const styles = { - modal: { - display: 'flex', - justifyContent: 'center', - flexDirection: 'column', - alignItems: 'center' - }, - wrapper: ({ width, height }) => ({ - width, - height, - display: 'flex', - flexDirection: 'column', - minHeight: height ?? 400, - maxHeight: '90vh', - overflowY: 'auto', - borderRadius: 8, - outline: 0 - }), - infoPanelWrapper: ({ width, infoPanelHeight }) => ({ - width, - height: infoPanelHeight, - marginTop: 16, - display: 'flex', - flexDirection: 'column', - minHeight: infoPanelHeight ?? 200, - maxHeight: '90vh', - overflowY: 'auto', - borderRadius: 8, - outline: 0 - }), - panelContent: { - width: '100%', - display: 'flex', - flexDirection: 'column', - flex: 1, - padding: [[0, 24]] - }, - content: ({ small, xl }) => ({ - width: '100%', - display: 'flex', - flexDirection: 'column', - flex: 1, - padding: xl ? [[0, 60 + 28]] : small ? [[0, 16]] : [[0, 32]] - }), - button: ({ small, xl }) => ({ - padding: [[0, 0, xl ? 26 : 0, 0]], - margin: xl - ? [[0, 0, 'auto', 'auto']] - : small - ? [[12, 12, 'auto', 'auto']] - : [[16, 16, 'auto', 'auto']] - }), - header: { - display: 'flex' - }, - title: ({ small }) => ({ - margin: small ? [[20, 0, 8, 16]] : [[28, 0, 8, 32]] - }) -} - -const useStyles = makeStyles(styles) - -const Modal = ({ - width, - height, - infoPanelHeight, - title, - small, - xl, - infoPanel, - handleClose, - children, - secondaryModal, - className, - closeOnEscape, - closeOnBackdropClick, - ...props -}) => { - const classes = useStyles({ width, height, small, infoPanelHeight, xl }) - const TitleCase = small ? H4 : H1 - const closeSize = xl ? 28 : small ? 16 : 20 - - const innerClose = (evt, reason) => { - if (!closeOnBackdropClick && reason === 'backdropClick') return - if (!closeOnEscape && reason === 'escapeKeyDown') return - handleClose() - } - - return ( - - <> - -
- {title && {title}} - handleClose()}> - - -
-
{children}
-
- {infoPanel && ( - -
{infoPanel}
-
- )} - -
- ) -} - -export default Modal diff --git a/new-lamassu-admin/src/components/NotificationCenter/NotificationCenter.styles.js b/new-lamassu-admin/src/components/NotificationCenter/NotificationCenter.styles.js deleted file mode 100644 index 91d1b720..00000000 --- a/new-lamassu-admin/src/components/NotificationCenter/NotificationCenter.styles.js +++ /dev/null @@ -1,143 +0,0 @@ -import { - spacer, - white, - zircon, - secondaryColor, - spring3, - comet -} from 'src/styling/variables' - -const styles = { - container: { - '@media only screen and (max-width: 1920px)': { - width: '30vw' - }, - width: '40vw', - height: '110vh', - right: 0, - backgroundColor: white, - boxShadow: '0 0 14px 0 rgba(0, 0, 0, 0.24)' - }, - header: { - display: 'flex', - justifyContent: 'space-between' - }, - headerText: { - marginTop: spacer * 2.5, - marginLeft: spacer * 3 - }, - actionButtons: { - display: 'flex', - marginLeft: spacer * 2, - height: 0 - }, - notificationIcon: ({ buttonCoords, xOffset }) => ({ - position: 'absolute', - top: buttonCoords ? buttonCoords.y : 0, - left: buttonCoords ? buttonCoords.x - xOffset : 0, - cursor: 'pointer', - background: 'transparent', - boxShadow: '0px 0px 0px transparent', - border: '0px solid transparent', - textShadow: '0px 0px 0px transparent', - outline: 'none' - }), - clearAllButton: { - marginTop: -spacer * 2, - marginLeft: spacer, - backgroundColor: zircon - }, - notificationsList: { - height: '90vh', - maxHeight: '100vh', - marginTop: spacer * 3, - marginLeft: 0, - overflowY: 'auto', - overflowX: 'hidden', - backgroundColor: white, - zIndex: 10 - }, - notificationRow: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'flex-start', - position: 'relative', - marginBottom: spacer / 2, - paddingTop: spacer * 1.5, - '& > *:first-child': { - marginRight: 24 - }, - '& > *': { - marginRight: 10 - }, - '& > *:last-child': { - marginRight: 0 - } - }, - notificationContent: { - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - width: 300 - }, - unread: { - backgroundColor: spring3 - }, - notificationRowIcon: { - alignSelf: 'center', - '& > *': { - marginLeft: spacer * 3 - } - }, - readIconWrapper: { - flexGrow: 1 - }, - unreadIcon: { - marginTop: 2, - width: '12px', - height: '12px', - backgroundColor: secondaryColor, - borderRadius: '50%', - cursor: 'pointer', - zIndex: 1 - }, - readIcon: { - marginLeft: spacer, - marginTop: 5, - width: '12px', - height: '12px', - border: [[1, 'solid', comet]], - borderRadius: '50%', - cursor: 'pointer', - zIndex: 1 - }, - notificationTitle: { - margin: 0, - color: comet - }, - notificationBody: { - margin: 0 - }, - notificationSubtitle: { - margin: 0, - marginBottom: spacer, - color: comet - }, - stripes: { - position: 'absolute', - height: '100%', - top: '0px', - opacity: '60%' - }, - hasUnread: { - position: 'absolute', - top: 0, - left: 16, - width: '9px', - height: '9px', - backgroundColor: secondaryColor, - borderRadius: '50%' - } -} - -export default styles diff --git a/new-lamassu-admin/src/components/Popper.jsx b/new-lamassu-admin/src/components/Popper.jsx deleted file mode 100644 index a933e39d..00000000 --- a/new-lamassu-admin/src/components/Popper.jsx +++ /dev/null @@ -1,173 +0,0 @@ -import { makeStyles, Popper as MaterialPopper, Paper } from '@material-ui/core' -import classnames from 'classnames' -import * as R from 'ramda' -import React, { useState } from 'react' - -import { white } from 'src/styling/variables' - -const Popover = ({ - children, - bgColor = white, - arrowSize = 6, - className, - ...props -}) => { - const [arrowRef, setArrowRef] = useState(null) - - const styles = { - popover: { - zIndex: 3000, - backgroundColor: bgColor, - borderRadius: 4 - }, - arrow: { - position: 'absolute', - fontSize: arrowSize, - width: '3em', - height: '3em' - }, - arrowBottom: { - top: 0, - width: 0, - height: 0, - borderLeft: [['2em', 'solid', 'transparent']], - borderRight: [['2em', 'solid', 'transparent']], - borderBottom: [['2em', 'solid', bgColor]], - marginTop: '-1.9em', - '&:after': { - zIndex: -10, - content: '""', - position: 'absolute', - width: arrowSize * 3, - height: arrowSize * 3, - marginLeft: 0, - bottom: 0, - top: 'calc(50% - 0px)', - left: 0, - border: '5px solid #fff', - borderColor: 'transparent transparent #fff #fff', - transformOrigin: '0 0', - transform: 'rotate(45deg)', - boxShadow: - '0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)' - } - }, - arrowTop: { - bottom: 0, - width: 0, - height: 0, - borderLeft: [['2em', 'solid', 'transparent']], - borderRight: [['2em', 'solid', 'transparent']], - borderTop: [['2em', 'solid', bgColor]], - marginBottom: '-1.9em', - '&:after': { - zIndex: -10, - content: '""', - position: 'absolute', - width: arrowSize * 3, - height: arrowSize * 3, - marginLeft: 0, - bottom: 0, - top: -(arrowSize * 4 + 2), - left: 0, - border: '5px solid #fff', - borderColor: 'transparent transparent #fff #fff', - transformOrigin: '0 0', - transform: 'rotate(45deg)', - boxShadow: - '0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)' - } - }, - arrowRight: { - left: 0, - width: 0, - height: 0, - borderTop: [['2em', 'solid', 'transparent']], - borderBottom: [['2em', 'solid', 'transparent']], - borderRight: [['2em', 'solid', bgColor]], - marginLeft: '-1.9em' - }, - arrowLeft: { - right: 0, - width: 0, - height: 0, - borderTop: [['2em', 'solid', 'transparent']], - borderBottom: [['2em', 'solid', 'transparent']], - borderLeft: [['2em', 'solid', bgColor]], - marginRight: '-1.9em' - }, - root: { - backgroundColor: bgColor - } - } - - const useStyles = makeStyles(styles) - - const classes = useStyles() - - const getArrowClasses = placement => ({ - [classes.arrow]: true, - [classes.arrowBottom]: placement === 'bottom', - [classes.arrowTop]: placement === 'top', - [classes.arrowRight]: placement === 'right', - [classes.arrowLeft]: placement === 'left' - }) - - const flipPlacements = { - top: ['bottom'], - bottom: ['top'], - left: ['right'], - right: ['left'] - } - - const modifiers = R.mergeDeepLeft(props.modifiers, { - flip: { - enabled: R.defaultTo(false, props.flip), - allowedAutoPlacements: flipPlacements[props.placement], - boundary: 'clippingParents' - }, - preventOverflow: { - enabled: R.defaultTo(true, props.preventOverflow), - boundariesElement: 'scrollParent' - }, - offset: { - enabled: true, - offset: '0, 10' - }, - arrow: { - enabled: R.defaultTo(true, props.showArrow), - element: arrowRef - }, - computeStyle: { - gpuAcceleration: false - } - }) - - if (props.preventOverflow === false) { - modifiers.hide = { - enabled: false - } - } - - return ( - <> - - {({ placement }) => ( - - - {children} - - )} - - - ) -} - -export default Popover diff --git a/new-lamassu-admin/src/components/PromptWhenDirty.jsx b/new-lamassu-admin/src/components/PromptWhenDirty.jsx deleted file mode 100644 index b7c4835a..00000000 --- a/new-lamassu-admin/src/components/PromptWhenDirty.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import { useFormikContext } from 'formik' -import React, { useEffect } from 'react' -import { Prompt } from 'react-router-dom' - -const PROMPT_DEFAULT_MESSAGE = - 'You have unsaved changes on this page. Are you sure you want to leave?' - -const PromptWhenDirty = ({ message = PROMPT_DEFAULT_MESSAGE }) => { - const formik = useFormikContext() - - const hasChanges = formik.dirty && formik.submitCount === 0 - - useEffect(() => { - if (hasChanges) { - window.onbeforeunload = confirmExit - } else { - window.onbeforeunload = undefined - } - }, [hasChanges]) - - const confirmExit = () => { - return PROMPT_DEFAULT_MESSAGE - } - - return -} - -export default PromptWhenDirty diff --git a/new-lamassu-admin/src/components/SearchBox.jsx b/new-lamassu-admin/src/components/SearchBox.jsx deleted file mode 100644 index 08219a96..00000000 --- a/new-lamassu-admin/src/components/SearchBox.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import InputBase from '@material-ui/core/InputBase' -import Paper from '@material-ui/core/Paper' -import { makeStyles } from '@material-ui/core/styles' -import MAutocomplete from '@material-ui/lab/Autocomplete' -import classnames from 'classnames' -import React, { memo, useState } from 'react' -import { P } from 'src/components/typography' -import SearchIcon from 'src/styling/icons/circle buttons/search/zodiac.svg?react' - -import styles from './SearchBox.styles' - -const useStyles = makeStyles(styles) - -const SearchBox = memo( - ({ - loading = false, - filters = [], - options = [], - inputPlaceholder = '', - size, - onChange, - ...props - }) => { - const classes = useStyles({ size }) - - const [popupOpen, setPopupOpen] = useState(false) - - const inputClasses = { - [classes.input]: true, - [classes.inputWithPopup]: popupOpen - } - - const innerOnChange = filters => onChange(filters) - - return ( - it.label || it.value} - renderOption={it => ( -
-

{it.label || it.value}

-

{it.type}

-
- )} - autoHighlight - disableClearable - clearOnEscape - multiple - filterSelectedOptions - getOptionSelected={(option, value) => option.type === value.type} - PaperComponent={({ children }) => ( - -
- {children} - - )} - renderInput={params => { - return ( - } - placeholder={inputPlaceholder} - inputProps={{ - className: classes.bold, - classes: { - root: classes.size - }, - ...params.inputProps - }} - /> - ) - }} - onOpen={() => setPopupOpen(true)} - onClose={() => setPopupOpen(false)} - onChange={(_, filters) => innerOnChange(filters)} - {...props} - /> - ) - } -) - -export default SearchBox diff --git a/new-lamassu-admin/src/components/SearchBox.styles.js b/new-lamassu-admin/src/components/SearchBox.styles.js deleted file mode 100644 index 336f3ff7..00000000 --- a/new-lamassu-admin/src/components/SearchBox.styles.js +++ /dev/null @@ -1,78 +0,0 @@ -import baseButtonStyles from 'src/components/buttons/BaseButton.styles' -import { bySize, bold } from 'src/styling/helpers' -import { zircon, comet, primaryColor } from 'src/styling/variables' - -const { baseButton } = baseButtonStyles - -const searchBoxBorderRadius = baseButton.height / 2 -const searchBoxHeight = 32 -const popupBorderRadiusFocus = baseButton.height / 4 - -const hoverColor = 'rgba(0, 0, 0, 0.08)' -const boxShadow = `0 4px 4px 0 ${hoverColor}` - -const styles = { - size: ({ size }) => ({ - marginTop: size === 'lg' ? 0 : 2, - ...bySize(size) - }), - bold, - autocomplete: { - '&[data-focus="true"]': { - backgroundColor: hoverColor - } - }, - popup: { - display: 'flex', - flexDirection: 'column', - borderRadius: [[0, 0, popupBorderRadiusFocus, popupBorderRadiusFocus]], - backgroundColor: zircon, - boxShadow - }, - separator: { - width: '88%', - height: 1, - margin: '0 auto', - border: 'solid 0.5px', - borderColor: comet - }, - item: { - display: 'flex', - flexDirection: 'row', - width: '100%', - height: 36, - alignItems: 'center' - }, - itemLabel: { - margin: [0], - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis' - }, - itemType: { - marginLeft: 'auto', - fontSize: 12, - color: comet, - margin: [0] - }, - input: { - display: 'flex', - flex: 1, - width: 273, - padding: [[8, 12]], - alignItems: 'center', - height: searchBoxHeight, - borderRadius: searchBoxBorderRadius, - backgroundColor: zircon, - color: primaryColor - }, - inputWithPopup: { - borderRadius: [[popupBorderRadiusFocus, popupBorderRadiusFocus, 0, 0]], - boxShadow - }, - iconButton: { - marginRight: 12 - } -} - -export default styles diff --git a/new-lamassu-admin/src/components/SearchFilter.jsx b/new-lamassu-admin/src/components/SearchFilter.jsx deleted file mode 100644 index c35b4a71..00000000 --- a/new-lamassu-admin/src/components/SearchFilter.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import React from 'react' -import Chip from 'src/components/Chip' -import { P, Label3 } from 'src/components/typography' -import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' -import FilterIcon from 'src/styling/icons/button/filter/white.svg?react' -import ReverseFilterIcon from 'src/styling/icons/button/filter/zodiac.svg?react' - -import { ActionButton } from 'src/components/buttons' -import { onlyFirstToUpper, singularOrPlural } from 'src/utils/string' - -import { chipStyles, styles } from './SearchFilter.styles' - -const useChipStyles = makeStyles(chipStyles) -const useStyles = makeStyles(styles) - -const SearchFilter = ({ - filters, - onFilterDelete, - deleteAllFilters, - entries = 0 -}) => { - const chipClasses = useChipStyles() - const classes = useStyles() - - return ( - <> -

{'Filters:'}

-
-
- {filters.map((f, idx) => ( - onFilterDelete(f)} - deleteIcon={} - /> - ))} -
-
- { - {`${entries} ${singularOrPlural( - entries, - `entry`, - `entries` - )}`} - } - - Delete filters - -
-
- - ) -} - -export default SearchFilter diff --git a/new-lamassu-admin/src/components/SearchFilter.styles.js b/new-lamassu-admin/src/components/SearchFilter.styles.js deleted file mode 100644 index fd2f8ccb..00000000 --- a/new-lamassu-admin/src/components/SearchFilter.styles.js +++ /dev/null @@ -1,62 +0,0 @@ -import { - primaryColor, - zircon, - smallestFontSize, - inputFontFamily, - inputFontWeight, - spacer, - offColor -} from 'src/styling/variables' - -const chipStyles = { - root: { - marginLeft: 0, - height: 20, - backgroundColor: zircon, - '&:hover, &:focus, &:active': { - backgroundColor: zircon - }, - marginBottom: 'auto' - }, - label: { - fontSize: smallestFontSize, - fontWeight: inputFontWeight, - fontFamily: inputFontFamily, - paddingRight: 0, - paddingLeft: spacer, - color: primaryColor - } -} - -const styles = { - button: { - width: 8, - height: 8, - marginLeft: 8, - marginRight: 8 - }, - text: { - marginTop: 0, - marginBottom: 0 - }, - filters: { - display: 'flex', - marginBottom: 16 - }, - deleteWrapper: { - display: 'flex', - marginLeft: 'auto', - justifyContent: 'flex-end', - flexDirection: 'row' - }, - entries: { - color: offColor, - margin: 'auto', - marginRight: 12 - }, - chips: { - marginTop: 'auto' - } -} - -export { chipStyles, styles } diff --git a/new-lamassu-admin/src/components/Stage.jsx b/new-lamassu-admin/src/components/Stage.jsx deleted file mode 100644 index 0d93080b..00000000 --- a/new-lamassu-admin/src/components/Stage.jsx +++ /dev/null @@ -1,112 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import classnames from 'classnames' -import * as R from 'ramda' -import React, { memo } from 'react' -import CompleteStageIconSpring from 'src/styling/icons/stage/spring/complete.svg?react' -import CurrentStageIconSpring from 'src/styling/icons/stage/spring/current.svg?react' -import EmptyStageIconSpring from 'src/styling/icons/stage/spring/empty.svg?react' -import CompleteStageIconZodiac from 'src/styling/icons/stage/zodiac/complete.svg?react' -import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.svg?react' -import EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react' - -import { - primaryColor, - secondaryColor, - offColor, - disabledColor -} from 'src/styling/variables' - -const styles = { - stages: { - display: 'flex', - alignItems: 'center' - }, - wrapper: { - display: 'flex', - alignItems: 'center', - margin: 0 - }, - stage: { - display: 'flex', - height: 28, - width: 28, - zIndex: 2, - '& > svg': { - height: '100%', - width: '100%', - overflow: 'visible' - } - }, - separator: { - width: 28, - height: 2, - border: [[2, 'solid']], - zIndex: 1 - }, - separatorSpring: { - borderColor: secondaryColor - }, - separatorZodiac: { - borderColor: primaryColor - }, - separatorSpringEmpty: { - borderColor: disabledColor - }, - separatorZodiacEmpty: { - borderColor: offColor - } -} - -const useStyles = makeStyles(styles) - -const Stage = memo(({ stages, currentStage, color = 'spring', className }) => { - if (currentStage < 1 || currentStage > stages) - throw Error('Value of currentStage is invalid') - if (stages < 1) throw Error('Value of stages is invalid') - - const classes = useStyles() - - const separatorClasses = { - [classes.separator]: true, - [classes.separatorSpring]: color === 'spring', - [classes.separatorZodiac]: color === 'zodiac' - } - - const separatorEmptyClasses = { - [classes.separator]: true, - [classes.separatorSpringEmpty]: color === 'spring', - [classes.separatorZodiacEmpty]: color === 'zodiac' - } - - return ( -
- {R.range(1, currentStage).map(idx => ( -
- {idx > 1 &&
} -
- {color === 'spring' && } - {color === 'zodiac' && } -
-
- ))} -
- {currentStage > 1 &&
} -
- {color === 'spring' && } - {color === 'zodiac' && } -
-
- {R.range(currentStage + 1, stages + 1).map(idx => ( -
-
-
- {color === 'spring' && } - {color === 'zodiac' && } -
-
- ))} -
- ) -}) - -export default Stage diff --git a/new-lamassu-admin/src/components/Status.jsx b/new-lamassu-admin/src/components/Status.jsx deleted file mode 100644 index f1d8ff59..00000000 --- a/new-lamassu-admin/src/components/Status.jsx +++ /dev/null @@ -1,74 +0,0 @@ -import Chip from '@material-ui/core/Chip' -import { makeStyles } from '@material-ui/core/styles' -import React from 'react' - -import { - tomato, - mistyRose, - pumpkin, - secondaryColorDarker as spring4, - inputFontWeight, - spring3, - zircon, - primaryColor, - smallestFontSize, - inputFontFamily, - spacer, - linen -} from '../styling/variables' - -const colors = { - error: tomato, - warning: pumpkin, - success: spring4, - neutral: primaryColor -} - -const backgroundColors = { - error: mistyRose, - warning: linen, - success: spring3, - neutral: zircon -} - -const useStyles = makeStyles({ - root: { - borderRadius: spacer / 2, - marginTop: spacer / 2, - marginRight: spacer / 4, - marginBottom: spacer / 2, - marginLeft: spacer / 4, - height: spacer * 3, - backgroundColor: ({ type }) => backgroundColors[type] - }, - label: { - fontSize: smallestFontSize, - fontWeight: inputFontWeight, - fontFamily: inputFontFamily, - paddingRight: spacer / 2, - paddingLeft: spacer / 2, - color: ({ type }) => colors[type] - } -}) - -const Status = ({ status }) => { - const classes = useStyles({ type: status.type }) - return -} - -const MainStatus = ({ statuses }) => { - const mainStatus = - statuses.find(s => s.type === 'error') || - statuses.find(s => s.type === 'warning') || - statuses[0] - const plus = { label: `+${statuses.length - 1}`, type: mainStatus.type } - - return ( -
- - {statuses.length > 1 && } -
- ) -} - -export { Status, MainStatus } diff --git a/new-lamassu-admin/src/components/Stepper.jsx b/new-lamassu-admin/src/components/Stepper.jsx deleted file mode 100644 index f827ff4b..00000000 --- a/new-lamassu-admin/src/components/Stepper.jsx +++ /dev/null @@ -1,112 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import classnames from 'classnames' -import * as R from 'ramda' -import React, { memo } from 'react' -import CompleteStageIconSpring from 'src/styling/icons/stage/spring/complete.svg?react' -import CurrentStageIconSpring from 'src/styling/icons/stage/spring/current.svg?react' -import EmptyStageIconSpring from 'src/styling/icons/stage/spring/empty.svg?react' -import CompleteStageIconZodiac from 'src/styling/icons/stage/zodiac/complete.svg?react' -import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.svg?react' -import EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react' - -import { - primaryColor, - secondaryColor, - offColor, - disabledColor -} from 'src/styling/variables' - -const styles = { - stages: { - display: 'flex', - alignItems: 'center' - }, - wrapper: { - display: 'flex', - alignItems: 'center', - margin: 0 - }, - stage: { - display: 'flex', - height: 28, - width: 28, - zIndex: 2, - '& > svg': { - height: '100%', - width: '100%', - overflow: 'visible' - } - }, - separator: { - width: 28, - height: 2, - border: [[2, 'solid']], - zIndex: 1 - }, - separatorSpring: { - borderColor: secondaryColor - }, - separatorZodiac: { - borderColor: primaryColor - }, - separatorSpringEmpty: { - borderColor: disabledColor - }, - separatorZodiacEmpty: { - borderColor: offColor - } -} - -const useStyles = makeStyles(styles) - -const Stepper = memo(({ steps, currentStep, color = 'spring', className }) => { - if (currentStep < 1 || currentStep > steps) - throw Error('Value of currentStage is invalid') - if (steps < 1) throw Error('Value of stages is invalid') - - const classes = useStyles() - - const separatorClasses = { - [classes.separator]: true, - [classes.separatorSpring]: color === 'spring', - [classes.separatorZodiac]: color === 'zodiac' - } - - const separatorEmptyClasses = { - [classes.separator]: true, - [classes.separatorSpringEmpty]: color === 'spring', - [classes.separatorZodiacEmpty]: color === 'zodiac' - } - - return ( -
- {R.range(1, currentStep).map(idx => ( -
- {idx > 1 &&
} -
- {color === 'spring' && } - {color === 'zodiac' && } -
-
- ))} -
- {currentStep > 1 &&
} -
- {color === 'spring' && } - {color === 'zodiac' && } -
-
- {R.range(currentStep + 1, steps + 1).map(idx => ( -
-
-
- {color === 'spring' && } - {color === 'zodiac' && } -
-
- ))} -
- ) -}) - -export default Stepper diff --git a/new-lamassu-admin/src/components/Subtitle.jsx b/new-lamassu-admin/src/components/Subtitle.jsx deleted file mode 100644 index 89a12a6d..00000000 --- a/new-lamassu-admin/src/components/Subtitle.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' - -import { spacer, offColor } from 'src/styling/variables' - -import { TL1 } from './typography' - -const useStyles = makeStyles({ - subtitle: { - color: offColor, - marginTop: spacer * 2, - marginBottom: spacer * 2 - }, - extraMarginTop: { - marginTop: spacer * 9 - } -}) - -const Subtitle = memo(({ children, className, extraMarginTop }) => { - const classes = useStyles() - const classNames = { - [classes.subtitle]: true, - [classes.extraMarginTop]: extraMarginTop - } - - return {children} -}) - -export default Subtitle diff --git a/new-lamassu-admin/src/components/TableLabel.jsx b/new-lamassu-admin/src/components/TableLabel.jsx deleted file mode 100644 index a0b8815b..00000000 --- a/new-lamassu-admin/src/components/TableLabel.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import { makeStyles } from '@material-ui/styles' -import classnames from 'classnames' -import React from 'react' - -import { Label1 } from './typography' - -const useStyles = makeStyles({ - wrapper: { - display: 'flex', - alignItems: 'center' - }, - colorIndicator: { - borderRadius: 3, - height: 12, - width: 12, - marginRight: 8 - } -}) - -const TableLabel = ({ className, label, color, ...props }) => { - const classes = useStyles() - return ( -
- {color && ( -
- )} - {label} -
- ) -} - -export default TableLabel diff --git a/new-lamassu-admin/src/components/Title.jsx b/new-lamassu-admin/src/components/Title.jsx deleted file mode 100644 index be96227b..00000000 --- a/new-lamassu-admin/src/components/Title.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import React, { memo } from 'react' - -import { spacer } from 'src/styling/variables' - -import { H1 } from './typography' - -const useStyles = makeStyles({ - title: { - marginTop: spacer * 3, - marginBottom: spacer * 3 - } -}) - -const Title = memo(({ children }) => { - const classes = useStyles() - return

{children}

-}) - -export default Title diff --git a/new-lamassu-admin/src/components/Uptime.jsx b/new-lamassu-admin/src/components/Uptime.jsx deleted file mode 100644 index d91848de..00000000 --- a/new-lamassu-admin/src/components/Uptime.jsx +++ /dev/null @@ -1,93 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import Chip from '@material-ui/core/Chip' -import * as R from 'ramda' -import React from 'react' - -import { - secondaryColorLighter, - secondaryColorDarker, - offErrorColor, - errorColor, - offColor, - inputFontWeight, - smallestFontSize, - inputFontFamily, - spacer -} from 'src/styling/variables' -import { onlyFirstToUpper } from 'src/utils/string' - -import typographyStyles from './typography/styles' -const { label1 } = typographyStyles - -const colors = { - running: secondaryColorDarker, - notRunning: offErrorColor -} - -const backgroundColors = { - running: secondaryColorLighter, - notRunning: errorColor -} - -const styles = { - uptimeContainer: { - display: 'inline-block', - minWidth: 104, - margin: [[0, 20]] - }, - name: { - extend: label1, - paddingLeft: 4, - color: offColor - } -} - -const useStyles = makeStyles(styles) - -const useChipStyles = makeStyles({ - root: { - borderRadius: spacer / 2, - marginTop: spacer / 2, - marginRight: spacer / 4, - marginBottom: spacer / 2, - marginLeft: spacer / 4, - height: spacer * 3, - backgroundColor: ({ type }) => backgroundColors[type] - }, - label: { - fontSize: smallestFontSize, - fontWeight: inputFontWeight, - fontFamily: inputFontFamily, - padding: [[spacer / 2, spacer]], - color: ({ type }) => colors[type] - } -}) - -const Uptime = ({ process, ...props }) => { - const classes = useStyles() - - const uptime = time => { - if (time < 60) return `${time}s` - if (time < 3600) return `${Math.floor(time / 60)}m` - if (time < 86400) return `${Math.floor(time / 60 / 60)}h` - return `${Math.floor(time / 60 / 60 / 24)}d` - } - - return ( -
-
{R.toLower(process.name)}
- -
- ) -} - -export default Uptime diff --git a/new-lamassu-admin/src/components/booleanPropertiesTable/BooleanPropertiesTable.styles.js b/new-lamassu-admin/src/components/booleanPropertiesTable/BooleanPropertiesTable.styles.js deleted file mode 100644 index f6a5c1b9..00000000 --- a/new-lamassu-admin/src/components/booleanPropertiesTable/BooleanPropertiesTable.styles.js +++ /dev/null @@ -1,74 +0,0 @@ -import baseStyles from 'src/pages/Logs.styles' -import { backgroundColor, zircon } from 'src/styling/variables' - -const { fillColumn } = baseStyles - -const booleanPropertiesTableStyles = { - booleanPropertiesTableWrapper: { - display: 'flex', - flexDirection: 'column', - width: 396 - }, - tableRow: { - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - '&:nth-child(even)': { - backgroundColor: backgroundColor - }, - '&:nth-child(odd)': { - backgroundColor: zircon - }, - minHeight: 32, - height: 'auto', - padding: [[8, 16, 8, 24]], - boxShadow: '0 0 0 0 rgba(0, 0, 0, 0)' - }, - leftTableCell: { - display: 'flex', - alignItems: 'center', - justifyContent: 'left', - width: 200, - padding: [0] - }, - rightTableCell: { - display: 'flex', - alignItems: 'center', - justifyContent: 'right', - padding: [0] - }, - transparentButton: { - '& > *': { - margin: 'auto 12px' - }, - '& button': { - border: 'none', - backgroundColor: 'transparent', - cursor: 'pointer' - } - }, - rowWrapper: { - display: 'flex', - alignItems: 'center', - position: 'relative', - flex: 'wrap' - }, - rightAligned: { - marginLeft: 'auto' - }, - radioButtons: { - display: 'flex', - flexDirection: 'row', - margin: [-15] - }, - rightLink: { - marginLeft: '20px' - }, - fillColumn, - popoverContent: { - width: 272, - padding: [[10, 15]] - } -} - -export { booleanPropertiesTableStyles } diff --git a/new-lamassu-admin/src/components/buttons/ActionButton.jsx b/new-lamassu-admin/src/components/buttons/ActionButton.jsx deleted file mode 100644 index 02d7d107..00000000 --- a/new-lamassu-admin/src/components/buttons/ActionButton.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' - -import styles from './ActionButton.styles' - -const useStyles = makeStyles(styles) - -const ActionButton = memo( - ({ className, Icon, InverseIcon, color, children, ...props }) => { - const classes = useStyles() - const classNames = { - [classes.actionButton]: true, - [classes.primary]: color === 'primary', - [classes.secondary]: color === 'secondary', - [classes.spring]: color === 'spring', - [classes.tomato]: color === 'tomato' - } - - return ( - - ) - } -) - -export default ActionButton diff --git a/new-lamassu-admin/src/components/buttons/ActionButton.styles.js b/new-lamassu-admin/src/components/buttons/ActionButton.styles.js deleted file mode 100644 index f924347a..00000000 --- a/new-lamassu-admin/src/components/buttons/ActionButton.styles.js +++ /dev/null @@ -1,123 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { - white, - subheaderColor, - subheaderDarkColor, - offColor, - offDarkColor, - offDarkerColor, - secondaryColor, - secondaryColorDark, - secondaryColorDarker, - errorColor, - errorColorDark, - errorColorDarker -} from 'src/styling/variables' - -const { p } = typographyStyles - -const colors = (color1, color2, color3) => { - return { - backgroundColor: color1, - '&:hover': { - backgroundColor: color2 - }, - '&:active': { - backgroundColor: color3 - } - } -} - -export default { - actionButton: { - extend: p, - cursor: 'pointer', - border: 'none', - height: 28, - outline: 0, - borderRadius: 6, - padding: '0 8px', - display: 'flex', - alignItems: 'center' - }, - primary: { - extend: colors(subheaderColor, subheaderDarkColor, offColor), - '&:active': { - color: white, - '& $actionButtonIcon': { - display: 'none' - }, - '& $actionButtonIconActive': { - display: 'flex' - } - }, - '& $actionButtonIconActive': { - display: 'none' - } - }, - secondary: { - extend: colors(offColor, offDarkColor, offDarkerColor), - color: white, - '&:active': { - '& $actionButtonIcon': { - display: 'flex' - }, - '& $actionButtonIconActive': { - display: 'none' - } - }, - '& $actionButtonIcon': { - display: 'none' - }, - '& $actionButtonIconActive': { - display: 'flex' - } - }, - spring: { - extend: colors(secondaryColorDark, secondaryColor, secondaryColorDarker), - color: white, - '&:active': { - '& $actionButtonIcon': { - display: 'flex' - }, - '& $actionButtonIconActive': { - display: 'none' - } - }, - '& $actionButtonIcon': { - display: 'none' - }, - '& $actionButtonIconActive': { - display: 'flex' - } - }, - tomato: { - extend: colors(errorColorDark, errorColor, errorColorDarker), - color: white, - '&:active': { - '& $actionButtonIcon': { - display: 'flex' - }, - '& $actionButtonIconActive': { - display: 'none' - } - }, - '& $actionButtonIcon': { - display: 'none' - }, - '& $actionButtonIconActive': { - display: 'flex' - } - }, - actionButtonIcon: { - display: 'flex', - paddingRight: 7, - '@global': { - svg: { - width: 14, - height: 14 - } - } - }, - actionButtonIconActive: {} -} diff --git a/new-lamassu-admin/src/components/buttons/AddButton.jsx b/new-lamassu-admin/src/components/buttons/AddButton.jsx deleted file mode 100644 index 267ebaee..00000000 --- a/new-lamassu-admin/src/components/buttons/AddButton.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' -import AddIcon from 'src/styling/icons/button/add/zodiac.svg?react' - -import typographyStyles from 'src/components/typography/styles' -import { zircon, zircon2, comet, fontColor, white } from 'src/styling/variables' - -const { p } = typographyStyles - -const styles = { - button: { - extend: p, - border: 'none', - backgroundColor: zircon, - cursor: 'pointer', - outline: 0, - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - width: 167, - height: 48, - color: fontColor, - '&:hover': { - backgroundColor: zircon2 - }, - '&:active': { - backgroundColor: comet, - color: white, - '& svg g *': { - stroke: white - } - }, - '& svg': { - marginRight: 8 - } - } -} - -const useStyles = makeStyles(styles) - -const SimpleButton = memo(({ className, children, ...props }) => { - const classes = useStyles() - - return ( - - ) -}) - -export default SimpleButton diff --git a/new-lamassu-admin/src/components/buttons/Button.jsx b/new-lamassu-admin/src/components/buttons/Button.jsx deleted file mode 100644 index 5945170a..00000000 --- a/new-lamassu-admin/src/components/buttons/Button.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' - -import styles from './Button.styles' - -const useStyles = makeStyles(styles) - -const ActionButton = memo( - ({ - size = 'lg', - children, - className, - buttonClassName, - backgroundColor, - ...props - }) => { - const classes = useStyles({ size, backgroundColor }) - return ( -
- -
- ) - } -) - -export default ActionButton diff --git a/new-lamassu-admin/src/components/buttons/Button.styles.js b/new-lamassu-admin/src/components/buttons/Button.styles.js deleted file mode 100644 index 157c37a1..00000000 --- a/new-lamassu-admin/src/components/buttons/Button.styles.js +++ /dev/null @@ -1,79 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { - white, - disabledColor, - secondaryColor, - secondaryColorDark, - secondaryColorDarker, - offColor, - offDarkColor, - offDarkerColor, - spacer -} from 'src/styling/variables' - -const { h1, h3 } = typographyStyles - -const pickSize = size => { - switch (size) { - case 'xl': - return spacer * 7.625 - case 'sm': - return spacer * 4 - case 'lg': - default: - return spacer * 5 - } -} - -export default { - wrapper: ({ size }) => { - const height = pickSize(size) - const shadowSize = height / 12 - return { height: height + shadowSize / 2 } - }, - button: ({ size, backgroundColor }) => { - const height = pickSize(size) - const shadowSize = size === 'xl' ? 3 : height / 12 - const padding = size === 'xl' ? 20 : height / 2 - const isGrey = backgroundColor === 'grey' - - return { - extend: size === 'xl' ? h1 : h3, - border: 'none', - color: white, - cursor: 'pointer', - fontWeight: 900, - outline: 0, - backgroundColor: isGrey ? offDarkColor : secondaryColor, - '&:disabled': { - backgroundColor: disabledColor, - boxShadow: 'none', - '&:hover': { - backgroundColor: disabledColor, - boxShadow: 'none' - }, - '&:active': { - marginTop: 0 - } - }, - shadowSize, - height, - padding: `0 ${padding}px`, - borderRadius: height / 4, - boxShadow: `0 ${shadowSize}px ${isGrey ? offColor : secondaryColorDark}`, - '&:hover': { - backgroundColor: isGrey ? offColor : secondaryColorDark, - boxShadow: `0 ${shadowSize}px ${ - isGrey ? offDarkerColor : secondaryColorDarker - }` - }, - '&:active': { - marginTop: shadowSize / 2, - backgroundColor: isGrey ? offDarkColor : secondaryColorDark, - boxShadow: `0 ${shadowSize / 2}px ${ - isGrey ? offDarkerColor : secondaryColorDarker - }` - } - } - } -} diff --git a/new-lamassu-admin/src/components/buttons/DeleteButton.jsx b/new-lamassu-admin/src/components/buttons/DeleteButton.jsx deleted file mode 100644 index 4be8a651..00000000 --- a/new-lamassu-admin/src/components/buttons/DeleteButton.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' -import DeleteIcon from 'src/styling/icons/button/cancel/zodiac.svg?react' - -import typographyStyles from 'src/components/typography/styles' -import { zircon, zircon2, comet, fontColor, white } from 'src/styling/variables' - -const { p } = typographyStyles - -const styles = { - button: { - extend: p, - border: 'none', - backgroundColor: zircon, - cursor: 'pointer', - outline: 0, - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - width: 167, - height: 48, - color: fontColor, - '&:hover': { - backgroundColor: zircon2 - }, - '&:active': { - backgroundColor: comet, - color: white, - '& svg g *': { - stroke: white - } - }, - '& svg': { - marginRight: 8 - } - } -} - -const useStyles = makeStyles(styles) - -const SimpleButton = memo(({ className, children, ...props }) => { - const classes = useStyles() - - return ( - - ) -}) - -export default SimpleButton diff --git a/new-lamassu-admin/src/components/buttons/FeatureButton.jsx b/new-lamassu-admin/src/components/buttons/FeatureButton.jsx deleted file mode 100644 index 3fe97cd7..00000000 --- a/new-lamassu-admin/src/components/buttons/FeatureButton.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' - -import baseButtonStyles from './BaseButton.styles' - -const { baseButton, primary } = baseButtonStyles - -const styles = { - featureButton: { - extend: baseButton, - width: baseButton.height, - borderRadius: baseButton.height / 2, - display: 'flex', - padding: 0 - }, - primary, - buttonIcon: { - margin: 'auto', - '& svg': { - width: 16, - height: 16, - overflow: 'visible', - '& g': { - strokeWidth: 1.8 - } - } - }, - buttonIconActive: {} // required to extend primary -} - -const useStyles = makeStyles(styles) - -const FeatureButton = memo( - ({ className, Icon, InverseIcon, children, ...props }) => { - const classes = useStyles() - - const classNames = { - [classes.featureButton]: true, - [classes.primary]: true - } - - return ( - - ) - } -) - -export default FeatureButton diff --git a/new-lamassu-admin/src/components/buttons/IconButton.jsx b/new-lamassu-admin/src/components/buttons/IconButton.jsx deleted file mode 100644 index f208c25f..00000000 --- a/new-lamassu-admin/src/components/buttons/IconButton.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import { makeStyles, IconButton as IconB } from '@material-ui/core' -import React from 'react' - -import { comet } from 'src/styling/variables' - -const styles = { - label: ({ size }) => ({ - width: size, - height: size - }), - root: { - '& svg': { - flex: 1 - }, - '&:hover': { - backgroundColor: 'inherit' - }, - '&:hover rect': { - stroke: comet - }, - '&:hover polygon': { - stroke: comet - }, - '&:hover path': { - stroke: comet - } - } -} - -const useStyles = makeStyles(styles) - -const IconButton = ({ size, children, onClick, ...props }) => { - const classes = useStyles({ size }) - return ( - - {children} - - ) -} - -export default IconButton diff --git a/new-lamassu-admin/src/components/buttons/Link.styles.js b/new-lamassu-admin/src/components/buttons/Link.styles.js deleted file mode 100644 index 0d05e9c1..00000000 --- a/new-lamassu-admin/src/components/buttons/Link.styles.js +++ /dev/null @@ -1,47 +0,0 @@ -import { alpha } from '@material-ui/core/styles/colorManipulator' - -import typographyStyles from 'src/components/typography/styles' -import { - white, - linkPrimaryColor, - linkSecondaryColor, - zircon -} from 'src/styling/variables' - -const { h4 } = typographyStyles - -const color = color => ({ - boxShadow: `inset 0 -4px 0 0 ${alpha(color, 0.8)}`, - '&:hover': { - boxShadow: 'none', - backgroundColor: alpha(color, 0.8) - } -}) - -export default { - link: { - extend: h4, - textDecoration: 'none', - border: 'none', - backgroundColor: 'transparent', - cursor: 'pointer', - padding: '0', - height: '100%' - }, - primary: { - extend: color(linkPrimaryColor) - }, - secondary: { - extend: color(linkSecondaryColor), - '&:hover': { - color: white - } - }, - noColor: { - extend: color(white) - }, - action: { - extend: color(linkPrimaryColor), - color: zircon - } -} diff --git a/new-lamassu-admin/src/components/buttons/SupportLinkButton.jsx b/new-lamassu-admin/src/components/buttons/SupportLinkButton.jsx deleted file mode 100644 index 12329fd3..00000000 --- a/new-lamassu-admin/src/components/buttons/SupportLinkButton.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import React from 'react' -import InverseLinkIcon from 'src/styling/icons/action/external link/white.svg?react' -import LinkIcon from 'src/styling/icons/action/external link/zodiac.svg?react' - -import { ActionButton } from 'src/components/buttons' -import { spacer, primaryColor } from 'src/styling/variables' - -const useStyles = makeStyles({ - actionButton: { - marginBottom: spacer * 4 - }, - actionButtonLink: { - textDecoration: 'none', - color: primaryColor - } -}) - -const SupportLinkButton = ({ link, label }) => { - const classes = useStyles() - return ( - - - {label} - - - ) -} - -export default SupportLinkButton diff --git a/new-lamassu-admin/src/components/date-range-picker/Tile.jsx b/new-lamassu-admin/src/components/date-range-picker/Tile.jsx deleted file mode 100644 index 228d806f..00000000 --- a/new-lamassu-admin/src/components/date-range-picker/Tile.jsx +++ /dev/null @@ -1,102 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React from 'react' - -import typographyStyles from 'src/components/typography/styles' -import { - primaryColor, - spring2, - spring3, - disabledColor -} from 'src/styling/variables' - -const { label1 } = typographyStyles - -const styles = { - wrapper: { - height: 26, - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - position: 'relative', - overflow: 'hidden' - }, - button: { - outline: 'none', - extend: label1, - border: 'none', - cursor: 'pointer', - backgroundColor: 'transparent', - color: primaryColor, - zIndex: 2 - }, - lowerBound: { - left: '50%' - }, - upperBound: { - right: '50%' - }, - selected: { - width: 26, - height: 26, - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - backgroundColor: spring2, - borderRadius: '50%', - position: 'absolute', - zIndex: 1 - }, - between: { - position: 'absolute', - width: '100%', - height: '100%', - zIndex: 0, - backgroundColor: spring3 - }, - disabled: { - color: disabledColor, - cursor: 'default' - } -} - -const useStyles = makeStyles(styles) - -const Tile = ({ - isLowerBound, - isUpperBound, - isBetween, - isDisabled, - children, - ...props -}) => { - const classes = useStyles() - const selected = isLowerBound || isUpperBound - - const rangeClasses = { - [classes.between]: isBetween && !(isLowerBound && isUpperBound), - [classes.lowerBound]: isLowerBound && !isUpperBound, - [classes.upperBound]: isUpperBound && !isLowerBound - } - - const buttonWrapperClasses = { - [classes.wrapper]: true, - [classes.selected]: selected - } - - const buttonClasses = { - [classes.button]: true, - [classes.disabled]: isDisabled - } - - return ( -
-
-
- -
-
- ) -} - -export default Tile diff --git a/new-lamassu-admin/src/components/editableProperty/EditableProperty.jsx b/new-lamassu-admin/src/components/editableProperty/EditableProperty.jsx deleted file mode 100644 index 28852792..00000000 --- a/new-lamassu-admin/src/components/editableProperty/EditableProperty.jsx +++ /dev/null @@ -1,74 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import React, { useState, memo } from 'react' -import { H4, P } from 'src/components/typography' -import EditIconDisabled from 'src/styling/icons/action/edit/disabled.svg?react' -import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react' - -import { Link } from 'src/components/buttons' -import { RadioGroup } from 'src/components/inputs' - -import { editablePropertyStyles } from './EditableProperty.styles' - -const useStyles = makeStyles(editablePropertyStyles) - -const EditableProperty = memo( - ({ title, prefixText, disabled, options, code, save }) => { - const [editing, setEditing] = useState(false) - const [currentCode, setCurrentCode] = useState(code) - - const classes = useStyles() - - const innerSave = () => { - save(currentCode) - setEditing(false) - } - - const innerCancel = () => setEditing(false) - - return ( - <> -
-

{title}

- {editing ? ( -
- - Cancel - - - Save - -
- ) : ( -
- -
- )} -
- {editing ? ( - setCurrentCode(event.target.value)} - className={classes.radioButtons} - /> - ) : ( -

- {`${prefixText} ${options - .find(it => it.code === currentCode) - .display.toLowerCase()}`} -

- )} - - ) - } -) - -export default EditableProperty diff --git a/new-lamassu-admin/src/components/editableProperty/EditableProperty.styles.js b/new-lamassu-admin/src/components/editableProperty/EditableProperty.styles.js deleted file mode 100644 index 91ebb25b..00000000 --- a/new-lamassu-admin/src/components/editableProperty/EditableProperty.styles.js +++ /dev/null @@ -1,36 +0,0 @@ -const optionsRowHeigth = 43 - -const editablePropertyStyles = { - transparentButton: { - '& > *': { - margin: 'auto 12px' - }, - '& button': { - border: 'none', - backgroundColor: 'transparent', - cursor: 'pointer' - } - }, - rowWrapper: { - display: 'flex', - alignItems: 'center', - position: 'relative', - flex: 'wrap', - height: optionsRowHeigth - }, - rightAligned: { - display: 'flex', - position: 'absolute', - right: 0 - }, - radioButtons: { - display: 'flex', - flexDirection: 'row', - height: optionsRowHeigth - }, - leftSpace: { - marginLeft: '20px' - } -} - -export { editablePropertyStyles } diff --git a/new-lamassu-admin/src/components/editableProperty/index.js b/new-lamassu-admin/src/components/editableProperty/index.js deleted file mode 100644 index 00091dd2..00000000 --- a/new-lamassu-admin/src/components/editableProperty/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import EditableProperty from './EditableProperty' - -export { EditableProperty } diff --git a/new-lamassu-admin/src/components/editableTable/Row.styles.js b/new-lamassu-admin/src/components/editableTable/Row.styles.js deleted file mode 100644 index 48c7a8f4..00000000 --- a/new-lamassu-admin/src/components/editableTable/Row.styles.js +++ /dev/null @@ -1,45 +0,0 @@ -import { bySize, bold } from 'src/styling/helpers' - -export default { - saveButton: { - marginRight: 20 - }, - lastOfGroup: { - marginBottom: 24 - }, - extraPadding: { - paddingLeft: 35, - paddingRight: 30 - }, - extraPaddingRight: { - paddingRight: 39 - }, - withSuffix: ({ textAlign }) => { - const justifyContent = textAlign === 'right' ? 'flex-end' : textAlign - return { - display: 'flex', - alignItems: 'center', - justifyContent - } - }, - suffix: { - margin: [[0, 0, 0, 7]] - }, - withPrefix: ({ textAlign }) => { - const justifyContent = textAlign === 'right' ? 'flex-end' : textAlign - return { - display: 'flex', - alignItems: 'center', - justifyContent - } - }, - prefix: { - margin: [[0, 7, 0, 0]] - }, - size: ({ size }) => bySize(size), - bold, - fields: { - display: 'flex', - flexDirection: 'column' - } -} diff --git a/new-lamassu-admin/src/components/editableTable/Table.styles.js b/new-lamassu-admin/src/components/editableTable/Table.styles.js deleted file mode 100644 index 00f93bd6..00000000 --- a/new-lamassu-admin/src/components/editableTable/Table.styles.js +++ /dev/null @@ -1,21 +0,0 @@ -import { offColor } from 'src/styling/variables' - -export default { - wrapper: ({ width }) => ({ - width: width - }), - addLink: { - marginLeft: 'auto' - }, - title: { - margin: 0, - color: offColor - }, - outerHeader: { - minHeight: 16, - marginBottom: 24, - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center' - } -} diff --git a/new-lamassu-admin/src/components/fake-table/Table.jsx b/new-lamassu-admin/src/components/fake-table/Table.jsx deleted file mode 100644 index 5b6acaa7..00000000 --- a/new-lamassu-admin/src/components/fake-table/Table.jsx +++ /dev/null @@ -1,133 +0,0 @@ -import Card from '@material-ui/core/Card' -import CardContent from '@material-ui/core/CardContent' -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React from 'react' - -import { Link } from 'src/components/buttons' - -import styles from './Table.styles' - -const useStyles = makeStyles(styles) - -const Table = ({ children, className, ...props }) => ( -
- {children} -
-) - -const THead = ({ children, className }) => { - const classes = useStyles() - return
{children}
-} - -const TDoubleLevelHead = ({ children, className }) => { - const classes = useStyles() - - return ( -
- {children} -
- ) -} - -const TBody = ({ children, className }) => { - return
{children}
-} - -const Td = ({ - children, - header, - className, - width = 100, - size, - bold, - textAlign, - action -}) => { - const classes = useStyles({ textAlign, width, size }) - const classNames = { - [classes.td]: true, - [classes.tdHeader]: header, - [classes.actionCol]: action, - [classes.size]: !header, - [classes.bold]: !header && bold - } - return
{children}
-} - -const Th = ({ children, ...props }) => { - return ( - - {children} - - ) -} - -const ThDoubleLevel = ({ title, children, className, width }) => { - const classes = useStyles({ width }) - - return ( -
-
{title}
-
{children}
-
- ) -} - -const Tr = ({ - onClick, - error, - errorMessage, - shouldShowError, - children, - className, - size, - newRow -}) => { - const classes = useStyles({ size }) - const cardClasses = { root: classes.cardContentRoot } - const classNames = { - [classes.tr]: true, - [classes.trError]: error, - [classes.card]: true, - [classes.trAdding]: newRow, - className - } - - return ( - <> - - -
{children}
- {error && shouldShowError && ( -
{errorMessage}
- )} -
-
- - ) -} - -const EditCell = ({ save, cancel }) => ( - - - Cancel - - - Save - - -) - -export { - Table, - THead, - TDoubleLevelHead, - TBody, - Tr, - Td, - Th, - ThDoubleLevel, - EditCell -} diff --git a/new-lamassu-admin/src/components/fake-table/Table.styles.js b/new-lamassu-admin/src/components/fake-table/Table.styles.js deleted file mode 100644 index 00586996..00000000 --- a/new-lamassu-admin/src/components/fake-table/Table.styles.js +++ /dev/null @@ -1,114 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { bySize, bold } from 'src/styling/helpers' -import { - tableHeaderColor, - tableHeaderHeight, - tableErrorColor, - tableSuccessColor, - spacer, - white, - tableDoubleHeaderHeight, - offColor, - errorColor -} from 'src/styling/variables' - -const { tl2, p, label1 } = typographyStyles - -export default { - size: ({ size }) => bySize(size), - bold, - header: { - extend: tl2, - backgroundColor: tableHeaderColor, - height: tableHeaderHeight, - textAlign: 'left', - color: white, - display: 'flex', - alignItems: 'center' - }, - doubleHeader: { - extend: tl2, - backgroundColor: tableHeaderColor, - height: tableDoubleHeaderHeight, - color: white, - display: 'table-row' - }, - thDoubleLevel: ({ width }) => ({ - width, - display: 'table-cell', - '& > :first-child': { - margin: [[0, 10]], - extend: label1, - fontWeight: 700, - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - backgroundColor: offColor, - color: white, - borderRadius: [[0, 0, 8, 8]], - height: 28 - }, - '& > :last-child': { - padding: [[0, 11]], - display: 'table-cell', - verticalAlign: 'middle', - height: tableDoubleHeaderHeight - 28 - } - }), - cellDoubleLevel: { - display: 'flex', - padding: [[0, spacer * 2]] - }, - td: ({ textAlign, width }) => ({ - width, - padding: [[1, spacer * 3, 0, spacer * 3]], - textAlign - }), - tdHeader: { - verticalAlign: 'middle', - display: 'table-cell', - padding: [[0, spacer * 3]] - }, - trError: { - backgroundColor: tableErrorColor - }, - trAdding: { - backgroundColor: tableSuccessColor - }, - mainContent: ({ size }) => { - const sizes = { - sm: 34, - lg: 68 - } - const minHeight = sizes[size] || 48 - return { - display: 'flex', - alignItems: 'center', - minHeight - } - }, - // mui-overrides - cardContentRoot: { - margin: 0, - padding: 0, - '&:last-child': { - padding: 0 - } - }, - card: { - extend: p, - '&:before': { - height: 0 - }, - margin: [[4, 0, 0, 0]], - width: '100%', - boxShadow: [[0, 0, 4, 0, 'rgba(0, 0, 0, 0.08)']] - }, - actionCol: { - marginLeft: 'auto' - }, - errorContent: { - padding: [[12, 0, 12, 24]], - color: errorColor - } -} diff --git a/new-lamassu-admin/src/components/inputs/base/Checkbox.jsx b/new-lamassu-admin/src/components/inputs/base/Checkbox.jsx deleted file mode 100644 index c70cc699..00000000 --- a/new-lamassu-admin/src/components/inputs/base/Checkbox.jsx +++ /dev/null @@ -1,82 +0,0 @@ -import Checkbox from '@material-ui/core/Checkbox' -import { makeStyles } from '@material-ui/core/styles' -import CheckBoxIcon from '@material-ui/icons/CheckBox' -import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank' -import React from 'react' -import { Label2, Info3 } from 'src/components/typography' -import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react' - -import { - fontSize2, - fontSize3, - secondaryColor, - offColor -} from 'src/styling/variables' - -const useStyles = makeStyles({ - root: { - color: secondaryColor, - '&$checked': { - color: secondaryColor - } - }, - checked: {}, - checkBoxLabel: { - display: 'flex' - }, - wrapper: { - display: 'flex', - alignItems: 'center', - '& > svg': { - marginRight: 10 - } - }, - message: { - display: 'flex', - alignItems: 'center', - color: offColor, - margin: 0, - whiteSpace: 'break-spaces' - } -}) - -const CheckboxInput = ({ name, onChange, value, settings, ...props }) => { - const { enabled, label, disabledMessage, rightSideLabel } = settings - const classes = useStyles() - - return ( - <> - {enabled ? ( -
- {!rightSideLabel && {label}} - - } - checkedIcon={} - disableRipple - {...props} - /> - {rightSideLabel && {label}} -
- ) : ( -
- - {disabledMessage} -
- )} - - ) -} - -export default CheckboxInput diff --git a/new-lamassu-admin/src/components/inputs/base/CodeInput.jsx b/new-lamassu-admin/src/components/inputs/base/CodeInput.jsx deleted file mode 100644 index a2d0f09d..00000000 --- a/new-lamassu-admin/src/components/inputs/base/CodeInput.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import classnames from 'classnames' -import React from 'react' -import OtpInput from 'react-otp-input' - -import typographyStyles from 'src/components/typography/styles' - -import styles from './CodeInput.styles' - -const useStyles = makeStyles(styles) -const useTypographyStyles = makeStyles(typographyStyles) - -const CodeInput = ({ - name, - value, - onChange, - numInputs, - error, - inputStyle, - containerStyle, - ...props -}) => { - const classes = useStyles() - const typographyClasses = useTypographyStyles() - - return ( - } - containerStyle={classnames(containerStyle, classes.container)} - inputStyle={classnames( - inputStyle, - classes.input, - typographyClasses.confirmationCode - )} - focusStyle={classes.focus} - errorStyle={classes.error} - hasErrored={error} - isInputNum={true} - {...props} - /> - ) -} - -export default CodeInput diff --git a/new-lamassu-admin/src/components/inputs/base/CodeInput.styles.js b/new-lamassu-admin/src/components/inputs/base/CodeInput.styles.js deleted file mode 100644 index 0f0bba93..00000000 --- a/new-lamassu-admin/src/components/inputs/base/CodeInput.styles.js +++ /dev/null @@ -1,27 +0,0 @@ -import { primaryColor, zircon, errorColor } from 'src/styling/variables' - -const styles = { - input: { - width: '3.5rem !important', - height: '5rem', - border: '2px solid', - borderColor: zircon, - borderRadius: '4px' - }, - focus: { - border: '2px solid', - borderColor: primaryColor, - borderRadius: '4px', - '&:focus': { - outline: 'none' - } - }, - error: { - borderColor: errorColor - }, - container: { - justifyContent: 'space-evenly' - } -} - -export default styles diff --git a/new-lamassu-admin/src/components/inputs/base/Select.styles.js b/new-lamassu-admin/src/components/inputs/base/Select.styles.js deleted file mode 100644 index aebce882..00000000 --- a/new-lamassu-admin/src/components/inputs/base/Select.styles.js +++ /dev/null @@ -1,96 +0,0 @@ -import { subheaderColor, offColor, white } from '../../../styling/variables' -import typographyStyles from '../../typography/styles' - -const { p, label1 } = typographyStyles - -const WIDTH = 152 - -export default { - selectedItem: { - width: WIDTH - 41, - display: 'block', - whiteSpace: 'nowrap', - overflow: 'hidden' - }, - select: { - width: WIDTH, - zIndex: 1, - '& label': { - extend: label1, - color: offColor, - paddingLeft: 10 - }, - '& button': { - extend: p, - position: 'relative', - border: 0, - backgroundColor: subheaderColor, - width: WIDTH, - padding: [[6, 0, 6, 12]], - borderRadius: 20, - lineHeight: '1.14', - textAlign: 'left', - color: offColor, - cursor: 'pointer', - outline: '0 none' - }, - '& ul': { - maxHeight: '200px', - width: WIDTH, - overflowY: 'auto', - position: 'absolute', - margin: 0, - borderTop: 0, - padding: 0, - borderRadius: [[0, 0, 8, 8]], - backgroundColor: subheaderColor, - outline: '0 none', - '& li': { - extend: p, - listStyleType: 'none', - padding: [[6, 12]], - cursor: 'pointer', - '& span': { - width: '100%', - display: 'block', - overflow: 'hidden', - whiteSpace: 'nowrap' - } - }, - '& li:hover': { - backgroundColor: offColor, - color: white - } - }, - '& svg': { - position: 'absolute', - top: 12, - right: 14, - fill: offColor - } - }, - selectFiltered: { - '& button': { - backgroundColor: offColor, - color: white - }, - '& ul': { - '& li': { - backgroundColor: offColor, - color: white - }, - '& li:hover': { - backgroundColor: subheaderColor, - color: offColor - } - }, - '& svg': { - fill: [[white], '!important'] - } - }, - open: { - '& button': { - borderRadius: [[8, 8, 0, 0]] - } - } -} diff --git a/new-lamassu-admin/src/components/inputs/base/Switch.jsx b/new-lamassu-admin/src/components/inputs/base/Switch.jsx deleted file mode 100644 index 2f2cdf0f..00000000 --- a/new-lamassu-admin/src/components/inputs/base/Switch.jsx +++ /dev/null @@ -1,80 +0,0 @@ -import Switch from '@material-ui/core/Switch' -import { makeStyles } from '@material-ui/core/styles' -import React, { memo } from 'react' - -import { - secondaryColor, - offColor, - disabledColor, - disabledColor2 -} from '../../../styling/variables' - -const useStyles = makeStyles(theme => ({ - root: { - width: 32, - height: 20, - padding: 0, - margin: theme.spacing(1) - }, - switchBase: { - padding: 2, - '&$disabled': { - color: disabledColor2, - '& + $track': { - backgroundColor: disabledColor, - opacity: 1 - } - }, - '&$checked': { - transform: 'translateX(58%)', - color: theme.palette.common.white, - '&$disabled': { - color: disabledColor2 - }, - '& + $track': { - backgroundColor: secondaryColor, - opacity: 1, - border: 'none' - } - }, - '&$focusVisible $thumb': { - border: '6px solid #fff', - boxShadow: '0 0 4px 0 rgba(0,0,0,0.24)' - } - }, - thumb: { - width: 16, - height: 16 - }, - track: { - borderRadius: 17, - border: 'none', - backgroundColor: offColor, - opacity: 1, - transition: theme.transitions.create(['background-color', 'border']) - }, - disabled: {}, - checked: {}, - focusVisible: {} -})) - -const SwitchInput = memo(({ ...props }) => { - const classes = useStyles() - return ( - - ) -}) - -export default SwitchInput diff --git a/new-lamassu-admin/src/components/inputs/base/TextInput.jsx b/new-lamassu-admin/src/components/inputs/base/TextInput.jsx deleted file mode 100644 index 9d75840a..00000000 --- a/new-lamassu-admin/src/components/inputs/base/TextInput.jsx +++ /dev/null @@ -1,59 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import TextField from '@material-ui/core/TextField' -import classnames from 'classnames' -import * as R from 'ramda' -import React, { memo } from 'react' - -import styles from './TextInput.styles' - -const useStyles = makeStyles(styles) - -const TextInput = memo( - ({ - name, - isPasswordFilled, - onChange, - onBlur, - value, - error, - suffix, - textAlign, - width, - // lg or sm - size, - bold, - className, - InputProps, - ...props - }) => { - const classes = useStyles({ textAlign, width, size }) - const isTextFilled = !error && !R.isNil(value) && !R.isEmpty(value) - const filled = isPasswordFilled || isTextFilled - const inputClasses = { - [classes.bold]: bold - } - - return ( - - ) - } -) - -export default TextInput diff --git a/new-lamassu-admin/src/components/inputs/base/TextInput.styles.js b/new-lamassu-admin/src/components/inputs/base/TextInput.styles.js deleted file mode 100644 index 1c8db3e5..00000000 --- a/new-lamassu-admin/src/components/inputs/base/TextInput.styles.js +++ /dev/null @@ -1,24 +0,0 @@ -import { bySize, bold } from 'src/styling/helpers' -import { secondaryColor } from 'src/styling/variables' - -export default { - size: ({ size }) => ({ - marginTop: size === 'lg' ? 0 : 2, - ...bySize(size) - }), - bold, - root: ({ width, textAlign }) => ({ - width, - '& input': { - textAlign - } - }), - underline: { - '&:before': { - borderBottomColor: secondaryColor - }, - '&:hover:not(.Mui-disabled)::before': { - borderBottomColor: secondaryColor - } - } -} diff --git a/new-lamassu-admin/src/components/inputs/base/ToggleButtonGroup.jsx b/new-lamassu-admin/src/components/inputs/base/ToggleButtonGroup.jsx deleted file mode 100644 index 72193ce2..00000000 --- a/new-lamassu-admin/src/components/inputs/base/ToggleButtonGroup.jsx +++ /dev/null @@ -1,75 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import { ToggleButtonGroup as MUIToggleButtonGroup } from '@material-ui/lab' -import ToggleButton from '@material-ui/lab/ToggleButton' -import React from 'react' -import { H4, P } from 'src/components/typography' - -import { backgroundColor, comet } from 'src/styling/variables' -const styles = { - noTextTransform: { - textTransform: 'none' - }, - flex: { - display: 'flex', - alignItems: 'center', - justifyContent: 'start', - width: '90%', - overflow: 'hidden', - maxHeight: 80 - }, - buttonTextContent: { - marginLeft: 32, - textTransform: 'none', - textAlign: 'left' - }, - button: { - backgroundColor: backgroundColor, - marginBottom: 16 - }, - paragraph: { - color: comet, - marginTop: -10 - } -} - -const useStyles = makeStyles(styles) -const ToggleButtonGroup = ({ - name, - orientation = 'vertical', - value, - exclusive = true, - onChange, - size = 'small', - ...props -}) => { - const classes = useStyles() - return ( - - {props.options.map(option => { - return ( - -
- -
-

{option.title}

-

{option.description}

-
-
-
- ) - })} -
- ) -} - -export default ToggleButtonGroup diff --git a/new-lamassu-admin/src/components/inputs/cashbox/Cashbox.styles.js b/new-lamassu-admin/src/components/inputs/cashbox/Cashbox.styles.js deleted file mode 100644 index df06ed6b..00000000 --- a/new-lamassu-admin/src/components/inputs/cashbox/Cashbox.styles.js +++ /dev/null @@ -1,88 +0,0 @@ -import { spacer, tomato, primaryColor as zodiac } from 'src/styling/variables' - -const colors = { - cashOut: { - empty: tomato, - full: zodiac - }, - cashIn: { - empty: zodiac, - full: tomato - } -} - -const colorPicker = ({ cashOut, applyColorVariant, isLow }) => { - return colors[cashOut ? 'cashOut' : 'cashIn'][ - applyColorVariant || !isLow ? 'full' : 'empty' - ] -} - -const cashboxStyles = { - cashbox: { - borderColor: colorPicker, - backgroundColor: colorPicker, - height: ({ height }) => height ?? 118, - width: ({ width }) => width ?? 80, - border: '2px solid', - textAlign: 'end', - display: 'inline-block' - }, - fiatBalanceAlertCashbox: { - borderColor: colorPicker, - backgroundColor: colorPicker, - height: 118, - width: 80, - border: '4px solid' - }, - emptyPart: { - backgroundColor: 'white', - height: ({ percent }) => `${100 - percent}%`, - position: 'relative', - '& > p': { - color: colorPicker, - display: 'inline-block', - position: 'absolute', - margin: 0, - bottom: 0, - right: 0 - } - }, - fullPart: { - backgroundColor: colorPicker, - '& > p': { - color: 'white', - display: 'inline' - } - } -} - -const gridStyles = { - row: { - display: 'flex', - alignItems: 'center' - }, - col: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center' - }, - innerRow: { - display: 'flex', - justifyContent: 'flex-start' - }, - col2: { - marginLeft: 14 - }, - noMarginText: { - marginTop: 0, - marginBottom: 0 - }, - link: { - marginTop: spacer - }, - chip: { - margin: [[0, 0, 0, 7]] - } -} - -export { cashboxStyles, gridStyles } diff --git a/new-lamassu-admin/src/components/inputs/formik/TextInput.styles.js b/new-lamassu-admin/src/components/inputs/formik/TextInput.styles.js deleted file mode 100644 index 5ec7672d..00000000 --- a/new-lamassu-admin/src/components/inputs/formik/TextInput.styles.js +++ /dev/null @@ -1,36 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { - fontColor, - offColor, - inputFontSize, - inputFontWeight -} from 'src/styling/variables' - -const { info3 } = typographyStyles - -const styles = { - masked: { - position: 'absolute', - bottom: 5, - left: 4, - color: fontColor, - fontSize: inputFontSize, - fontWeight: inputFontWeight - }, - secretSpan: { - extend: info3, - color: offColor - }, - hideSpan: { - display: 'none' - }, - maskedInput: { - '& input': { - pointerEvents: 'none', - backgroundColor: 'transparent', - zIndex: -1 - } - } -} - -export { styles } diff --git a/new-lamassu-admin/src/components/layout/Header.styles.js b/new-lamassu-admin/src/components/layout/Header.styles.js deleted file mode 100644 index 6c254594..00000000 --- a/new-lamassu-admin/src/components/layout/Header.styles.js +++ /dev/null @@ -1,182 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { - version, - mainWidth, - spacer, - white, - primaryColor, - secondaryColor, - placeholderColor, - subheaderColor, - fontColor -} from 'src/styling/variables' - -const { p } = typographyStyles - -let headerHeight = spacer * 7 -let subheaderHeight = spacer * 5 - -if (version === 8) { - headerHeight = spacer * 8 - subheaderHeight = spacer * 7 -} - -const styles = { - headerContainer: { - position: 'relative' - }, - header: { - backgroundColor: primaryColor, - color: white, - height: headerHeight, - display: 'flex' - }, - content: { - maxWidth: mainWidth, - flex: 1, - display: 'flex', - alignItems: 'center', - margin: '0 auto' - }, - nav: { - flex: 1, - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between' - }, - ul: { - display: 'flex', - paddingLeft: spacer * 4.5, - height: spacer * 7, - margin: 0 - }, - li: { - // extend: tl2, - // height: spacer * 7, - listStyle: 'none', - color: white, - margin: [[spacer * 2.5, spacer * 2.5, 0, spacer * 2.5]], - '&:hover': { - color: white - }, - '&:hover::after': { - width: '50%', - marginLeft: '-25%' - }, - position: 'relative', - '&:after': { - content: '""', - display: 'block', - background: white, - width: 0, - height: 4, - left: '50%', - marginLeft: 0, - bottom: -8, - position: 'absolute', - borderRadius: 1000, - transition: [['all', '0.2s', 'cubic-bezier(0.95, 0.1, 0.45, 0.94)']] - } - }, - link: { - extend: p, - textDecoration: 'none', - border: 'none', - color: white, - backgroundColor: 'transparent' - }, - forceSize: { - display: 'inline-block', - textAlign: 'center', - '&:after': { - display: 'block', - content: 'attr(data-forcesize)', - fontWeight: 700, - height: 0, - overflow: 'hidden', - visibility: 'hidden' - } - }, - activeLink: { - color: white, - '& li::after': { - width: '50%', - marginLeft: '-25%' - } - }, - addMachine: { - marginLeft: 'auto' - }, - subheader: { - backgroundColor: subheaderColor, - color: white, - height: subheaderHeight, - display: 'flex' - }, - subheaderUl: { - display: 'flex', - paddingLeft: 0, - margin: 0 - }, - subheaderLi: { - listStyle: 'none', - padding: [[0, spacer * 2.5]], - '&:first-child': { - paddingLeft: 0 - } - }, - subheaderLink: { - extend: p, - textDecoration: 'none', - border: 'none', - color: placeholderColor - }, - activeSubheaderLink: { - textShadow: '0.2px 0 0 currentColor', - color: fontColor - }, - white: { - color: white - }, - logo: { - display: 'flex', - alignItems: 'center', - '& > svg': { - marginRight: 16 - } - }, - logoLink: { - cursor: 'pointer' - }, - actionButtonsContainer: { - zIndex: 1, - position: 'relative', - display: 'flex', - justifyContent: 'space-between', - minWidth: 200, - transform: 'translateZ(0)' - }, - notificationIcon: { - marginTop: spacer / 2, - cursor: 'pointer', - background: 'transparent', - boxShadow: '0px 0px 0px transparent', - border: '0px solid transparent', - textShadow: '0px 0px 0px transparent', - outline: 'none' - }, - hasUnread: { - position: 'absolute', - top: 4, - left: 186, - width: '9px', - height: '9px', - backgroundColor: secondaryColor, - borderRadius: '50%' - }, - popper: { - zIndex: 1 - } -} - -export default styles diff --git a/new-lamassu-admin/src/components/layout/Section.jsx b/new-lamassu-admin/src/components/layout/Section.jsx deleted file mode 100644 index 6f0e9302..00000000 --- a/new-lamassu-admin/src/components/layout/Section.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import React from 'react' -import ErrorMessage from 'src/components/ErrorMessage' -import Subtitle from 'src/components/Subtitle' - -import styles from './Section.styles' - -const useStyles = makeStyles(styles) - -const Section = ({ error, children, title }) => { - const classes = useStyles() - return ( -
- {(title || error) && ( -
- {title} - {error && Failed to save changes} -
- )} - {children} -
- ) -} - -export default Section diff --git a/new-lamassu-admin/src/components/layout/Section.styles.js b/new-lamassu-admin/src/components/layout/Section.styles.js deleted file mode 100644 index 9898e41c..00000000 --- a/new-lamassu-admin/src/components/layout/Section.styles.js +++ /dev/null @@ -1,12 +0,0 @@ -export default { - section: { - marginBottom: 72 - }, - sectionHeader: { - display: 'flex', - alignItems: 'center' - }, - sectionTitle: { - margin: [[16, 20, 23, 0]] - } -} diff --git a/new-lamassu-admin/src/components/layout/Sidebar.styles.js b/new-lamassu-admin/src/components/layout/Sidebar.styles.js deleted file mode 100644 index 1165ed59..00000000 --- a/new-lamassu-admin/src/components/layout/Sidebar.styles.js +++ /dev/null @@ -1,107 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { respondTo } from 'src/styling/helpers' -import { - primaryColor, - spacer, - placeholderColor, - zircon, - xxl -} from 'src/styling/variables' - -const { tl2, p } = typographyStyles - -const sidebarColor = zircon - -export default { - sidebar: { - display: 'flex', - backgroundColor: sidebarColor, - width: 520, - marginLeft: -300, - boxShadow: `-500px 0px 0px 0px ${sidebarColor}`, - borderRadius: '0 20px 0 0', - alignItems: 'flex-end', - padding: spacer * 3, - flexDirection: 'column', - [respondTo(xxl)]: { - width: 'auto', - marginLeft: 0, - minWidth: 250, - boxShadow: `-200px 0px 0px 0px ${sidebarColor}` - } - }, - linkWrapper: { - cursor: 'pointer' - }, - link: { - extend: p, - position: 'relative', - color: placeholderColor, - margin: '12px 24px 12px 0', - cursor: 'pointer', - '&:hover::after': { - height: '140%' - }, - '&:after': { - content: '""', - display: 'block', - background: primaryColor, - width: 4, - height: 0, - left: '100%', - marginLeft: 20, - bottom: -2, - position: 'absolute', - borderRadius: 1000, - transition: 'all 0.2s cubic-bezier(0.95, 0.1, 0.45, 0.94)' - } - }, - activeLink: { - extend: tl2, - color: primaryColor, - '&::after': { - height: '140%' - } - }, - customRenderLink: { - '&:hover::after': { - height: '100%' - }, - '&:after': { - bottom: 0 - } - }, - customRenderActiveLink: { - '&::after': { - height: '100%' - } - }, - item: { - position: 'relative', - margin: '12px 0 12px 0', - display: 'flex' - }, - itemText: { - extend: p, - color: placeholderColor, - marginRight: 24 - }, - itemTextActive: { - extend: tl2, - color: primaryColor - }, - itemTextPast: { - color: primaryColor - }, - stepperPath: { - position: 'absolute', - height: 25, - width: 1, - border: [[1, 'solid', placeholderColor]], - right: 8, - top: 18 - }, - stepperPast: { - border: [[1, 'solid', primaryColor]] - } -} diff --git a/new-lamassu-admin/src/components/layout/TitleSection.jsx b/new-lamassu-admin/src/components/layout/TitleSection.jsx deleted file mode 100644 index 563bb275..00000000 --- a/new-lamassu-admin/src/components/layout/TitleSection.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import { makeStyles, Box } from '@material-ui/core' -import classnames from 'classnames' -import * as R from 'ramda' -import React from 'react' -import ErrorMessage from 'src/components/ErrorMessage' -import Title from 'src/components/Title' -import { Info1, Label1 } from 'src/components/typography' - -import { SubpageButton } from 'src/components/buttons' - -import styles from './TitleSection.styles' - -const useStyles = makeStyles(styles) - -const TitleSection = ({ - className, - title, - error, - labels, - buttons = [], - children, - appendix, - appendixRight -}) => { - const classes = useStyles() - return ( -
-
- {title} - {!!appendix && appendix} - {error && ( - Failed to save - )} - {buttons.length > 0 && ( - <> - {buttons.map((button, idx) => - !R.isNil(button.component) ? ( - button.component - ) : ( - - {button.text} - - ) - )} - - )} -
- - {(labels ?? []).map(({ icon, label }, idx) => ( - -
{icon}
- {label} -
- ))} - {appendixRight} -
- {children} -
- ) -} - -export default TitleSection diff --git a/new-lamassu-admin/src/components/layout/TitleSection.styles.js b/new-lamassu-admin/src/components/layout/TitleSection.styles.js deleted file mode 100644 index 351193da..00000000 --- a/new-lamassu-admin/src/components/layout/TitleSection.styles.js +++ /dev/null @@ -1,31 +0,0 @@ -import { backgroundColor } from 'src/styling/variables' - -export default { - titleWrapper: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - flexDirection: 'row' - }, - titleAndButtonsContainer: { - display: 'flex', - alignItems: 'center' - }, - error: { - marginLeft: 12 - }, - subpageButton: { - marginLeft: 12 - }, - buttonText: { - color: backgroundColor, - fontFamily: 'Mont', - fontSize: 15 - }, - icon: { - marginRight: 6 - }, - label: { - marginRight: 24 - } -} diff --git a/new-lamassu-admin/src/components/machineActions/MachineActions.styles.js b/new-lamassu-admin/src/components/machineActions/MachineActions.styles.js deleted file mode 100644 index 1f2d86f6..00000000 --- a/new-lamassu-admin/src/components/machineActions/MachineActions.styles.js +++ /dev/null @@ -1,61 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { offColor, spacer, errorColor } from 'src/styling/variables' - -const { label1 } = typographyStyles - -const machineActionsStyles = { - label: { - extend: label1, - color: offColor, - marginBottom: 4 - }, - inlineChip: { - marginInlineEnd: '0.25em' - }, - stack: { - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'start' - }, - mr: { - marginRight: spacer, - marginBottom: spacer - }, - warning: { - color: errorColor - } -} - -const diagnosticsModal = { - modal: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - padding: '1em' - }, - photo: { - width: 350 - }, - photoWrapper: { - marginTop: spacer * 3, - display: 'flex' - }, - footer: { - display: 'flex', - flexDirection: 'row', - margin: [['auto', 0, spacer * 3, 0]] - }, - downloadLogs: { - margin: [['auto', spacer, 0, 'auto']] - }, - message: { - margin: 'auto', - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center' - } -} - -export { machineActionsStyles, diagnosticsModal } diff --git a/new-lamassu-admin/src/components/single-row-table/SingleRowTable.jsx b/new-lamassu-admin/src/components/single-row-table/SingleRowTable.jsx deleted file mode 100644 index ccb22539..00000000 --- a/new-lamassu-admin/src/components/single-row-table/SingleRowTable.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import classnames from 'classnames' -import React from 'react' -import { - Table, - THead, - TBody, - Td, - Th, - Tr -} from 'src/components/fake-table/Table' -import EditIcon from 'src/styling/icons/action/edit/white.svg?react' - -import { IconButton } from 'src/components/buttons' - -import styles from './SingleRowTable.styles' - -const useStyles = makeStyles(styles) - -const SingleRowTable = ({ - width = 378, - height = 128, - title, - items, - onEdit, - className -}) => { - const classes = useStyles({ width, height }) - - return ( - <> - - - - - - - - - -
- {title} - - - -
- {items && ( - <> - {items[0] && ( -
-
{items[0].label}
-
{items[0].value}
-
- )} - {items[1] && ( -
-
{items[1].label}
-
{items[1].value}
-
- )} - - )} -
- - ) -} - -export default SingleRowTable diff --git a/new-lamassu-admin/src/components/single-row-table/SingleRowTable.styles.js b/new-lamassu-admin/src/components/single-row-table/SingleRowTable.styles.js deleted file mode 100644 index f4a5608d..00000000 --- a/new-lamassu-admin/src/components/single-row-table/SingleRowTable.styles.js +++ /dev/null @@ -1,41 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { offColor } from 'src/styling/variables' - -const { label1, p } = typographyStyles - -export default { - tr: ({ height }) => ({ - margin: 0, - height - }), - table: ({ width }) => ({ - width - }), - head: { - display: 'flex', - flex: 1, - justifyContent: 'space-between', - alignItems: 'center', - paddingRight: 12 - }, - button: { - marginBottom: 1 - }, - itemWrapper: { - display: 'flex', - flexDirection: 'column', - marginTop: 16, - minHeight: 35 - }, - label: { - extend: label1, - color: offColor, - marginBottom: 4 - }, - item: { - extend: p, - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap' - } -} diff --git a/new-lamassu-admin/src/components/table/EmptyTable.jsx b/new-lamassu-admin/src/components/table/EmptyTable.jsx deleted file mode 100644 index b755c746..00000000 --- a/new-lamassu-admin/src/components/table/EmptyTable.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import classNames from 'classnames' -import React, { memo } from 'react' -import { H4 } from 'src/components/typography' -import EmptyTableIcon from 'src/styling/icons/table/empty-table.svg?react' - -const styles = { - emptyTable: { - width: '100%', - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - marginTop: 52 - } -} - -const useStyles = makeStyles(styles) - -const EmptyTable = memo(({ message, className }) => { - const classes = useStyles() - - return ( -
- -

{message}

-
- ) -}) - -export default EmptyTable diff --git a/new-lamassu-admin/src/components/table/Table.jsx b/new-lamassu-admin/src/components/table/Table.jsx deleted file mode 100644 index d7e92bd5..00000000 --- a/new-lamassu-admin/src/components/table/Table.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' - -const useStyles = makeStyles({ - table: { - // backgroundColor: tableHeaderColor, - tableLayout: 'fixed', - borderCollapse: 'separate', - borderSpacing: '0 0' - } -}) - -const Table = memo(({ className, children, ...props }) => { - const classes = useStyles() - return ( - - {children} -
- ) -}) - -export default Table diff --git a/new-lamassu-admin/src/components/table/TableCell.jsx b/new-lamassu-admin/src/components/table/TableCell.jsx deleted file mode 100644 index d99a4f50..00000000 --- a/new-lamassu-admin/src/components/table/TableCell.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' - -import { spacer } from 'src/styling/variables' - -const useStyles = makeStyles({ - td: { - padding: [[0, spacer * 3]] - }, - alignRight: { - textAlign: 'right' - } -}) - -const TableCell = memo( - ({ colspan, rightAlign, className, children, ...props }) => { - const classes = useStyles() - const styles = { - [classes.td]: true, - [classes.alignRight]: rightAlign - } - - return ( - - {children} - - ) - } -) - -export default TableCell diff --git a/new-lamassu-admin/src/components/table/TableHeader.jsx b/new-lamassu-admin/src/components/table/TableHeader.jsx deleted file mode 100644 index 0318f055..00000000 --- a/new-lamassu-admin/src/components/table/TableHeader.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' - -import typographyStyles from 'src/components/typography/styles' -import { - tableHeaderColor, - tableHeaderHeight, - spacer, - white -} from 'src/styling/variables' - -const { tl2 } = typographyStyles - -const useStyles = makeStyles({ - th: { - extend: tl2, - backgroundColor: tableHeaderColor, - height: tableHeaderHeight, - textAlign: 'left', - color: white, - padding: `0 ${spacer * 3}px` - }, - alignRight: { - textAlign: 'right' - } -}) - -const TableHeaderCell = memo( - ({ rightAlign, children, className, ...props }) => { - const classes = useStyles() - const styles = { - [classes.th]: true, - [classes.alignRight]: rightAlign - } - - return ( - - {children} - - ) - } -) - -export default TableHeaderCell diff --git a/new-lamassu-admin/src/components/table/TableRow.jsx b/new-lamassu-admin/src/components/table/TableRow.jsx deleted file mode 100644 index f5b28256..00000000 --- a/new-lamassu-admin/src/components/table/TableRow.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' - -import typographyStyles from 'src/components/typography/styles' -import { - tableCellColor, - tableCellHeight, - tableSmCellHeight, - tableLgCellHeight, - tableErrorColor, - tableSuccessColor -} from 'src/styling/variables' - -const { info2, p } = typographyStyles - -const useStyles = makeStyles({ - tr: { - extend: p, - padding: 4, - height: tableCellHeight, - backgroundColor: tableCellColor - }, - lg: { - extend: info2, - height: tableLgCellHeight - }, - sm: { - height: tableSmCellHeight - }, - error: { - backgroundColor: tableErrorColor - }, - success: { - backgroundColor: tableSuccessColor - } -}) - -const TableRow = memo( - ({ className, children, header, error, success, size = 'sm', ...props }) => { - const classes = useStyles() - const classnamesObj = { - [classes.tr]: !header, - [classes.sm]: !header && size === 'sm', - [classes.lg]: !header && size === 'lg', - [classes.error]: error, - [classes.success]: success - } - - return ( - - {children} - - ) - } -) - -export default TableRow diff --git a/new-lamassu-admin/src/components/tables/DataTable.styles.js b/new-lamassu-admin/src/components/tables/DataTable.styles.js deleted file mode 100644 index 3dee4849..00000000 --- a/new-lamassu-admin/src/components/tables/DataTable.styles.js +++ /dev/null @@ -1,50 +0,0 @@ -import { zircon } from 'src/styling/variables' - -export default { - expandButton: { - outline: 'none', - border: 'none', - backgroundColor: 'transparent', - cursor: 'pointer', - padding: 4 - }, - rowWrapper: { - // workaround to shadows cut by r-virtualized when scroll is visible - padding: 1 - }, - row: { - border: [[2, 'solid', 'transparent']], - borderRadius: 0 - }, - expanded: { - border: [[2, 'solid', zircon]], - boxShadow: '0 0 8px 0 rgba(0,0,0,0.08)' - }, - before: { - paddingTop: 12 - }, - after: { - paddingBottom: 12 - }, - pointer: { - cursor: 'pointer' - }, - body: { - flex: [[1, 1, 'auto']] - }, - table: ({ width }) => ({ - marginBottom: 30, - minHeight: 200, - width, - flex: 1, - display: 'flex', - flexDirection: 'column' - }), - emptyTable: { - width: '100%', - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - marginTop: 52 - } -} diff --git a/new-lamassu-admin/src/components/tables/Stripes.jsx b/new-lamassu-admin/src/components/tables/Stripes.jsx deleted file mode 100644 index 6f84869e..00000000 --- a/new-lamassu-admin/src/components/tables/Stripes.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' -import { Td } from 'src/components/fake-table/Table' -import StripesSvg from 'src/styling/icons/stripes.svg?react' - -const Stripes = ({ width }) => ( - - - -) - -export default Stripes diff --git a/new-lamassu-admin/src/index.jsx b/new-lamassu-admin/src/index.jsx deleted file mode 100644 index 638af18d..00000000 --- a/new-lamassu-admin/src/index.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom' - -import App from './App' - -ReactDOM.render( - - - , - document.getElementById('root') -) diff --git a/new-lamassu-admin/src/pages/AddMachine/styles.js b/new-lamassu-admin/src/pages/AddMachine/styles.js deleted file mode 100644 index 75d3c608..00000000 --- a/new-lamassu-admin/src/pages/AddMachine/styles.js +++ /dev/null @@ -1,149 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { - placeholderColor, - backgroundColor, - primaryColor, - mainWidth, - spring2, - spring3, - errorColor -} from 'src/styling/variables' - -const { tl2, p } = typographyStyles - -const fill = '100%' -const flexDirection = 'column' - -const styles = { - dialog: { - backgroundColor, - width: fill, - minHeight: fill, - display: 'flex', - flexDirection, - padding: 0 - }, - wrapper: { - width: mainWidth, - height: fill, - margin: '0 auto', - flex: 1, - display: 'flex', - flexDirection - }, - contentDiv: { - display: 'flex', - flex: 1, - flexDirection: 'row' - }, - headerDiv: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center' - }, - contentWrapper: { - marginLeft: 48 - }, - button: { - marginTop: 64 - }, - nameTitle: { - marginTop: 16, - marginBottom: 25 - }, - qrTitle: { - marginTop: 12, - marginBottom: 40 - }, - qrCodeWrapper: { - display: 'flex' - }, - qrTextInfoWrapper: { - display: 'flex', - flexDirection: 'row' - }, - qrTextWrapper: { - width: 381, - marginLeft: 80, - display: 'flex', - flexDirection: 'column' - }, - textWrapper: { - display: 'flex', - flexDirection: 'column' - }, - qrTextIcon: { - marginRight: 16 - }, - qrText: { - marginTop: 0 - }, - item: { - position: 'relative', - margin: '12px 0 12px 0', - display: 'flex' - }, - itemText: { - extend: p, - color: placeholderColor, - marginRight: 24 - }, - itemTextActive: { - extend: tl2, - color: primaryColor - }, - itemTextPast: { - color: primaryColor - }, - stepperPath: { - position: 'absolute', - height: 25, - width: 1, - border: [[1, 'solid', placeholderColor]], - right: 8, - top: 18 - }, - stepperPast: { - border: [[1, 'solid', primaryColor]] - }, - successMessageWrapper: { - backgroundColor: spring3, - display: 'flex', - flexDirection: 'row', - padding: '0px 10px', - borderRadius: '8px' - }, - successMessage: { - color: spring2, - margin: '8px 0px' - }, - successMessageIcon: { - marginRight: 16, - marginBottom: 2, - display: 'flex', - flexDirection: 'col', - alignItems: 'center' - }, - errorMessage: { - color: errorColor - }, - qrCodeImageWrapper: { - display: 'flex', - flexDirection: 'column', - backgroundColor: 'white', - border: `5px solid ${primaryColor}`, - padding: 5, - borderRadius: 15 - }, - qrCodeScanMessage: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - margin: [[0, 0, 20, 20]], - '& > p': { - marginLeft: 10 - } - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/Analytics/Analytics.styles.js b/new-lamassu-admin/src/pages/Analytics/Analytics.styles.js deleted file mode 100644 index 8274d929..00000000 --- a/new-lamassu-admin/src/pages/Analytics/Analytics.styles.js +++ /dev/null @@ -1,163 +0,0 @@ -import { - offColor, - offDarkColor, - tomato, - neon, - java -} from 'src/styling/variables' - -import typographyStyles from '../../components/typography/styles' - -const { label1 } = typographyStyles - -const styles = { - overviewLegend: { - display: 'flex', - justifyContent: 'flex-end', - '& span': { - marginRight: 24 - }, - '& > :last-child': { - marginRight: 0 - } - }, - legendEntry: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - '& > :first-child': { - marginRight: 8 - } - }, - dropdownsOverviewWrapper: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 16 - }, - verticalLine: { - height: 64, - width: 1, - border: 'solid', - borderWidth: 0.5, - borderColor: offDarkColor - }, - dropdowns: { - display: 'flex', - flexDirection: 'row', - '& div': { - marginRight: 24 - }, - '& > :last-child': { - marginRight: 0 - } - }, - overview: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - '& div': { - marginRight: 40 - }, - '& > :last-child': { - marginRight: 0 - } - }, - overviewFieldWrapper: { - marginTop: 6, - marginBottom: 6, - '& span': { - fontSize: 24 - } - }, - overviewGrowth: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - '& p': { - marginLeft: 4 - } - }, - growthPercentage: { - fontWeight: 'bold' - }, - growth: { - color: '#00CD5A' - }, - decline: { - color: tomato - }, - // Graph - graphHeaderWrapper: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - marginBottom: 40 - }, - graphHeaderLeft: { - display: 'flex', - flexDirection: 'column' - }, - graphHeaderRight: { - marginTop: 15, - display: 'flex', - flexDirection: 'row', - '& > *': { - marginRight: 30, - '&:last-child': { - marginRight: 0 - } - } - }, - graphLegend: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - '& span': { - marginRight: 24 - }, - '& > :last-child': { - marginRight: 0 - } - }, - machineSelector: { - width: 248 - }, - cashInIcon: { - width: 12, - height: 12, - borderRadius: 12, - backgroundColor: java - }, - cashOutIcon: { - width: 12, - height: 12, - borderRadius: 12, - backgroundColor: neon - }, - txIcon: { - width: 12, - height: 12, - borderRadius: 12, - backgroundColor: '#000' - }, - topMachinesRadio: { - display: 'flex', - flexDirection: 'row' - }, - graphHeaderSwitchBox: { - display: 'flex', - flexDirection: 'column', - '& > *': { - margin: 0 - }, - '& > :first-child': { - marginBottom: 2, - extend: label1, - color: offColor - } - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/Analytics/components/tooltips/GraphTooltip.styles.js b/new-lamassu-admin/src/pages/Analytics/components/tooltips/GraphTooltip.styles.js deleted file mode 100644 index 01fa39ea..00000000 --- a/new-lamassu-admin/src/pages/Analytics/components/tooltips/GraphTooltip.styles.js +++ /dev/null @@ -1,29 +0,0 @@ -import { comet } from 'src/styling/variables' - -const styles = { - dotOtWrapper: { - position: 'absolute', - top: coords => coords?.y ?? 0, - left: coords => coords?.x ?? 0, - width: 150, - padding: 12, - borderRadius: 8 - }, - dotOtTransactionAmount: { - margin: [[8, 0, 8, 0]] - }, - dotOtTransactionVolume: { - color: comet - }, - dotOtTransactionClasses: { - marginTop: 15, - '& p > span': { - marginLeft: 5 - }, - '& p:last-child': { - marginTop: 5 - } - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/AuthRegister.jsx b/new-lamassu-admin/src/pages/AuthRegister.jsx deleted file mode 100644 index b4499d34..00000000 --- a/new-lamassu-admin/src/pages/AuthRegister.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import useAxios from '@use-hooks/axios' -import React from 'react' -import { useLocation, useHistory } from 'react-router-dom' - -const useQuery = () => new URLSearchParams(useLocation().search) - -const AuthRegister = () => { - const history = useHistory() - const query = useQuery() - - useAxios({ - url: `/api/register?otp=${query.get('otp')}`, - method: 'GET', - options: { - withCredentials: true - }, - trigger: [], - customHandler: (err, res) => { - if (err) return - if (res) { - history.push('/wizard', { fromAuthRegister: true }) - } - } - }) - - return registering... -} - -export default AuthRegister diff --git a/new-lamassu-admin/src/pages/Authentication/shared.styles.js b/new-lamassu-admin/src/pages/Authentication/shared.styles.js deleted file mode 100644 index 20ed5058..00000000 --- a/new-lamassu-admin/src/pages/Authentication/shared.styles.js +++ /dev/null @@ -1,109 +0,0 @@ -import { backgroundColor, errorColor } from 'src/styling/variables' - -const styles = { - title: { - paddingTop: 8 - }, - input: { - marginBottom: 25, - marginTop: -15 - }, - wrapper: { - padding: '2.5em 4em', - width: 575, - display: 'flex', - flexDirection: 'column' - }, - titleWrapper: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - marginBottom: 30 - }, - rememberMeWrapper: { - marginTop: 35, - display: 'flex', - flexDirection: 'row' - }, - icon: { - transform: 'scale(1.5)', - marginRight: 25 - }, - checkbox: { - transform: 'scale(1.5)', - marginRight: 5, - marginLeft: -5 - }, - footer: { - marginTop: '10vh' - }, - twofaFooter: { - marginTop: '6vh' - }, - fidoLoginButtonWrapper: { - marginBottom: 12 - }, - loginButton: { - display: 'block', - width: '100%' - }, - welcomeBackground: { - background: 'url(/wizard-background.svg) no-repeat center center fixed', - backgroundColor: backgroundColor, - backgroundSize: 'cover', - height: '100vh', - width: '100vw', - position: 'relative', - left: '50%', - right: '50%', - marginLeft: '-50vw', - marginRight: '-50vw', - minHeight: '100vh' - }, - info: { - marginBottom: '5vh' - }, - info2: { - textAlign: 'justify' - }, - infoWrapper: { - marginBottom: '3vh' - }, - errorMessage: { - color: errorColor - }, - qrCodeWrapper: { - display: 'flex', - justifyContent: 'center', - marginBottom: '3vh' - }, - secretWrapper: { - display: 'flex', - justifyContent: 'center', - alignItems: 'center' - }, - secretLabel: { - marginRight: 15 - }, - secret: { - marginRight: 35 - }, - hiddenSecret: { - marginRight: 35, - filter: 'blur(8px)' - }, - confirm2FAInput: { - marginTop: 25 - }, - confirmPassword: { - marginTop: 25 - }, - error: { - color: errorColor - }, - enterButton: { - display: 'none' - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js b/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js deleted file mode 100644 index 3cfc09ec..00000000 --- a/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js +++ /dev/null @@ -1,75 +0,0 @@ -import { spacer, white } from 'src/styling/variables' -const styles = { - grid: { - flex: 1, - height: '100%' - }, - content: { - display: 'flex', - flexDirection: 'column', - flex: 1 - }, - advancedForm: { - '& > *': { - marginTop: 20 - }, - display: 'flex', - flexDirection: 'column', - height: '100%' - }, - footer: { - display: 'flex', - flexDirection: 'row', - margin: [['auto', 0, spacer * 3, 0]] - }, - submit: { - margin: [['auto', 0, 0, 'auto']] - }, - modalTitle: { - margin: [['auto', 0, 8.5, 'auto']] - }, - subtitle: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - flexDirection: 'row' - }, - white: { - color: white - }, - deleteButton: { - paddingLeft: 13 - }, - addressRow: { - marginLeft: 8 - }, - error: { - marginTop: 20 - }, - closeButton: { - display: 'flex', - padding: [[spacer * 2, spacer * 2, 0, spacer * 2]], - paddingRight: spacer * 1.5, - justifyContent: 'end' - }, - dialogTitle: { - margin: [[0, spacer * 2, spacer, spacer * 4 + spacer]] - }, - dialogContent: { - width: 615, - marginLeft: 16 - }, - dialogActions: { - padding: spacer * 4, - paddingTop: spacer * 2 - }, - cancelButton: { - marginRight: 8, - padding: 0 - }, - resetToDefault: { - width: 145 - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/Cashout/WizardSplash.jsx b/new-lamassu-admin/src/pages/Cashout/WizardSplash.jsx deleted file mode 100644 index 0360ce66..00000000 --- a/new-lamassu-admin/src/pages/Cashout/WizardSplash.jsx +++ /dev/null @@ -1,78 +0,0 @@ -import { makeStyles } from '@material-ui/core' -import React from 'react' -import { H1, P, Info2 } from 'src/components/typography' -import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react' - -import { Button } from 'src/components/buttons' -import { neon, spacer } from 'src/styling/variables' - -const styles = { - logo: { - maxHeight: 80, - maxWidth: 200 - }, - subtitle: { - margin: 0, - marginBottom: 42, - textAlign: 'center' - }, - text: { - margin: 0 - }, - button: { - margin: [[0, 'auto']] - }, - modalContent: { - display: 'flex', - flexDirection: 'column', - justifyContent: 'space-between', - flex: 1, - padding: [[0, 34, 107, 34]] - }, - innerContent: { - paddingBottom: 72 - }, - title: { - color: neon, - marginBottom: 12, - marginTop: 30, - textAlign: 'center' - }, - titleDecorator: { - verticalAlign: 'bottom', - marginRight: spacer * 1.5, - width: spacer * 3, - height: spacer * 3.25 - } -} - -const useStyles = makeStyles(styles) - -const WizardSplash = ({ name, onContinue }) => { - const classes = useStyles() - - return ( -
-
-

- - Enable cash-out -

- {name} -

- You are about to activate cash-out functionality on your {name}{' '} - machine which will allow your customers to sell crypto to you. -

-

- In order to activate cash-out for this machine, please enter the - denominations for the machine. -

-
- -
- ) -} - -export default WizardSplash diff --git a/new-lamassu-admin/src/pages/Cashout/WizardStep.styles.js b/new-lamassu-admin/src/pages/Cashout/WizardStep.styles.js deleted file mode 100644 index 4cd13301..00000000 --- a/new-lamassu-admin/src/pages/Cashout/WizardStep.styles.js +++ /dev/null @@ -1,61 +0,0 @@ -import { errorColor, spacer } from 'src/styling/variables' - -const LABEL_WIDTH = 150 - -export default { - title: { - margin: [[0, 0, 12, 0]] - }, - titleDiv: { - paddingBottom: 32 - }, - subtitle: { - margin: [[32, 0, 21, 0]] - }, - edit: { - margin: [[0, 0, 0, 0]] - }, - error: { - color: errorColor - }, - bill: { - width: 131, - display: 'flex', - alignItems: 'center', - justifyContent: 'end' - }, - billInput: { - width: '100%' - }, - suffix: { - paddingLeft: spacer * 2 - }, - submit: { - alignSelf: 'flex-end' - }, - picker: { - width: LABEL_WIDTH - }, - header: { - display: 'flex' - }, - column: { - display: 'flex', - flexGrow: 2, - flexDirection: 'column', - paddingBottom: 32, - justifyContent: 'space-between' - }, - step: { - flex: 1 - }, - stepImage: { - position: 'relative', - top: -20, - right: 14 - }, - disclaimerIcon: { - float: 'left', - margin: [[2, 16, 48, 0]] - } -} diff --git a/new-lamassu-admin/src/pages/Customers/CustomerData.styles.js b/new-lamassu-admin/src/pages/Customers/CustomerData.styles.js deleted file mode 100644 index 373e2f0c..00000000 --- a/new-lamassu-admin/src/pages/Customers/CustomerData.styles.js +++ /dev/null @@ -1,49 +0,0 @@ -import { offColor } from 'src/styling/variables' - -export default { - header: { - display: 'flex', - flexDirection: 'row', - marginBottom: 15 - }, - title: { - marginTop: 7, - marginRight: 24 - }, - editIcon: { - marginTop: 5 - }, - cardIcon: { - marginTop: 7 - }, - viewIcons: { - marginRight: 12 - }, - wrapper: { - display: 'block', - overflow: 'hidden', - whiteSpace: 'nowrap' - }, - separator: { - color: offColor, - margin: [[8, 0, 8, 150]], - position: 'relative', - display: 'inline-block', - '&:before, &:after': { - content: '""', - position: 'absolute', - background: offColor, - top: '50%', - width: 1000, - height: 1 - }, - '&:before': { - right: '100%', - marginRight: 15 - }, - '&:after': { - left: '100%', - marginLeft: 15 - } - } -} diff --git a/new-lamassu-admin/src/pages/Customers/CustomerNotes.styles.js b/new-lamassu-admin/src/pages/Customers/CustomerNotes.styles.js deleted file mode 100644 index 4ba177b2..00000000 --- a/new-lamassu-admin/src/pages/Customers/CustomerNotes.styles.js +++ /dev/null @@ -1,17 +0,0 @@ -const styles = { - header: { - display: 'flex', - flexDirection: 'row' - }, - title: { - marginTop: 7, - marginRight: 24 - }, - notesChipList: { - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap' - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/Customers/CustomerPhotos.styles.js b/new-lamassu-admin/src/pages/Customers/CustomerPhotos.styles.js deleted file mode 100644 index 93d8637f..00000000 --- a/new-lamassu-admin/src/pages/Customers/CustomerPhotos.styles.js +++ /dev/null @@ -1,38 +0,0 @@ -const styles = { - header: { - display: 'flex', - flexDirection: 'row' - }, - title: { - marginTop: 7, - marginRight: 24, - marginBottom: 32 - }, - photosChipList: { - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - gap: 14 - }, - image: { - objectFit: 'cover', - objectPosition: 'center', - width: 224, - height: 200, - borderTopLeftRadius: 4, - borderTopRightRadius: 4 - }, - photoCardChip: { - cursor: 'pointer' - }, - footer: { - display: 'flex', - flexDirection: 'row', - margin: [[8, 0, 0, 8]] - }, - date: { - margin: [[0, 0, 8, 12]] - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/Customers/CustomerProfile.styles.js b/new-lamassu-admin/src/pages/Customers/CustomerProfile.styles.js deleted file mode 100644 index 76337795..00000000 --- a/new-lamassu-admin/src/pages/Customers/CustomerProfile.styles.js +++ /dev/null @@ -1,81 +0,0 @@ -import { comet, subheaderColor, spacer } from 'src/styling/variables' - -export default { - labelLink: { - cursor: 'pointer', - color: comet - }, - breadcrumbs: { - margin: [[20, 0]] - }, - actionLabel: { - color: comet, - margin: [[4, 0]] - }, - customerDetails: { - marginBottom: 18 - }, - actionButton: { - margin: [[0, 0, 4, 0]], - display: 'flex', - flexDirection: 'row', - justifyContent: 'center' - }, - actionBar: { - display: 'flex', - flexDirection: 'column', - width: 219 - }, - panels: { - display: 'flex' - }, - rightSidePanel: { - display: 'block', - width: 1100, - marginBottom: 25 - }, - leftSidePanel: { - width: 300, - '& > *': { - marginBottom: 25 - }, - '& > *:last-child': { - marginBottom: 0 - }, - '& > *:first-child': { - marginBottom: 50 - } - }, - userStatusAction: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - backgroundColor: subheaderColor, - borderRadius: 8, - padding: [[0, 5]] - }, - closeButton: { - display: 'flex', - padding: [[spacer * 2, spacer * 2, 0, spacer * 2]], - paddingRight: spacer * 1.5, - justifyContent: 'end' - }, - dialogTitle: { - margin: [[0, spacer * 2, spacer, spacer * 4 + spacer]] - }, - dialogContent: { - width: 615, - marginLeft: 16 - }, - dialogActions: { - padding: spacer * 4, - paddingTop: spacer * 2 - }, - cancelButton: { - marginRight: 8, - padding: 0 - }, - errorMessage: { - marginLeft: 38 - } -} diff --git a/new-lamassu-admin/src/pages/Customers/CustomersList.styles.js b/new-lamassu-admin/src/pages/Customers/CustomersList.styles.js deleted file mode 100644 index f2637636..00000000 --- a/new-lamassu-admin/src/pages/Customers/CustomersList.styles.js +++ /dev/null @@ -1,117 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import baseStyles from 'src/pages/Logs.styles' -import { zircon, comet, primaryColor, fontSize4 } from 'src/styling/variables' - -const { label1 } = typographyStyles -const { titleWrapper, titleAndButtonsContainer } = baseStyles - -export default { - titleWrapper, - titleAndButtonsContainer, - row: { - display: 'flex', - flexFlow: 'row nowrap' - }, - rowSpaceBetween: { - display: 'flex', - flexFlow: 'row nowrap', - alignItems: 'center', - justifyContent: 'space-between' - }, - column: { - display: 'flex', - flexFlow: 'column nowrap', - width: '100%', - height: '100%', - justifyContent: 'space-between' - }, - textInput: { - width: 144 - }, - p: { - fontFamily: 'MuseoSans', - fontSize: fontSize4, - fontWeight: 500, - fontStretch: 'normal', - fontStyle: 'normal', - lineHeight: 1.14, - letterSpacing: 'normal', - color: primaryColor - }, - txId: { - fontFamily: 'MuseoSans', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis' - }, - txClassIconLeft: { - marginRight: 11 - }, - txClassIconRight: { - marginLeft: 11 - }, - headerLabels: { - display: 'flex', - flexDirection: 'row', - '& div': { - display: 'flex', - alignItems: 'center' - }, - '& > div:first-child': { - marginRight: 24 - }, - '& span': { - extend: label1, - marginLeft: 6 - } - }, - photo: { - width: 92, - height: 92, - borderRadius: 8, - backgroundColor: zircon, - margin: [[0, 28, 0, 0]], - alignItems: 'center', - justifyContent: 'center', - display: 'flex' - }, - img: { - width: 80 - }, - customerName: { - marginBottom: 32 - }, - icon: { - marginRight: 11 - }, - name: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center' - }, - value: { - height: 16 - }, - label: { - marginBottom: 4, - color: comet - }, - txSummaryValue: { - height: 16, - marginRight: 25 - }, - txSummaryLabel: { - marginBottom: 4, - color: comet, - marginRight: 25 - }, - idIcon: { - marginRight: 10 - }, - subpageButton: { - marginLeft: 16 - }, - txTableSpacing: { - marginTop: 40 - } -} diff --git a/new-lamassu-admin/src/pages/Customers/components/CustomInfoRequestsData.jsx b/new-lamassu-admin/src/pages/Customers/components/CustomInfoRequestsData.jsx deleted file mode 100644 index e57064aa..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/CustomInfoRequestsData.jsx +++ /dev/null @@ -1,194 +0,0 @@ -import { useMutation } from '@apollo/react-hooks' -import { makeStyles } from '@material-ui/core' -import classnames from 'classnames' -import gql from 'graphql-tag' -import React, { useState } from 'react' -import Modal from 'src/components/Modal' -import { MainStatus } from 'src/components/Status' -import { - Table, - THead, - Th, - Tr, - Td, - TBody -} from 'src/components/fake-table/Table' -import { H3, Label1 } from 'src/components/typography' -import AuthorizeReversedIcon from 'src/styling/icons/button/authorize/white.svg?react' -import AuthorizeIcon from 'src/styling/icons/button/authorize/zodiac.svg?react' -import RejectReversedIcon from 'src/styling/icons/button/cancel/white.svg?react' -import RejectIcon from 'src/styling/icons/button/cancel/zodiac.svg?react' -import LinkIcon from 'src/styling/icons/month arrows/right.svg?react' - -import { ActionButton } from 'src/components/buttons' -import { white, disabledColor } from 'src/styling/variables' - -import DetailsCard from '../../Triggers/CustomInfoRequests/DetailsCard' -const styles = { - white: { - color: white - }, - actionButton: { - display: 'flex', - height: 28, - marginRight: 'auto' - }, - flex: { - display: 'flex' - }, - disabledBtn: { - backgroundColor: disabledColor, - '&:hover': { - backgroundColor: disabledColor - } - }, - linkIcon: { - marginTop: 12, - marginLeft: 4, - cursor: 'pointer' - } -} - -const SET_AUTHORIZED_REQUEST = gql` - mutation setAuthorizedCustomRequest( - $customerId: ID! - $infoRequestId: ID! - $override: String! - ) { - setAuthorizedCustomRequest( - customerId: $customerId - infoRequestId: $infoRequestId - override: $override - ) - } -` - -const useStyles = makeStyles(styles) -const CustomInfoRequestsData = ({ data }) => { - const classes = useStyles() - const [toView, setToView] = useState(null) - const [setAuthorized] = useMutation(SET_AUTHORIZED_REQUEST, { - onError: () => console.error('Error while clearing notification'), - refetchQueries: () => ['customer'] - }) - - const authorize = it => - setAuthorized({ - variables: { - customerId: it.customerId, - infoRequestId: it.customInfoRequest.id, - isAuthorized: true - } - }) - - const reject = it => - setAuthorized({ - variables: { - customerId: it.customerId, - infoRequestId: it.customInfoRequest.id, - isAuthorized: false - } - }) - - const getBtnClasses = (it, isAuthorize) => { - return { - [classes.actionButton]: true, - [classes.disabledBtn]: - (isAuthorize && it.approved === true) || - (!isAuthorize && it.approved === false) - } - } - - const AuthorizeButton = it => ( - authorize(it)}> - Authorize - - ) - - const RejectButton = it => ( - reject(it)}> - Reject - - ) - - const getActionButtons = it => { - return ( - <> - {AuthorizeButton(it)} - {RejectButton(it)} - - ) - } - - const getAuthorizedStatus = it => - it.approved === null - ? { label: 'Pending', type: 'neutral' } - : it.approved === false - ? { label: 'Rejected', type: 'error' } - : { label: 'Accepted', type: 'success' } - - return ( - <> -

Custom Info Requests Data

-
- - - - - - - - - {data.map((it, idx) => ( - - - - - - - - - ))} - -
Custom Request NameCustom Request DataStatus - Actions -
-
- {it.customInfoRequest.customRequest.name} -
setToView(it)}> - -
-
-
-
{JSON.stringify(it.customerData.data, null, 2)}
-
- - -
{getActionButtons(it)}
-
- {toView && ( - setToView(null)}> -

Custom Information Request Details

- -
- )} -
- - ) -} - -export default CustomInfoRequestsData diff --git a/new-lamassu-admin/src/pages/Customers/components/CustomerSidebar.jsx b/new-lamassu-admin/src/pages/Customers/components/CustomerSidebar.jsx deleted file mode 100644 index e4e90871..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/CustomerSidebar.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React from 'react' -import CustomerDataReversedIcon from 'src/styling/icons/customer-nav/data/comet.svg?react' -import CustomerDataIcon from 'src/styling/icons/customer-nav/data/white.svg?react' -import NoteReversedIcon from 'src/styling/icons/customer-nav/note/comet.svg?react' -import NoteIcon from 'src/styling/icons/customer-nav/note/white.svg?react' -import OverviewReversedIcon from 'src/styling/icons/customer-nav/overview/comet.svg?react' -import OverviewIcon from 'src/styling/icons/customer-nav/overview/white.svg?react' -import PhotosReversedIcon from 'src/styling/icons/customer-nav/photos/comet.svg?react' -import Photos from 'src/styling/icons/customer-nav/photos/white.svg?react' - -import styles from './CustomerSidebar.styles' - -const useStyles = makeStyles(styles) - -const CustomerSidebar = ({ isSelected, onClick }) => { - const classes = useStyles() - const sideBarOptions = [ - { - code: 'overview', - display: 'Overview', - Icon: OverviewIcon, - InverseIcon: OverviewReversedIcon - }, - { - code: 'customerData', - display: 'Customer data', - Icon: CustomerDataIcon, - InverseIcon: CustomerDataReversedIcon - }, - { - code: 'notes', - display: 'Notes', - Icon: NoteIcon, - InverseIcon: NoteReversedIcon - }, - { - code: 'photos', - display: 'Photos & files', - Icon: Photos, - InverseIcon: PhotosReversedIcon - } - ] - - return ( -
- {sideBarOptions?.map(({ Icon, InverseIcon, display, code }, idx) => ( -
onClick(code)}> -
- {isSelected(code) ? : } -
- {display} -
- ))} -
- ) -} - -export default CustomerSidebar diff --git a/new-lamassu-admin/src/pages/Customers/components/CustomerSidebar.styles.js b/new-lamassu-admin/src/pages/Customers/components/CustomerSidebar.styles.js deleted file mode 100644 index 9485c7f4..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/CustomerSidebar.styles.js +++ /dev/null @@ -1,41 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { zircon, offDarkColor, white } from 'src/styling/variables' - -const { tl2, p } = typographyStyles - -const sidebarColor = zircon - -export default { - sidebar: { - display: 'flex', - backgroundColor: sidebarColor, - width: 219, - flexDirection: 'column', - borderRadius: 5 - }, - link: { - alignItems: 'center', - display: 'flex', - extend: p, - position: 'relative', - color: offDarkColor, - padding: 15, - cursor: 'pointer' - }, - activeLink: { - display: 'flex', - alignItems: 'center', - extend: tl2, - color: white, - backgroundColor: offDarkColor, - '&:first-child': { - borderRadius: [[5, 5, 0, 0]] - }, - '&:last-child': { - borderRadius: [[0, 0, 5, 5]] - } - }, - icon: { - marginRight: 15 - } -} diff --git a/new-lamassu-admin/src/pages/Customers/components/EditableCard.jsx b/new-lamassu-admin/src/pages/Customers/components/EditableCard.jsx deleted file mode 100644 index bef6d6b0..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/EditableCard.jsx +++ /dev/null @@ -1,421 +0,0 @@ -import { CardContent, Card, Grid } from '@material-ui/core' -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import { Form, Formik, Field as FormikField } from 'formik' -import * as R from 'ramda' -import { useState, React, useRef } from 'react' -// import { HelpTooltip } from 'src/components/Tooltip' -import ErrorMessage from 'src/components/ErrorMessage' -import PromptWhenDirty from 'src/components/PromptWhenDirty' -import { MainStatus } from 'src/components/Status' -import { Label1, P, H3 } from 'src/components/typography' -import DeleteIcon from 'src/styling/icons/action/delete/enabled.svg?react' -import DeleteReversedIcon from 'src/styling/icons/action/delete/white.svg?react' -import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react' -import EditReversedIcon from 'src/styling/icons/action/edit/white.svg?react' -import AuthorizeIcon from 'src/styling/icons/button/authorize/white.svg?react' -import BlockIcon from 'src/styling/icons/button/block/white.svg?react' -import CancelReversedIcon from 'src/styling/icons/button/cancel/white.svg?react' -import DataReversedIcon from 'src/styling/icons/button/data/white.svg?react' -import DataIcon from 'src/styling/icons/button/data/zodiac.svg?react' -import ReplaceReversedIcon from 'src/styling/icons/button/replace/white.svg?react' -import SaveReversedIcon from 'src/styling/icons/circle buttons/save/white.svg?react' - -import { ActionButton } from 'src/components/buttons' -import { - OVERRIDE_AUTHORIZED, - OVERRIDE_REJECTED, - OVERRIDE_PENDING -} from 'src/pages/Customers/components/propertyCard' -import { comet } from 'src/styling/variables' - -import styles from './EditableCard.styles' - -const useStyles = makeStyles(styles) - -const fieldStyles = { - field: { - position: 'relative', - width: 280, - height: 48, - padding: [[0, 4, 4, 0]], - marginTop: 2 - }, - label: { - color: comet, - margin: [[0, 0, 0, 0]] - }, - notEditing: { - display: 'flex', - flexDirection: 'column', - '& > p:first-child': { - height: 16, - lineHeight: '16px', - transformOrigin: 'left', - paddingLeft: 0, - margin: [[3, 0, 3, 0]] - }, - '& > p:last-child': { - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - margin: 0 - } - }, - editing: { - '& > div': { - '& > input': { - padding: 0, - fontSize: 14 - } - } - }, - readOnlyLabel: { - color: comet, - margin: [[3, 0, 3, 0]] - }, - readOnlyValue: { - margin: 0 - } -} - -const fieldUseStyles = makeStyles(fieldStyles) - -const EditableField = ({ editing, field, value, size, ...props }) => { - const classes = fieldUseStyles() - const classNames = { - [classes.field]: true, - [classes.notEditing]: !editing - } - - return ( -
- {!editing && ( - <> - {field.label} -

{value}

- - )} - {editing && ( - <> - {field.label} - - - )} -
- ) -} - -const ReadOnlyField = ({ field, value, ...props }) => { - const classes = fieldUseStyles() - const classNames = { - [classes.field]: true, - [classes.notEditing]: true - } - - return ( - <> -
- {field.label} -

{value}

-
- - ) -} - -const EditableCard = ({ - fields, - save = () => {}, - cancel = () => {}, - authorize = () => {}, - hasImage, - reject = () => {}, - state, - title, - titleIcon, - children = () => {}, - validationSchema, - initialValues, - deleteEditedData, - retrieveAdditionalData, - hasAdditionalData = true, - editable, - checkAgainstSanctions -}) => { - const classes = useStyles() - - const formRef = useRef() - - const [editing, setEditing] = useState(false) - const [input, setInput] = useState(null) - const [error, setError] = useState(null) - - const triggerInput = () => input.click() - - const label1ClassNames = { - [classes.label1]: true, - [classes.label1Pending]: state === OVERRIDE_PENDING, - [classes.label1Rejected]: state === OVERRIDE_REJECTED, - [classes.label1Accepted]: state === OVERRIDE_AUTHORIZED - } - const authorized = - state === OVERRIDE_PENDING - ? { label: 'Pending', type: 'neutral' } - : state === OVERRIDE_REJECTED - ? { label: 'Rejected', type: 'error' } - : { label: 'Accepted', type: 'success' } - - return ( -
- - -
-
- {titleIcon} -

{title}

- { - // TODO: Enable for next release - /* */ - } -
- {state && authorize && ( -
- -
- )} -
- {children(formRef.current?.values ?? {})} - { - save(values) - setEditing(false) - }} - onReset={() => { - setEditing(false) - setError(false) - }}> - {({ setFieldValue }) => ( -
- -
- - - {!hasImage && - fields?.map((field, idx) => { - return idx >= 0 && idx < 4 ? ( - !field.editable ? ( - - ) : ( - - ) - ) : null - })} - - - {!hasImage && - fields?.map((field, idx) => { - return idx >= 4 ? ( - !field.editable ? ( - - ) : ( - - ) - ) : null - })} - - -
-
- {!editing && ( -
-
- {/*{false && (*/} - {/* deleteEditedData()}>*/} - {/* Delete*/} - {/* */} - {/*)}*/} - {!hasAdditionalData && ( - retrieveAdditionalData()}> - Retrieve API data - - )} - {checkAgainstSanctions && ( - checkAgainstSanctions()}> - Check against OFAC sanction list - - )} -
- {editable && ( - setEditing(true)}> - Edit - - )} - {!editable && - authorize && - authorized.label !== 'Accepted' && ( -
- authorize()}> - Authorize - -
- )} - {!editable && - authorize && - authorized.label !== 'Rejected' && ( - reject()}> - Reject - - )} -
- )} - {editing && ( -
-
- {hasImage && state !== OVERRIDE_PENDING && ( - triggerInput()}> - { -
- setInput(fileInput)} - onChange={event => { - // need to store it locally if we want to display it even after saving to db - const file = R.head(event.target.files) - if (!file) return - setFieldValue(R.head(fields).name, file) - }} - /> - Replace -
- } -
- )} -
-
- {fields && ( -
- - Save - -
- )} -
- cancel()} - type="reset"> - Cancel - -
- {authorize && authorized.label !== 'Accepted' && ( -
- authorize()}> - Authorize - -
- )} - {authorize && authorized.label !== 'Rejected' && ( - reject()}> - Reject - - )} - {error && ( - Failed to save changes - )} -
-
- )} -
- - )} -
-
-
-
- ) -} - -export default EditableCard diff --git a/new-lamassu-admin/src/pages/Customers/components/EditableCard.styles.js b/new-lamassu-admin/src/pages/Customers/components/EditableCard.styles.js deleted file mode 100644 index 3ef803d2..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/EditableCard.styles.js +++ /dev/null @@ -1,70 +0,0 @@ -import { tomato, spring4, comet } from 'src/styling/variables' - -export default { - label1: { - display: 'flex', - width: 85, - justifyContent: 'right' - }, - label1Pending: { - color: comet - }, - label1Rejected: { - color: tomato - }, - label1Accepted: { - color: spring4 - }, - editButton: { - marginTop: 20, - display: 'flex', - justifyContent: 'right' - }, - deleteButton: { - marginRight: 8 - }, - headerWrapper: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - height: 40 - }, - editingWrapper: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - marginTop: 20 - }, - replace: { - marginRight: 5 - }, - input: { - display: 'none' - }, - button: { - marginRight: 5 - }, - editingButtons: { - display: 'flex', - justifyContent: 'right' - }, - card: { - borderRadius: 10, - marginRight: 15, - marginBottom: 15 - }, - cardHeader: { - display: 'flex', - flexDirection: 'row', - marginBottom: 15 - }, - editIcon: { - marginTop: 5 - }, - cardIcon: { - marginTop: 7 - }, - cardTitle: { - margin: [[8, 15, 15, 15]] - } -} diff --git a/new-lamassu-admin/src/pages/Customers/components/Field.jsx b/new-lamassu-admin/src/pages/Customers/components/Field.jsx deleted file mode 100644 index ed15738d..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/Field.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' -import { Info3, Label1 } from 'src/components/typography' - -import { comet } from 'src/styling/variables' - -const useStyles = makeStyles({ - field: { - height: 46 - }, - label: { - color: comet, - margin: [[0, 3]] - }, - value: { - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - margin: 0, - paddingLeft: 4 - } -}) - -const Field = memo(({ label, display, size, className }) => { - const classes = useStyles() - - return ( -
- {label} - {display} -
- ) -}) - -export default Field diff --git a/new-lamassu-admin/src/pages/Customers/components/FrontCameraPhoto.jsx b/new-lamassu-admin/src/pages/Customers/components/FrontCameraPhoto.jsx deleted file mode 100644 index 10ee5ffa..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/FrontCameraPhoto.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Paper } from '@material-ui/core' -import { makeStyles } from '@material-ui/core/styles' -import React, { memo } from 'react' -import CrossedCameraIcon from 'src/styling/icons/ID/photo/crossed-camera.svg?react' - -import mainStyles from '../CustomersList.styles' - -const useStyles = makeStyles(mainStyles) - -const FrontCameraPhoto = memo(({ frontCameraPath }) => { - const classes = useStyles() - - return ( - - {frontCameraPath ? ( - - ) : ( - - )} - - ) -}) - -export default FrontCameraPhoto diff --git a/new-lamassu-admin/src/pages/Customers/components/IdCardPhotoCard.jsx b/new-lamassu-admin/src/pages/Customers/components/IdCardPhotoCard.jsx deleted file mode 100644 index 44ac023f..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/IdCardPhotoCard.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import { makeStyles, Box } from '@material-ui/core' -import * as R from 'ramda' -import React, { memo } from 'react' -import CrossedCameraIcon from 'src/styling/icons/ID/photo/crossed-camera.svg?react' - -import { - PropertyCard, - OVERRIDE_AUTHORIZED, - OVERRIDE_REJECTED -} from 'src/pages/Customers/components/propertyCard' - -const useStyles = makeStyles({ - idCardPhotoCard: { - width: 325, - height: 240, - margin: [[32, 0, 0, 0]] - }, - idCardPhoto: { - maxHeight: 130 - }, - field: { - marginLeft: 14 - } -}) - -const IdCardPhotoCard = memo(({ customerData, updateCustomer }) => { - const classes = useStyles() - - return ( - - updateCustomer({ idCardPhotoOverride: OVERRIDE_AUTHORIZED }) - } - reject={() => updateCustomer({ idCardPhotoOverride: OVERRIDE_REJECTED })}> - - {customerData.idCardPhotoPath ? ( - - ) : ( - - )} - - - ) -}) - -export default IdCardPhotoCard diff --git a/new-lamassu-admin/src/pages/Customers/components/IdDataCard.jsx b/new-lamassu-admin/src/pages/Customers/components/IdDataCard.jsx deleted file mode 100644 index 12a838db..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/IdDataCard.jsx +++ /dev/null @@ -1,89 +0,0 @@ -import { Box } from '@material-ui/core' -import { differenceInYears, format, parse } from 'date-fns/fp' -import * as R from 'ramda' -import React, { memo } from 'react' - -import { - PropertyCard, - OVERRIDE_AUTHORIZED, - OVERRIDE_REJECTED -} from 'src/pages/Customers/components/propertyCard' -import { ifNotNull } from 'src/utils/nullCheck' - -import { getName } from '../helper' - -import Field from './Field' - -const IdDataCard = memo(({ customerData, updateCustomer }) => { - const idData = R.path(['idCardData'])(customerData) - const rawExpirationDate = R.path(['expirationDate'])(idData) - const country = R.path(['country'])(idData) - const rawDob = R.path(['dateOfBirth'])(idData) - - const elements = [ - { - header: 'Name', - display: `${getName(customerData)}`, - size: 190 - }, - { - header: 'ID number', - display: R.path(['documentNumber'])(idData), - size: 160 - }, - { - header: 'Birth date', - display: - (rawDob && - format('yyyy-MM-dd')(parse(new Date(), 'yyyyMMdd', rawDob))) ?? - '', - size: 110 - }, - { - header: 'Age', - display: - (rawDob && - differenceInYears( - parse(new Date(), 'yyyyMMdd', rawDob), - new Date() - )) ?? - '', - size: 50 - }, - { - header: 'Gender', - display: R.path(['gender'])(idData) ?? R.path(['sex'])(idData), - size: 80 - }, - { - header: country === 'Canada' ? 'Province' : 'State', - display: R.path(['state'])(idData), - size: 120 - }, - { - header: 'Expiration date', - display: ifNotNull( - rawExpirationDate, - format('yyyy-MM-dd', rawExpirationDate) - ) - } - ] - - return ( - - updateCustomer({ idCardDataOverride: OVERRIDE_AUTHORIZED }) - } - reject={() => updateCustomer({ idCardDataOverride: OVERRIDE_REJECTED })}> - - {elements.map(({ header, display, size }, idx) => ( - - ))} - - - ) -}) - -export default IdDataCard diff --git a/new-lamassu-admin/src/pages/Customers/components/PhoneCard.jsx b/new-lamassu-admin/src/pages/Customers/components/PhoneCard.jsx deleted file mode 100644 index 74dcd3f5..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/PhoneCard.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import { parsePhoneNumberFromString } from 'libphonenumber-js' -import * as R from 'ramda' -import React, { memo } from 'react' - -import { - PropertyCard, - OVERRIDE_AUTHORIZED, - OVERRIDE_REJECTED -} from 'src/pages/Customers/components/propertyCard' - -import Field from './Field' - -const PhoneCard = memo( - ({ className, customerData, updateCustomer, locale }) => ( - updateCustomer({ smsOverride: OVERRIDE_AUTHORIZED })} - reject={() => updateCustomer({ smsOverride: OVERRIDE_REJECTED })}> - - - ) -) - -export default PhoneCard diff --git a/new-lamassu-admin/src/pages/Customers/components/PhotosCard.styles.js b/new-lamassu-admin/src/pages/Customers/components/PhotosCard.styles.js deleted file mode 100644 index 5d974078..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/PhotosCard.styles.js +++ /dev/null @@ -1,42 +0,0 @@ -import { zircon, backgroundColor } from 'src/styling/variables' - -export default { - photo: { - width: 135, - height: 135, - borderRadius: 8, - backgroundColor: zircon, - margin: [[0, 28, 0, 0]], - alignItems: 'center', - justifyContent: 'center', - display: 'flex' - }, - img: { - objectFit: 'cover', - objectPosition: 'center', - width: 135, - height: 135 - }, - container: { - position: 'relative', - '& > img': { - display: 'block' - }, - '& > circle': { - position: 'absolute', - top: '0', - right: '0', - marginRight: 5, - marginTop: 5 - } - }, - circle: { - background: backgroundColor, - borderRadius: '50%', - width: 25, - height: 25, - alignItems: 'center', - justifyContent: 'center', - display: 'flex' - } -} diff --git a/new-lamassu-admin/src/pages/Customers/components/PhotosCarousel.styles.js b/new-lamassu-admin/src/pages/Customers/components/PhotosCarousel.styles.js deleted file mode 100644 index 03d3f755..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/PhotosCarousel.styles.js +++ /dev/null @@ -1,30 +0,0 @@ -import typographyStyles from 'src/components/typography/styles' -import { offColor } from 'src/styling/variables' - -const { p } = typographyStyles - -export default { - label: { - color: offColor, - margin: [[0, 0, 6, 0]] - }, - firstRow: { - padding: [[8]], - display: 'flex', - flexDirection: 'column' - }, - secondRow: { - extend: p, - display: 'flex', - padding: [[8]], - '& > div': { - display: 'flex', - flexDirection: 'column', - '& > div': { - height: 37, - marginBottom: 15, - marginRight: 55 - } - } - } -} diff --git a/new-lamassu-admin/src/pages/Customers/components/Upload.jsx b/new-lamassu-admin/src/pages/Customers/components/Upload.jsx deleted file mode 100644 index 17bce94f..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/Upload.jsx +++ /dev/null @@ -1,105 +0,0 @@ -import { makeStyles } from '@material-ui/core/styles' -import { useFormikContext } from 'formik' -import * as R from 'ramda' -import React, { useState, useCallback } from 'react' -import { useDropzone } from 'react-dropzone' -import { Label3, H3 } from 'src/components/typography' -import UploadPhotoIcon from 'src/styling/icons/button/photo/zodiac-resized.svg?react' -import UploadFileIcon from 'src/styling/icons/button/upload-file/zodiac-resized.svg?react' - -import { offColor, subheaderColor } from 'src/styling/variables' - -const useStyles = makeStyles({ - box: { - boxSizing: 'border-box', - width: 450, - height: 120, - borderStyle: 'dashed', - borderColor: offColor, - borderRadius: 4, - borderWidth: 1, - backgroundColor: subheaderColor, - display: 'flex', - justifyContent: 'center' - }, - inputContent: { - marginTop: 35, - display: 'flex' - }, - uploadContent: { - marginTop: 50, - display: 'flex' - }, - board: { - marginTop: 40, - width: 450, - height: 120 - }, - icon: { - margin: [[14, 20, 0, 0]] - } -}) - -const Upload = ({ type }) => { - const classes = useStyles() - - const [data, setData] = useState({}) - - const { setFieldValue } = useFormikContext() - - const IMAGE = 'image' - const ID_CARD_PHOTO = 'idCardPhoto' - const FRONT_CAMERA = 'frontCamera' - - const isImage = - type === IMAGE || type === FRONT_CAMERA || type === ID_CARD_PHOTO - - const onDrop = useCallback( - acceptedData => { - setFieldValue(type, R.head(acceptedData)) - - setData({ - preview: isImage - ? URL.createObjectURL(R.head(acceptedData)) - : R.head(acceptedData).name - }) - }, - [isImage, type, setFieldValue] - ) - - const { getRootProps, getInputProps } = useDropzone({ onDrop }) - - return ( - <> -
- {R.isEmpty(data) && ( -
- -
- {isImage ? ( - - ) : ( - - )} - {`Drag and drop ${ - isImage ? 'an image' : 'a file' - } or click to open the explorer`} -
-
- )} - {!R.isEmpty(data) && isImage && ( -
- -
- )} - {!R.isEmpty(data) && !isImage && ( -
-

{data.preview}

-
- )} -
- - ) -} - -export default Upload diff --git a/new-lamassu-admin/src/pages/Customers/components/notes/NewNoteCard.jsx b/new-lamassu-admin/src/pages/Customers/components/notes/NewNoteCard.jsx deleted file mode 100644 index 65388602..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/notes/NewNoteCard.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import { makeStyles, Paper } from '@material-ui/core' -import classNames from 'classnames' -import { React } from 'react' -import { P } from 'src/components/typography' -import AddIcon from 'src/styling/icons/button/add/zodiac.svg?react' - -import styles from './NoteCard.styles' - -const useStyles = makeStyles(styles) - -const NewNoteCard = ({ setOpenModal }) => { - const classes = useStyles() - return ( -
setOpenModal(true)}> - - -

Add new

-
-
- ) -} - -export default NewNoteCard diff --git a/new-lamassu-admin/src/pages/Customers/components/notes/NewNoteModal.styles.js b/new-lamassu-admin/src/pages/Customers/components/notes/NewNoteModal.styles.js deleted file mode 100644 index a42ecd41..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/notes/NewNoteModal.styles.js +++ /dev/null @@ -1,25 +0,0 @@ -import { spacer } from 'src/styling/variables' - -const styles = { - form: { - display: 'flex', - flexDirection: 'column', - height: '100%', - '& > *': { - marginTop: 20 - }, - '& > *:last-child': { - marginTop: 'auto' - } - }, - submit: { - margin: [['auto', 0, 0, 'auto']] - }, - footer: { - display: 'flex', - flexDirection: 'row', - margin: [['auto', 0, spacer * 3, 0]] - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/Customers/components/notes/NoteCard.jsx b/new-lamassu-admin/src/pages/Customers/components/notes/NoteCard.jsx deleted file mode 100644 index 3ce56ce3..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/notes/NoteCard.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import { makeStyles, Paper } from '@material-ui/core' -import * as R from 'ramda' -import { React } from 'react' -import { H3, P } from 'src/components/typography' -import DeleteIcon from 'src/styling/icons/action/delete/enabled.svg?react' - -import { formatDate } from 'src/utils/timezones' - -import styles from './NoteCard.styles' - -const useStyles = makeStyles(styles) - -const formatContent = content => { - const fragments = R.split(/\n/)(content) - return R.map((it, idx) => { - if (idx === fragments.length) return <>{it} - return ( - <> - {it} -
- - ) - }, fragments) -} - -const NoteCard = ({ note, deleteNote, handleClick, timezone }) => { - const classes = useStyles() - - return ( -
- handleClick(note)}> -
-
-

{note?.title}

-

{formatDate(note?.created, timezone, 'yyyy-MM-dd')}

-
-
- { - e.stopPropagation() - deleteNote({ noteId: note.id }) - }} - /> -
-
-

- {formatContent(note?.content)} -

-
-
- ) -} - -export default NoteCard diff --git a/new-lamassu-admin/src/pages/Customers/components/notes/NoteCard.styles.js b/new-lamassu-admin/src/pages/Customers/components/notes/NoteCard.styles.js deleted file mode 100644 index 9712fa77..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/notes/NoteCard.styles.js +++ /dev/null @@ -1,93 +0,0 @@ -import { zircon } from 'src/styling/variables' - -const styles = { - noteCardWrapper: { - flexGrow: 0, - flexShrink: 0, - flexBasis: `25%`, - minWidth: 0, - maxWidth: 500, - '&:nth-child(4n+1)': { - '& > div': { - margin: [[0, 10, 0, 0]] - } - }, - '&:nth-child(4n)': { - '& > div': { - margin: [[0, 0, 0, 10]] - } - }, - margin: [[10, 0]] - }, - noteCardChip: { - height: 200, - margin: [[0, 10]], - padding: [[10, 10]], - cursor: 'pointer' - }, - newNoteCard: { - backgroundColor: zircon, - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center' - }, - noteCardHeader: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - width: '100%' - }, - noteCardTitle: { - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - marginRight: 10 - }, - noteCardContent: { - display: 'box', - lineClamp: 7, - boxOrient: 'vertical', - margin: [[15, 0]], - overflow: 'hidden', - textOverflow: 'ellipsis', - wordWrap: 'break-word' - }, - editCardChip: { - height: 325, - padding: 15 - }, - editCardHeader: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 15 - }, - editCardActions: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - '& > *': { - marginRight: 10 - }, - '& > *:last-child': { - marginRight: 0 - } - }, - editNotesContent: { - '& > div': { - '&:after': { - borderBottom: 'none' - }, - '&:before': { - borderBottom: 'none' - }, - '&:hover:not(.Mui-disabled)::before': { - borderBottom: 'none' - } - } - } -} - -export default styles diff --git a/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.jsx b/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.jsx deleted file mode 100644 index 9db47b44..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.jsx +++ /dev/null @@ -1,132 +0,0 @@ -import { Paper } from '@material-ui/core' -import { makeStyles } from '@material-ui/core/styles' -import classnames from 'classnames' -import React, { memo } from 'react' -import { MainStatus } from 'src/components/Status' -import { H3 } from 'src/components/typography' -import AuthorizeReversedIcon from 'src/styling/icons/button/authorize/white.svg?react' -import AuthorizeIcon from 'src/styling/icons/button/authorize/zodiac.svg?react' -import RejectReversedIcon from 'src/styling/icons/button/cancel/white.svg?react' -import RejectIcon from 'src/styling/icons/button/cancel/zodiac.svg?react' -import EditReversedIcon from 'src/styling/icons/button/edit/white.svg?react' -import EditIcon from 'src/styling/icons/button/edit/zodiac.svg?react' - -import { ActionButton } from 'src/components/buttons' - -import { propertyCardStyles } from './PropertyCard.styles' - -const useStyles = makeStyles(propertyCardStyles) - -const OVERRIDE_PENDING = 'automatic' -const OVERRIDE_AUTHORIZED = 'verified' -const OVERRIDE_REJECTED = 'blocked' - -const PropertyCard = memo( - ({ - className, - contentClassName, - title, - state, - authorize, - reject, - edit, - confirm, - isEditing, - formName, - children - }) => { - const classes = useStyles() - - const label1ClassNames = { - [classes.label1]: true, - [classes.label1Pending]: state === OVERRIDE_PENDING, - [classes.label1Rejected]: state === OVERRIDE_REJECTED, - [classes.label1Accepted]: state === OVERRIDE_AUTHORIZED - } - - const AuthorizeButton = () => ( - authorize()}> - Authorize - - ) - - const RejectButton = () => ( - reject()}> - Reject - - ) - - const EditButton = () => ( - edit()}> - Edit - - ) - - const ConfirmButton = () => ( - - Confirm - - ) - - const authorized = - state === OVERRIDE_PENDING - ? { label: 'Pending', type: 'neutral' } - : state === OVERRIDE_REJECTED - ? { label: 'Rejected', type: 'error' } - : { label: 'Accepted', type: 'success' } - - return ( - -

{title}

-
- {state && ( -
- -
- )} - {children} -
- {authorize && state !== OVERRIDE_AUTHORIZED && AuthorizeButton()} - {reject && state !== OVERRIDE_REJECTED && RejectButton()} - {edit && !isEditing && EditButton()} - {confirm && isEditing && ConfirmButton()} -
-
-
- ) - } -) - -export { - PropertyCard, - OVERRIDE_PENDING, - OVERRIDE_AUTHORIZED, - OVERRIDE_REJECTED -} diff --git a/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.styles.js b/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.styles.js deleted file mode 100644 index ff8b334f..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.styles.js +++ /dev/null @@ -1,69 +0,0 @@ -import { white, tomato, spring4, comet } from 'src/styling/variables' - -const propertyCardStyles = { - label1: { - display: 'flex', - marginBottom: 2, - marginTop: 'auto', - width: 85 - }, - label1Pending: { - color: comet - }, - label1Rejected: { - color: tomato - }, - label1Accepted: { - color: spring4 - }, - cardActionButton: { - display: 'flex', - height: 28, - marginRight: 'auto', - marginLeft: 12 - }, - propertyCardTopRow: { - display: 'flex', - margin: [[0, 10, 5, 0]] - }, - propertyCardBottomRow: { - display: 'flex', - flexDirection: 'row', - height: 45 - }, - propertyCard: { - display: 'flex', - flexDirection: 'column', - borderRadius: 8, - width: '100%', - height: 100, - padding: [[20]], - boxSizing: 'border-box', - boxShadow: '0 0 8px 0 rgba(0, 0, 0, 0.04)', - border: 'solid 0', - backgroundColor: white, - margin: [[20, 0, 0, 0]] - }, - rowSpaceBetween: { - display: 'flex', - flexFlow: 'row nowrap', - alignItems: 'center', - justifyContent: 'space-between' - }, - columnSpaceBetween: { - display: 'flex', - flexFlow: 'column nowrap', - alignItems: 'center', - justifyContent: 'space-between', - width: 90 - }, - buttonsWrapper: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'flex-end', - marginLeft: 'auto', - marginTop: 'auto' - } -} - -export { propertyCardStyles } diff --git a/new-lamassu-admin/src/pages/Customers/components/propertyCard/index.js b/new-lamassu-admin/src/pages/Customers/components/propertyCard/index.js deleted file mode 100644 index 3002e26a..00000000 --- a/new-lamassu-admin/src/pages/Customers/components/propertyCard/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import { - PropertyCard, - OVERRIDE_PENDING, - OVERRIDE_AUTHORIZED, - OVERRIDE_REJECTED -} from './PropertyCard' - -export { - PropertyCard, - OVERRIDE_PENDING, - OVERRIDE_AUTHORIZED, - OVERRIDE_REJECTED -} diff --git a/new-lamassu-admin/src/pages/Dashboard/Alerts/Alerts.styles.js b/new-lamassu-admin/src/pages/Dashboard/Alerts/Alerts.styles.js deleted file mode 100644 index eb188b65..00000000 --- a/new-lamassu-admin/src/pages/Dashboard/Alerts/Alerts.styles.js +++ /dev/null @@ -1,57 +0,0 @@ -import { primaryColor, comet } from 'src/styling/variables' - -const styles = { - container: { - display: 'flex', - justifyContent: 'space-between' - }, - h4: { - margin: 0, - marginBottom: 10 - }, - centerLabel: { - marginBottom: 0, - padding: 0, - textAlign: 'center' - }, - upperButtonLabel: { - marginTop: -3, - marginBottom: 24 - }, - button: { - color: primaryColor, - marginTop: 0, - minHeight: 0, - minWidth: 0, - padding: 0, - textTransform: 'none', - '&:hover': { - backgroundColor: 'transparent' - } - }, - alertsTableContainer: { - margin: 0 - }, - expandedAlertsTableContainer: { - margin: 0, - maxHeight: 460 - }, - noAlertsLabel: { - color: comet, - marginLeft: -5, - height: 100 - }, - table: { - maxHeight: 465, - overflowX: 'hidden', - overflowY: 'auto' - }, - listItemText: { - margin: '8px 0 8px 0' - }, - linkIcon: { - marginLeft: 'auto', - cursor: 'pointer' - } -} -export default styles diff --git a/new-lamassu-admin/src/pages/Dashboard/Dashboard.jsx b/new-lamassu-admin/src/pages/Dashboard/Dashboard.jsx deleted file mode 100644 index d64c8b56..00000000 --- a/new-lamassu-admin/src/pages/Dashboard/Dashboard.jsx +++ /dev/null @@ -1,108 +0,0 @@ -import { useQuery } from '@apollo/react-hooks' -import Grid from '@material-ui/core/Grid' -import { makeStyles } from '@material-ui/core/styles' -import gql from 'graphql-tag' -import * as R from 'ramda' -import React, { useState } from 'react' -import { useHistory } from 'react-router-dom' -import TitleSection from 'src/components/layout/TitleSection' -import { H1, Info2, TL2, Label1 } from 'src/components/typography' -import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react' -import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react' - -import { Button } from 'src/components/buttons' -import AddMachine from 'src/pages/AddMachine' -import { errorColor } from 'src/styling/variables' - -import styles from './Dashboard.styles' -import Footer from './Footer' -import LeftSide from './LeftSide' -import RightSide from './RightSide' -const useStyles = makeStyles(styles) - -const GET_DATA = gql` - query getData { - machines { - name - } - serverVersion - } -` - -const Dashboard = () => { - const history = useHistory() - const classes = useStyles() - const [open, setOpen] = useState(false) - - const { data, loading } = useQuery(GET_DATA) - - const onPaired = machine => { - setOpen(false) - history.push('/maintenance/machine-status', { id: machine.deviceId }) - } - - return !loading ? ( - !R.isEmpty(data.machines) ? ( - <> - -
-
- - Cash-in -
-
- - Cash-out -
-
- - - - Action Required -
-
-
-
- - - - - - - - -
-