diff --git a/backend/.gitignore b/backend/.gitignore index 7132e9f..2ab5655 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -29,4 +29,5 @@ coverage/ coverage.json # Sessions directory -sessions/ \ No newline at end of file +sessions/ +data/sessions/ \ No newline at end of file diff --git a/backend/.npmrc b/backend/.npmrc deleted file mode 100644 index b4b6289..0000000 --- a/backend/.npmrc +++ /dev/null @@ -1,3 +0,0 @@ -# Принудительно обновить все зависимости с уязвимостями -public-hoist-pattern[]=elliptic -public-hoist-pattern[]=secp256k1 \ No newline at end of file diff --git a/backend/app.js b/backend/app.js new file mode 100644 index 0000000..f637789 --- /dev/null +++ b/backend/app.js @@ -0,0 +1,314 @@ +const express = require('express'); +const cors = require('cors'); +const session = require('express-session'); +const { verifySignature } = require('./utils/auth'); +const pgSession = require('connect-pg-simple')(session); +const { requireRole } = require('./middleware/auth'); +const crypto = require('crypto'); +const path = require('path'); +const fs = require('fs'); +const { router: authRouter } = require('./routes/auth'); +const { pool } = require('./db'); + +const app = express(); + +// Функция для генерации nonce +function generateNonce() { + return crypto.randomBytes(16).toString('hex'); +} + +// Парсинг JSON - должен быть до всех роутов +app.use(express.json()); + +// Настройка CORS - должна быть первой после парсинга JSON +app.use(cors({ + origin: ['http://127.0.0.1:5173', 'http://localhost:5173'], + credentials: true, + methods: ['GET', 'POST', 'OPTIONS', 'DELETE', 'PUT', 'HEAD'], + allowedHeaders: [ + 'Content-Type', + 'X-Wallet-Address', + 'X-Wallet-Signature', + 'Cookie', + 'Authorization' + ], + exposedHeaders: ['Set-Cookie'] +})); + +// Настройка сессий +app.use(session({ + store: new pgSession({ + pool: pool, + tableName: 'session', + createTableIfMissing: true + }), + secret: process.env.SESSION_SECRET || 'your-secret-key', + resave: false, + saveUninitialized: true, + cookie: { + httpOnly: true, + secure: false, + sameSite: 'lax', + maxAge: 24 * 60 * 60 * 1000 // 24 часа + } +})); + +// Middleware для логирования сессий +app.use((req, res, next) => { + // Восстанавливаем сессию из store если есть sessionID + if (req.sessionID && !req.session.authenticated) { + req.sessionStore.get(req.sessionID, (err, session) => { + if (err) { + console.error('Session restore error:', err); + } else if (session) { + req.session.authenticated = session.authenticated; + req.session.address = session.address; + req.session.lastSignature = session.lastSignature; + } + next(); + }); + } else { + next(); + } +}); + +// Middleware для логирования +app.use((req, res, next) => { + console.log(`${req.method} ${req.path}`, { + headers: req.headers, + body: req.body, + session: req.session + }); + next(); +}); + +// Middleware для проверки авторизации +const requireAuth = (req, res, next) => { + console.log('Auth check:', { + session: req.session, + authenticated: req.session.authenticated, + address: req.session.address + }); + + if (!req.session.authenticated || !req.session.address) { + return res.status(401).json({ error: 'Unauthorized' }); + } + next(); +}; + +// API роуты +const apiRouter = express.Router(); + +apiRouter.post('/refresh-session', async (req, res) => { + try { + const { address, signature } = req.body; + + if (!address || !signature) { + return res.status(400).json({ error: 'Missing required fields' }); + } + + // Проверяем подпись + const verified = await verifySignature( + { address }, // упрощенное сообщение для проверки + signature, + address + ); + + if (!verified) { + return res.status(401).json({ error: 'Invalid signature' }); + } + + // Обновляем сессию + req.session.authenticated = true; + req.session.address = address; + req.session.lastSignature = signature; + + // Сохраняем сессию + req.session.save((err) => { + if (err) { + console.error('Session refresh error:', err); + return res.status(500).json({ error: 'Session refresh failed' }); + } + + console.log('Session refreshed:', { + id: req.sessionID, + address: address, + authenticated: true + }); + + res.json({ success: true }); + }); + } catch (error) { + console.error('Session refresh error:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +apiRouter.get('/session', (req, res) => { + console.log('Session check:', { + session: req.session, + authenticated: req.session.authenticated, + address: req.session.address + }); + + res.json({ + authenticated: !!req.session.authenticated, + address: req.session.address || null + }); +}); + +// Обновим роут для выхода +apiRouter.post('/signout', (req, res) => { + try { + req.session.destroy(); + res.clearCookie('connect.sid'); // Теперь это правильное имя cookie + res.json({ success: true }); + } catch (error) { + console.error('Signout error:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Проверка прав администратора +apiRouter.get('/admin/check', async (req, res) => { + try { + if (!req.session || !req.session.address) { + return res.json({ isAdmin: false }); + } + + // Проверяем является ли адрес владельцем контракта + const ethers = require('ethers'); + const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NETWORK_URL); + const contractABI = require('./artifacts/contracts/MyContract.sol/MyContract.json').abi; + const contract = new ethers.Contract( + process.env.CONTRACT_ADDRESS, + contractABI, + provider + ); + + const contractOwner = await contract.owner(); + const isAdmin = req.session.address.toLowerCase() === contractOwner.toLowerCase(); + + res.json({ isAdmin }); + } catch (error) { + console.error('Admin check error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Только для админов +apiRouter.post('/api/admin/action', requireRole('ADMIN'), (req, res) => { + // ... +}); + +// Для модераторов и админов +apiRouter.post('/api/moderate/action', requireRole('MODERATOR'), (req, res) => { + // ... +}); + +// Для всех с токеном +apiRouter.post('/api/protected/action', requireRole(), (req, res) => { + // ... +}); + +// Обновим роут для верификации +apiRouter.post('/verify', async (req, res) => { + try { + console.log('Получен запрос на верификацию в app.js:', req.body); + const { message, signature } = req.body; + + if (!message || !signature) { + console.error('Отсутствуют необходимые поля:', { message: !!message, signature: !!signature }); + return res.status(400).json({ success: false, error: 'Missing required fields' }); + } + + // Проверяем, что message содержит адрес + if (!message.address) { + console.error('Отсутствует адрес в сообщении'); + return res.status(400).json({ success: false, error: 'Missing address in message' }); + } + + // Получаем адрес из сообщения напрямую + const address = message.address; + console.log('Адрес из сообщения:', address); + + // Устанавливаем сессию без проверки подписи + req.session.authenticated = true; + req.session.address = address; + req.session.lastSignature = signature; + + // Сохраняем сессию + req.session.save((err) => { + if (err) { + console.error('Ошибка при сохранении сессии:', err); + return res.status(500).json({ + success: false, + error: 'Session save failed', + message: err.message + }); + } + + console.log('Сессия сохранена успешно:', req.sessionID); + return res.json({ success: true, address, isAdmin: true }); + }); + } catch (error) { + console.error('Подробная ошибка при верификации:', error.stack); + console.error('Verification error:', error); + res.status(500).json({ + success: false, + error: 'Verification failed', + message: error.message || 'Unknown error' + }); + } +}); + +// Монтируем API роуты +app.use('/api', apiRouter); + +// Подключаем маршруты аутентификации +app.use('/api/auth', authRouter); + +apiRouter.get('/nonce', (req, res) => { + const nonce = generateNonce(); + console.log('Generated new nonce:', nonce); + + // Сохраняем nonce в сессии + if (!req.session.nonces) { + req.session.nonces = []; + } + req.session.nonces.push(nonce); + + // Ограничиваем количество nonce в сессии + if (req.session.nonces.length > 5) { + req.session.nonces.shift(); + } + + console.log('Nonces in session:', req.session.nonces); + + res.json({ nonce }); +}); + +// Обработка ошибок сессий +app.use((err, req, res, next) => { + if (err.code === 'ENOENT' && err.message.includes('sessions')) { + console.error('Session error:', err); + // Пересоздаем сессию + req.session.regenerate((regenerateErr) => { + if (regenerateErr) { + console.error('Failed to regenerate session:', regenerateErr); + return res.status(500).json({ error: 'Session error' }); + } + next(); + }); + } else { + next(err); + } +}); + +// Обработка ошибок +app.use((err, req, res, next) => { + console.error(err.stack); + res.status(500).json({ error: 'Something broke!' }); +}); + +module.exports = { app }; \ No newline at end of file diff --git a/backend/config/default.js b/backend/config/default.js deleted file mode 100644 index 4d501b7..0000000 --- a/backend/config/default.js +++ /dev/null @@ -1,28 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -export default { - port: process.env.PORT || 3000, - ethereumNetwork: { - url: process.env.ETHEREUM_NETWORK_URL, - privateKey: process.env.PRIVATE_KEY - }, - etherscan: { - apiKey: process.env.ETHERSCAN_API_KEY - }, - cors: { - origin: 'http://localhost:5173', // URL фронтенда - credentials: true - }, - session: { - secret: 'your-secret-key', - resave: false, - saveUninitialized: false, - cookie: { - secure: process.env.NODE_ENV === 'production', - sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax', - maxAge: 24 * 60 * 60 * 1000 // 24 часа - } - } -}; - diff --git a/backend/contracts/AccessToken.sol b/backend/contracts/AccessToken.sol new file mode 100644 index 0000000..db1d0e9 --- /dev/null +++ b/backend/contracts/AccessToken.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/utils/Counters.sol"; + +contract AccessToken is ERC721, Ownable { + using Counters for Counters.Counter; + Counters.Counter private _tokenIds; + + // Роли для токенов + enum Role { ADMIN, MODERATOR, SUPPORT } + + // Маппинг токен ID => роль + mapping(uint256 => Role) public tokenRoles; + + // Маппинг адрес => активный токен + mapping(address => uint256) public activeTokens; + + constructor() ERC721("DApp Access Token", "DAT") Ownable() { + // Инициализация владельца происходит в Ownable() + } + + // Создание нового токена доступа + function mintAccessToken(address to, Role role) public onlyOwner { + _tokenIds.increment(); + uint256 newTokenId = _tokenIds.current(); + + _safeMint(to, newTokenId); + tokenRoles[newTokenId] = role; + activeTokens[to] = newTokenId; + } + + // Проверка роли по адресу + function checkRole(address user) public view returns (Role) { + uint256 tokenId = activeTokens[user]; + require(tokenId != 0, "No active token"); + require(ownerOf(tokenId) == user, "Token not owned"); + return tokenRoles[tokenId]; + } + + // Отзыв токена + function revokeToken(uint256 tokenId) public onlyOwner { + address tokenOwner = ownerOf(tokenId); + activeTokens[tokenOwner] = 0; + _burn(tokenId); + } + + // Передача токена запрещена + function _beforeTokenTransfer( + address from, + address to, + uint256 tokenId, + uint256 batchSize + ) internal override { + require(from == address(0) || to == address(0), "Token transfer not allowed"); + super._beforeTokenTransfer(from, to, tokenId, batchSize); + } +} \ No newline at end of file diff --git a/backend/data/documents/example.md b/backend/data/documents/example.md new file mode 100644 index 0000000..7354c2e --- /dev/null +++ b/backend/data/documents/example.md @@ -0,0 +1,16 @@ +# Пример документа для RAG + + Это пример документа, который будет использоваться в RAG системе. + + ## Блокчейн + + Блокчейн - это распределенная база данных, которая хранит информацию о всех транзакциях участников системы в виде "цепочки блоков". Каждый блок содержит набор транзакций и ссылку на предыдущий блок. + + ## Смарт-контракты + + Смарт-контракты - это программы, которые автоматически выполняются при соблюдении определенных условий. Они работают на блокчейне и могут автоматизировать выполнение соглашений. + + ## Web3 + + Web3 - это новое поколение интернета, основанное на блокчейне и децентрализованных технологиях. Оно позволяет пользователям контролировать свои данные и взаимодействовать без посредников. + \ No newline at end of file diff --git a/backend/db.js b/backend/db.js new file mode 100644 index 0000000..b8dda3c --- /dev/null +++ b/backend/db.js @@ -0,0 +1,95 @@ +const { Pool } = require('pg'); +require('dotenv').config(); + +// Создаем пул соединений с базой данных +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false +}); + +// Проверяем подключение к базе данных +pool.query('SELECT NOW()', (err, res) => { + if (err) { + console.error('Ошибка подключения к базе данных:', err); + console.log('Переключение на временное хранилище данных в памяти...'); + + // Если не удалось подключиться к базе данных, используем временное хранилище + module.exports = createInMemoryStorage(); + } else { + console.log('Успешное подключение к базе данных:', res.rows[0]); + } +}); + +// Функция для выполнения SQL-запросов +const query = (text, params) => { + return pool.query(text, params); +}; + +// Экспортируем функции для работы с базой данных +module.exports = { + query, + pool +}; + +// Функция для создания временного хранилища данных в памяти +function createInMemoryStorage() { + console.log('Используется временное хранилище данных в памяти'); + + const users = []; + let userId = 1; + + // Эмуляция функции query для работы с пользователями + const inMemoryQuery = async (text, params) => { + console.log('SQL query (in-memory):', text, 'Params:', params); + + // Эмуляция запроса SELECT * FROM users WHERE address = $1 + if (text.includes('SELECT * FROM users WHERE address = $1')) { + const address = params[0]; + const user = users.find(u => u.address === address); + return { rows: user ? [user] : [] }; + } + + // Эмуляция запроса SELECT * FROM users WHERE email = $1 + if (text.includes('SELECT * FROM users WHERE email = $1')) { + const email = params[0]; + const user = users.find(u => u.email === email); + return { rows: user ? [user] : [] }; + } + + // Эмуляция запроса INSERT INTO users + if (text.includes('INSERT INTO users')) { + let newUser; + + if (text.includes('address')) { + newUser = { id: userId++, address: params[0], created_at: new Date(), is_admin: false }; + } else if (text.includes('email')) { + newUser = { id: userId++, email: params[0], created_at: new Date(), is_admin: false }; + } + + if (newUser) { + users.push(newUser); + return { rows: [newUser] }; + } + } + + return { rows: [] }; + }; + + return { + query: inMemoryQuery, + pool: { + query: (text, params, callback) => { + if (callback) { + try { + const result = inMemoryQuery(text, params); + callback(null, result); + } catch (err) { + callback(err); + } + } else { + return inMemoryQuery(text, params); + } + } + } + }; +} \ No newline at end of file diff --git a/backend/hardhat.config.js b/backend/hardhat.config.js index 79ee7b3..3bdc956 100644 --- a/backend/hardhat.config.js +++ b/backend/hardhat.config.js @@ -1,13 +1,12 @@ -require("dotenv").config(); -require("@nomicfoundation/hardhat-ethers"); -require("@nomicfoundation/hardhat-chai-matchers"); +require("@nomicfoundation/hardhat-toolbox"); +require('dotenv').config(); module.exports = { - solidity: "0.8.19", + solidity: "0.8.20", networks: { sepolia: { url: process.env.ETHEREUM_NETWORK_URL, accounts: [process.env.PRIVATE_KEY] } } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/backend/middleware/auth.js b/backend/middleware/auth.js index 021411e..20d5dc0 100644 --- a/backend/middleware/auth.js +++ b/backend/middleware/auth.js @@ -1,4 +1,32 @@ -export const authMiddleware = (req, res, next) => { - // Логика аутентификации - next(); +const { checkAccess } = require('../utils/access-check'); + +// Middleware для проверки роли +const requireRole = (requiredRole) => async (req, res, next) => { + try { + const address = req.headers['x-wallet-address']; + if (!address) { + return res.status(401).json({ error: 'No wallet address' }); + } + + const { hasAccess, role } = await checkAccess(address); + + if (!hasAccess) { + return res.status(403).json({ error: 'No access token' }); + } + + if (requiredRole && role !== requiredRole) { + return res.status(403).json({ error: 'Insufficient permissions' }); + } + + // Добавляем информацию о роли в request + req.userRole = role; + next(); + } catch (error) { + console.error('Auth check error:', error); + res.status(500).json({ error: 'Auth check failed' }); + } +}; + +module.exports = { + requireRole }; \ No newline at end of file diff --git a/backend/migrations/003_access_roles.sql b/backend/migrations/003_access_roles.sql new file mode 100644 index 0000000..e21a870 --- /dev/null +++ b/backend/migrations/003_access_roles.sql @@ -0,0 +1,7 @@ +-- Добавляем поле для роли в таблицу users +ALTER TABLE users +ADD COLUMN role VARCHAR(20) DEFAULT NULL, +ADD COLUMN token_id INTEGER DEFAULT NULL; + +-- Индекс для быстрого поиска по роли +CREATE INDEX idx_users_role ON users(role); \ No newline at end of file diff --git a/backend/migrations/004_personalization_tables.sql b/backend/migrations/004_personalization_tables.sql new file mode 100644 index 0000000..94001aa --- /dev/null +++ b/backend/migrations/004_personalization_tables.sql @@ -0,0 +1,44 @@ +-- Создание таблицы для связи идентификаторов пользователей +CREATE TABLE IF NOT EXISTS user_identities ( + id SERIAL PRIMARY KEY, + user_id INTEGER REFERENCES users(id), + identity_type VARCHAR(20) NOT NULL, -- 'ethereum', 'telegram', 'email' + identity_value VARCHAR(255) NOT NULL, + created_at TIMESTAMP DEFAULT NOW(), + UNIQUE(identity_type, identity_value) +); + +-- Создание таблицы для предпочтений пользователей +CREATE TABLE IF NOT EXISTS user_preferences ( + id SERIAL PRIMARY KEY, + user_id INTEGER REFERENCES users(id), + preference_key VARCHAR(50) NOT NULL, + preference_value TEXT, + updated_at TIMESTAMP DEFAULT NOW(), + UNIQUE(user_id, preference_key) +); + +-- Создание таблицы для взаимодействий пользователей +CREATE TABLE IF NOT EXISTS user_interactions ( + id SERIAL PRIMARY KEY, + user_id INTEGER REFERENCES users(id), + interaction_type VARCHAR(50) NOT NULL, + interaction_data JSONB, + created_at TIMESTAMP DEFAULT NOW() +); + +-- Создание таблицы для тем пользователей +CREATE TABLE IF NOT EXISTS user_topics ( + id SERIAL PRIMARY KEY, + user_id INTEGER REFERENCES users(id), + topic VARCHAR(100) NOT NULL, + relevance_score FLOAT DEFAULT 1.0, + updated_at TIMESTAMP DEFAULT NOW(), + UNIQUE(user_id, topic) +); + +-- Индексы для оптимизации запросов +CREATE INDEX IF NOT EXISTS idx_user_identities_user_id ON user_identities(user_id); +CREATE INDEX IF NOT EXISTS idx_user_preferences_user_id ON user_preferences(user_id); +CREATE INDEX IF NOT EXISTS idx_user_interactions_user_id ON user_interactions(user_id); +CREATE INDEX IF NOT EXISTS idx_user_topics_user_id ON user_topics(user_id); \ No newline at end of file diff --git a/backend/migrations/005_kanban_tables.sql b/backend/migrations/005_kanban_tables.sql new file mode 100644 index 0000000..f977b7b --- /dev/null +++ b/backend/migrations/005_kanban_tables.sql @@ -0,0 +1,64 @@ +-- Таблица для Канбан-досок +CREATE TABLE IF NOT EXISTS kanban_boards ( + id SERIAL PRIMARY KEY, + title VARCHAR(100) NOT NULL, + description TEXT, + owner_id INTEGER REFERENCES users(id), + is_public BOOLEAN DEFAULT false, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() +); + +-- Таблица для колонок Канбан-доски +CREATE TABLE IF NOT EXISTS kanban_columns ( + id SERIAL PRIMARY KEY, + board_id INTEGER REFERENCES kanban_boards(id) ON DELETE CASCADE, + title VARCHAR(100) NOT NULL, + position INTEGER NOT NULL, + wip_limit INTEGER DEFAULT NULL, -- Лимит задач в работе (Work In Progress) + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() +); + +-- Таблица для карточек (задач) Канбан-доски +CREATE TABLE IF NOT EXISTS kanban_cards ( + id SERIAL PRIMARY KEY, + column_id INTEGER REFERENCES kanban_columns(id) ON DELETE CASCADE, + title VARCHAR(200) NOT NULL, + description TEXT, + position INTEGER NOT NULL, + assigned_to INTEGER REFERENCES users(id), + due_date TIMESTAMP, + labels JSONB DEFAULT '[]', + created_by INTEGER REFERENCES users(id), + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() +); + +-- Таблица для комментариев к карточкам +CREATE TABLE IF NOT EXISTS kanban_comments ( + id SERIAL PRIMARY KEY, + card_id INTEGER REFERENCES kanban_cards(id) ON DELETE CASCADE, + user_id INTEGER REFERENCES users(id), + content TEXT NOT NULL, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() +); + +-- Таблица для доступа к доскам +CREATE TABLE IF NOT EXISTS kanban_board_access ( + id SERIAL PRIMARY KEY, + board_id INTEGER REFERENCES kanban_boards(id) ON DELETE CASCADE, + user_id INTEGER REFERENCES users(id), + access_level VARCHAR(20) NOT NULL, -- 'read', 'write', 'admin' + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW(), + UNIQUE(board_id, user_id) +); + +-- Индексы для оптимизации запросов +CREATE INDEX IF NOT EXISTS idx_kanban_columns_board_id ON kanban_columns(board_id); +CREATE INDEX IF NOT EXISTS idx_kanban_cards_column_id ON kanban_cards(column_id); +CREATE INDEX IF NOT EXISTS idx_kanban_comments_card_id ON kanban_comments(card_id); +CREATE INDEX IF NOT EXISTS idx_kanban_board_access_board_id ON kanban_board_access(board_id); +CREATE INDEX IF NOT EXISTS idx_kanban_board_access_user_id ON kanban_board_access(user_id); \ No newline at end of file diff --git a/backend/migrations/cleanup.sql b/backend/migrations/cleanup.sql deleted file mode 100644 index a3c99ca..0000000 --- a/backend/migrations/cleanup.sql +++ /dev/null @@ -1,21 +0,0 @@ --- Создаем временную таблицу для уникальных адресов -CREATE TEMP TABLE unique_users AS -SELECT DISTINCT ON (LOWER(address)) - id, - LOWER(address) as address, - created_at -FROM users -ORDER BY LOWER(address), created_at ASC; - --- Удаляем все записи из users -TRUNCATE users CASCADE; - --- Восстанавливаем уникальные записи -INSERT INTO users (id, address, created_at) -SELECT id, address, created_at FROM unique_users; - --- Обновляем последовательность id -SELECT setval('users_id_seq', (SELECT MAX(id) FROM users)); - --- Удаляем временную таблицу -DROP TABLE unique_users; \ No newline at end of file diff --git a/backend/migrations/init.sql b/backend/migrations/init.sql deleted file mode 100644 index 850a29a..0000000 --- a/backend/migrations/init.sql +++ /dev/null @@ -1,44 +0,0 @@ --- Создаем расширение для векторов -CREATE EXTENSION IF NOT EXISTS vector; - --- Создаем таблицу пользователей -CREATE TABLE IF NOT EXISTS users ( - id SERIAL PRIMARY KEY, - address VARCHAR(42) UNIQUE NOT NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -); - --- Создаем таблицу документов -DROP TABLE IF EXISTS documents; -CREATE TABLE documents ( - id bigserial PRIMARY KEY, - content text NOT NULL, - metadata jsonb, - embedding vector(4096) -); - --- Создаем таблицу истории чата -CREATE TABLE IF NOT EXISTS chat_history ( - id SERIAL PRIMARY KEY, - user_id INTEGER REFERENCES users(id), - message TEXT NOT NULL, - response TEXT NOT NULL, - context_docs INTEGER[], - created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, - is_approved BOOLEAN DEFAULT false -); - --- Даем права пользователю -GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO postgres; -GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO postgres; - --- Обновляем существующие адреса -UPDATE users SET address = LOWER(address); - --- Удаляем дубликаты -DELETE FROM users a USING users b -WHERE a.id > b.id -AND LOWER(a.address) = LOWER(b.address); - -ALTER TABLE chat_history -ADD COLUMN IF NOT EXISTS is_approved BOOLEAN DEFAULT false; \ No newline at end of file diff --git a/backend/nodemon.json b/backend/nodemon.json index 2054f3c..223e986 100644 --- a/backend/nodemon.json +++ b/backend/nodemon.json @@ -1,5 +1,20 @@ { - "ignore": ["sessions/*", "*.json"], - "ext": "js", - "delay": "2500" + "verbose": true, + "ignore": [ + ".git", + "node_modules/**/node_modules", + "sessions", + "data/vector_store" + ], + "watch": [ + "*.js", + "routes/", + "services/", + "utils/", + "middleware/" + ], + "env": { + "NODE_ENV": "development" + }, + "ext": "js,json,env" } \ No newline at end of file diff --git a/backend/package.json b/backend/package.json index ae53eec..ea36ca2 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,54 +1,45 @@ { - "name": "backend", + "name": "dapp-for-business-backend", "version": "1.0.0", + "description": "Backend for DApp for Business", + "main": "server.js", "license": "MIT", "scripts": { - "compile": "hardhat compile", - "deploy": "hardhat run scripts/deploy.js --network sepolia", - "node": "hardhat node", - "test": "hardhat test", - "server": "nodemon --signal SIGUSR2 server.js" + "check-deps": "node scripts/check-dependencies.js", + "prestart": "npm run check-deps", + "start": "node server.js", + "dev": "nodemon server.js", + "server": "nodemon server.js --signal SIGUSR2", + "migrate": "node scripts/run-migrations.js", + "prod": "NODE_ENV=production node server.js", + "test": "mocha test/**/*.test.js" }, "dependencies": { - "@langchain/community": "^0.3.31", - "@langchain/core": "^0.3.39", + "@langchain/community": "^0.0.32", + "@langchain/core": "0.3.0", "@langchain/ollama": "^0.2.0", - "@langchain/openai": "^0.4.4", - "axios": "^1.7.9", + "axios": "^1.6.7", + "connect-pg-simple": "^10.0.0", "cors": "^2.8.5", - "express": "^4.18.3", - "express-session": "^1.18.0", + "csurf": "^1.11.0", + "dotenv": "^16.0.3", + "ethers": "^6.7.1", + "express": "^4.18.2", + "express-rate-limit": "^7.5.0", + "express-session": "^1.17.3", + "helmet": "^8.0.0", + "hnswlib-node": "^3.0.0", "imap": "^0.8.19", - "langchain": "^0.3.19", + "langchain": "^0.1.21", "mailparser": "^3.7.2", - "node-telegram-bot-api": "^0.66.0", - "nodemailer": "^6.10.0", - "nodemon": "^3.1.0", - "openai": "^4.85.2", - "pg": "^8.13.3", - "pgvector": "^0.2.0", + "node-telegram-bot-api": "^0.64.0", + "nodemailer": "^6.9.9", + "pg": "^8.10.0", "session-file-store": "^1.5.0", - "siwe": "^3.0.0" + "siwe": "^2.1.4", + "winston": "^3.17.0" }, "devDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.5", - "@openzeppelin/contracts": "^4.9.6", - "chai": "4.3.7", - "dotenv": "^16.4.7", - "elliptic": "^6.6.1", - "ethers": "^6.11.1", - "hardhat": "^2.21.0" - }, - "resolutions": { - "elliptic": "^6.6.1", - "secp256k1": "^5.0.0", - "cookie": "^0.7.0" - }, - "nodemonConfig": { - "delay": "2000", - "events": { - "restart": "kill -SIGUSR2 $PPID" - } + "nodemon": "^2.0.22" } } diff --git a/backend/routes/access.js b/backend/routes/access.js new file mode 100644 index 0000000..3ee95dd --- /dev/null +++ b/backend/routes/access.js @@ -0,0 +1,182 @@ +const express = require('express'); +const router = express.Router(); +const { Pool } = require('pg'); + +// Подключение к БД +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false +}); + +// Проверка доступа +router.get('/check', async (req, res) => { + const walletAddress = req.headers['x-wallet-address']; + + if (!walletAddress) { + return res.status(400).json({ error: 'No wallet address provided' }); + } + + try { + // Проверяем наличие активного токена для адреса + const result = await pool.query( + 'SELECT * FROM access_tokens WHERE wallet_address = $1 AND expires_at > NOW()', + [walletAddress.toLowerCase()] + ); + + if (result.rows.length === 0) { + return res.json({ hasAccess: false }); + } + + const token = result.rows[0]; + + res.json({ + hasAccess: true, + tokenId: token.id, + role: token.role, + expiresAt: token.expires_at + }); + } catch (error) { + console.error('Access check error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Проверка прав администратора +router.get('/admin-only', async (req, res) => { + const walletAddress = req.headers['x-wallet-address']; + + if (!walletAddress) { + return res.status(400).json({ error: 'No wallet address provided' }); + } + + try { + // Временное решение: разрешаем доступ для всех + console.log('Admin access requested by:', walletAddress); + + res.json({ success: true }); + } catch (error) { + console.error('Admin check error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Получение списка токенов +router.get('/tokens', async (req, res) => { + const walletAddress = req.headers['x-wallet-address']; + + if (!walletAddress) { + return res.status(400).json({ error: 'No wallet address provided' }); + } + + try { + // Проверяем права администратора + const adminCheck = await pool.query( + 'SELECT * FROM access_tokens WHERE wallet_address = $1 AND role = $2 AND expires_at > NOW()', + [walletAddress.toLowerCase(), 'ADMIN'] + ); + + if (adminCheck.rows.length === 0) { + return res.status(403).json({ error: 'Access denied' }); + } + + // Получаем список всех токенов + const result = await pool.query( + 'SELECT * FROM access_tokens ORDER BY created_at DESC' + ); + + res.json(result.rows.map(token => ({ + id: token.id, + walletAddress: token.wallet_address, + role: token.role, + createdAt: token.created_at, + expiresAt: token.expires_at + }))); + } catch (error) { + console.error('Tokens list error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Создание токена +router.post('/tokens', async (req, res) => { + const walletAddress = req.headers['x-wallet-address']; + + if (!walletAddress) { + return res.status(400).json({ error: 'No wallet address provided' }); + } + + try { + // Проверяем права администратора + const adminCheck = await pool.query( + 'SELECT * FROM access_tokens WHERE wallet_address = $1 AND role = $2 AND expires_at > NOW()', + [walletAddress.toLowerCase(), 'ADMIN'] + ); + + if (adminCheck.rows.length === 0) { + return res.status(403).json({ error: 'Access denied' }); + } + + const { walletAddress: targetAddress, role, expiresInDays } = req.body; + + if (!targetAddress || !role || !expiresInDays) { + return res.status(400).json({ error: 'Missing required fields' }); + } + + // Вычисляем дату истечения + const expiresAt = new Date(); + expiresAt.setDate(expiresAt.getDate() + parseInt(expiresInDays)); + + // Создаем токен + const result = await pool.query( + 'INSERT INTO access_tokens (wallet_address, role, expires_at) VALUES ($1, $2, $3) RETURNING *', + [targetAddress.toLowerCase(), role, expiresAt] + ); + + res.json({ + id: result.rows[0].id, + walletAddress: result.rows[0].wallet_address, + role: result.rows[0].role, + createdAt: result.rows[0].created_at, + expiresAt: result.rows[0].expires_at + }); + } catch (error) { + console.error('Token creation error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Отзыв токена +router.delete('/tokens/:id', async (req, res) => { + const walletAddress = req.headers['x-wallet-address']; + + if (!walletAddress) { + return res.status(400).json({ error: 'No wallet address provided' }); + } + + try { + // Проверяем права администратора + const adminCheck = await pool.query( + 'SELECT * FROM access_tokens WHERE wallet_address = $1 AND role = $2 AND expires_at > NOW()', + [walletAddress.toLowerCase(), 'ADMIN'] + ); + + if (adminCheck.rows.length === 0) { + return res.status(403).json({ error: 'Access denied' }); + } + + const { id } = req.params; + + // Удаляем токен + await pool.query( + 'DELETE FROM access_tokens WHERE id = $1', + [id] + ); + + res.json({ success: true }); + } catch (error) { + console.error('Token revocation error:', error); + res.status(500).json({ error: error.message }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/api.js b/backend/routes/api.js deleted file mode 100644 index 8663815..0000000 --- a/backend/routes/api.js +++ /dev/null @@ -1,855 +0,0 @@ -const express = require('express'); -const router = express.Router(); -const { ChatOllama } = require('@langchain/ollama'); -const { PGVectorStore } = require('@langchain/community/vectorstores/pgvector'); -const { OllamaEmbeddings } = require('@langchain/ollama'); -const { RunnableSequence } = require('@langchain/core/runnables'); -const { StringOutputParser } = require('@langchain/core/output_parsers'); -const { PromptTemplate } = require('@langchain/core/prompts'); -const { Pool } = require('pg'); -const { ethers } = require('ethers'); -const contractABI = require('../artifacts/contracts/MyContract.sol/MyContract.json').abi; -const crypto = require('crypto'); -const TelegramBotService = require('../services/telegramBot'); -require('dotenv').config(); - -const pool = new Pool({ - connectionString: process.env.DATABASE_URL, - ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false -}); - -const chat = new ChatOllama({ - model: 'mistral', - baseUrl: 'http://localhost:11434', - temperature: 0.7, - format: 'json' -}); - -const embeddings = new OllamaEmbeddings({ - model: 'mistral', - baseUrl: 'http://localhost:11434', - requestOptions: { - headers: { - 'Content-Type': 'application/json' - } - }, - dimensions: 4096, - stripNewLines: true, - maxConcurrency: 1, - maxRetries: 3, - timeout: 10000 -}); - -let vectorStore; -let contract; - -async function initVectorStore() { - try { - console.log('Начинаем инициализацию векторного хранилища...'); - vectorStore = await PGVectorStore.initialize( - embeddings, - { - postgresConnectionOptions: { - connectionString: process.env.DATABASE_URL - }, - tableName: 'documents', - columns: { - idColumnName: 'id', - vectorColumnName: 'embedding', - contentColumnName: 'content', - metadataColumnName: 'metadata', - } - } - ); - console.log('Векторное хранилище инициализировано:', { - tableName: 'documents', - columns: { - structure: (await pool.query(` - SELECT - column_name, - data_type, - is_nullable, - column_default - FROM information_schema.columns - WHERE table_name = 'documents' - ORDER BY ordinal_position - `)).rows.map(row => ({ - name: row.column_name, - type: row.data_type, - nullable: row.is_nullable, - default: row.column_default - })) - }, - config: { - tableName: vectorStore.tableName, - columns: vectorStore.columns, - client: vectorStore.client ? 'Connected' : 'Not connected', - embeddings: vectorStore.embeddings ? 'Initialized' : 'Not initialized' - } - }); - } catch (error) { - console.error('Ошибка инициализации векторного хранилища:', error); - throw error; - } -} - -async function initContract() { - try { - const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NETWORK_URL); - // Проверяем подключение к сети - const network = await provider.getNetwork(); - console.log('Подключены к сети:', network.chainId); - - contract = new ethers.Contract( - process.env.CONTRACT_ADDRESS, - contractABI, - provider - ); - - // Проверяем что контракт существует - const code = await provider.getCode(process.env.CONTRACT_ADDRESS); - if (code === '0x') { - throw new Error('Contract not deployed at this address'); - } - - // Проверяем подключение - const owner = await contract.owner(); - console.log('Владелец контракта:', owner); - console.log('Контракт инициализирован:', process.env.CONTRACT_ADDRESS); - } catch (error) { - console.error('Ошибка инициализации контракта:', error); - // Если контракт не найден, не пытаемся переподключиться - if (error.message.includes('not deployed')) { - console.error('Контракт не найден по указанному адресу'); - return; - } - // Пробуем переподключиться через 5 секунд - setTimeout(initContract, 5000); - } -} - -// Инициализируем при старте -initVectorStore().catch(console.error); -initContract().catch(console.error); - -// Проверяем подключение к БД при старте -pool.connect((err, client, release) => { - if (err) { - console.error('Ошибка подключения к PostgreSQL:', err); - } else { - console.log('Успешное подключение к PostgreSQL'); - release(); - } -}); - -// Middleware для проверки аутентификации -function requireAuth(req, res, next) { - if (!req.session?.siwe?.address) { - return res.status(401).json({ error: 'Not authenticated' }); - } - next(); -} - -// Генерация случайного nonce -function generateNonce() { - return crypto.randomBytes(16).toString('base64').replace(/[^a-zA-Z0-9]/g, ''); -} - -// Получение nonce для подписи -router.get('/nonce', (req, res) => { - try { - setCorsHeaders(res); - const nonce = generateNonce(); - console.log('Сгенерирован новый nonce:', nonce); - res.json({ nonce }); - } catch (error) { - console.error('Ошибка генерации nonce:', error); - res.status(500).json({ error: 'Server error' }); - } -}); - -// Верификация подписи -router.post('/verify', async (req, res) => { - try { - const { message, signature } = req.body; - - // Обновляем данные сессии - Object.assign(req.session, { - authenticated: true, - siwe: message, - userAddress: message.address, - cookie: { - maxAge: 7 * 24 * 60 * 60 * 1000 - } - }); - - // Ждем сохранения - await new Promise((resolve) => { - req.session.save(resolve); - }); - - console.log('Session saved:', { - id: req.sessionID, - authenticated: req.session.authenticated, - address: req.session.userAddress - }); - - // Проверяем права админа сразу после входа - const contractOwner = await contract.owner(); - const isAdmin = message.address.toLowerCase() === contractOwner.toLowerCase(); - - console.log('Проверка прав после входа:', { - userAddress: message.address, - contractOwner, - isAdmin - }); - - res.json({ - ok: true, - isAdmin - }); - } catch (error) { - console.error('Verify error:', error); - res.status(400).json({ error: error.message }); - } -}); - -// Создаем шаблон промпта для RAG -const TEMPLATE = `Вы - ассистент в DApp приложении. Используйте следующий контекст для ответа: - -Контекст: {context} -Вопрос пользователя: {question} - -Отвечайте кратко и по существу, основываясь на предоставленном контексте. Если контекст пустой или не релевантный, -используйте свои базовые знания о DApp и блокчейне.`; - -const prompt = PromptTemplate.fromTemplate(TEMPLATE); - -// Создаем RAG цепочку -const chain = RunnableSequence.from([ - { - context: async (input) => { - try { - const results = await vectorStore.similaritySearch( - input.question, - 1, - { type: 'approved_chat' } - ); - if (!results.length) return ''; - return results - .filter(doc => doc.pageContent) - .map(doc => doc.pageContent) - .join('\n\n'); - } catch (error) { - console.error('Ошибка поиска контекста:', error); - return ''; - } - }, - question: (input) => input.message - }, - prompt, - chat, - new StringOutputParser() -]); - -// Функция проверки работоспособности эмбеддингов -async function checkEmbeddings() { - try { - const testEmbed = await embeddings.embedQuery('test'); - console.log('Эмбеддинги работают, размерность:', testEmbed.length); - if (testEmbed.length !== 4096) { - throw new Error(`Неверная размерность: ${testEmbed.length}, ожидалось: 4096`); - } - return true; - } catch (error) { - console.error('Ошибка эмбеддингов:', error); - return false; - } -} - -router.post('/chat', requireAuth, async (req, res) => { - try { - const { message } = req.body; - const userAddress = req.session.siwe.address; - - // Получаем или создаем пользователя - let userResult = await pool.query( - 'SELECT id FROM users WHERE LOWER(address) = LOWER($1)', - [userAddress] - ); - - if (userResult.rows.length === 0) { - userResult = await pool.query( - 'INSERT INTO users (address) VALUES (LOWER($1)) RETURNING id', - [userAddress] - ); - } - - const userId = userResult.rows[0].id; - - // Создаем входные данные для chain - const input = { - message: message, - question: message - }; - - // Проверяем эмбеддинги перед использованием - if (!await checkEmbeddings()) { - console.warn('Embeddings service unavailable, continuing without context'); - try { - const response = await chain.invoke(input); - - // Сохраняем в базу без контекста - await pool.query( - 'INSERT INTO chat_history (user_id, message, response) VALUES ($1, $2, $3)', - [userId, message, response] - ); - - return res.json({ response }); - } catch (error) { - console.error('Ошибка генерации ответа:', error); - throw error; - } - } - - const response = await chain.invoke(input); - - // Сохраняем в базу с обработкой ошибок - try { - // Получаем похожие документы - const similarDocs = await vectorStore.similaritySearch( - message, - 1, - { type: 'approved_chat' } - ); - - // Извлекаем ID чатов из метаданных - const contextIds = similarDocs - .map(doc => doc.metadata?.chatId) - .filter(id => typeof id === 'number'); - - await pool.query( - 'INSERT INTO chat_history (user_id, message, response, context_docs) VALUES ($1, $2, $3, $4::integer[])', - [userId, message, response, contextIds] - ); - } catch (dbError) { - console.error('Ошибка сохранения в БД:', dbError); - // Продолжаем выполнение даже при ошибке сохранения - } - - res.json({ response }); - } catch (error) { - console.error('Ошибка чата:', error); - res.status(500).json({ - error: error.message, - details: error.stack - }); - } -}); - -// Получение истории чата -router.get('/chat/history', requireAuth, async (req, res) => { - try { - setCorsHeaders(res); - - const userAddress = req.session.siwe.address; - - // Получаем историю чата пользователя - const result = await pool.query( - `SELECT ch.* - FROM chat_history ch - JOIN users u ON ch.user_id = u.id - WHERE LOWER(u.address) = LOWER($1) - ORDER BY ch.created_at DESC`, - [userAddress] - ); - - res.json({ history: result.rows }); - } catch (error) { - console.error('Ошибка получения истории:', error); - res.status(500).json({ error: 'Server error' }); - } -}); - -// Получение списка пользователей -router.get('/users', requireAuth, async (req, res) => { - try { - console.log('Запрос списка пользователей'); - const users = await pool.query( - 'SELECT id, LOWER(address) as address, created_at FROM users ORDER BY created_at DESC' - ); - console.log('Найдено пользователей:', users.rows); - res.json({ users: users.rows }); - } catch (error) { - console.error('Ошибка получения пользователей:', error); - res.status(500).json({ error: 'Ошибка сервера' }); - } -}); - -// Проверка на админа -router.get('/admin/check', requireAuth, async (req, res) => { - try { - if (!contract) { - await initContract(); - if (!contract) { - throw new Error('Contract not initialized'); - } - } - - // Получаем адрес из сессии - const userAddress = req.session.siwe.address; - console.log('Проверка админа, адрес из сессии:', userAddress); - - const contractOwner = await contract.owner(); - console.log('Проверка админа:', { - userAddress, - contractOwner - }); - - const isAdmin = userAddress.toLowerCase() === contractOwner.toLowerCase(); - console.log('Результат проверки админа:', isAdmin); - - res.json({ isAdmin }); - } catch (error) { - console.error('Ошибка проверки админа:', error); - res.status(500).json({ - error: 'Server error', - details: error.message, - code: error.code - }); - } -}); - -// Общая функция для установки CORS заголовков -function setCorsHeaders(res) { - res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:5173'); - res.header('Access-Control-Allow-Credentials', 'true'); - res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); - res.header('Access-Control-Allow-Headers', 'Content-Type, Accept'); -} - -// Получение всех чатов для админа -router.get('/admin/chats', requireAdmin, async (req, res) => { - try { - setCorsHeaders(res); - - const chats = await pool.query(` - SELECT - ch.id, - LOWER(u.address) as address, - ch.message, - ch.response, - ch.created_at, - ch.context_docs, - EXISTS ( - SELECT 1 FROM documents d - WHERE d.metadata->>'chatId' = ch.id::text - AND d.metadata->>'type' = 'approved_chat' - ) as is_approved - FROM chat_history ch - JOIN users u ON ch.user_id = u.id - ORDER BY ch.created_at DESC - `); - - console.log('Получено чатов:', chats.rows.length); - if (chats.rows.length > 0) { - console.log('Пример чата:', { - id: chats.rows[0].id, - address: chats.rows[0].address, - is_approved: chats.rows[0].is_approved - }); - } - - res.json({ chats: chats.rows }); - } catch (error) { - console.error('Ошибка получения чатов:', error); - res.status(500).json({ - error: 'Server error', - details: error.message - }); - } -}); - -// Одобрение чата для обучения -router.post('/admin/approve', requireAuth, async (req, res) => { - try { - const userAddress = req.session.siwe.address; - const contractOwner = await contract.owner(); - - if (userAddress.toLowerCase() !== contractOwner.toLowerCase()) { - return res.status(403).json({ error: 'Not authorized' }); - } - - const { chatId } = req.body; - - // Обновляем статус в базе - await pool.query( - 'UPDATE chat_history SET is_approved = true WHERE id = $1', - [chatId] - ); - - // Добавляем в векторное хранилище для обучения - const chat = await pool.query( - `SELECT message, response FROM chat_history WHERE id = $1`, - [chatId] - ); - - if (chat.rows.length > 0) { - const { message, response } = chat.rows[0]; - console.log('Добавляем в векторное хранилище:', { - message: message.substring(0, 50) + '...', - response: response.substring(0, 50) + '...', - chatId - }); - - const document = { - pageContent: `Q: ${message}\nA: ${response}`, - metadata: { - type: 'approved_chat', - approvedBy: userAddress, - chatId: chatId - } - }; - - // Проверяем работу эмбеддингов - try { - const testEmbedding = await embeddings.embedQuery('test'); - console.log('Эмбеддинги работают, размерность:', testEmbedding.length); - } catch (error) { - console.error('Ошибка проверки эмбеддингов:', error); - throw new Error('Embeddings error: ' + error.message); - } - - console.log('Документ для добавления:', { - pageContent: document.pageContent.substring(0, 100) + '...', - metadata: document.metadata, - vectorStore: { - tableName: vectorStore.tableName, - columns: vectorStore.columns - } - }); - - // Проверяем существование таблицы и её структуру - const tableInfo = await pool.query(` - SELECT EXISTS ( - SELECT FROM information_schema.tables - WHERE table_name = 'documents' - ); - `); - console.log('Таблица documents существует:', tableInfo.rows[0].exists); - - if (tableInfo.rows[0].exists) { - const columns = await pool.query(` - SELECT column_name, data_type - FROM information_schema.columns - WHERE table_name = 'documents' - ORDER BY ordinal_position; - `); - console.log('Структура таблицы documents:', - columns.rows.map(row => `${row.column_name} (${row.data_type})`) - ); - } - - await vectorStore.addDocuments([ - document - ]); - - // Проверяем, что документ добавлен - const added = await vectorStore.similaritySearch( - document.pageContent, - 1, - { chatId: chatId } - ); - console.log('Проверка добавления документа:', { - found: added.length > 0, - document: added[0]?.pageContent.substring(0, 100) + '...' - }); - - console.log('Успешно добавлено в векторное хранилище'); - } - - res.json({ success: true }); - } catch (error) { - console.error('Ошибка одобрения:', error); - res.status(500).json({ - error: 'Server error', - details: error.message, - code: error.code - }); - } -}); - -// Улучшаем проверку авторизации админа -async function requireAdmin(req, res, next) { - if (!req.session?.siwe?.address) { - return res.status(401).json({ - error: 'Not authenticated', - details: 'Please sign in first' - }); - } - - try { - // Получаем адреса - const userAddress = req.session.siwe.address; - const contractOwner = await contract.owner(); - - console.log('Проверка админа:', { - userAddress: userAddress, - contractOwner: contractOwner - }); - - if (userAddress.toLowerCase() !== contractOwner.toLowerCase()) { - return res.status(403).json({ - error: 'Not authorized', - details: 'Only contract owner can access this endpoint' - }); - } - - next(); - } catch (error) { - console.error('Ошибка проверки админа:', error); - return res.status(500).json({ - error: 'Server error', - details: error.message - }); - } -} - -// Получение векторного хранилища для админа -router.get('/admin/vectors', requireAdmin, async (req, res) => { - try { - setCorsHeaders(res); - - // Добавляем колонку created_at если её нет - await pool.query(` - ALTER TABLE documents - ADD COLUMN IF NOT EXISTS created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP - `); - console.log('Проверена/добавлена колонка created_at'); - - // Проверяем структуру таблицы - const tableInfo = await pool.query(` - SELECT column_name, data_type - FROM information_schema.columns - WHERE table_name = 'documents' - `); - console.log('Структура таблицы documents:', tableInfo.rows); - - // Получаем все документы из векторного хранилища - const documents = await pool.query(` - SELECT - d.id, - d.content, - d.metadata, - length(d.embedding::text) as embedding_size, - COALESCE(d.created_at, CURRENT_TIMESTAMP) as created_at, - CASE - WHEN d.metadata->>'type' = 'approved_chat' THEN true - ELSE false - END as is_approved - FROM documents d - ORDER BY d.created_at DESC NULLS LAST - `); - - // Форматируем ответ - const vectors = documents.rows.map(doc => ({ - id: doc.id, - content: doc.content, - metadata: doc.metadata, - embedding_size: doc.embedding ? 4096 : 0, // Фиксированный размер для mistral - created: doc.created_at, - is_approved: doc.is_approved - })); - - console.log('Получено векторов:', vectors.length); - console.log('Пример вектора:', vectors[0]); - res.json({ vectors }); - } catch (error) { - console.error('Ошибка получения векторов:', error); - console.error('Детали ошибки:', { - code: error.code, - detail: error.detail, - hint: error.hint, - position: error.position - }); - res.status(500).json({ - error: 'Server error', - details: error.message, - code: error.code - }); - } -}); - -// Обработка CORS preflight запросов для админских роутов -router.options('/admin/*', (req, res) => { - setCorsHeaders(res); - res.sendStatus(200); -}); - -// Очистка кэша и данных -router.post('/admin/clear-cache', requireAdmin, async (req, res) => { - try { - setCorsHeaders(res); - - // Очищаем таблицы - await pool.query('TRUNCATE TABLE documents CASCADE'); - await pool.query('TRUNCATE TABLE chat_history CASCADE'); - await pool.query('TRUNCATE TABLE users CASCADE'); - - // Сбрасываем автоинкремент - await pool.query('ALTER SEQUENCE documents_id_seq RESTART WITH 1'); - await pool.query('ALTER SEQUENCE chat_history_id_seq RESTART WITH 1'); - await pool.query('ALTER SEQUENCE users_id_seq RESTART WITH 1'); - - // Реинициализируем векторное хранилище - await initVectorStore(); - - console.log('Кэш и данные очищены'); - res.json({ success: true }); - } catch (error) { - console.error('Ошибка очистки кэша:', error); - res.status(500).json({ - error: 'Server error', - details: error.message - }); - } -}); - -// Выход из системы -router.post('/signout', requireAuth, async (req, res) => { - try { - setCorsHeaders(res); - - // Уничтожаем сессию - req.session.destroy((err) => { - if (err) { - console.error('Ошибка при удалении сессии:', err); - return res.status(500).json({ error: 'Failed to destroy session' }); - } - - console.log('Сессия успешно завершена'); - res.json({ success: true }); - }); - } catch (error) { - console.error('Ошибка выхода:', error); - res.status(500).json({ error: 'Server error' }); - } -}); - -// Проверка сессии -router.get('/session', (req, res) => { - try { - setCorsHeaders(res); - - if (req.session?.authenticated && req.session?.siwe?.address) { - res.json({ - authenticated: true, - address: req.session.siwe.address - }); - } else { - res.json({ - authenticated: false - }); - } - } catch (error) { - console.error('Ошибка проверки сессии:', error); - res.status(500).json({ error: 'Server error' }); - } -}); - -// Создание нового пользователя -router.post('/users', async (req, res) => { - try { - setCorsHeaders(res); - - const { address } = req.body; - - // Проверяем существование пользователя - const existingUser = await pool.query( - 'SELECT * FROM users WHERE address = $1', - [address.toLowerCase()] - ); - - if (existingUser.rows.length > 0) { - return res.json({ user: existingUser.rows[0] }); - } - - // Создаем нового пользователя - const result = await pool.query( - 'INSERT INTO users (address) VALUES ($1) RETURNING *', - [address.toLowerCase()] - ); - - res.json({ user: result.rows[0] }); - } catch (error) { - console.error('Ошибка создания пользователя:', error); - res.status(500).json({ error: 'Server error' }); - } -}); - -// Создание необходимых таблиц при старте -async function initializeTables() { - try { - await pool.query(` - CREATE TABLE IF NOT EXISTS users ( - id SERIAL PRIMARY KEY, - address VARCHAR(42) NOT NULL UNIQUE, - created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP - ); - - CREATE TABLE IF NOT EXISTS chat_history ( - id SERIAL PRIMARY KEY, - user_id INTEGER REFERENCES users(id), - message TEXT, - response TEXT, - is_user BOOLEAN DEFAULT true, - created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP - ); - `); - console.log('Таблицы успешно инициализированы'); - - // Инициализируем vectorStore - vectorStore = await PGVectorStore.initialize( - embeddings, - { - postgresConnectionOptions: { - connectionString: process.env.DATABASE_URL - }, - tableName: 'documents', - columns: { - idColumnName: 'id', - vectorColumnName: 'embedding', - contentColumnName: 'content', - metadataColumnName: 'metadata' - } - } - ); - - console.log('Векторное хранилище инициализировано:', { - tableName: 'documents', - columns: vectorStore.columns, - config: { - tableName: vectorStore.tableName, - columns: vectorStore.columns, - client: vectorStore.client ? 'Connected' : 'Not Connected', - embeddings: vectorStore.embeddings ? 'Initialized' : 'Not Initialized' - } - }); - - // Создаем экземпляр TelegramBotService только после инициализации vectorStore - if (vectorStore) { - const telegramBot = new TelegramBotService( - process.env.TELEGRAM_BOT_TOKEN, - vectorStore - ); - } - - } catch (error) { - console.error('Ошибка при инициализации:', error); - } -} - -// Вызываем инициализацию при старте -initializeTables(); - -module.exports = router; \ No newline at end of file diff --git a/backend/routes/auth.js b/backend/routes/auth.js new file mode 100644 index 0000000..795dcf8 --- /dev/null +++ b/backend/routes/auth.js @@ -0,0 +1,357 @@ +const express = require('express'); +const router = express.Router(); +const { ethers } = require('ethers'); +const crypto = require('crypto'); +const db = require('../db'); +const logger = require('../utils/logger'); +const helmet = require('helmet'); +const rateLimit = require('express-rate-limit'); + +// Создайте лимитер для попыток аутентификации +const authLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 минут + max: 20, // Увеличьте лимит с 5 до 20 + standardHeaders: true, + legacyHeaders: false, + message: { error: 'Слишком много попыток аутентификации. Попробуйте позже.' } +}); + +// Маршрут для получения nonce для подписи +router.get('/nonce', async (req, res) => { + try { + const { address } = req.query; + + // Удалите или закомментируйте эти логи + // console.log('Nonce request:', { + // address, + // sessionID: req.sessionID, + // session: req.session + // }); + + if (!address) { + return res.status(400).json({ error: 'Address is required' }); + } + + // Генерируем случайный nonce + const nonce = crypto.randomBytes(32).toString('hex'); + + // Создаем сообщение для подписи + const message = `Sign this message to authenticate with DApp for Business. Nonce: ${nonce}`; + + // Сохраняем nonce в сессии + req.session.nonce = nonce; + req.session.pendingAddress = address; + + // Получаем IP-адрес клиента + const clientIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress; + + // Сохраняем IP-адрес в сессии при генерации nonce + req.session.clientIP = clientIP; + + // Явно сохраняем сессию + req.session.save((err) => { + if (err) { + // Удалите или закомментируйте эти логи + // console.error('Error saving session:', err); + return res.status(500).json({ error: 'Failed to save session' }); + } + + // Удалите или закомментируйте + // console.log('Nonce saved in session:', { + // nonce, + // pendingAddress: address, + // sessionID: req.sessionID + // }); + + res.json({ message }); + }); + } catch (error) { + // Удалите или закомментируйте эти логи + // console.error('Error generating nonce:', error); + logger.error('Error generating nonce:', error); + res.status(500).json({ error: 'Failed to generate nonce' }); + } +}); + +// Маршрут для верификации подписи +router.post('/verify', authLimiter, async (req, res) => { + try { + const { address, signature } = req.body; + + if (!address || !signature) { + return res.status(400).json({ error: 'Address and signature are required' }); + } + + // Удалите или закомментируйте эти логи + // console.log('Verify request:', { + // address, + // signature, + // sessionID: req.sessionID, + // session: { + // nonce: req.session.nonce, + // pendingAddress: req.session.pendingAddress + // } + // }); + + // Получаем nonce из сессии + const nonce = req.session.nonce; + const pendingAddress = req.session.pendingAddress; + + if (!nonce || !pendingAddress) { + return res.status(400).json({ error: 'No pending authentication request' }); + } + + // Получаем IP-адрес клиента + const clientIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress; + + // Проверяем, что IP-адрес совпадает + if (req.session.clientIP !== clientIP) { + return res.status(400).json({ error: 'IP address mismatch' }); + } + + // Проверяем, что адрес совпадает с тем, для которого был сгенерирован nonce + if (pendingAddress.toLowerCase() !== address.toLowerCase()) { + return res.status(400).json({ error: 'Address mismatch' }); + } + + // Создаем сообщение для проверки подписи + const message = `Sign this message to authenticate with DApp for Business. Nonce: ${nonce}`; + + // Восстанавливаем адрес из подписи + const recoveredAddress = ethers.verifyMessage(message, signature); + + // Проверяем, что восстановленный адрес совпадает с предоставленным + if (recoveredAddress.toLowerCase() !== address.toLowerCase()) { + return res.status(400).json({ error: 'Invalid signature' }); + } + + // Проверяем, существует ли пользователь в базе данных + const user = await db.query('SELECT * FROM users WHERE address = $1', [address]); + + let userId; + let isAdmin = false; + + if (user.rows.length === 0) { + // Если пользователь не существует, создаем его + const newUser = await db.query( + 'INSERT INTO users (address, created_at) VALUES ($1, NOW()) RETURNING id', + [address] + ); + userId = newUser.rows[0].id; + } else { + userId = user.rows[0].id; + isAdmin = user.rows[0].is_admin || false; + } + + // Устанавливаем состояние аутентификации в сессии + req.session.authenticated = true; + req.session.address = address; + req.session.isAdmin = isAdmin; + req.session.authType = 'wallet'; + req.session.userId = userId; + + // Удаляем nonce из сессии + delete req.session.nonce; + delete req.session.pendingAddress; + + // Явно сохраняем сессию + req.session.save((err) => { + if (err) { + // Удалите или закомментируйте эти логи + // console.error('Error saving session:', err); + return res.status(500).json({ error: 'Failed to save session' }); + } + + // Удалите или закомментируйте + // console.log('Authentication successful:', { + // address, + // isAdmin, + // sessionID: req.sessionID + // }); + + res.json({ + authenticated: true, + address, + isAdmin, + authType: 'wallet' + }); + }); + } catch (error) { + console.error('Error verifying signature:', error); + + // Более подробная обработка ошибок + if (error.message.includes('invalid signature')) { + return res.status(400).json({ + error: 'Недействительная подпись', + message: 'Подпись не соответствует адресу. Пожалуйста, попробуйте снова.' + }); + } + + if (error.message.includes('invalid address')) { + return res.status(400).json({ + error: 'Недействительный адрес', + message: 'Указанный адрес имеет неверный формат.' + }); + } + + res.status(500).json({ + error: 'Ошибка верификации подписи', + message: 'Не удалось проверить подпись. Пожалуйста, попробуйте снова позже.' + }); + } +}); + +// Маршрут для проверки состояния аутентификации +router.get('/check', (req, res) => { + // Удалите или закомментируйте эти логи + // console.log('Session check:', { + // session: req.session, + // authenticated: req.session.authenticated + // }); + + if (req.session.authenticated) { + res.json({ + authenticated: true, + address: req.session.address, + isAdmin: req.session.isAdmin, + authType: req.session.authType + }); + } else { + res.json({ + authenticated: false, + address: null, + isAdmin: false, + authType: null + }); + } +}); + +// Маршрут для выхода из системы +router.post('/logout', (req, res) => { + req.session.destroy(err => { + if (err) { + // Удалите или закомментируйте эти логи + // console.error('Error destroying session:', err); + return res.status(500).json({ error: 'Failed to logout' }); + } + + res.json({ success: true }); + }); +}); + +// Маршрут для авторизации через Telegram +router.get('/telegram', (req, res) => { + // Генерируем случайный токен для авторизации + const token = crypto.randomBytes(32).toString('hex'); + + // Сохраняем токен в сессии + req.session.telegramToken = token; + + // Создаем URL для авторизации через Telegram + const botName = process.env.TELEGRAM_BOT_NAME || 'YourBotName'; + const authUrl = `https://t.me/${botName}?start=${token}`; + + res.json({ authUrl }); +}); + +// Маршрут для авторизации через Email +router.post('/email', async (req, res) => { + try { + const { email } = req.body; + + if (!email) { + return res.status(400).json({ error: 'Email is required' }); + } + + // Генерируем код подтверждения + const verificationCode = Math.floor(100000 + Math.random() * 900000).toString(); + + // Сохраняем код в сессии + req.session.emailVerificationCode = verificationCode; + req.session.pendingEmail = email; + + // В реальном приложении здесь нужно отправить email с кодом подтверждения + // Удалите или закомментируйте эти логи + // console.log(`Verification code for ${email}: ${verificationCode}`); + + res.json({ success: true, message: 'Verification code sent' }); + } catch (error) { + // Удалите или закомментируйте эти логи + // console.error('Error sending verification code:', error); + logger.error('Error sending verification code:', error); + res.status(500).json({ error: 'Failed to send verification code' }); + } +}); + +// Маршрут для проверки кода подтверждения Email +router.post('/email/verify', async (req, res) => { + try { + const { email, code } = req.body; + + if (!email || !code) { + return res.status(400).json({ error: 'Email and code are required' }); + } + + // Получаем код из сессии + const verificationCode = req.session.emailVerificationCode; + const pendingEmail = req.session.pendingEmail; + + if (!verificationCode || !pendingEmail) { + return res.status(400).json({ error: 'No pending verification' }); + } + + // Проверяем, что email совпадает с тем, для которого был сгенерирован код + if (pendingEmail !== email) { + return res.status(400).json({ error: 'Email mismatch' }); + } + + // Проверяем код + if (verificationCode !== code) { + return res.status(400).json({ error: 'Invalid verification code' }); + } + + // Проверяем, существует ли пользователь в базе данных + const user = await db.query('SELECT * FROM users WHERE email = $1', [email]); + + let userId; + let isAdmin = false; + + if (user.rows.length === 0) { + // Если пользователь не существует, создаем его + const newUser = await db.query( + 'INSERT INTO users (email, created_at) VALUES ($1, NOW()) RETURNING id', + [email] + ); + userId = newUser.rows[0].id; + } else { + userId = user.rows[0].id; + isAdmin = user.rows[0].is_admin || false; + } + + // Устанавливаем состояние аутентификации в сессии + req.session.isAuthenticated = true; + req.session.authenticated = true; + req.session.address = email; + req.session.userId = userId; + req.session.isAdmin = isAdmin; + req.session.authType = 'email'; + + // Удаляем код из сессии + delete req.session.emailVerificationCode; + delete req.session.pendingEmail; + + res.json({ + authenticated: true, + address: email, + isAdmin, + authType: 'email' + }); + } catch (error) { + // Удалите или закомментируйте эти логи + // console.error('Error verifying email code:', error); + logger.error('Error verifying email code:', error); + res.status(500).json({ error: 'Failed to verify email code' }); + } +}); + +module.exports = { router }; \ No newline at end of file diff --git a/backend/routes/chat.js b/backend/routes/chat.js new file mode 100644 index 0000000..50e43b5 --- /dev/null +++ b/backend/routes/chat.js @@ -0,0 +1,185 @@ +const express = require('express'); +const router = express.Router(); +const { checkAccess } = require('../utils/access-check'); +const { createOllamaChain, directOllamaQuery, checkOllamaAvailability, ChatOllama } = require('../services/ollama'); +const { getVectorStore } = require('../services/vectorStore'); + +// Хранилище истории чатов +const chatHistory = {}; + +// Обработка чат-сообщений с проверкой сессии +router.post('/', async (req, res) => { + try { + console.log('Получен запрос в chat.js:', { + body: req.body, + session: req.session ? { + id: req.sessionID, + address: req.session.address, + isAuthenticated: req.session.isAuthenticated, + authenticated: req.session.authenticated + } : null, + cookies: req.cookies, + headers: { + cookie: req.headers.cookie, + origin: req.headers.origin, + referer: req.headers.referer, + 'content-type': req.headers['content-type'] + } + }); + + // Проверяем, что тело запроса правильно парсится + if (req.headers['content-type'] === 'application/json') { + console.log('JSON body:', JSON.stringify(req.body)); + } else { + console.log('Non-JSON body:', req.body); + } + + // ВАЖНО: Принимаем любой адрес из запроса без проверки сессии + const userAddress = req.body.address || '0xdefault'; + + const { message } = req.body; + + if (!message) { + return res.status(400).json({ error: 'Message is required' }); + } + + console.log(`Processing chat message from ${userAddress}: ${message}`); + + // Инициализируем историю чата для пользователя, если её нет + if (!chatHistory[userAddress]) { + chatHistory[userAddress] = []; + } + + // Временно возвращаем тестовый ответ для отладки + const responseText = `Тестовый ответ на сообщение: ${message}`; + + // Сохраняем историю чата + chatHistory[userAddress].push({ + type: 'human', + text: message + }); + + chatHistory[userAddress].push({ + type: 'ai', + text: responseText + }); + + return res.json({ response: responseText }); + } catch (error) { + console.error('Подробная ошибка:', error.stack); + console.error('Chat error:', error); + res.status(500).json({ + error: "Извините, произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже." + }); + } +}); + +// Добавьте новый эндпоинт для проверки сессии +router.get('/check-session', (req, res) => { + try { + console.log('Проверка сессии в chat.js:', { + sessionID: req.sessionID, + session: req.session ? { + isAuthenticated: req.session.isAuthenticated, + authenticated: req.session.authenticated, + address: req.session.address + } : null, + cookies: req.cookies, + headers: { + cookie: req.headers.cookie + } + }); + + // Если сессия отсутствует, но есть адрес в куки authToken, создаем временную сессию + if ((!req.session || (!req.session.isAuthenticated && !req.session.authenticated)) && req.cookies.authToken) { + console.log('Создаем временную сессию для проверки'); + + // Инициализируем сессию, если она не существует + if (!req.session) { + req.session = {}; + } + + req.session.isAuthenticated = true; + req.session.authenticated = true; + req.session.isAdmin = true; + + return res.json({ + success: true, + message: 'Temporary session created', + isAdmin: true + }); + } + + if (!req.session) { + return res.status(401).json({ error: 'No session' }); + } + + if (!req.session.isAuthenticated && !req.session.authenticated) { + return res.status(401).json({ error: 'Unauthorized' }); + } + + res.json({ + success: true, + address: req.session.address, + isAdmin: req.session.isAdmin + }); + } catch (error) { + console.error('Ошибка при проверке сессии:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Добавьте новый эндпоинт для прямой отправки сообщений в Ollama +router.post('/ollama', async (req, res) => { + try { + const { message, model = 'mistral' } = req.body; + + console.log(`Отправка сообщения в Ollama (${model}):`, message); + + if (!message) { + return res.status(400).json({ error: 'Message is required' }); + } + + // Используем функцию directOllamaQuery вместо создания нового экземпляра ChatOllama + const result = await directOllamaQuery(message, model); + + console.log('Ответ от Ollama:', result); + + // Возвращаем ответ клиенту + res.json({ + response: result, + model: model + }); + } catch (error) { + console.error('Ошибка при отправке сообщения в Ollama:', error); + res.status(500).json({ + error: "Ошибка при отправке сообщения в Ollama. Убедитесь, что сервер Ollama запущен." + }); + } +}); + +// Проверьте, что маршрут правильно настроен +router.post('/message', async (req, res) => { + try { + const { message } = req.body; + + if (!message) { + return res.status(400).json({ error: 'Message is required' }); + } + + console.log('Получено сообщение:', message); + + // Здесь ваш код обработки сообщения + // ... + + // Временный ответ для тестирования + res.json({ + response: `Это тестовый ответ на ваше сообщение: "${message}". Сервер работает.` + }); + } catch (error) { + console.error('Error processing message:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/contracts.js b/backend/routes/contracts.js new file mode 100644 index 0000000..3bfb99d --- /dev/null +++ b/backend/routes/contracts.js @@ -0,0 +1,32 @@ +const express = require('express'); +const router = express.Router(); +const { requireRole } = require('../middleware/auth'); + +// Получение информации о контрактах +router.get('/', (req, res) => { + res.json({ + message: 'Contracts API endpoint', + contracts: [ + { + name: 'AccessToken', + address: process.env.ACCESS_TOKEN_ADDRESS + } + ] + }); +}); + +// Защищенный эндпоинт для получения детальной информации о контрактах +router.get('/details', requireRole('ADMIN'), (req, res) => { + res.json({ + message: 'Contract details endpoint', + contracts: [ + { + name: 'AccessToken', + address: process.env.ACCESS_TOKEN_ADDRESS, + network: process.env.ETHEREUM_NETWORK_URL.includes('sepolia') ? 'Sepolia' : 'Unknown' + } + ] + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/debug.js b/backend/routes/debug.js new file mode 100644 index 0000000..7801057 --- /dev/null +++ b/backend/routes/debug.js @@ -0,0 +1,189 @@ +const express = require('express'); +const router = express.Router(); + +// Эндпоинт для отладки сессий +router.get('/session', (req, res) => { + try { + console.log('Отладка сессии:', { + sessionID: req.sessionID, + session: req.session ? { + isAuthenticated: req.session.isAuthenticated, + authenticated: req.session.authenticated, + address: req.session.address, + isAdmin: req.session.isAdmin + } : null, + cookies: req.cookies, + headers: { + cookie: req.headers.cookie + } + }); + + res.json({ + sessionID: req.sessionID, + session: req.session ? { + isAuthenticated: req.session.isAuthenticated, + authenticated: req.session.authenticated, + address: req.session.address, + isAdmin: req.session.isAdmin + } : null, + cookies: req.cookies + }); + } catch (error) { + console.error('Ошибка при отладке сессии:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Эндпоинт для создания тестовой сессии +router.post('/create-session', (req, res) => { + const { address } = req.body; + + if (!address) { + return res.status(400).json({ error: 'Address is required' }); + } + + // Инициализируем сессию, если она не существует + if (!req.session) { + req.session = {}; + } + + req.session.isAuthenticated = true; + req.session.authenticated = true; + req.session.address = address.toLowerCase(); + req.session.isAdmin = true; + + // Сохраняем сессию + req.session.save((err) => { + if (err) { + console.error('Ошибка сохранения тестовой сессии:', err); + return res.status(500).json({ error: 'Session save error' }); + } + + console.log('Тестовая сессия создана:', { + sessionID: req.sessionID, + session: { + isAuthenticated: req.session.isAuthenticated, + authenticated: req.session.authenticated, + address: req.session.address, + isAdmin: req.session.isAdmin + } + }); + + res.cookie('authToken', 'true', { + maxAge: 86400000, + httpOnly: false, + secure: false, + sameSite: 'lax', + path: '/' + }); + + res.json({ + success: true, + sessionID: req.sessionID, + address: req.session.address, + isAdmin: req.session.isAdmin + }); + }); +}); + +// Тестовый эндпоинт для отправки сообщений без проверки сессии +router.post('/test-chat', (req, res) => { + try { + const { message, address } = req.body; + + console.log('Тестовый чат-запрос:', { + message, + address, + headers: { + cookie: req.headers.cookie, + 'content-type': req.headers['content-type'] + }, + cookies: req.cookies, + session: req.session ? { + isAuthenticated: req.session.isAuthenticated, + authenticated: req.session.authenticated, + address: req.session.address, + isAdmin: req.session.isAdmin + } : null + }); + + if (!message) { + return res.status(400).json({ error: 'Message is required' }); + } + + // Возвращаем тестовый ответ + res.json({ + response: `Тестовый ответ на сообщение: ${message}`, + receivedAddress: address, + sessionAddress: req.session?.address + }); + } catch (error) { + console.error('Ошибка в тестовом чате:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Тестовый эндпоинт для проверки соединения +router.get('/ping', (req, res) => { + res.json({ + message: 'pong', + timestamp: new Date().toISOString(), + server: { + port: process.env.PORT || 8080, + address: req.socket.localAddress, + hostname: require('os').hostname() + } + }); +}); + +// Тестовый эндпоинт для проверки Ollama +router.get('/ollama-test', async (req, res) => { + try { + const { directOllamaQuery } = require('../services/ollama'); + + // Тестовый запрос к Ollama + const result = await directOllamaQuery('Привет, как дела?', 'mistral'); + + res.json({ + success: true, + response: result, + model: 'mistral' + }); + } catch (error) { + console.error('Ошибка при тестировании Ollama:', error); + res.status(500).json({ + success: false, + error: error.message || 'Ошибка при тестировании Ollama' + }); + } +}); + +// Тестовый эндпоинт для проверки доступности Ollama +router.get('/ollama-status', async (req, res) => { + try { + const { checkOllamaAvailability } = require('../services/ollama'); + + // Проверяем доступность Ollama + const isAvailable = await checkOllamaAvailability(); + + if (isAvailable) { + res.json({ + status: 'ok', + message: 'Ollama доступен' + }); + } else { + res.status(503).json({ + status: 'error', + message: 'Ollama недоступен' + }); + } + } catch (error) { + console.error('Ошибка при проверке доступности Ollama:', error); + res.status(500).json({ + status: 'error', + message: error.message || 'Ошибка при проверке доступности Ollama' + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/health.js b/backend/routes/health.js new file mode 100644 index 0000000..1f9f61c --- /dev/null +++ b/backend/routes/health.js @@ -0,0 +1,36 @@ +const express = require('express'); +const router = express.Router(); +const db = require('../db'); + +router.get('/', async (req, res) => { + try { + // Проверка соединения с базой данных + const dbResult = await db.query('SELECT NOW()'); + + // Проверка состояния сервера + const memoryUsage = process.memoryUsage(); + const uptime = process.uptime(); + + res.json({ + status: 'ok', + timestamp: new Date(), + uptime: uptime, + memory: { + rss: Math.round(memoryUsage.rss / 1024 / 1024) + 'MB', + heapTotal: Math.round(memoryUsage.heapTotal / 1024 / 1024) + 'MB', + heapUsed: Math.round(memoryUsage.heapUsed / 1024 / 1024) + 'MB' + }, + database: { + connected: true, + timestamp: dbResult.rows[0].now + } + }); + } catch (error) { + res.status(500).json({ + status: 'error', + error: error.message + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/identities.js b/backend/routes/identities.js new file mode 100644 index 0000000..aaffa5b --- /dev/null +++ b/backend/routes/identities.js @@ -0,0 +1,75 @@ +const express = require('express'); +const router = express.Router(); +const { linkIdentity, getUserIdentities } = require('../utils/identity-linker'); +const { Pool } = require('pg'); + +// Подключение к БД +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false +}); + +// Middleware для проверки аутентификации +function requireAuth(req, res, next) { + if (!req.session || (!req.session.isAuthenticated && !req.session.authenticated)) { + return res.status(401).json({ error: 'Unauthorized' }); + } + next(); +} + +// Получение связанных идентификаторов пользователя +router.get('/', requireAuth, async (req, res) => { + try { + // Получаем ID пользователя по Ethereum-адресу + const result = await pool.query( + 'SELECT id FROM users WHERE address = $1', + [req.session.address] + ); + + if (result.rows.length === 0) { + return res.status(404).json({ error: 'User not found' }); + } + + const userId = result.rows[0].id; + + // Получаем все идентификаторы пользователя + const identities = await getUserIdentities(userId); + + res.json({ identities }); + } catch (error) { + console.error('Error getting user identities:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Удаление связанного идентификатора +router.delete('/:type/:value', requireAuth, async (req, res) => { + try { + const { type, value } = req.params; + + // Получаем ID пользователя по Ethereum-адресу + const result = await pool.query( + 'SELECT id FROM users WHERE address = $1', + [req.session.address] + ); + + if (result.rows.length === 0) { + return res.status(404).json({ error: 'User not found' }); + } + + const userId = result.rows[0].id; + + // Удаляем идентификатор + await pool.query( + 'DELETE FROM user_identities WHERE user_id = $1 AND identity_type = $2 AND identity_value = $3', + [userId, type, value] + ); + + res.json({ success: true }); + } catch (error) { + console.error('Error deleting user identity:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/kanban.js b/backend/routes/kanban.js new file mode 100644 index 0000000..1b179a8 --- /dev/null +++ b/backend/routes/kanban.js @@ -0,0 +1,340 @@ +const express = require('express'); +const router = express.Router(); +const { Pool } = require('pg'); +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false +}); + +// Middleware для проверки аутентификации +function requireAuth(req, res, next) { + if (!req.session || (!req.session.isAuthenticated && !req.session.authenticated)) { + return res.status(401).json({ error: 'Unauthorized' }); + } + next(); +} + +// Получение всех досок пользователя +router.get('/boards', async (req, res) => { + try { + // Для разработки: если сессия не содержит адрес, используем тестовый + const userAddress = (req.session.address || '0xf45aa4917b3775ba37f48aeb3dc1a943561e9e0b').toLowerCase(); + + console.log('Запрос досок для адреса:', userAddress); + + // Проверяем, существует ли пользователь + const userResult = await pool.query( + 'SELECT id FROM users WHERE address = $1', + [userAddress] + ); + + console.log('Результат запроса пользователя:', userResult.rows); + + if (userResult.rows.length === 0) { + console.log('Пользователь не найден, создаем нового'); + // Если пользователь не найден, создаем его + const newUserResult = await pool.query( + 'INSERT INTO users (address, created_at) VALUES ($1, NOW()) RETURNING id', + [userAddress] + ); + console.log('Создан новый пользователь:', newUserResult.rows); + } + + // Получаем доски пользователя + const ownBoardsQuery = 'SELECT kb.* FROM kanban_boards kb ' + + 'JOIN users u ON kb.owner_id = u.id ' + + 'WHERE u.address = $1 ' + + 'ORDER BY kb.updated_at DESC'; + + console.log('Запрос досок пользователя:', ownBoardsQuery); + + const ownBoardsResult = await pool.query(ownBoardsQuery, [userAddress]); + + console.log('Результат запроса досок пользователя:', ownBoardsResult.rows); + + // Получаем доски, к которым у пользователя есть доступ + const sharedBoardsResult = await pool.query( + 'SELECT kb.* FROM kanban_boards kb ' + + 'JOIN kanban_board_access kba ON kb.id = kba.board_id ' + + 'JOIN users u1 ON kba.user_id = u1.id ' + + 'JOIN users u2 ON kb.owner_id = u2.id ' + + 'WHERE u1.address = $1 AND u2.address != $1 ' + + 'ORDER BY kb.updated_at DESC', + [userAddress] + ); + + // Получаем публичные доски + const publicBoardsResult = await pool.query( + 'SELECT kb.* FROM kanban_boards kb ' + + 'JOIN users u ON kb.owner_id = u.id ' + + 'WHERE kb.is_public = true AND u.address != $1 ' + + 'AND NOT EXISTS (' + + ' SELECT 1 FROM kanban_board_access kba ' + + ' JOIN users u2 ON kba.user_id = u2.id ' + + ' WHERE kba.board_id = kb.id AND u2.address = $1' + + ') ' + + 'ORDER BY kb.updated_at DESC', + [userAddress] + ); + + res.json({ + ownBoards: ownBoardsResult.rows, + sharedBoards: sharedBoardsResult.rows, + publicBoards: publicBoardsResult.rows + }); + } catch (error) { + console.error('Error fetching boards:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Создание новой доски +router.post('/boards', requireAuth, async (req, res) => { + try { + const { title, description, isPublic } = req.body; + + // Получаем ID пользователя + let userResult = await pool.query( + 'SELECT id FROM users WHERE address = $1', + [req.session.address] + ); + + let userId; + + if (userResult.rows.length === 0) { + // Если пользователь не найден, создаем его + const newUserResult = await pool.query( + 'INSERT INTO users (address, created_at, preferred_language) VALUES ($1, NOW(), $2) RETURNING id', + [req.session.address, 'ru'] + ); + + userId = newUserResult.rows[0].id; + } else { + userId = userResult.rows[0].id; + } + + // Создаем новую доску + const result = await pool.query( + `INSERT INTO kanban_boards (title, description, owner_id, is_public, created_at, updated_at) + VALUES ($1, $2, $3, $4, NOW(), NOW()) + RETURNING *`, + [title, description, userId, isPublic] + ); + + // Создаем стандартные колонки + const columns = ['Backlog', 'In Progress', 'Review', 'Done']; + for (let i = 0; i < columns.length; i++) { + await pool.query( + `INSERT INTO kanban_columns (board_id, title, position, created_at, updated_at) + VALUES ($1, $2, $3, NOW(), NOW())`, + [result.rows[0].id, columns[i], i] + ); + } + + res.status(201).json(result.rows[0]); + } catch (error) { + console.error('Error creating kanban board:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Получение конкретной доски со всеми колонками и карточками +router.get('/boards/:id', requireAuth, async (req, res) => { + try { + const boardId = req.params.id; + + // Получаем ID пользователя + let userResult = await pool.query( + 'SELECT id FROM users WHERE address = $1', + [req.session.address] + ); + + let userId; + + if (userResult.rows.length === 0) { + // Если пользователь не найден, создаем его + const newUserResult = await pool.query( + 'INSERT INTO users (address, created_at, preferred_language) VALUES ($1, NOW(), $2) RETURNING id', + [req.session.address, 'ru'] + ); + + userId = newUserResult.rows[0].id; + } else { + userId = userResult.rows[0].id; + } + + // Проверяем доступ к доске + const boardResult = await pool.query( + 'SELECT * FROM kanban_boards WHERE id = $1', + [boardId] + ); + + if (boardResult.rows.length === 0) { + return res.status(404).json({ error: 'Board not found' }); + } + + const board = boardResult.rows[0]; + + // Проверяем, имеет ли пользователь доступ к доске + if (board.owner_id !== userId && !board.is_public) { + const accessResult = await pool.query( + 'SELECT * FROM kanban_board_access WHERE board_id = $1 AND user_id = $2', + [boardId, userId] + ); + + if (accessResult.rows.length === 0) { + return res.status(403).json({ error: 'Access denied' }); + } + } + + // Получаем колонки доски + const columnsResult = await pool.query( + 'SELECT * FROM kanban_columns WHERE board_id = $1 ORDER BY position', + [boardId] + ); + + // Получаем карточки для всех колонок + const cardsResult = await pool.query( + `SELECT kc.*, u.address as assigned_address + FROM kanban_cards kc + LEFT JOIN users u ON kc.assigned_to = u.id + WHERE kc.column_id IN ( + SELECT id FROM kanban_columns WHERE board_id = $1 + ) + ORDER BY kc.position`, + [boardId] + ); + + // Группируем карточки по колонкам + const columns = columnsResult.rows.map(column => { + const cards = cardsResult.rows.filter(card => card.column_id === column.id); + return { + ...column, + cards + }; + }); + + res.json({ + ...board, + columns + }); + } catch (error) { + console.error('Error getting kanban board:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Добавление колонки к доске +router.post('/boards/:boardId/columns', requireAuth, async (req, res) => { + try { + const { boardId } = req.params; + const { title, wipLimit } = req.body; + + // Проверяем, существует ли доска + const boardResult = await pool.query( + 'SELECT * FROM kanban_boards WHERE id = $1', + [boardId] + ); + + if (boardResult.rows.length === 0) { + return res.status(404).json({ error: 'Board not found' }); + } + + // Получаем максимальную позицию колонок + const positionResult = await pool.query( + 'SELECT MAX(position) as max_position FROM kanban_columns WHERE board_id = $1', + [boardId] + ); + + const position = positionResult.rows[0].max_position ? positionResult.rows[0].max_position + 1 : 0; + + // Создаем новую колонку + const result = await pool.query( + `INSERT INTO kanban_columns (board_id, title, position, wip_limit, created_at, updated_at) + VALUES ($1, $2, $3, $4, NOW(), NOW()) + RETURNING *`, + [boardId, title, position, wipLimit] + ); + + res.status(201).json(result.rows[0]); + } catch (error) { + console.error('Error creating column:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Получение колонок доски +router.get('/boards/:boardId/columns', requireAuth, async (req, res) => { + try { + const { boardId } = req.params; + + const result = await pool.query( + 'SELECT * FROM kanban_columns WHERE board_id = $1 ORDER BY position', + [boardId] + ); + + res.json(result.rows); + } catch (error) { + console.error('Error getting columns:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Создание карточки +router.post('/cards', requireAuth, async (req, res) => { + try { + const { title, description, columnId, dueDate } = req.body; + + // Получаем ID пользователя + let userResult = await pool.query( + 'SELECT id FROM users WHERE address = $1', + [req.session.address] + ); + + let userId; + + if (userResult.rows.length === 0) { + // Если пользователь не найден, создаем его + const newUserResult = await pool.query( + 'INSERT INTO users (address, created_at, preferred_language) VALUES ($1, NOW(), $2) RETURNING id', + [req.session.address, 'ru'] + ); + + userId = newUserResult.rows[0].id; + } else { + userId = userResult.rows[0].id; + } + + // Получаем максимальную позицию карточек в колонке + const positionResult = await pool.query( + 'SELECT MAX(position) as max_position FROM kanban_cards WHERE column_id = $1', + [columnId] + ); + + const position = positionResult.rows[0].max_position ? positionResult.rows[0].max_position + 1 : 0; + + // Создаем новую карточку + const result = await pool.query( + `INSERT INTO kanban_cards (column_id, title, description, position, due_date, created_by, created_at, updated_at) + VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW()) + RETURNING *`, + [columnId, title, description, position, dueDate, userId] + ); + + // Получаем информацию о пользователе для отображения + const cardWithUser = { + ...result.rows[0], + assigned_address: null + }; + + res.status(201).json(cardWithUser); + } catch (error) { + console.error('Error creating card:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Добавляем остальные маршруты для работы с колонками, карточками и т.д. +// ... + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/users.js b/backend/routes/users.js new file mode 100644 index 0000000..8e5109e --- /dev/null +++ b/backend/routes/users.js @@ -0,0 +1,18 @@ +const express = require('express'); +const router = express.Router(); + +// Получение списка пользователей +router.get('/', (req, res) => { + res.json({ message: 'Users API endpoint' }); +}); + +// Получение информации о пользователе +router.get('/:address', (req, res) => { + const { address } = req.params; + res.json({ + address, + message: 'User details endpoint' + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/scripts/check-dependencies.js b/backend/scripts/check-dependencies.js new file mode 100644 index 0000000..b2a801f --- /dev/null +++ b/backend/scripts/check-dependencies.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const path = require('path'); + +const packageJson = require('../package.json'); +const dependencies = packageJson.dependencies || {}; + +const requiredDependencies = [ + 'express-rate-limit', + 'winston', + 'helmet', + 'csurf' +]; + +const missingDependencies = requiredDependencies.filter(dep => !dependencies[dep]); + +if (missingDependencies.length > 0) { + console.error('Missing dependencies:', missingDependencies); + console.error('Please install them with: yarn add ' + missingDependencies.join(' ')); + process.exit(1); +} + +console.log('All required dependencies are installed.'); \ No newline at end of file diff --git a/backend/scripts/check-state.js b/backend/scripts/check-state.js new file mode 100644 index 0000000..bd9a800 --- /dev/null +++ b/backend/scripts/check-state.js @@ -0,0 +1,43 @@ +const hre = require("hardhat"); + +async function main() { + const accessToken = await hre.ethers.getContractAt( + "AccessToken", + "0xF352c498cF0857F472dC473E4Dd39551E79B1063" + ); + + const owner = await accessToken.owner(); + console.log("Contract owner:", owner); + + // Проверяем все токены и их владельцев + console.log("\nAll tokens:"); + for (let i = 1; i <= 10; i++) { + try { + const tokenOwner = await accessToken.ownerOf(i); + console.log(`Token ${i} owner: ${tokenOwner}`); + } catch (error) { + if (!error.message.includes("invalid token ID")) { + console.log(`Token ${i} error:`, error.message); + } + } + } + + // Проверяем активные токены для всех известных адресов + const addresses = [ + owner, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" + ]; + + console.log("\nActive tokens:"); + for (const address of addresses) { + const activeToken = await accessToken.activeTokens(address); + console.log(`${address}: Token ${activeToken.toString()}`); + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); \ No newline at end of file diff --git a/backend/scripts/create-moderator.js b/backend/scripts/create-moderator.js new file mode 100644 index 0000000..b01cee9 --- /dev/null +++ b/backend/scripts/create-moderator.js @@ -0,0 +1,51 @@ +const hre = require("hardhat"); + +async function main() { + const accessToken = await hre.ethers.getContractAt( + "AccessToken", + "0xF352c498cF0857F472dC473E4Dd39551E79B1063" + ); + + const moderatorAddress = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"; + + try { + console.log("\nMinting moderator token..."); + const mintTx = await accessToken.mintAccessToken(moderatorAddress, 1); // MODERATOR + console.log("Waiting for transaction:", mintTx.hash); + await mintTx.wait(); + console.log("Moderator token minted"); + + // Проверяем результат + const activeToken = await accessToken.activeTokens(moderatorAddress); + console.log(`Moderator's active token: ${activeToken}`); + + const role = await accessToken.checkRole(moderatorAddress); + console.log(`Moderator role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`); + } catch (error) { + console.log("Moderator token minting error:", error.message); + } + + // Проверяем все активные токены + console.log("\nAll active tokens:"); + const addresses = [ + await accessToken.owner(), + moderatorAddress + ]; + + for (const address of addresses) { + try { + const activeToken = await accessToken.activeTokens(address); + const role = await accessToken.checkRole(address); + console.log(`${address}: Token ${activeToken}, Role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`); + } catch (error) { + console.log(`${address}: ${error.message}`); + } + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error("Script error:", error); + process.exit(1); + }); \ No newline at end of file diff --git a/backend/scripts/deploy-access.js b/backend/scripts/deploy-access.js new file mode 100644 index 0000000..6d1a448 --- /dev/null +++ b/backend/scripts/deploy-access.js @@ -0,0 +1,23 @@ +const hre = require("hardhat"); + +async function main() { + const AccessToken = await hre.ethers.getContractFactory("AccessToken"); + const accessToken = await AccessToken.deploy(); + await accessToken.waitForDeployment(); + + const address = await accessToken.getAddress(); + console.log("AccessToken deployed to:", address); + + // Создаем первый админский токен для владельца контракта + const [owner] = await hre.ethers.getSigners(); + const tx = await accessToken.mintAccessToken(owner.address, 0); // 0 = ADMIN + await tx.wait(); + console.log("Admin token minted for:", owner.address); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); \ No newline at end of file diff --git a/backend/scripts/init-db.js b/backend/scripts/init-db.js new file mode 100644 index 0000000..9787829 --- /dev/null +++ b/backend/scripts/init-db.js @@ -0,0 +1,62 @@ +const { Pool } = require('pg'); +const dotenv = require('dotenv'); + +dotenv.config(); + +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false +}); + +async function initDb() { + try { + console.log('Инициализация базы данных...'); + + // Добавляем тестового пользователя + await pool.query(` + INSERT INTO users (address, is_admin) + VALUES ('0xf45aa4917b3775ba37f48aeb3dc1a943561e9e0b', TRUE) + ON CONFLICT (address) DO NOTHING + `); + + // Добавляем тестовую доску + await pool.query(` + INSERT INTO kanban_boards (title, description, owner_id, is_public) + VALUES ( + 'Тестовая доска', + 'Описание тестовой доски', + (SELECT id FROM users WHERE address = '0xf45aa4917b3775ba37f48aeb3dc1a943561e9e0b'), + TRUE + ) + ON CONFLICT DO NOTHING + `); + + // Получаем ID доски + const boardResult = await pool.query(` + SELECT id FROM kanban_boards WHERE title = 'Тестовая доска' LIMIT 1 + `); + + if (boardResult.rows.length > 0) { + const boardId = boardResult.rows[0].id; + + // Добавляем тестовые колонки + await pool.query(` + INSERT INTO kanban_columns (board_id, title, position) + VALUES + ($1, 'Backlog', 0), + ($1, 'In Progress', 1), + ($1, 'Review', 2), + ($1, 'Done', 3) + ON CONFLICT DO NOTHING + `, [boardId]); + } + + console.log('База данных инициализирована успешно'); + } catch (error) { + console.error('Ошибка при инициализации базы данных:', error); + } finally { + await pool.end(); + } +} + +initDb(); \ No newline at end of file diff --git a/backend/scripts/init-roles.js b/backend/scripts/init-roles.js new file mode 100644 index 0000000..87c4233 --- /dev/null +++ b/backend/scripts/init-roles.js @@ -0,0 +1,58 @@ +const hre = require("hardhat"); + +async function main() { + const accessToken = await hre.ethers.getContractAt( + "AccessToken", + "0xF352c498cF0857F472dC473E4Dd39551E79B1063" + ); + + const owner = await accessToken.owner(); + console.log("Contract owner:", owner); + + // Создаем админский токен для владельца + try { + const tx = await accessToken.mintAccessToken(owner, 0); // 0 = ADMIN + await tx.wait(); + console.log(`Admin token minted for ${owner}`); + + const role = await accessToken.checkRole(owner); + console.log("Owner role:", ["ADMIN", "MODERATOR", "SUPPORT"][role]); + } catch (error) { + console.log("Admin token minting error:", error.message); + } + + // Создаем тестовый токен модератора + const moderatorAddress = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"; // Тестовый адрес модератора + try { + const tx = await accessToken.mintAccessToken(moderatorAddress, 1); // 1 = MODERATOR + await tx.wait(); + console.log(`Moderator token minted for ${moderatorAddress}`); + + const role = await accessToken.checkRole(moderatorAddress); + console.log("Moderator role:", ["ADMIN", "MODERATOR", "SUPPORT"][role]); + } catch (error) { + console.log("Moderator token minting error:", error.message); + } + + // Проверяем все токены + console.log("\nChecking all tokens:"); + for (let i = 1; i <= 5; i++) { + try { + const owner = await accessToken.ownerOf(i); + const role = await accessToken.checkRole(owner); + console.log(`Token ${i}: Owner ${owner}, Role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`); + } catch (error) { + // Пропускаем несуществующие токены + if (!error.message.includes("nonexistent token")) { + console.log(`Token ${i} error:`, error.message); + } + } + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); \ No newline at end of file diff --git a/backend/scripts/manage-access.js b/backend/scripts/manage-access.js new file mode 100644 index 0000000..ccd04a9 --- /dev/null +++ b/backend/scripts/manage-access.js @@ -0,0 +1,72 @@ +const hre = require("hardhat"); + +async function main() { + const accessToken = await hre.ethers.getContractAt( + "AccessToken", + "0xF352c498cF0857F472dC473E4Dd39551E79B1063" // Адрес нашего контракта + ); + + // Проверим текущего владельца + const owner = await accessToken.owner(); + console.log("Contract owner:", owner); + + // Проверим роль владельца + try { + const ownerRole = await accessToken.checkRole(owner); + console.log("Owner role:", ["ADMIN", "MODERATOR", "SUPPORT"][ownerRole]); + } catch (error) { + console.log("Owner role check error:", error.message); + } + + // Создадим токен модератора для тестового адреса + const moderatorAddress = "0xF45aa4917b3775bA37f48Aeb3dc1a943561e9e0B"; + try { + const tx = await accessToken.mintAccessToken(moderatorAddress, 1); // 1 = MODERATOR + await tx.wait(); + console.log(`Moderator token minted for ${moderatorAddress}`); + + // Проверим роль модератора + const modRole = await accessToken.checkRole(moderatorAddress); + console.log("Moderator role:", ["ADMIN", "MODERATOR", "SUPPORT"][modRole]); + } catch (error) { + console.log("Moderator token minting error:", error.message); + } + + // Получим все активные токены (с ограничением по блокам) + const currentBlock = await hre.ethers.provider.getBlockNumber(); + const fromBlock = currentBlock - 1000; // Последние 1000 блоков + + const filter = accessToken.filters.Transfer(null, null, null); + const events = await accessToken.queryFilter(filter, fromBlock); + console.log("\nActive tokens (last 1000 blocks):"); + for (let event of events) { + if (event.args.from === "0x0000000000000000000000000000000000000000") { + console.log(`Token ID: ${event.args.tokenId}, Owner: ${event.args.to}`); + try { + const role = await accessToken.checkRole(event.args.to); + console.log(`Role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`); + } catch (error) { + console.log("Role check error:", error.message); + } + } + } + + // Альтернативный способ - проверить конкретный токен + console.log("\nChecking specific tokens:"); + for (let i = 1; i <= 2; i++) { + try { + const owner = await accessToken.ownerOf(i); + const role = await accessToken.checkRole(owner); + console.log(`Token ${i}: Owner ${owner}, Role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`); + } catch (error) { + console.log(`Token ${i} not found or error:`, error.message); + } + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); \ No newline at end of file diff --git a/backend/scripts/revoke-all.js b/backend/scripts/revoke-all.js new file mode 100644 index 0000000..b91d601 --- /dev/null +++ b/backend/scripts/revoke-all.js @@ -0,0 +1,26 @@ +const hre = require("hardhat"); + +async function main() { + const accessToken = await hre.ethers.getContractAt( + "AccessToken", + "0xF352c498cF0857F472dC473E4Dd39551E79B1063" + ); + + // Отзываем все токены от 1 до 3 + for (let i = 1; i <= 3; i++) { + try { + const tx = await accessToken.revokeToken(i); + await tx.wait(); + console.log(`Token ${i} revoked`); + } catch (error) { + console.log(`Token ${i} revoke error:`, error.message); + } + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); \ No newline at end of file diff --git a/backend/scripts/run-migrations.js b/backend/scripts/run-migrations.js new file mode 100644 index 0000000..3613e9c --- /dev/null +++ b/backend/scripts/run-migrations.js @@ -0,0 +1,68 @@ +const { Pool } = require('pg'); +const fs = require('fs'); +const path = require('path'); +require('dotenv').config(); + +// Подключение к БД +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false +}); + +async function runMigrations() { + try { + console.log('Запуск миграций...'); + + // Создаем таблицу для отслеживания миграций, если её нет + await pool.query(` + CREATE TABLE IF NOT EXISTS migrations ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + applied_at TIMESTAMP DEFAULT NOW() + ) + `); + + // Получаем список уже примененных миграций + const { rows } = await pool.query('SELECT name FROM migrations'); + const appliedMigrations = rows.map(row => row.name); + + // Получаем список файлов миграций + const migrationsDir = path.join(__dirname, '../migrations'); + const migrationFiles = fs.readdirSync(migrationsDir) + .filter(file => file.endsWith('.sql')) + .sort(); // Сортируем файлы по имени + + // Применяем миграции, которые еще не были применены + for (const file of migrationFiles) { + if (!appliedMigrations.includes(file)) { + console.log(`Применение миграции: ${file}`); + + // Читаем содержимое файла миграции + const filePath = path.join(migrationsDir, file); + const sql = fs.readFileSync(filePath, 'utf8'); + + // Выполняем SQL-запросы из файла + await pool.query(sql); + + // Записываем информацию о примененной миграции + await pool.query( + 'INSERT INTO migrations (name) VALUES ($1)', + [file] + ); + + console.log(`Миграция ${file} успешно применена`); + } else { + console.log(`Миграция ${file} уже применена`); + } + } + + console.log('Все миграции успешно применены'); + } catch (error) { + console.error('Ошибка при выполнении миграций:', error); + process.exit(1); + } finally { + await pool.end(); + } +} + +runMigrations(); \ No newline at end of file diff --git a/backend/server.js b/backend/server.js index d43fb06..aaf99c4 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,399 +1,676 @@ +require('dotenv').config(); const express = require('express'); const cors = require('cors'); -const session = require('express-session'); const { SiweMessage, generateNonce } = require('siwe'); -const path = require('path'); -const apiRoutes = require('./routes/api.js'); -const FileStore = require('session-file-store')(session); +const { ethers } = require('ethers'); const TelegramBotService = require('./services/telegramBot'); const EmailBotService = require('./services/emailBot'); -const { PGVectorStore } = require('@langchain/community/vectorstores/pgvector'); -const { OpenAIEmbeddings } = require('@langchain/openai'); -const { exec } = require('child_process'); -const util = require('util'); -const execAsync = util.promisify(exec); +const { initializeVectorStore } = require('./services/vectorStore'); +const session = require('express-session'); +const { app, nonceStore } = require('./app'); +const usersRouter = require('./routes/users'); +const { router: authRouter } = require('./routes/auth'); +const contractsRouter = require('./routes/contracts'); +const accessRouter = require('./routes/access'); +const chatRouter = require('./routes/chat'); +const path = require('path'); +const axios = require('axios'); +const { ChatOllama } = require('@langchain/ollama'); +const { getVectorStore } = require('./services/vectorStore'); +const debugRouter = require('./routes/debug'); +const identitiesRouter = require('./routes/identities'); +const kanbanRouter = require('./routes/kanban'); +const { pool } = require('./db'); +const fs = require('fs'); +const pgSession = require('connect-pg-simple')(session); +const sessionStore = new pgSession({ + pool: pool, + tableName: 'session', + createTableIfMissing: true +}); +const helmet = require('helmet'); +const csrf = require('csurf'); -const app = express(); +const PORT = process.env.PORT || 8000; -// Флаг для отслеживания состояния сервера -let isShuttingDown = false; +console.log('Начало выполнения server.js'); +console.log('Переменная окружения PORT:', process.env.PORT); +console.log('Используемый порт:', process.env.PORT || 8000); -// Глобальные переменные для сервисов +// Инициализация сервисов let telegramBot; let emailBot; -let vectorStore; -// 1. Парсинг JSON -app.use(express.json()); +// Получаем ABI из артефактов +const contractArtifact = require('./artifacts/contracts/MyContract.sol/MyContract.json'); +const contractABI = contractArtifact.abi; -// 2. CORS +// Добавим логирование для отладки контракта +const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NETWORK_URL); +console.log('Provider URL:', process.env.ETHEREUM_NETWORK_URL); +console.log('Contract address:', process.env.CONTRACT_ADDRESS); + +const contract = new ethers.Contract( + process.env.CONTRACT_ADDRESS, + contractABI, + provider +); + +// Проверяем, что библиотека ethers.js правильно импортирована +console.log('Ethers.js version:', ethers.version); + +// Порядок middleware важен! +// 1. CORS должен быть первым app.use(cors({ - origin: [ - 'http://127.0.0.1:5173', - 'http://127.0.0.1:5174' - ], + origin: ['http://127.0.0.1:5173', 'http://localhost:5173'], credentials: true, - methods: ['GET', 'POST'], - allowedHeaders: ['Content-Type', 'Authorization', 'X-SIWE-Nonce', 'X-Requested-With', 'Accept'], + methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'], exposedHeaders: ['Set-Cookie'] })); -// 3. Сессии +// Добавьте после настройки CORS +app.use(helmet()); + +// 2. Затем парсеры +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); + +// 3. Затем сессии app.use(session({ - name: 'siwe-dapp', - secret: "siwe-dapp-secret", + secret: process.env.SESSION_SECRET || 'your-secret-key', resave: true, - saveUninitialized: false, - store: new FileStore({ - path: './sessions', - ttl: 86400, - retries: 0, - logFn: function(){}, - reapInterval: 86400, - reapAsync: true, - reapSyncCheck: true, - retryTimeout: 100 - }), + saveUninitialized: true, cookie: { httpOnly: true, secure: false, sameSite: 'lax', - path: '/', - domain: '127.0.0.1', - maxAge: 30 * 24 * 60 * 60 * 1000 - } + maxAge: 24 * 60 * 60 * 1000 + }, + store: sessionStore })); -// Middleware для сохранения сессии +// Добавьте после настройки сессий app.use((req, res, next) => { - const oldEnd = res.end; - res.end = function (chunk, encoding) { - if (req.session && req.session.save) { - req.session.save((err) => { - if (err) console.error('Session save error:', err); - oldEnd.apply(res, arguments); - }); - } else { - oldEnd.apply(res, arguments); - } - }; + // console.log('Middleware для проверки сессии:', { + // url: req.url, + // method: req.method, + // sessionID: req.sessionID, + // session: req.session ? { + // isAuthenticated: req.session.isAuthenticated, + // authenticated: req.session.authenticated, + // address: req.session.address, + // isAdmin: req.session.isAdmin + // } : null, + // cookies: req.cookies, + // headers: { + // cookie: req.headers.cookie + // } + // }); + if (req.session.store) { + req.session.store.on('error', (error) => { + console.error('Session store error:', error); + }); + } next(); }); -// Генерация nonce -app.get('/nonce', (req, res) => { - try { - if (!req.session) { - throw new Error('No session available'); - } +// Добавьте после настройки парсеров +app.use((req, res, next) => { + // if (req.method === 'POST' && req.headers['content-type'] === 'application/json') { + // console.log('POST request body:', { + // url: req.url, + // body: JSON.stringify(req.body) + // }); + // } + next(); +}); - req.session.nonce = generateNonce(); - console.log('Сгенерирован новый nonce:', req.session.nonce); - res.json({ nonce: req.session.nonce }); - } catch (error) { - console.error('Ошибка генерации nonce:', error); - res.status(500).json({ error: 'Internal Server Error' }); +const requireAuth = (req, res, next) => { + if (!req.session.authenticated || !req.session.address) { + return res.status(401).json({ error: 'Unauthorized' }); + } + next(); +}; + +app.use('/api/protected', requireAuth); + +// Добавляем middleware для проверки состояния аутентификации +app.use((req, res, next) => { + // console.log('Auth check middleware:', { + // url: req.url, + // method: req.method, + // sessionID: req.sessionID, + // session: req.session ? { + // isAuthenticated: req.session.isAuthenticated, + // authenticated: req.session.authenticated, + // address: req.session.address, + // isAdmin: req.session.isAdmin + // } : null + // }); + next(); +}); + +// Добавьте после настройки парсеров +app.use((req, res, next) => { + // if (req.method === 'POST' && req.headers['content-type'] === 'application/json') { + // console.log('POST request body:', { + // url: req.url, + // body: JSON.stringify(req.body) + // }); + // } + next(); +}); + +// Добавляем middleware для отладки сессий +app.use((req, res, next) => { + // console.log('Session debug:', { + // url: req.url, + // method: req.method, + // sessionID: req.sessionID, + // cookies: req.headers.cookie, + // session: req.session ? { + // isAuthenticated: req.session.isAuthenticated, + // authenticated: req.session.authenticated, + // address: req.session.address, + // isAdmin: req.session.isAdmin, + // nonce: req.session.nonce ? '[REDACTED]' : undefined, + // pendingAddress: req.session.pendingAddress + // } : null + // }); + next(); +}); + +// Настройка CSRF-защиты +const csrfProtection = csrf({ + cookie: { + key: '_csrf', + path: '/', + httpOnly: true, + secure: process.env.NODE_ENV === 'production', // true в production, false в development + sameSite: process.env.NODE_ENV === 'production' ? 'strict' : 'lax' } }); -// Функция для проверки формата адреса EIP-55 -function isValidEIP55Address(address) { - return /^0x[0-9A-F]{40}$/.test(address); -} +// Применяем CSRF-защиту только к определенным маршрутам +app.use('/api/protected', csrfProtection); +app.use('/api/admin', csrfProtection); +app.use('/api/kanban', csrfProtection); -// Верификация сообщения -app.post('/verify', async (req, res) => { - try { - const clientNonce = req.headers['x-siwe-nonce']; - const { signature, message } = req.body; - - console.log('Received message:', message); - - if (!req.session) { - throw new Error('No session available'); - } - - // Создаем и проверяем SIWE сообщение - let siweMessage; - try { - siweMessage = new SiweMessage(message); - console.log('SIWE message parsed:', siweMessage); - - // Проверяем nonce - if (siweMessage.nonce !== clientNonce) { - throw new Error('Invalid nonce'); - } - - // Проверяем подпись - const fields = await siweMessage.verify({ - signature: signature, - domain: siweMessage.domain, - nonce: clientNonce - }); - - console.log('SIWE validation successful:', fields); - console.log('Сообщение успешно верифицировано'); - - // Сохраняем данные в сессии - req.session.siwe = fields.data; - req.session.authenticated = true; - req.session.nonce = null; - - // Принудительно сохраняем сессию - await new Promise((resolve, reject) => { - req.session.save((err) => { - if (err) reject(err); - else resolve(); - }); - }); - - res.json({ - success: true, - address: fields.data.address - }); - } catch (error) { - console.error('Ошибка валидации сообщения:', error); - req.session.authenticated = false; - req.session.siwe = null; - req.session.nonce = null; - throw error; - } - } catch (error) { - console.error('Ошибка верификации:', error); - res.status(400).json({ - success: false, - error: error.message, - details: error.stack - }); - } +// Маршрут для получения CSRF-токена +app.get('/api/csrf-token', csrfProtection, (req, res) => { + res.json({ csrfToken: req.csrfToken() }); }); -// Получение сессии -app.get('/session', (req, res) => { - try { - if (!req.session) { - return res.status(401).json({ - authenticated: false, - error: 'No session' - }); - } - - res.json({ - authenticated: !!req.session.authenticated, - address: req.session.siwe?.address - }); - } catch (error) { - console.error('Ошибка получения сессии:', error); - res.status(500).json({ error: 'Internal Server Error' }); - } -}); - -// Выход -app.get('/signout', (req, res) => { - try { - req.session.destroy((err) => { - if (err) { - console.error('Ошибка при удалении сессии:', err); - return res.status(500).json({ error: 'Failed to destroy session' }); - } - res.status(200).json({ success: true }); - }); - } catch (error) { - console.error('Ошибка выхода:', error); - res.status(500).json({ error: 'Internal Server Error' }); - } -}); - -// Базовый маршрут -app.get('/', (req, res) => { - res.json({ - status: 'ok', - endpoints: { - nonce: 'GET /nonce', - verify: 'POST /verify', - session: 'GET /session', - signout: 'GET /signout', - shutdown: 'POST /shutdown' - } - }); -}); - -// Эндпоинт для остановки сервера -app.post('/shutdown', (req, res) => { - res.json({ message: 'Сервер останавливается...' }); - console.log('Получен запрос на остановку сервера'); - setTimeout(() => { - process.exit(0); - }, 1000); -}); - -// 4. API роуты -app.use('/api', apiRoutes); - -// Обработка 404 -app.use((req, res) => { - console.log(`404: ${req.method} ${req.url}`); - res.status(404).json({ - error: 'Not Found', - message: `Endpoint ${req.method} ${req.url} не существует` - }); -}); - -// Обработка ошибок +// Обработчик ошибок CSRF app.use((err, req, res, next) => { - console.error('Ошибка сервера:', err); - res.status(500).json({ - error: 'Internal Server Error', - message: err.message - }); -}); - -const PORT = process.env.PORT || 3000; -const server = app.listen(PORT, '127.0.0.1', () => { - console.log(`SIWE сервер запущен на порту ${PORT}`); - console.log('Доступные эндпоинты:'); - console.log(' GET / - Информация о сервере'); - console.log(' GET /nonce - Получить nonce'); - console.log(' POST /verify - Верифицировать сообщение'); - console.log(' GET /session - Получить текущую сессию'); - console.log(' GET /signout - Выйти из системы'); - console.log(' POST /shutdown - Остановить сервер'); -}); - -// Обработка ошибки занятого порта -server.on('error', (error) => { - if (error.code === 'EADDRINUSE') { - console.log(`Порт ${PORT} занят. Останавливаем предыдущий процесс...`); - require('child_process').exec(`lsof -i :${PORT} | grep LISTEN | awk '{print $2}' | xargs kill -9`, (err) => { - if (err) { - console.error('Ошибка при остановке процесса:', err); - process.exit(1); - } - console.log('Предыдущий процесс остановлен. Перезапускаем сервер...'); - server.listen(PORT); + if (err.code === 'EBADCSRFTOKEN') { + console.error('CSRF error:', { + url: req.url, + method: req.method, + headers: req.headers, + body: req.body + }); + return res.status(403).json({ + error: 'CSRF token validation failed', + message: 'Your session may have expired. Please refresh the page and try again.' }); } + next(err); }); -// Функция корректного завершения работы -async function gracefulShutdown(signal) { - if (isShuttingDown) return; - isShuttingDown = true; - - console.log(`Получен сигнал ${signal}, начинаем корректное завершение...`); - +async function initServices() { try { - if (telegramBot) { - console.log('Останавливаем Telegram бота...'); - await telegramBot.stop(); - } - if (emailBot) { - console.log('Останавливаем Email бота...'); - await emailBot.stop(); - } - console.log('Все сервисы остановлены'); - } catch (error) { - console.error('Ошибка при остановке сервисов:', error); - } - - // Даем время на завершение всех процессов - setTimeout(() => { - process.exit(0); - }, 1000); -} - -// Обработчики сигналов -process.on('SIGTERM', () => gracefulShutdown('SIGTERM')); -process.on('SIGINT', () => gracefulShutdown('SIGINT')); -process.on('SIGUSR2', () => gracefulShutdown('SIGUSR2')); // Для nodemon - -// Обработка необработанных исключений -process.on('uncaughtException', (error) => { - console.error('Необработанное исключение:', error); - gracefulShutdown('uncaughtException'); -}); - -process.on('unhandledRejection', (reason, promise) => { - console.error('Необработанное отклонение промиса:', reason); - gracefulShutdown('unhandledRejection'); -}); - -// Функция для проверки и остановки существующих процессов бота -async function killExistingBotProcesses() { - try { - console.log('Проверяем существующие процессы бота...'); - const { stdout } = await execAsync('ps aux | grep "[n]ode.*telegram"'); + console.log('Инициализация сервисов...'); - if (stdout) { - console.log('Найдены существующие процессы бота, останавливаем...'); - await execAsync('pkill -SIGTERM -f "[n]ode.*telegram"'); - // Ждем немного, чтобы процессы успели завершиться - await new Promise(resolve => setTimeout(resolve, 2000)); + // Инициализируем ботов, если они нужны + if (process.env.TELEGRAM_BOT_TOKEN) { + telegramBot = new TelegramBotService(process.env.TELEGRAM_BOT_TOKEN); + console.log('Telegram бот инициализирован'); } + + if (process.env.EMAIL_USER && process.env.EMAIL_PASS) { + emailBot = new EmailBotService(process.env.EMAIL_USER, process.env.EMAIL_PASS); + console.log('Email бот инициализирован'); + } + + console.log('Все сервисы успешно инициализированы'); } catch (error) { - // Ошибка означает, что процессы не найдены - это нормально - console.log('Активные процессы бота не найдены'); + console.error('Ошибка при инициализации сервисов:', error); } } -// Инициализация векторного хранилища -async function initializeVectorStore() { +app.use('/api/users', usersRouter); +app.use('/api/auth', authRouter); +app.use('/api/contracts', contractsRouter); +app.use('/api/access', accessRouter); +app.use('/api/chat', chatRouter); +app.use('/api/debug', debugRouter); +app.use('/api/identities', identitiesRouter); +app.use('/api/kanban', kanbanRouter); + +// Добавьте простой эндпоинт для проверки состояния сервера +app.get('/api/health', (req, res) => { + res.json({ status: 'ok', timestamp: new Date().toISOString() }); +}); + +// Добавьте после настройки маршрутов +app.post('/api/verify', async (req, res) => { try { - // Сначала останавливаем существующие процессы - await killExistingBotProcesses(); - - // Даем время на освобождение ресурсов - await new Promise(resolve => setTimeout(resolve, 2000)); - - // Инициализируем embeddings - const embeddings = new OpenAIEmbeddings({ - openAIApiKey: process.env.OPENAI_API_KEY, - configuration: { - baseURL: process.env.OPENAI_API_BASE || 'https://api.openai.com/v1' + // Перенаправляем запрос на /api/auth/verify + const { message, signature } = req.body; + console.log("Перенаправление запроса на /api/auth/verify:", { message, signature }); + + // Проверяем наличие необходимых данных + if (!message || !message.address || !signature) { + return res.status(400).json({ + success: false, + error: 'Отсутствуют необходимые данные для верификации' + }); + } + + const address = message.address.toLowerCase(); + console.log("Адрес из сообщения:", address); + + // Проверяем, является ли пользователь администратором + const isAdmin = true; // Для примера всегда true + + try { + const siweMessage = new SiweMessage(message); + const fields = await siweMessage.validate(signature); + + if (fields.address.toLowerCase() !== address.toLowerCase()) { + return res.status(401).json({ success: false, error: 'Invalid signature' }); } - }); - - // Инициализируем векторное хранилище - vectorStore = await PGVectorStore.initialize(embeddings, { - postgresConnectionOptions: { - connectionString: process.env.DATABASE_URL - }, - tableName: 'documents', - columns: { - idColumnName: 'id', - vectorColumnName: 'embedding', - contentColumnName: 'content', - metadataColumnName: 'metadata', + + // Только после проверки устанавливаем сессию + req.session.authenticated = true; + req.session.address = fields.address; + req.session.lastSignature = signature; + + // Сохраняем сессию + req.session.save(); + } catch (error) { + return res.status(401).json({ success: false, error: error.message }); + } + + // Сохраняем данные в сессии + req.session.isAuthenticated = true; + req.session.isAdmin = isAdmin; + + // Явно сохраняем сессию + req.session.save((err) => { + if (err) { + console.error('Ошибка сохранения сессии:', err); + return res.status(500).json({ error: 'Session save error' }); } - }); - - console.log('Векторное хранилище инициализировано'); - - // Инициализируем ботов только после успешной инициализации хранилища - if (!telegramBot) { - telegramBot = new TelegramBotService(process.env.TELEGRAM_BOT_TOKEN, vectorStore); - await telegramBot.initialize().catch(error => { - if (error.code === 409) { - console.log('Telegram бот уже запущен в другом процессе'); - } else { - throw error; + + console.log('Сессия успешно сохранена:', { + sessionID: req.sessionID, + session: { + isAuthenticated: req.session.isAuthenticated, + authenticated: req.session.authenticated, + address: req.session.address, + isAdmin: req.session.isAdmin } }); - } - if (!emailBot) { - emailBot = new EmailBotService(vectorStore); - } - - return vectorStore; + + res.cookie('authToken', 'true', { + maxAge: 86400000, + httpOnly: false, + secure: false, + sameSite: 'lax', + path: '/' + }); + + res.json({ + success: true, + address: address, + isAdmin: isAdmin + }); + }); } catch (error) { - console.error('Ошибка при инициализации:', error); - throw error; + console.error("Ошибка верификации:", error); + res.status(500).json({ + success: false, + error: error.message || 'Внутренняя ошибка сервера' + }); + } +}); + +// Добавьте после настройки маршрутов +app.get('/api/session', (req, res) => { + console.log('Запрос сессии в server.js:', { + sessionExists: !!req.session, + sessionID: req.sessionID, + isAuthenticated: req.session?.isAuthenticated, + authenticated: req.session?.authenticated, + address: req.session?.address + }); + + if (req.session && (req.session.isAuthenticated || req.session.authenticated)) { + res.json({ + isAuthenticated: true, + authenticated: true, + address: req.session.address, + isAdmin: req.session.isAdmin + }); + } else { + res.json({ + isAuthenticated: false, + authenticated: false, + address: null, + isAdmin: false + }); + } +}); + +app.get('/api/balance', requireAuth, async (req, res) => { + try { + const balance = await contract.balanceOf(req.session.address); + res.json({ balance: balance.toString() }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// Добавляем тестовые маршруты API +app.get('/api/public', (req, res) => { + res.json({ message: 'This is a public API endpoint' }); +}); + +app.get('/api/protected', (req, res) => { + res.json({ + message: 'This is a protected API endpoint', + user: { + address: req.session.address, + isAdmin: req.session.isAdmin + } + }); +}); + +app.get('/api/admin', (req, res) => { + res.json({ + message: 'This is an admin API endpoint', + user: { + address: req.session.address, + isAdmin: req.session.isAdmin + } + }); +}); + +// Добавьте обработчик ошибок +app.use((err, req, res, next) => { + console.error('Глобальный обработчик ошибок:', err); + + // Обработка ошибок CSRF + if (err.code === 'EBADCSRFTOKEN') { + return res.status(403).json({ + error: 'Недействительный CSRF-токен', + message: 'Возможно, ваша сессия истекла. Пожалуйста, обновите страницу и попробуйте снова.' + }); + } + + // Обработка ошибок валидации + if (err.name === 'ValidationError') { + return res.status(400).json({ + error: 'Ошибка валидации', + details: err.details || err.message + }); + } + + // Обработка ошибок базы данных + if (err.code === '23505') { // Postgres unique violation + return res.status(409).json({ + error: 'Конфликт данных', + message: 'Запись с такими данными уже существует.' + }); + } + + // Общая обработка ошибок + res.status(err.status || 500).json({ + error: 'Внутренняя ошибка сервера', + message: process.env.NODE_ENV === 'production' ? 'Что-то пошло не так' : err.message + }); +}); + +// Перед запуском сервера +console.log('Перед запуском сервера на порту:', PORT); + +// Запуск сервера и инициализация сервисов +const server = app.listen(PORT, '0.0.0.0', async () => { + console.log(`Server is running on port ${PORT}`); + console.log('Server address:', server.address()); + + // Инициализируем сервисы без блокировки запуска сервера + initServices().catch(err => { + console.error('Ошибка при инициализации сервисов:', err); + }); + + // Проверяем доступность Ollama в фоновом режиме + try { + const { checkOllamaAvailability } = require('./services/ollama'); + checkOllamaAvailability().catch(err => { + console.error('Ошибка при проверке Ollama:', err); + }); + } catch (error) { + console.error('Ошибка при импорте модуля Ollama:', error); + } +}).on('error', (err) => { + if (err.code === 'EADDRINUSE') { + console.error(`Port ${PORT} is already in use. Please try another port.`); + process.exit(1); + } else { + console.error('Server error:', err); + } +}); + +// Добавляем graceful shutdown +process.on('SIGTERM', () => { + console.log('SIGTERM signal received: closing HTTP server'); + server.close(() => { + console.log('HTTP server closed'); + process.exit(0); + }); +}); + +// Проверяем доступность Ollama сервера +async function checkOllamaServer() { + try { + const response = await axios.get('http://localhost:11434/api/tags'); + if (response.status === 200) { + console.log('Ollama сервер доступен'); + + // Тестируем прямой запрос к Ollama + try { + console.log('Тестируем прямой запрос к Ollama...'); + const model = new ChatOllama({ + baseUrl: 'http://localhost:11434', + model: 'llama3', + temperature: 0.2, + }); + + const result = await model.invoke('Привет, как дела?'); + console.log('Ответ от Ollama:', result); + } catch (testError) { + console.error('Ошибка при тестировании Ollama:', testError); + } + + // Инициализируем векторное хранилище + try { + console.log('Инициализируем векторное хранилище...'); + const vectorStore = await getVectorStore(); + console.log('Векторное хранилище инициализировано'); + } catch (vectorError) { + console.error('Ошибка при инициализации векторного хранилища:', vectorError); + } + + return true; + } + return false; + } catch (error) { + console.error('Ollama сервер недоступен:', error.message); + return false; } } -// Запускаем инициализацию -console.log('Начинаем инициализацию векторного хранилища...'); -initializeVectorStore().catch(error => { - console.error('Критическая ошибка при инициализации:', error); - process.exit(1); -}); \ No newline at end of file +// Настройка периодической очистки устаревших сессий +const pgSessionCleanup = setInterval(function() { + console.log('Cleaning up expired sessions...'); + pool.query('DELETE FROM session WHERE expire < NOW()') + .then(result => { + if (result.rowCount > 0) { + console.log(`Removed ${result.rowCount} expired sessions`); + } + }) + .catch(err => console.error('Error cleaning up sessions:', err)); +}, 3600000); // Очистка каждый час + +// Очистка интервала при завершении работы +process.on('SIGTERM', () => { + clearInterval(pgSessionCleanup); + console.log('SIGTERM signal received: closing HTTP server'); + server.close(() => { + console.log('HTTP server closed'); + process.exit(0); + }); +}); + +// Функция для создания таблиц +async function ensureTablesExist() { + try { + // Проверяем существование таблицы users + const result = await pool.query(` + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_schema = 'public' + AND table_name = 'users' + ); + `); + + // Если таблица не существует, создаем все таблицы + if (!result.rows[0].exists) { + console.log('Таблицы не найдены, создаем...'); + + // SQL-запросы для создания таблиц + const createTablesSql = ` + -- Таблица пользователей + CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + address VARCHAR(255) UNIQUE, + email VARCHAR(255) UNIQUE, + telegram_id VARCHAR(255) UNIQUE, + username VARCHAR(255), + is_admin BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() + ); + + -- Индексы для таблицы пользователей + CREATE INDEX IF NOT EXISTS idx_users_address ON users(address); + CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); + CREATE INDEX IF NOT EXISTS idx_users_telegram_id ON users(telegram_id); + + -- Таблица сессий + CREATE TABLE IF NOT EXISTS session ( + sid VARCHAR NOT NULL, + sess JSON NOT NULL, + expire TIMESTAMP(6) NOT NULL, + CONSTRAINT session_pkey PRIMARY KEY (sid) + ); + + -- Индекс для таблицы сессий + CREATE INDEX IF NOT EXISTS idx_session_expire ON session(expire); + + -- Таблица канбан-досок + CREATE TABLE IF NOT EXISTS kanban_boards ( + id SERIAL PRIMARY KEY, + title VARCHAR(255) NOT NULL, + description TEXT, + owner_id INTEGER REFERENCES users(id), + is_public BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() + ); + + -- Таблица колонок канбан-доски + CREATE TABLE IF NOT EXISTS kanban_columns ( + id SERIAL PRIMARY KEY, + board_id INTEGER REFERENCES kanban_boards(id) ON DELETE CASCADE, + title VARCHAR(255) NOT NULL, + position INTEGER NOT NULL, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() + ); + + -- Таблица карточек канбан-доски + CREATE TABLE IF NOT EXISTS kanban_cards ( + id SERIAL PRIMARY KEY, + column_id INTEGER REFERENCES kanban_columns(id) ON DELETE CASCADE, + title VARCHAR(255) NOT NULL, + description TEXT, + position INTEGER NOT NULL, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() + ); + + -- Индексы для таблиц канбан + CREATE INDEX IF NOT EXISTS idx_kanban_boards_owner ON kanban_boards(owner_id); + CREATE INDEX IF NOT EXISTS idx_kanban_columns_board ON kanban_columns(board_id); + CREATE INDEX IF NOT EXISTS idx_kanban_cards_column ON kanban_cards(column_id); + + -- Таблица сообщений чата + CREATE TABLE IF NOT EXISTS chat_messages ( + id SERIAL PRIMARY KEY, + user_id INTEGER REFERENCES users(id), + sender VARCHAR(50) NOT NULL, + message TEXT NOT NULL, + created_at TIMESTAMP DEFAULT NOW() + ); + + -- Индекс для таблицы сообщений + CREATE INDEX IF NOT EXISTS idx_chat_messages_user ON chat_messages(user_id); + `; + + await pool.query(createTablesSql); + console.log('Таблицы успешно созданы'); + } else { + console.log('Таблицы уже существуют'); + } + } catch (error) { + console.error('Ошибка при проверке/создании таблиц:', error); + } +} + +// Вызываем функцию при запуске сервера +ensureTablesExist(); + +// Добавляем middleware для проверки аутентификации +app.use('/api/protected', (req, res, next) => { + // console.log('Protected route middleware:', { + // session: req.session, + // authenticated: req.session.authenticated, + // address: req.session.address + // }); + + if (!req.session.authenticated) { + return res.status(401).json({ error: 'Unauthorized' }); + } + + next(); +}); + +// Добавляем middleware для проверки прав администратора +app.use('/api/admin', (req, res, next) => { + // console.log('Admin route middleware:', { + // session: req.session, + // authenticated: req.session.authenticated, + // isAdmin: req.session.isAdmin + // }); + + if (!req.session.authenticated || !req.session.isAdmin) { + return res.status(403).json({ error: 'Forbidden' }); + } + + next(); +}); \ No newline at end of file diff --git a/backend/services/documents.js b/backend/services/documents.js new file mode 100644 index 0000000..565d20a --- /dev/null +++ b/backend/services/documents.js @@ -0,0 +1,47 @@ +const fs = require('fs'); +const path = require('path'); +const { Document } = require('langchain/document'); +const { RecursiveCharacterTextSplitter } = require('langchain/text_splitter'); + +// Функция для загрузки документов из файлов +async function loadDocumentsFromFiles(directory) { + const documents = []; + + try { + const files = fs.readdirSync(directory); + + for (const file of files) { + const filePath = path.join(directory, file); + const stat = fs.statSync(filePath); + + if (stat.isFile() && (file.endsWith('.txt') || file.endsWith('.md'))) { + const content = fs.readFileSync(filePath, 'utf-8'); + + documents.push( + new Document({ + pageContent: content, + metadata: { + source: filePath, + filename: file, + }, + }) + ); + } + } + + // Разделяем документы на чанки + const textSplitter = new RecursiveCharacterTextSplitter({ + chunkSize: 1000, + chunkOverlap: 200, + }); + + const splitDocs = await textSplitter.splitDocuments(documents); + + return splitDocs; + } catch (error) { + console.error('Error loading documents:', error); + throw error; + } +} + +module.exports = { loadDocumentsFromFiles }; \ No newline at end of file diff --git a/backend/services/emailBot.js b/backend/services/emailBot.js index feb8d32..ce00540 100644 --- a/backend/services/emailBot.js +++ b/backend/services/emailBot.js @@ -6,280 +6,63 @@ const Imap = require('imap'); const { simpleParser } = require('mailparser'); const { checkMailServer } = require('../utils/checkMail'); const { sleep, isValidEmail } = require('../utils/helpers'); +const { linkIdentity, getUserIdByIdentity } = require('../utils/identity-linker'); require('dotenv').config(); class EmailBotService { - constructor(vectorStore) { - if (!vectorStore) { - throw new Error('Vector store is required'); - } - - console.log('Инициализация Email бота...'); - console.log('Проверяем настройки почты:', { - smtp: { - host: process.env.EMAIL_SMTP_HOST, - port: process.env.EMAIL_SMTP_PORT - }, - imap: { - host: process.env.EMAIL_IMAP_HOST, - port: process.env.EMAIL_IMAP_PORT - } - }); - - // Инициализация базы данных - this.pool = new Pool({ - connectionString: process.env.DATABASE_URL - }); - - this.vectorStore = vectorStore; - - // Инициализация LLM - this.chat = new ChatOllama({ - model: 'mistral', - baseUrl: 'http://localhost:11434' - }); - - // Настройка почтового клиента для отправки - this.transporter = nodemailer.createTransport({ - host: process.env.EMAIL_SMTP_HOST, - port: process.env.EMAIL_SMTP_PORT, - secure: true, - auth: { - user: process.env.EMAIL_USER, - pass: process.env.EMAIL_PASSWORD - }, - tls: { - rejectUnauthorized: false, - minVersion: 'TLSv1', - ciphers: 'HIGH:MEDIUM:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:!LOW:!SSLv2:!MD5' - }, - debug: true, - logger: true - }); - - // Проверяем подключение к SMTP - this.transporter.verify((error, success) => { - if (error) { - console.error('Ошибка подключения к SMTP:', { - name: error.name, - message: error.message, - code: error.code, - command: error.command, - stack: error.stack - }); - setTimeout(() => this.initSMTP(), 30000); - } - }); - - // Настройка IMAP для получения писем - const imapConfig = { - user: process.env.EMAIL_USER, - password: process.env.EMAIL_PASSWORD, - host: process.env.EMAIL_IMAP_HOST, - port: process.env.EMAIL_IMAP_PORT, - tls: true, - tlsOptions: { rejectUnauthorized: false }, - keepalive: true, - authTimeout: 30000, - connTimeout: 30000 - } - this.imap = new Imap(imapConfig); - - // Добавляем обработчик для всех событий IMAP - this.imap.on('*', function(event, data) { - console.log('IMAP Event:', event, data); - }); - - // Проверяем MX записи - const domain = process.env.EMAIL_USER ? process.env.EMAIL_USER.split('@')[1] : ''; - if (domain) { - checkMailServer(domain).then(records => { - if (!records) { - console.error('Не удалось найти MX записи для домена'); - } - }); - } else { - console.error('EMAIL_USER не настроен в .env файле'); - } - - this.isRunning = false; - this.initSMTP(); - this.initIMAP(); - console.log('Email bot service initialized'); + constructor() { + this.enabled = false; + console.log('EmailBotService: Сервис отключен (заглушка)'); } - async initSMTP() { - try { - console.log('Попытка подключения к SMTP...'); - await this.transporter.verify(); - console.log('SMTP сервер готов к отправке сообщений'); - } catch (error) { - console.error('Ошибка подключения к SMTP:', { - name: error.name, - message: error.message, - code: error.code, - command: error.command, - stack: error.stack - }); - } - } - - async initIMAP() { - try { - await this.initEmailListener(); - console.log('IMAP подключение установлено'); - } catch (error) { - console.error('Ошибка инициализации IMAP:', error); - } - } - - async initEmailListener() { - try { - this.imap.on('ready', () => { - this.imap.openBox('INBOX', false, (err, box) => { - if (err) throw err; - - // Слушаем новые письма - this.imap.on('mail', () => { - this.checkNewEmails(); - }); - }); - }); - - this.imap.on('error', (err) => { - console.log('IMAP ошибка:', err); - if (err.source === 'timeout-auth') { - setTimeout(() => { - console.log('Попытка переподключения к IMAP...'); - this.imap.connect(); - }, 5000); - } - }); - - this.imap.connect(); - } catch (error) { - console.error('Ошибка при инициализации IMAP:', error); - } - } - - async processEmail(message) { - try { - // Очищаем и валидируем email адрес - const cleanEmail = message.from.replace(/[<>]/g, '').trim(); - if (!isValidEmail(cleanEmail)) { - console.log('Некорректный email адрес:', message.from); - return; - } - - // Проверяем, не является ли отправитель no-reply адресом - if (cleanEmail.toLowerCase().includes('no-reply') || - cleanEmail.toLowerCase().includes('noreply')) { - console.log('Пропускаем письмо от no-reply адреса:', cleanEmail); - return; - } - - // Проверяем валидность домена получателя - const domain = cleanEmail.split('@')[1]; - try { - console.log(`Проверяем MX записи для домена ${domain}...`); - const records = await checkMailServer(domain); - if (!records || records.length === 0) { - console.log('Пропускаем письмо - домен не найден:', domain); - return; - } - console.log('Найдены MX записи:', records); - } catch (err) { - console.error('Ошибка при проверке MX записей:', err); - return; - } - - // Получаем ответ от Ollama - const result = await this.chat.invoke(message.text); - - // Отправляем ответ - await this.transporter.sendMail({ - from: process.env.EMAIL_USER, - to: cleanEmail, - subject: `Re: ${message.subject}`, - text: result.content - }); - - console.log('Ответ отправлен:', { - to: cleanEmail, - subject: message.subject - }); - } catch (error) { - console.error('Ошибка при обработке email:', error); - } - } - - async checkNewEmails() { - try { - const messages = await new Promise((resolve, reject) => { - this.imap.search(['UNSEEN'], (err, results) => { - if (err) reject(err); - - if (!results || !results.length) { - resolve([]); - return; - } - - const fetch = this.imap.fetch(results, { - bodies: '', - markSeen: true - }); - - const messages = []; - - fetch.on('message', (msg) => { - msg.on('body', (stream) => { - let buffer = ''; - stream.on('data', (chunk) => { - buffer += chunk.toString('utf8'); - }); - stream.once('end', () => { - messages.push({ - from: buffer.match(/From: (.*)/i)?.[1], - subject: buffer.match(/Subject: (.*)/i)?.[1], - text: buffer.split('\n\n').slice(1).join('\n\n') - }); - }); - }); - }); - - fetch.once('error', reject); - fetch.once('end', () => resolve(messages)); - }); - }); - - // Добавляем задержку между обработкой писем - for (const message of messages) { - await this.processEmail(message); - await new Promise(resolve => setTimeout(resolve, 1000)); // 1 секунда между письмами - } - } catch (error) { - console.error('Ошибка при проверке новых писем:', error); - } + async start() { + console.log('EmailBotService: Запуск сервиса отключен (заглушка)'); + return false; } async stop() { - if (this.isRunning) { - console.log('Останавливаем Email бота...'); - - // Закрываем SMTP соединение - if (this.transporter) { - await this.transporter.close(); - } - - // Закрываем IMAP соединение - if (this.imap) { - this.imap.end(); - } - - this.isRunning = false; - console.log('Email бот остановлен'); - } + console.log('EmailBotService: Остановка сервиса отключена (заглушка)'); + return true; + } + + isEnabled() { + return this.enabled; } } +// В обработчике команд добавьте код для связывания аккаунтов +async function processCommand(email, command, args) { + if (command === 'link' && args.length > 0) { + const ethAddress = args[0]; + + // Проверяем формат Ethereum-адреса + if (!/^0x[a-fA-F0-9]{40}$/.test(ethAddress)) { + return 'Неверный формат Ethereum-адреса. Используйте формат 0x...'; + } + + try { + // Получаем ID пользователя по Ethereum-адресу + const userId = await getUserIdByIdentity('ethereum', ethAddress); + + if (!userId) { + return 'Пользователь с таким Ethereum-адресом не найден. Сначала войдите через веб-интерфейс.'; + } + + // Связываем Email-аккаунт с пользователем + const success = await linkIdentity(userId, 'email', email); + + if (success) { + return `Ваш Email-аккаунт успешно связан с Ethereum-адресом ${ethAddress}`; + } else { + return 'Не удалось связать аккаунты. Возможно, этот Email-аккаунт уже связан с другим пользователем.'; + } + } catch (error) { + console.error('Ошибка при связывании аккаунтов:', error); + return 'Произошла ошибка при связывании аккаунтов. Попробуйте позже.'; + } + } + + // Обработка других команд... +} + module.exports = EmailBotService; \ No newline at end of file diff --git a/backend/services/ollama.js b/backend/services/ollama.js new file mode 100644 index 0000000..336429d --- /dev/null +++ b/backend/services/ollama.js @@ -0,0 +1,149 @@ +const { ChatOllama } = require('@langchain/ollama'); +const { RetrievalQAChain } = require("langchain/chains"); +const { PromptTemplate } = require("@langchain/core/prompts"); +const axios = require('axios'); + +// Создаем шаблон для контекстного запроса +const PROMPT_TEMPLATE = ` +Ты - AI-ассистент для бизнеса, специализирующийся на блокчейн-технологиях и Web3. +Используй следующий контекст для ответа на вопрос пользователя. +Если ты не знаешь ответа, просто скажи, что не знаешь, не пытайся придумать ответ. + +Контекст: {context} + +Вопрос: {query} + +Ответ: +`; + +// Функция для проверки доступности Ollama +async function checkOllamaAvailability() { + console.log('Проверка доступности Ollama...'); + + try { + // Добавляем таймаут для запроса + const response = await axios.get('http://localhost:11434/api/tags', { + timeout: 5000 // 5 секунд таймаут + }); + + if (response.status === 200) { + console.log('Ollama доступен. Доступные модели:'); + if (response.data && response.data.models) { + response.data.models.forEach(model => { + console.log(`- ${model.name}`); + }); + } + return true; + } + } catch (error) { + console.error('Ollama недоступен:', error.message); + console.log('Приложение продолжит работу без Ollama'); + return false; + } +} + +// Функция для прямого запроса к Ollama API +async function directOllamaQuery(message, model = 'mistral') { + try { + console.log(`Отправка запроса к Ollama (модель: ${model}):`, message); + + // Проверяем доступность Ollama перед отправкой запроса + const isAvailable = await checkOllamaAvailability(); + if (!isAvailable) { + throw new Error('Сервер Ollama недоступен'); + } + + // Создаем экземпляр ChatOllama + const ollama = new ChatOllama({ + baseUrl: 'http://localhost:11434', + model: model, + temperature: 0.7, + }); + + console.log('Отправка запроса к Ollama...'); + const result = await ollama.invoke(message); + console.log('Получен ответ от Ollama'); + + return result.content; + } catch (error) { + console.error('Ошибка при запросе к Ollama:', error); + throw error; + } +} + +// Функция для создания цепочки Ollama с RAG +async function createOllamaChain(vectorStore) { + try { + console.log('Создаем модель Ollama...'); + // Создаем модель Ollama + const model = new ChatOllama({ + baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434', + model: process.env.OLLAMA_MODEL || 'mistral', + temperature: 0.2, + timeout: 60000, // 60 секунд таймаут + }); + console.log('Модель Ollama создана'); + + // Проверяем модель прямым запросом + try { + console.log('Тестируем модель прямым запросом...'); + const testResponse = await model.invoke('Тестовый запрос'); + console.log('Тест модели успешен:', testResponse); + } catch (testError) { + console.error('Ошибка при тестировании модели:', testError); + // Продолжаем выполнение, даже если тест не прошел + } + + console.log('Создаем шаблон запроса...'); + // Создаем шаблон запроса + const prompt = new PromptTemplate({ + template: PROMPT_TEMPLATE, + inputVariables: ["context", "query"], + }); + console.log('Шаблон запроса создан'); + + console.log('Получаем retriever из векторного хранилища...'); + const retriever = vectorStore.asRetriever(); + console.log('Retriever получен'); + + console.log('Создаем цепочку для поиска и ответа...'); + // Создаем цепочку для поиска и ответа + const chain = RetrievalQAChain.fromLLM( + model, + retriever, + { + returnSourceDocuments: true, + prompt: prompt, + inputKey: "query", + outputKey: "text", + verbose: true + } + ); + console.log('Цепочка для поиска и ответа создана'); + + return chain; + } catch (error) { + console.error('Error creating Ollama chain:', error); + throw error; + } +} + +// Функция для получения модели Ollama +async function getOllamaModel() { + try { + // Создаем модель Ollama + const model = new ChatOllama({ + baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434', + model: process.env.OLLAMA_MODEL || 'mistral', + temperature: 0.2, + timeout: 60000, // 60 секунд таймаут + }); + + return model; + } catch (error) { + console.error('Error creating Ollama model:', error); + throw error; + } +} + +module.exports = { getOllamaModel, createOllamaChain, checkOllamaAvailability, directOllamaQuery }; \ No newline at end of file diff --git a/backend/services/telegramBot.js b/backend/services/telegramBot.js index 4b936aa..0fc0e2f 100644 --- a/backend/services/telegramBot.js +++ b/backend/services/telegramBot.js @@ -6,10 +6,12 @@ require('dotenv').config(); const { sleep } = require('../utils/helpers'); const util = require('util'); const exec = util.promisify(require('child_process').exec); +const { linkIdentity, getUserIdByIdentity } = require('../utils/identity-linker'); class TelegramBotService { - constructor(token) { - if (!token) { + constructor() { + // Проверяем наличие токена + if (!process.env.TELEGRAM_BOT_TOKEN) { throw new Error('Token is required'); } @@ -18,7 +20,7 @@ class TelegramBotService { this.retryDelay = 5000; // 5 секунд между попытками // Создаем бота без polling - this.bot = new TelegramBot(token, { + this.bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, { polling: false, request: { proxy: null, @@ -30,7 +32,7 @@ class TelegramBotService { } }); - this.token = token; + this.token = process.env.TELEGRAM_BOT_TOKEN; this.chat = new ChatOllama({ model: 'mistral', baseUrl: 'http://localhost:11434' @@ -45,6 +47,8 @@ class TelegramBotService { minVersion: 'TLSv1.2' }) }; + + this.initialize(); } setupHandlers() { @@ -73,6 +77,39 @@ class TelegramBotService { ); } }); + + this.bot.onText(/\/link (.+)/, async (msg, match) => { + const chatId = msg.chat.id; + const ethAddress = match[1]; + + // Проверяем формат Ethereum-адреса + if (!/^0x[a-fA-F0-9]{40}$/.test(ethAddress)) { + this.bot.sendMessage(chatId, 'Неверный формат Ethereum-адреса. Используйте формат 0x...'); + return; + } + + try { + // Получаем ID пользователя по Ethereum-адресу + const userId = await getUserIdByIdentity('ethereum', ethAddress); + + if (!userId) { + this.bot.sendMessage(chatId, 'Пользователь с таким Ethereum-адресом не найден. Сначала войдите через веб-интерфейс.'); + return; + } + + // Связываем Telegram-аккаунт с пользователем + const success = await linkIdentity(userId, 'telegram', chatId.toString()); + + if (success) { + this.bot.sendMessage(chatId, `Ваш Telegram-аккаунт успешно связан с Ethereum-адресом ${ethAddress}`); + } else { + this.bot.sendMessage(chatId, 'Не удалось связать аккаунты. Возможно, этот Telegram-аккаунт уже связан с другим пользователем.'); + } + } catch (error) { + console.error('Ошибка при связывании аккаунтов:', error); + this.bot.sendMessage(chatId, 'Произошла ошибка при связывании аккаунтов. Попробуйте позже.'); + } + }); } setupCommands() { diff --git a/backend/services/telegramBot.js: b/backend/services/telegramBot.js: deleted file mode 100644 index fbe2ecb..0000000 --- a/backend/services/telegramBot.js: +++ /dev/null @@ -1,75 +0,0 @@ -const TelegramBot = require('node-telegram-bot-api'); -const { ChatOllama } = require('@langchain/ollama'); -const { PGVectorStore } = require('@langchain/community/vectorstores/pgvector'); - -class TelegramBotService { - constructor(token, vectorStore) { - this.bot = new TelegramBot(token, { polling: true }); - this.vectorStore = vectorStore; - this.chat = new ChatOllama({ - model: 'mistral', - baseUrl: 'http://localhost:11434' - }); - - this.userRequests = new Map(); // для отслеживания запросов - - this.setupHandlers(); - } - - isRateLimited(userId) { - const now = Date.now(); - const userReqs = this.userRequests.get(userId) || []; - - // Очищаем старые запросы - const recentReqs = userReqs.filter(time => now - time < 60000); - - // Максимум 10 запросов в минуту - if (recentReqs.length >= 10) return true; - - recentReqs.push(now); - this.userRequests.set(userId, recentReqs); - return false; - } - - setupHandlers() { - this.bot.on('message', async (msg) => { - const userId = msg.from.id; - - if (this.isRateLimited(userId)) { - await this.bot.sendMessage(msg.chat.id, - 'Пожалуйста, подождите минуту перед следующим запросом.'); - return; - } - - try { - const chatId = msg.chat.id; - const userQuestion = msg.text; - - // Поиск релевантных документов - const relevantDocs = await this.vectorStore.similaritySearch(userQuestion, 3); - - // Формируем контекст из найденных документов - const context = relevantDocs.map(doc => doc.pageContent).join('\n'); - - // Получаем ответ от LLM - const response = await this.chat.invoke([ - { - role: 'system', - content: `You are a helpful assistant. Use this context to answer: ${context}` - }, - { - role: 'user', - content: userQuestion - } - ]); - - await this.bot.sendMessage(chatId, response); - - } catch (error) { - console.error('Telegram bot error:', error); - } - }); - } -} - -module.exports = TelegramBotService; diff --git a/backend/services/vectorStore.js b/backend/services/vectorStore.js new file mode 100644 index 0000000..ab3699a --- /dev/null +++ b/backend/services/vectorStore.js @@ -0,0 +1,134 @@ +const { HNSWLib } = require("@langchain/community/vectorstores/hnswlib"); +const { OllamaEmbeddings } = require("@langchain/ollama"); +const { DirectoryLoader } = require("langchain/document_loaders/fs/directory"); +const { TextLoader } = require("langchain/document_loaders/fs/text"); +const { RecursiveCharacterTextSplitter } = require("langchain/text_splitter"); +const fs = require('fs'); +const path = require('path'); + +// Путь к директории с документами +const DOCS_DIR = path.join(__dirname, '../data/documents'); +// Путь к директории для хранения векторного индекса +const VECTOR_STORE_DIR = path.join(__dirname, '../data/vector_store'); + +// Создаем директории, если они не существуют +if (!fs.existsSync(DOCS_DIR)) { + fs.mkdirSync(DOCS_DIR, { recursive: true }); + console.log(`Создана директория для документов: ${DOCS_DIR}`); +} + +if (!fs.existsSync(VECTOR_STORE_DIR)) { + fs.mkdirSync(VECTOR_STORE_DIR, { recursive: true }); + console.log(`Создана директория для векторного хранилища: ${VECTOR_STORE_DIR}`); +} + +// Глобальная переменная для хранения экземпляра векторного хранилища +let vectorStore = null; + +// Функция для инициализации векторного хранилища +async function initializeVectorStore() { + try { + console.log('Инициализация векторного хранилища...'); + + // Проверяем, существует ли директория с документами + if (!fs.existsSync(DOCS_DIR)) { + console.warn(`Директория с документами не найдена: ${DOCS_DIR}`); + return null; + } + + // Проверяем, есть ли документы в директории + const files = fs.readdirSync(DOCS_DIR); + if (files.length === 0) { + console.warn(`В директории с документами нет файлов: ${DOCS_DIR}`); + return null; + } + + console.log(`Найдено ${files.length} файлов в директории с документами`); + + // Загружаем документы из директории + const loader = new DirectoryLoader( + DOCS_DIR, + { + ".txt": (path) => new TextLoader(path), + ".md": (path) => new TextLoader(path), + } + ); + + console.log('Загрузка документов...'); + const docs = await loader.load(); + console.log(`Загружено ${docs.length} документов`); + + if (docs.length === 0) { + console.warn('Не удалось загрузить документы'); + return null; + } + + // Разбиваем документы на чанки + const textSplitter = new RecursiveCharacterTextSplitter({ + chunkSize: 1000, + chunkOverlap: 200, + }); + + console.log('Разбиение документов на чанки...'); + const splitDocs = await textSplitter.splitDocuments(docs); + console.log(`Документы разбиты на ${splitDocs.length} чанков`); + + // Создаем эмбеддинги с помощью Ollama + console.log('Создание эмбеддингов...'); + const embeddings = new OllamaEmbeddings({ + model: "mistral", + baseUrl: "http://localhost:11434", + }); + + // Проверяем, существует ли уже векторное хранилище + if (fs.existsSync(path.join(VECTOR_STORE_DIR, 'hnswlib.index'))) { + console.log('Загрузка существующего векторного хранилища...'); + try { + vectorStore = await HNSWLib.load( + VECTOR_STORE_DIR, + embeddings + ); + console.log('Векторное хранилище успешно загружено'); + return vectorStore; + } catch (error) { + console.error('Ошибка при загрузке векторного хранилища:', error); + console.log('Создание нового векторного хранилища...'); + } + } + + // Создаем новое векторное хранилище + console.log('Создание нового векторного хранилища...'); + vectorStore = await HNSWLib.fromDocuments( + splitDocs, + embeddings + ); + + // Сохраняем векторное хранилище + console.log('Сохранение векторного хранилища...'); + await vectorStore.save(VECTOR_STORE_DIR); + console.log('Векторное хранилище успешно сохранено'); + + return vectorStore; + } catch (error) { + console.error('Ошибка при инициализации векторного хранилища:', error); + console.log('Приложение продолжит работу без векторного хранилища'); + // Возвращаем заглушку вместо реального хранилища + return { + addDocuments: async () => console.log('Векторное хранилище недоступно: addDocuments'), + similaritySearch: async () => { + console.log('Векторное хранилище недоступно: similaritySearch'); + return []; + } + }; + } +} + +// Функция для получения экземпляра векторного хранилища +async function getVectorStore() { + if (!vectorStore) { + vectorStore = await initializeVectorStore(); + } + return vectorStore; +} + +module.exports = { initializeVectorStore, getVectorStore }; \ No newline at end of file diff --git a/backend/sessions/GkxncRD9Nurb3W4-3DIckEwmjfOmT8r5.json b/backend/sessions/GkxncRD9Nurb3W4-3DIckEwmjfOmT8r5.json deleted file mode 100644 index 402e117..0000000 --- a/backend/sessions/GkxncRD9Nurb3W4-3DIckEwmjfOmT8r5.json +++ /dev/null @@ -1 +0,0 @@ -{"cookie":{"originalMaxAge":2592000000,"expires":"2025-03-23T13:02:38.982Z","secure":false,"httpOnly":true,"domain":"127.0.0.1","path":"/","sameSite":"lax"},"__lastAccess":1740142958982} \ No newline at end of file diff --git a/backend/sessions/MQ7gY14YfnCv8X0bQKUNjZjITzdTWz58.json b/backend/sessions/MQ7gY14YfnCv8X0bQKUNjZjITzdTWz58.json deleted file mode 100644 index be1bed4..0000000 --- a/backend/sessions/MQ7gY14YfnCv8X0bQKUNjZjITzdTWz58.json +++ /dev/null @@ -1 +0,0 @@ -{"cookie":{"originalMaxAge":2591999999,"expires":"2025-03-24T09:38:02.826Z","secure":false,"httpOnly":true,"domain":"127.0.0.1","path":"/","sameSite":"lax"},"nonce":null,"__lastAccess":1740217082827,"siwe":{"domain":"127.0.0.1:5173","address":"0xF45aa4917b3775bA37f48Aeb3dc1a943561e9e0B","statement":"Sign in with Ethereum to access DApp features and AI Assistant","uri":"http://127.0.0.1:5173","version":"1","nonce":"3ZIxF8sn0dDIbwWZz","issuedAt":"2025-02-22T09:37:59.804Z","chainId":11155111,"resources":["http://127.0.0.1:5173/api/chat","http://127.0.0.1:5173/api/contract"]},"authenticated":true} \ No newline at end of file diff --git a/backend/sessions/OgJhv73wKRJ4xuAAUBa9k5CtZ9E4dcFJ.json b/backend/sessions/OgJhv73wKRJ4xuAAUBa9k5CtZ9E4dcFJ.json deleted file mode 100644 index b710c12..0000000 --- a/backend/sessions/OgJhv73wKRJ4xuAAUBa9k5CtZ9E4dcFJ.json +++ /dev/null @@ -1 +0,0 @@ -{"cookie":{"originalMaxAge":2592000000,"expires":"2025-03-23T14:54:20.531Z","secure":false,"httpOnly":true,"domain":"127.0.0.1","path":"/","sameSite":"lax"},"__lastAccess":1740149660531} \ No newline at end of file diff --git a/backend/sessions/P6j78qGOxf6uv3j-AGfgu0la3luxKbaV.json b/backend/sessions/P6j78qGOxf6uv3j-AGfgu0la3luxKbaV.json deleted file mode 100644 index 519ec36..0000000 --- a/backend/sessions/P6j78qGOxf6uv3j-AGfgu0la3luxKbaV.json +++ /dev/null @@ -1 +0,0 @@ -{"cookie":{"originalMaxAge":2592000000,"expires":"2025-03-23T14:53:08.151Z","secure":false,"httpOnly":true,"domain":"127.0.0.1","path":"/","sameSite":"lax"},"__lastAccess":1740149588151} \ No newline at end of file diff --git a/backend/sessions/VO2T1gK1S6E0sq7-yYtjHx6p3nsixeGv.json b/backend/sessions/VO2T1gK1S6E0sq7-yYtjHx6p3nsixeGv.json deleted file mode 100644 index ba2a55a..0000000 --- a/backend/sessions/VO2T1gK1S6E0sq7-yYtjHx6p3nsixeGv.json +++ /dev/null @@ -1 +0,0 @@ -{"cookie":{"originalMaxAge":2592000000,"expires":"2025-03-23T14:36:28.622Z","secure":false,"httpOnly":true,"domain":"127.0.0.1","path":"/","sameSite":"lax"},"__lastAccess":1740148588623} \ No newline at end of file diff --git a/backend/sessions/jK4QzdazTk9W_ubXZTLnIEwgGD2xcwmE.json b/backend/sessions/jK4QzdazTk9W_ubXZTLnIEwgGD2xcwmE.json deleted file mode 100644 index 6c28ad7..0000000 --- a/backend/sessions/jK4QzdazTk9W_ubXZTLnIEwgGD2xcwmE.json +++ /dev/null @@ -1 +0,0 @@ -{"cookie":{"originalMaxAge":2592000000,"expires":"2025-03-23T14:49:54.299Z","secure":false,"httpOnly":true,"domain":"127.0.0.1","path":"/","sameSite":"lax"},"__lastAccess":1740149394299} \ No newline at end of file diff --git a/backend/sessions/t4gYbGFB1rs62XHWoVIOf__LteYmcpJx.json b/backend/sessions/t4gYbGFB1rs62XHWoVIOf__LteYmcpJx.json deleted file mode 100644 index 6c878a2..0000000 --- a/backend/sessions/t4gYbGFB1rs62XHWoVIOf__LteYmcpJx.json +++ /dev/null @@ -1 +0,0 @@ -{"cookie":{"originalMaxAge":2592000000,"expires":"2025-03-23T13:32:20.745Z","secure":false,"httpOnly":true,"domain":"127.0.0.1","path":"/","sameSite":"lax"},"__lastAccess":1740144740745} \ No newline at end of file diff --git a/backend/test/AccessToken.test.js b/backend/test/AccessToken.test.js new file mode 100644 index 0000000..f1a0dac --- /dev/null +++ b/backend/test/AccessToken.test.js @@ -0,0 +1,45 @@ +const { expect } = require("chai"); +const { ethers } = require("hardhat"); + +describe("AccessToken", function () { + let AccessToken; + let accessToken; + let owner; + let addr1; + let addr2; + + beforeEach(async function () { + [owner, addr1, addr2] = await ethers.getSigners(); + AccessToken = await ethers.getContractFactory("AccessToken"); + accessToken = await AccessToken.deploy(); + }); + + describe("Minting", function () { + it("Should mint admin token", async function () { + await accessToken.mintAccessToken(addr1.address, 0); + expect(await accessToken.checkRole(addr1.address)).to.equal(0); + }); + + it("Should mint moderator token", async function () { + await accessToken.mintAccessToken(addr1.address, 1); + expect(await accessToken.checkRole(addr1.address)).to.equal(1); + }); + }); + + describe("Access Control", function () { + it("Should fail for non-token holders", async function () { + await expect( + accessToken.checkRole(addr1.address) + ).to.be.revertedWith("No active token"); + }); + + it("Should revoke access", async function () { + await accessToken.mintAccessToken(addr1.address, 0); + const tokenId = await accessToken.activeTokens(addr1.address); + await accessToken.revokeToken(tokenId); + await expect( + accessToken.checkRole(addr1.address) + ).to.be.revertedWith("No active token"); + }); + }); +}); \ No newline at end of file diff --git a/backend/test/MyContract.test.js b/backend/test/MyContract.test.js deleted file mode 100644 index 0565d1e..0000000 --- a/backend/test/MyContract.test.js +++ /dev/null @@ -1,42 +0,0 @@ -const { expect } = require("chai"); -const { ethers } = require("hardhat"); - -describe("MyContract", function () { - let myContract; - let owner; - let addr1; - let addr2; - - beforeEach(async function () { - // Получаем аккаунты из Hardhat - [owner, addr1, addr2] = await ethers.getSigners(); - - // Деплоим контракт - const MyContract = await ethers.getContractFactory("MyContract"); - myContract = await MyContract.deploy(); - await myContract.deployed(); - }); - - describe("Deployment", function () { - it("Should set the right owner", async function () { - expect(await myContract.owner()).to.equal(owner.address); - }); - }); - - describe("Transactions", function () { - it("Should allow owner to set new owner", async function () { - await myContract.setOwner(addr1.address); - expect(await myContract.owner()).to.equal(addr1.address); - }); - - it("Should fail if non-owner tries to set new owner", async function () { - // Подключаемся к контракту от имени addr1 - const contractConnectedToAddr1 = myContract.connect(addr1); - - // Ожидаем, что транзакция будет отменена - await expect( - contractConnectedToAddr1.setOwner(addr2.address) - ).to.be.revertedWith("Only owner can call this function"); - }); - }); -}); \ No newline at end of file diff --git a/backend/utils/access-check.js b/backend/utils/access-check.js new file mode 100644 index 0000000..c01e652 --- /dev/null +++ b/backend/utils/access-check.js @@ -0,0 +1,89 @@ +const { ethers } = require('ethers'); +require('dotenv').config(); +const contractArtifact = require('../artifacts/contracts/MyContract.sol/MyContract.json'); +const contractABI = contractArtifact.abi; + +// Проверяем наличие необходимых переменных окружения +if (!process.env.ACCESS_TOKEN_ADDRESS) { + console.error('ACCESS_TOKEN_ADDRESS не указан в .env файле'); +} + +if (!process.env.ETHEREUM_NETWORK_URL) { + console.error('ETHEREUM_NETWORK_URL не указан в .env файле'); +} + +// Подключение к контракту +const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NETWORK_URL); +let accessToken; + +try { + const AccessTokenABI = require('../artifacts/contracts/AccessToken.sol/AccessToken.json').abi; + accessToken = new ethers.Contract( + process.env.ACCESS_TOKEN_ADDRESS, + AccessTokenABI, + provider + ); +} catch (error) { + console.error('Ошибка инициализации контракта AccessToken:', error); +} + +/** + * Проверяет доступ и роль пользователя + * @param {string} address - Ethereum адрес пользователя + * @returns {Promise<{hasAccess: boolean, role: string|null}>} + */ +async function checkAccess(address) { + try { + if (!address || !accessToken) { + return { hasAccess: false, role: null }; + } + + // Проверяем активный токен + const activeTokenId = await accessToken.activeTokens(address); + if (activeTokenId.toString() === '0') { + return { hasAccess: false, role: null }; + } + + // Получаем роль + const roleId = await accessToken.checkRole(address); + const roles = ['ADMIN', 'MODERATOR', 'SUPPORT']; + const role = roles[roleId]; + + return { + hasAccess: true, + role, + tokenId: activeTokenId.toString() + }; + } catch (error) { + console.error('Access check error:', error); + return { hasAccess: false, role: null }; + } +} + +async function checkAdmin(address) { + try { + console.log('Проверка прав администратора для адреса:', address); + // Проверяем, является ли пользователь администратором через смарт-контракт + const contract = new ethers.Contract( + process.env.CONTRACT_ADDRESS, + contractABI, + provider + ); + + console.log('Контракт инициализирован:', { + address: process.env.CONTRACT_ADDRESS, + provider: provider.connection.url + }); + + const isAdmin = await contract.isAdmin(address); + console.log('Результат проверки из контракта:', isAdmin); + + return isAdmin; + } catch (error) { + console.error('Ошибка при проверке прав администратора:', error); + // В случае ошибки возвращаем false вместо выброса исключения + return false; + } +} + +module.exports = { checkAccess, checkAdmin }; \ No newline at end of file diff --git a/backend/utils/auth.js b/backend/utils/auth.js new file mode 100644 index 0000000..d2850c6 --- /dev/null +++ b/backend/utils/auth.js @@ -0,0 +1,84 @@ +const { SiweMessage } = require('siwe'); +const { ethers } = require('ethers'); +const AccessTokenABI = require('../artifacts/contracts/AccessToken.sol/AccessToken.json').abi; +require('dotenv').config(); + +const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NETWORK_URL); +const accessToken = new ethers.Contract( + process.env.ACCESS_TOKEN_ADDRESS, + AccessTokenABI, + provider +); + +// Проверяем наличие адреса контракта +if (!process.env.ACCESS_TOKEN_ADDRESS) { + console.error('ACCESS_TOKEN_ADDRESS не указан в .env файле'); +} + +/** + * Проверяет подпись сообщения + * @param {Object} message - Сообщение для проверки + * @param {string} signature - Подпись сообщения + * @param {string} address - Адрес кошелька + * @returns {Promise} - Результат проверки + */ +async function verifySignature(message, signature, address) { + try { + // Формируем сообщение для проверки + const domain = message.domain || window.location.host; + const statement = message.statement || 'Sign in with Ethereum to the app.'; + const uri = message.uri || window.location.origin; + const version = message.version || '1'; + const chainId = message.chainId || '1'; + const nonce = message.nonce; + + const messageToVerify = `${domain} wants you to sign in with your Ethereum account: +${address} + +${statement} + +URI: ${uri} +Version: ${version} +Chain ID: ${chainId} +Nonce: ${nonce} +`; + + // Восстанавливаем адрес из подписи + const recoveredAddress = ethers.verifyMessage(messageToVerify, signature); + + return recoveredAddress.toLowerCase() === address.toLowerCase(); + } catch (error) { + console.error('Signature verification error:', error); + return false; + } +} + +async function checkAccess(address) { + // Временная заглушка + return { hasAccess: false, role: null }; +} + +async function verifyAndCheckAccess(message, signature, address) { + // Проверяем подпись + const verified = await verifySignature(message, signature, address); + if (!verified) { + return { + verified: false, + access: { hasAccess: false } + }; + } + + // Проверяем доступ + const access = await checkAccess(address); + + return { + verified: true, + access + }; +} + +module.exports = { + verifyAndCheckAccess, + verifySignature, + checkAccess +}; \ No newline at end of file diff --git a/backend/utils/identity-linker.js b/backend/utils/identity-linker.js new file mode 100644 index 0000000..843a16c --- /dev/null +++ b/backend/utils/identity-linker.js @@ -0,0 +1,95 @@ +const { Pool } = require('pg'); + +// Подключение к БД +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false +}); + +/** + * Связывает идентификатор с пользователем + * @param {number} userId - ID пользователя + * @param {string} identityType - Тип идентификатора ('ethereum', 'telegram', 'email') + * @param {string} identityValue - Значение идентификатора + * @returns {Promise} - Результат операции + */ +async function linkIdentity(userId, identityType, identityValue) { + try { + // Проверяем, существует ли уже такой идентификатор + const existingResult = await pool.query( + 'SELECT * FROM user_identities WHERE identity_type = $1 AND identity_value = $2', + [identityType, identityValue] + ); + + if (existingResult.rows.length > 0) { + // Если идентификатор уже связан с другим пользователем, возвращаем ошибку + if (existingResult.rows[0].user_id !== userId) { + console.warn(`Identity ${identityType}:${identityValue} already linked to another user`); + return false; + } + // Если идентификатор уже связан с этим пользователем, ничего не делаем + return true; + } + + // Добавляем новую связь + await pool.query( + 'INSERT INTO user_identities (user_id, identity_type, identity_value, created_at) VALUES ($1, $2, $3, NOW())', + [userId, identityType, identityValue] + ); + + console.log(`Successfully linked ${identityType}:${identityValue} to user ${userId}`); + return true; + } catch (error) { + console.error('Error linking identity:', error); + return false; + } +} + +/** + * Получает ID пользователя по идентификатору + * @param {string} identityType - Тип идентификатора ('ethereum', 'telegram', 'email') + * @param {string} identityValue - Значение идентификатора + * @returns {Promise} - ID пользователя или null, если не найден + */ +async function getUserIdByIdentity(identityType, identityValue) { + try { + const result = await pool.query( + 'SELECT user_id FROM user_identities WHERE identity_type = $1 AND identity_value = $2', + [identityType, identityValue] + ); + + if (result.rows.length === 0) { + return null; + } + + return result.rows[0].user_id; + } catch (error) { + console.error('Error getting user ID by identity:', error); + return null; + } +} + +/** + * Получает все идентификаторы пользователя + * @param {number} userId - ID пользователя + * @returns {Promise} - Массив идентификаторов или null в случае ошибки + */ +async function getUserIdentities(userId) { + try { + const result = await pool.query( + 'SELECT identity_type, identity_value FROM user_identities WHERE user_id = $1', + [userId] + ); + + return result.rows; + } catch (error) { + console.error('Error getting user identities:', error); + return null; + } +} + +module.exports = { + linkIdentity, + getUserIdByIdentity, + getUserIdentities +}; \ No newline at end of file diff --git a/backend/utils/logger.js b/backend/utils/logger.js new file mode 100644 index 0000000..73c6076 --- /dev/null +++ b/backend/utils/logger.js @@ -0,0 +1,27 @@ +const winston = require('winston'); +const path = require('path'); + +const logger = winston.createLogger({ + level: process.env.LOG_LEVEL || 'info', + format: winston.format.combine( + winston.format.timestamp(), + winston.format.json() + ), + transports: [ + new winston.transports.Console({ + format: winston.format.combine( + winston.format.colorize(), + winston.format.simple() + ) + }), + new winston.transports.File({ + filename: path.join(__dirname, '../logs/error.log'), + level: 'error' + }), + new winston.transports.File({ + filename: path.join(__dirname, '../logs/combined.log') + }) + ] +}); + +module.exports = logger; \ No newline at end of file diff --git a/backend/yarn.lock b/backend/yarn.lock index c9cd304..4322b18 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -7,10 +7,25 @@ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== -"@cfworker/json-schema@^4.0.2": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@cfworker/json-schema/-/json-schema-4.1.1.tgz#4a2a3947ee9fa7b7c24be981422831b8674c3be6" - integrity sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og== +"@anthropic-ai/sdk@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@anthropic-ai/sdk/-/sdk-0.9.1.tgz#b2d2b7bf05c90dce502c9a2e869066870f69ba88" + integrity sha512-wa1meQ2WSfoY8Uor3EdrJq0jTiZJoKoSii2ZVWRY1oN4Tlr5s59pADg9T79FTbPe1/se5c3pBeZgJL63wmuoBA== + dependencies: + "@types/node" "^18.11.18" + "@types/node-fetch" "^2.6.4" + abort-controller "^3.0.0" + agentkeepalive "^4.2.1" + digest-fetch "^1.3.0" + form-data-encoder "1.7.2" + formdata-node "^4.3.2" + node-fetch "^2.6.7" + web-streams-polyfill "^3.2.1" + +"@colors/colors@1.6.0", "@colors/colors@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" + integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== "@cypress/request-promise@^5.0.0": version "5.0.0" @@ -46,215 +61,51 @@ tunnel-agent "^0.6.0" uuid "^8.3.2" -"@ethersproject/abi@^5.1.2": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== +"@dabh/diagnostics@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" + integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" + colorspace "1.1.x" + enabled "2.0.x" + kuler "^2.0.0" -"@ethersproject/abstract-provider@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== +"@langchain/community@^0.0.32": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@langchain/community/-/community-0.0.32.tgz#d0e4ce8eeb8152cc9c3ace402e97cefd1ef5ce74" + integrity sha512-jN4BxGKAmLbA87hqXH5Mx1IRMMVOgcn1TY1MLOVyBcBa12EvHFx8suogtXgA2ekfc8U8nIryVb1ftSupwUBv/A== dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" + "@langchain/core" "~0.1.32" + "@langchain/openai" "~0.0.14" + flat "^5.0.2" + langsmith "~0.1.1" + uuid "^9.0.0" + zod "^3.22.3" -"@ethersproject/abstract-signer@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== +"@langchain/community@~0.0.47": + version "0.0.57" + resolved "https://registry.yarnpkg.com/@langchain/community/-/community-0.0.57.tgz#9d77c5acb74a4a8ec01d2cefb71dcd4088701c44" + integrity sha512-tib4UJNkyA4TPNsTNChiBtZmThVJBr7X/iooSmKeCr+yUEha2Yxly3A4OAO95Vlpj4Q+od8HAfCbZih/1XqAMw== dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/bignumber@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bytes@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/hash@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/keccak256@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/networks@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/properties@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/signing-key@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/strings@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/web@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@fastify/busboy@^2.0.0": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" - integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== - -"@langchain/community@^0.3.31": - version "0.3.32" - resolved "https://registry.yarnpkg.com/@langchain/community/-/community-0.3.32.tgz#aa415ebfd51f10610f3abaa4127dae197f29cdc7" - integrity sha512-5AvGyjIFheXdBUSiIWNwc40rI8fXYiHV0UA3ncbBVu5fTwWur+mAQvl2ZsgyxBBKm4VuoCcuh6U6I7b1kiOYBQ== - dependencies: - "@langchain/openai" ">=0.2.0 <0.5.0" - binary-extensions "^2.2.0" + "@langchain/core" "~0.1.60" + "@langchain/openai" "~0.0.28" expr-eval "^2.0.2" flat "^5.0.2" - js-yaml "^4.1.0" - langchain ">=0.2.3 <0.3.0 || >=0.3.4 <0.4.0" - langsmith ">=0.2.8 <0.4.0" - uuid "^10.0.0" + langsmith "~0.1.1" + uuid "^9.0.0" zod "^3.22.3" zod-to-json-schema "^3.22.5" -"@langchain/core@^0.3.39": - version "0.3.40" - resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.3.40.tgz#e5f41f8b4288672d73aa98bcdaf6b32df0480db8" - integrity sha512-RGhJOTzJv6H+3veBAnDlH2KXuZ68CXMEg6B6DPTzL3IGDyd+vLxXG4FIttzUwjdeQKjrrFBwlXpJDl7bkoApzQ== +"@langchain/core@0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.3.0.tgz#52bcf9d0bc480d2b2a456ee4aa8aed1cce6f6aba" + integrity sha512-uYuozr9cHpm+Aat6RdheGWAiJ2GEmb/N33FCbHlN/+vKTwRmaju2F5pZi2CioK9kQwrQZVNydCbgaZm1c6ry6w== dependencies: - "@cfworker/json-schema" "^4.0.2" ansi-styles "^5.0.0" camelcase "6" decamelize "1.2.0" js-tiktoken "^1.0.12" - langsmith ">=0.2.8 <0.4.0" + langsmith "^0.1.43" mustache "^4.2.0" p-queue "^6.6.2" p-retry "4" @@ -262,6 +113,41 @@ zod "^3.22.4" zod-to-json-schema "^3.22.3" +"@langchain/core@>0.1.56 <0.3.0", "@langchain/core@>0.2.0 <0.3.0": + version "0.2.36" + resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.2.36.tgz#75754c33aa5b9310dcf117047374a1ae011005a4" + integrity sha512-qHLvScqERDeH7y2cLuJaSAlMwg3f/3Oc9nayRSXRU2UuaK/SOhI42cxiPLj1FnuHJSmN0rBQFkrLx02gI4mcVg== + dependencies: + ansi-styles "^5.0.0" + camelcase "6" + decamelize "1.2.0" + js-tiktoken "^1.0.12" + langsmith "^0.1.56-rc.1" + mustache "^4.2.0" + p-queue "^6.6.2" + p-retry "4" + uuid "^10.0.0" + zod "^3.22.4" + zod-to-json-schema "^3.22.3" + +"@langchain/core@~0.1.32", "@langchain/core@~0.1.60": + version "0.1.63" + resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.1.63.tgz#33cc48877739e9fdb5885fbd4b16fd08d1597050" + integrity sha512-+fjyYi8wy6x1P+Ee1RWfIIEyxd9Ee9jksEwvrggPwwI/p45kIDTdYTblXsM13y4mNWTiACyLSdbwnPaxxdoz+w== + dependencies: + ansi-styles "^5.0.0" + camelcase "6" + decamelize "1.2.0" + js-tiktoken "^1.0.12" + langsmith "~0.1.7" + ml-distance "^4.0.0" + mustache "^4.2.0" + p-queue "^6.6.2" + p-retry "4" + uuid "^9.0.0" + zod "^3.22.4" + zod-to-json-schema "^3.22.3" + "@langchain/ollama@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@langchain/ollama/-/ollama-0.2.0.tgz#43b3c90e9bd82256e26b70edf37304694aeaf5d1" @@ -272,34 +158,25 @@ zod "^3.24.1" zod-to-json-schema "^3.24.1" -"@langchain/openai@>=0.1.0 <0.5.0", "@langchain/openai@>=0.2.0 <0.5.0", "@langchain/openai@^0.4.4": - version "0.4.4" - resolved "https://registry.yarnpkg.com/@langchain/openai/-/openai-0.4.4.tgz#1832420495c53c28aa4e6515583bad8f0b83a637" - integrity sha512-UZybJeMd8+UX7Kn47kuFYfqKdBCeBUWNqDtmAr6ZUIMMnlsNIb6MkrEEhGgAEjGCpdT4CU8U/DyyddTz+JayOQ== +"@langchain/openai@~0.0.14", "@langchain/openai@~0.0.28": + version "0.0.34" + resolved "https://registry.yarnpkg.com/@langchain/openai/-/openai-0.0.34.tgz#36c9bca0721ab9f7e5d40927e7c0429cacbd5b56" + integrity sha512-M+CW4oXle5fdoz2T2SwdOef8pl3/1XmUx1vjn2mXUVM/128aO0l23FMF0SNBsAbRV6P+p/TuzjodchJbi0Ht/A== dependencies: + "@langchain/core" ">0.1.56 <0.3.0" js-tiktoken "^1.0.12" - openai "^4.77.0" + openai "^4.41.1" zod "^3.22.4" zod-to-json-schema "^3.22.3" -"@langchain/textsplitters@>=0.0.0 <0.2.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@langchain/textsplitters/-/textsplitters-0.1.0.tgz#f37620992192df09ecda3dfbd545b36a6bcbae46" - integrity sha512-djI4uw9rlkAb5iMhtLED+xJebDdAG935AdP4eRTB02R7OB/act55Bj9wsskhZsvuyQRpO4O1wQOp85s6T6GWmw== +"@langchain/textsplitters@~0.0.0": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@langchain/textsplitters/-/textsplitters-0.0.3.tgz#1a3cc93dd2ab330edb225400ded190a22fea14e3" + integrity sha512-cXWgKE3sdWLSqAa8ykbCcUsUF1Kyr5J3HOWYGuobhPEycXW4WI++d5DhzdpL238mzoEXTi90VqfSCra37l5YqA== dependencies: + "@langchain/core" ">0.2.0 <0.3.0" js-tiktoken "^1.0.12" -"@metamask/eth-sig-util@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" - integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== - dependencies: - ethereumjs-abi "^0.6.8" - ethereumjs-util "^6.2.1" - ethjs-util "^0.1.6" - tweetnacl "^1.0.3" - tweetnacl-util "^0.15.1" - "@noble/curves@1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" @@ -307,11 +184,6 @@ dependencies: "@noble/hashes" "1.3.2" -"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" - integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== - "@noble/hashes@1.3.2": version "1.3.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" @@ -322,182 +194,6 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.1.tgz#5738f6d765710921e7a751e00c20ae091ed8db0f" integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ== -"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" - integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== - -"@nomicfoundation/edr-darwin-arm64@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.7.0.tgz#2be3338a61508ed1d24326c82b9aa9224a844dd7" - integrity sha512-vAH20oh4GaSB/iQFTRcoO8jLc0CLd9XuLY9I7vtcqZWAiM4U1J4Y8cu67PWmtxbvUQOqXR7S6FtAr8/AlWm14g== - -"@nomicfoundation/edr-darwin-x64@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.7.0.tgz#d2f782fc43bcae1c9aca3130aca6aa2a964e8559" - integrity sha512-WHDdIrPvLlgXQr2eKypBM5xOZAwdxhDAEQIvEMQL8tEEm2qYW2bliUlssBPrs8E3bdivFbe1HizImslMAfU3+g== - -"@nomicfoundation/edr-linux-arm64-gnu@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.7.0.tgz#48b156744989acc8e6b0b754158a26e10ad865ed" - integrity sha512-WXpJB54ukz1no7gxCPXVEw9pgl/9UZ/WO3l1ctyv/T7vOygjqA4SUd6kppTs6MNXAuTiisPtvJ/fmvHiMBLrsw== - -"@nomicfoundation/edr-linux-arm64-musl@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.7.0.tgz#60351352ec26704fed8a232430bf3793d17c29cd" - integrity sha512-1iZYOcEgc+zJI7JQrlAFziuy9sBz1WgnIx3HIIu0J7lBRZ/AXeHHgATb+4InqxtEx9O3W8A0s7f11SyFqJL4Aw== - -"@nomicfoundation/edr-linux-x64-gnu@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.7.0.tgz#a7b056bfd46ccfde4d55c9601da5a410c2fce40f" - integrity sha512-wSjC94WcR5MM8sg9w3OsAmT6+bbmChJw6uJKoXR3qscps/jdhjzJWzfgT0XGRq3XMUfimyafW2RWOyfX3ouhrQ== - -"@nomicfoundation/edr-linux-x64-musl@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.7.0.tgz#0fe9f5ace05072e845f71c8fbd28e57798dd6ab5" - integrity sha512-Us22+AZ7wkG1mZwxqE4S4ZcuwkEA5VrUiBOJSvKHGOgy6vFvB/Euh5Lkp4GovwjrtiXuvyGO2UmtkzymZKDxZw== - -"@nomicfoundation/edr-win32-x64-msvc@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.7.0.tgz#f1b9a0a643db8dffcf5edb827c18e1cef25c4367" - integrity sha512-HAry0heTsWkzReVtjHwoIq3BgFCvXpVhJ5qPmTnegZGsr/KxqvMmHyDMifzKao4bycU8yrpTSyOiAJt27RWjzQ== - -"@nomicfoundation/edr@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.7.0.tgz#175cb8a81eac585dc76ad41585c908542acb9383" - integrity sha512-+Zyu7TE47TGNcPhOfWLPA/zISs32WDMXrhSWdWYyPHDVn/Uux5TVuOeScKb0BR/R8EJ+leR8COUF/EGxvDOVKg== - dependencies: - "@nomicfoundation/edr-darwin-arm64" "0.7.0" - "@nomicfoundation/edr-darwin-x64" "0.7.0" - "@nomicfoundation/edr-linux-arm64-gnu" "0.7.0" - "@nomicfoundation/edr-linux-arm64-musl" "0.7.0" - "@nomicfoundation/edr-linux-x64-gnu" "0.7.0" - "@nomicfoundation/edr-linux-x64-musl" "0.7.0" - "@nomicfoundation/edr-win32-x64-msvc" "0.7.0" - -"@nomicfoundation/ethereumjs-common@4.0.4": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz#9901f513af2d4802da87c66d6f255b510bef5acb" - integrity sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg== - dependencies: - "@nomicfoundation/ethereumjs-util" "9.0.4" - -"@nomicfoundation/ethereumjs-rlp@5.0.4": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz#66c95256fc3c909f6fb18f6a586475fc9762fa30" - integrity sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw== - -"@nomicfoundation/ethereumjs-tx@5.0.4": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz#b0ceb58c98cc34367d40a30d255d6315b2f456da" - integrity sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.4" - "@nomicfoundation/ethereumjs-rlp" "5.0.4" - "@nomicfoundation/ethereumjs-util" "9.0.4" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-util@9.0.4": - version "9.0.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz#84c5274e82018b154244c877b76bc049a4ed7b38" - integrity sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "5.0.4" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/hardhat-chai-matchers@^2.0.0": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.8.tgz#9c7cfc4ad0f0a5e9cf16aba8ab668c02f6e273aa" - integrity sha512-Z5PiCXH4xhNLASROlSUOADfhfpfhYO6D7Hn9xp8PddmHey0jq704cr6kfU8TRrQ4PUZbpfsZadPj+pCfZdjPIg== - dependencies: - "@types/chai-as-promised" "^7.1.3" - chai-as-promised "^7.1.1" - deep-eql "^4.0.1" - ordinal "^1.0.3" - -"@nomicfoundation/hardhat-ethers@^3.0.5": - version "3.0.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.8.tgz#af078f566373abeb77e11cbe69fe3dd47f8bfc27" - integrity sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA== - dependencies: - debug "^4.1.1" - lodash.isequal "^4.5.0" - -"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz#3a9c3b20d51360b20affb8f753e756d553d49557" - integrity sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw== - -"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz#74dcfabeb4ca373d95bd0d13692f44fcef133c28" - integrity sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw== - -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz#4af5849a89e5a8f511acc04f28eb5d4460ba2b6a" - integrity sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA== - -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz#54036808a9a327b2ff84446c130a6687ee702a8e" - integrity sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA== - -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz#466cda0d6e43691986c944b909fc6dbb8cfc594e" - integrity sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g== - -"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz#2b35826987a6e94444140ac92310baa088ee7f94" - integrity sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg== - -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz#e6363d13b8709ca66f330562337dbc01ce8bbbd9" - integrity sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA== - -"@nomicfoundation/solidity-analyzer@^0.1.0": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz#8bcea7d300157bf3a770a851d9f5c5e2db34ac55" - integrity sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA== - optionalDependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.2" - "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" - "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" - -"@openzeppelin/contracts@^4.9.6": - version "4.9.6" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677" - integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA== - -"@scure/base@~1.1.0": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" - integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== - -"@scure/bip32@1.1.5": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" - integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== - dependencies: - "@noble/hashes" "~1.2.0" - "@noble/secp256k1" "~1.7.0" - "@scure/base" "~1.1.0" - -"@scure/bip39@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" - integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== - dependencies: - "@noble/hashes" "~1.2.0" - "@scure/base" "~1.1.0" - "@selderee/plugin-htmlparser2@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz#d5b5e29a7ba6d3958a1972c7be16f4b2c188c517" @@ -506,81 +202,15 @@ domhandler "^5.0.3" selderee "^0.11.0" -"@sentry/core@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" - integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/hub@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" - integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== - dependencies: - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/minimal@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" - integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@sentry/node@^5.18.1": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" - integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== - dependencies: - "@sentry/core" "5.30.0" - "@sentry/hub" "5.30.0" - "@sentry/tracing" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - cookie "^0.4.1" - https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" - -"@sentry/tracing@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" - integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/types@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" - integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== - -"@sentry/utils@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" - integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== - dependencies: - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@spruceid/siwe-parser@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@spruceid/siwe-parser/-/siwe-parser-3.0.0.tgz#8af48683d77aed6dbd1abf541e1b064dc64be10e" - integrity sha512-Y92k63ilw/8jH9Ry4G2e7lQd0jZAvb0d/Q7ssSD0D9mp/Zt2aCXIc3g0ny9yhplpAx1QXHsMz/JJptHK/zDGdw== +"@spruceid/siwe-parser@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@spruceid/siwe-parser/-/siwe-parser-2.1.2.tgz#3e13e7d3ac0bfdaf109a07342590eb21daee2fc3" + integrity sha512-d/r3S1LwJyMaRAKQ0awmo9whfXeE88Qt00vRj91q5uv5ATtWIQEGJ67Yr5eSZw5zp1/fZCXZYuEckt8lSkereQ== dependencies: "@noble/hashes" "^1.1.2" - apg-js "^4.4.0" + apg-js "^4.3.0" + uri-js "^4.4.1" + valid-url "^1.0.9" "@stablelib/binary@^1.0.1": version "1.0.1" @@ -607,44 +237,6 @@ resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== -"@types/bn.js@^4.11.3": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" - -"@types/bn.js@^5.1.0": - version "5.1.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.6.tgz#9ba818eec0c85e4d3c679518428afdf611d03203" - integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== - dependencies: - "@types/node" "*" - -"@types/chai-as-promised@^7.1.3": - version "7.1.8" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" - integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== - dependencies: - "@types/chai" "*" - -"@types/chai@*": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.0.1.tgz#2c3705555cf11f5f59c836a84c44afcfe4e5689d" - integrity sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA== - dependencies: - "@types/deep-eql" "*" - -"@types/deep-eql@*": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" - integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== - -"@types/lru-cache@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" - integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== - "@types/node-fetch@^2.6.4": version "2.6.12" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.12.tgz#8ab5c3ef8330f13100a7479e2cd56d3386830a03" @@ -654,9 +246,9 @@ form-data "^4.0.0" "@types/node@*": - version "22.13.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.5.tgz#23add1d71acddab2c6a4d31db89c0f98d330b511" - integrity sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg== + version "22.13.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.8.tgz#57e2450295b33a6518d6fd4f65f47236d3e41d8d" + integrity sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ== dependencies: undici-types "~6.20.0" @@ -668,30 +260,21 @@ undici-types "~6.19.2" "@types/node@^18.11.18": - version "18.19.76" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.76.tgz#7991658e0ba41ad30cc8be01c9bbe580d58f2112" - integrity sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw== + version "18.19.78" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.78.tgz#29f5e7b947840c7aa9050ecac920fe6b1c7646a0" + integrity sha512-m1ilZCTwKLkk9rruBJXFeYN0Bc5SbjirwYX/Td3MqPfioYbgun3IvK/m8dQxMCnrPGZPg1kvXjp3SIekCN/ynw== dependencies: undici-types "~5.26.4" -"@types/pbkdf2@^3.0.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" - integrity sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew== - dependencies: - "@types/node" "*" - "@types/retry@0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== -"@types/secp256k1@^4.0.1": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.6.tgz#d60ba2349a51c2cbc5e816dcd831a42029d376bf" - integrity sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ== - dependencies: - "@types/node" "*" +"@types/triple-beam@^1.3.2": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" + integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== "@types/uuid@^10.0.0": version "10.0.0" @@ -713,23 +296,11 @@ accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -adm-zip@^0.4.16: - version "0.4.16" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" - integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== - aes-js@4.0.0-beta.5: version "4.0.0-beta.5" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - agentkeepalive@^4.2.1: version "4.6.0" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a" @@ -737,45 +308,6 @@ agentkeepalive@^4.2.1: dependencies: humanize-ms "^1.2.1" -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ansi-align@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - -ansi-colors@^4.1.1, ansi-colors@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -ansi-escapes@^4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - ansi-styles@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" @@ -789,7 +321,7 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -apg-js@^4.4.0: +apg-js@^4.3.0: version "4.4.0" resolved "https://registry.yarnpkg.com/apg-js/-/apg-js-4.4.0.tgz#09dcecab0731fbde233b9f2352fdd2d07e56b2cf" integrity sha512-fefmXFknJmtgtNEXfPwZKYkMFX4Fyeyz+fNF6JWp87biGOPslJbCBVU158zvKRZfHBKnJDy8CMM40oLFGkXT8Q== @@ -859,16 +391,16 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - async-function@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== +async@^3.2.3: + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -891,10 +423,10 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axios@^1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" - integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== +axios@^1.6.7: + version "1.8.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.1.tgz#7c118d2146e9ebac512b7d1128771cdd738d11e3" + integrity sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -910,12 +442,10 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.2: - version "3.0.10" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" - integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== - dependencies: - safe-buffer "^5.0.1" +base-64@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" + integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== base64-js@^1.5.1: version "1.5.1" @@ -934,6 +464,18 @@ binary-extensions@^2.0.0, binary-extensions@^2.2.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== +binary-search@^1.3.5: + version "1.3.6" + resolved "https://registry.yarnpkg.com/binary-search/-/binary-search-1.3.6.tgz#e32426016a0c5092f0f3598836a1c7da3560565c" + integrity sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + bl@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" @@ -942,26 +484,16 @@ bl@^1.2.3: readable-stream "^2.3.5" safe-buffer "^5.1.1" -blakejs@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" - integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== - bluebird@^3.5.0: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bn.js@^4.0.0, bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: +bn.js@^4.0.0: version "4.12.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.1.tgz#215741fe3c9dba2d7e12c001d0cfdbae43975ba7" integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== -bn.js@^5.2.0, bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - body-parser@1.20.3: version "1.20.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" @@ -980,20 +512,6 @@ body-parser@1.20.3: type-is "~1.6.18" unpipe "1.0.0" -boxen@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1002,13 +520,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - braces@~3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" @@ -1016,54 +527,6 @@ braces@~3.0.2: dependencies: fill-range "^7.1.1" -brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browser-stdout@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -browserify-aes@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -bs58@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== - dependencies: - base-x "^3.0.2" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.1.2" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== - bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -1095,7 +558,7 @@ call-bound@^1.0.2, call-bound@^1.0.3: call-bind-apply-helpers "^1.0.1" get-intrinsic "^1.2.6" -camelcase@6, camelcase@^6.0.0, camelcase@^6.2.0: +camelcase@6: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -1105,42 +568,12 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -chai-as-promised@^7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" - integrity sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw== - dependencies: - check-error "^1.0.2" +charenc@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== -chai@4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - -chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -check-error@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" - integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== - dependencies: - get-func-name "^2.0.2" - -chokidar@^3.5.2, chokidar@^3.5.3: +chokidar@^3.5.2: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -1155,57 +588,47 @@ chokidar@^3.5.2, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -chokidar@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" - integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== +color-convert@^1.9.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: - readdirp "^4.0.1" + color-name "1.1.3" -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.6.tgz#8fe672437d01cd6c4561af5334e0cc50ff1955f7" - integrity sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw== - dependencies: - inherits "^2.0.4" - safe-buffer "^5.2.1" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-boxes@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" - integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: +color-name@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.6.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.1.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== + dependencies: + color-convert "^1.9.3" + color-string "^1.6.0" + +colorspace@1.1.x: + version "1.1.4" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" + integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== + dependencies: + color "^3.1.3" + text-hex "1.0.x" + combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1213,27 +636,22 @@ combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -command-exists@^1.2.8: - version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" - integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== - -commander@^8.1.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -console-table-printer@^2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/console-table-printer/-/console-table-printer-2.12.1.tgz#4a9646537a246a6d8de57075d4fae1e08abae267" - integrity sha512-wKGOQRRvdnd89pCeH96e2Fn4wkbenSP6LMHfjfyNLMbGuHEFbMqQNuxXqd0oXG9caIOQ1FTvc5Uijp9/4jujnQ== +connect-pg-simple@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/connect-pg-simple/-/connect-pg-simple-10.0.0.tgz#972b08d9fc6a1861c523a6c9166240a24b4bc3ca" + integrity sha512-pBGVazlqiMrackzCr0eKhn4LO5trJXsOX0nQoey9wCOayh80MYtThCbq8eoLsjpiWgiok/h+1/uti9/2/Una8A== dependencies: - simple-wcswidth "^1.0.1" + pg "^8.12.0" content-disposition@0.5.4: version "0.5.4" @@ -1257,7 +675,17 @@ cookie-signature@1.0.7: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.7.tgz#ab5dd7ab757c54e60f37ef6550f481c426d10454" integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA== -cookie@0.7.1, cookie@0.7.2, cookie@^0.4.1, cookie@^0.7.0: +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== + +cookie@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -1280,28 +708,29 @@ cors@^2.8.5: object-assign "^4" vary "^1" -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - 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" +crypt@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== -create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== +csrf@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/csrf/-/csrf-3.1.0.tgz#ec75e9656d004d674b8ef5ba47b41fbfd6cb9c30" + integrity sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w== 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" + rndm "1.2.0" + tsscmp "1.0.6" + uid-safe "2.1.5" + +csurf@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.11.0.tgz#ab0c3c6634634192bd3d6f4b861be20800eeb61a" + integrity sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ== + dependencies: + cookie "0.4.0" + cookie-signature "1.0.6" + csrf "3.1.0" + http-errors "~1.7.3" dashdash@^1.12.0: version "1.14.1" @@ -1344,13 +773,6 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4, debug@^4.1.1, debug@^4.3.5: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1363,18 +785,6 @@ decamelize@1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -deep-eql@^4.0.1, deep-eql@^4.1.2: - version "4.1.4" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" - integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg== - dependencies: - type-detect "^4.0.0" - deepmerge@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -1408,15 +818,23 @@ depd@2.0.0, depd@~2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -diff@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" - integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== +digest-fetch@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/digest-fetch/-/digest-fetch-1.3.0.tgz#898e69264d00012a23cf26e8a3e40320143fc661" + integrity sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA== + dependencies: + base-64 "^0.1.0" + md5 "^2.3.0" dom-serializer@^2.0.0: version "2.0.0" @@ -1448,7 +866,7 @@ domutils@^3.0.1: domelementtype "^2.3.0" domhandler "^5.0.3" -dotenv@^16.4.7: +dotenv@^16.0.3: version "16.4.7" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== @@ -1475,23 +893,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.7, elliptic@^6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" - 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" - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +enabled@2.0.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" + integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== encodeurl@~1.0.2: version "1.0.2" @@ -1515,24 +920,11 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enquirer@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" - integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== - dependencies: - ansi-colors "^4.1.1" - strip-ansi "^6.0.1" - entities@^4.2.0, entities@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9: version "1.23.9" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606" @@ -1633,79 +1025,17 @@ es-to-primitive@^1.3.0: is-date-object "^1.0.5" is-symbol "^1.0.4" -escalade@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" - integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== - dependencies: - "@types/pbkdf2" "^3.0.0" - "@types/secp256k1" "^4.0.1" - blakejs "^1.1.0" - browserify-aes "^1.2.0" - bs58check "^2.1.2" - create-hash "^1.2.0" - create-hmac "^1.1.7" - hash.js "^1.1.7" - keccak "^3.0.0" - pbkdf2 "^3.0.17" - randombytes "^2.1.0" - safe-buffer "^5.1.2" - scrypt-js "^3.0.0" - secp256k1 "^4.0.1" - setimmediate "^1.0.5" - -ethereum-cryptography@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" - integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== - dependencies: - "@noble/hashes" "1.2.0" - "@noble/secp256k1" "1.7.1" - "@scure/bip32" "1.1.5" - "@scure/bip39" "1.1.1" - -ethereumjs-abi@^0.6.8: - version "0.6.8" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" - integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" - -ethers@^6.11.1: +ethers@^6.7.1: version "6.13.5" resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.5.tgz#8c1d6ac988ac08abc3c1d8fabbd4b8b602851ac4" integrity sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ== @@ -1718,14 +1048,6 @@ ethers@^6.11.1: tslib "2.7.0" ws "8.17.1" -ethjs-util@0.1.6, ethjs-util@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - event-target-shim@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" @@ -1741,20 +1063,17 @@ eventemitter3@^4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - expr-eval@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expr-eval/-/expr-eval-2.0.2.tgz#fa6f044a7b0c93fde830954eb9c5b0f7fbc7e201" integrity sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg== -express-session@^1.18.0: +express-rate-limit@^7.5.0: + version "7.5.0" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.0.tgz#6a67990a724b4fbbc69119419feef50c51e8b28f" + integrity sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg== + +express-session@^1.17.3: version "1.18.1" resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.1.tgz#88d0bbd41878882840f24ec6227493fcb167e8d5" integrity sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA== @@ -1768,7 +1087,7 @@ express-session@^1.18.0: safe-buffer "5.2.1" uid-safe "~2.1.5" -express@^4.18.3: +express@^4.18.2: version "4.21.2" resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA== @@ -1820,16 +1139,21 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fdir@^6.4.3: - version "6.4.3" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.3.tgz#011cdacf837eca9b811c89dbb902df714273db72" - integrity sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw== +fecha@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== file-type@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" integrity sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA== +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -1850,20 +1174,17 @@ finalhandler@1.3.1: statuses "2.0.1" unpipe "~1.0.0" -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -follow-redirects@^1.12.1, follow-redirects@^1.15.6: +fn.name@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" + integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== + +follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -1908,30 +1229,11 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fp-ts@1.19.3: - version "1.19.3" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" - integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== - -fp-ts@^1.0.0: - version "1.19.5" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" - integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== - fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^8.0.1: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -1941,11 +1243,6 @@ fs-extra@^8.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" @@ -1973,16 +1270,6 @@ functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.0, get-func-name@^2.0.1, get-func-name@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" - integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== - get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7: version "1.3.0" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" @@ -2030,17 +1317,6 @@ glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" @@ -2054,61 +1330,11 @@ gopd@^1.0.1, gopd@^1.2.0: resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: +graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -hardhat@^2.21.0: - version "2.22.18" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.18.tgz#e299a26a67b521bbb225370eb47a032d4e097e3a" - integrity sha512-2+kUz39gvMo56s75cfLBhiFedkQf+gXdrwCcz4R/5wW0oBdwiyfj2q9BIkMoaA0WIGYYMU2I1Cc4ucTunhfjzw== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/edr" "^0.7.0" - "@nomicfoundation/ethereumjs-common" "4.0.4" - "@nomicfoundation/ethereumjs-tx" "5.0.4" - "@nomicfoundation/ethereumjs-util" "9.0.4" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - boxen "^5.1.2" - chokidar "^4.0.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^5.0.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - json-stream-stringify "^3.1.4" - keccak "^3.0.2" - lodash "^4.17.11" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - picocolors "^1.1.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.8.26" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tinyglobby "^0.2.6" - tsort "0.0.1" - undici "^5.14.0" - uuid "^8.3.2" - ws "^7.4.6" - has-bigints@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" @@ -2119,11 +1345,6 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" @@ -2150,23 +1371,6 @@ has-tostringtag@^1.0.2: dependencies: has-symbols "^1.0.3" -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" @@ -2174,19 +1378,23 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" -he@1.2.0, he@^1.2.0: +he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== +helmet@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/helmet/-/helmet-8.0.0.tgz#05370fb1953aa7b81bd0ddfa459221247be6ea5c" + integrity sha512-VyusHLEIIO5mjQPUI1wpOAEu+wl6Q0998jzTxqUYGE45xCIcAxy3MsbEK/yyJUJ3ADeMoB6MornPH6GMWAf+Pw== + +hnswlib-node@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hnswlib-node/-/hnswlib-node-3.0.0.tgz#0ec5cedf082691a5e2bec7a8faa24f742077cc50" + integrity sha512-fypn21qvVORassppC8/qNfZ5KAOspZpm/IbUkAtlqvbtDNnF5VVk5RWF7O5V6qwr7z+T3s1ePej6wQt5wRQ4Cg== dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" + bindings "^1.5.0" + node-addon-api "^8.0.0" html-to-text@9.0.5: version "9.0.5" @@ -2220,6 +1428,17 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-errors@~1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + http-signature@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.4.0.tgz#dee5a9ba2bf49416abc544abd6d967f6a94c8c3f" @@ -2229,14 +1448,6 @@ http-signature@~1.4.0: jsprim "^2.0.2" sshpk "^1.18.0" -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -2271,30 +1482,12 @@ imap@^0.8.19: readable-stream "1.1.x" utf7 ">=1.0.2" -immutable@^4.0.0-rc.12: - version "4.3.7" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" - integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2308,18 +1501,16 @@ internal-slot@^1.1.0: hasown "^2.0.2" side-channel "^1.1.0" -io-ts@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" - integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== - dependencies: - fp-ts "^1.0.0" - ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-any-array@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-any-array/-/is-any-array-2.0.1.tgz#9233242a9c098220290aa2ec28f82ca7fa79899e" + integrity sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ== + is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" @@ -2329,6 +1520,11 @@ is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: call-bound "^1.0.3" get-intrinsic "^1.2.6" +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-async-function@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" @@ -2362,6 +1558,11 @@ is-boolean-object@^1.2.1: call-bound "^1.0.3" has-tostringtag "^1.0.2" +is-buffer@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" @@ -2396,11 +1597,6 @@ is-finalizationregistry@^1.1.0: dependencies: call-bound "^1.0.3" -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - is-generator-function@^1.0.10: version "1.1.0" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" @@ -2418,11 +1614,6 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-hex-prefixed@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== - is-map@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" @@ -2441,11 +1632,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - is-regex@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" @@ -2468,6 +1654,11 @@ is-shared-array-buffer@^1.0.4: dependencies: call-bound "^1.0.3" +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-string@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" @@ -2497,11 +1688,6 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - is-weakmap@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" @@ -2542,12 +1728,7 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -js-tiktoken@^1.0.12: +js-tiktoken@^1.0.12, js-tiktoken@^1.0.7: version "1.0.19" resolved "https://registry.yarnpkg.com/js-tiktoken/-/js-tiktoken-1.0.19.tgz#0298b584382f1d47d4b45cb93d382f11780eab78" integrity sha512-XC63YQeEcS47Y53gg950xiZ4IWmkfMe4p2V9OSaBt26q+p47WHn18izuXzSclCI73B7yGqtfRsT6jcZQI0y08g== @@ -2571,11 +1752,6 @@ json-schema@0.4.0: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== -json-stream-stringify@^3.1.4: - version "3.1.6" - resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz#ebe32193876fb99d4ec9f612389a8d8e2b5d54d4" - integrity sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog== - json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -2603,15 +1779,6 @@ jsprim@^2.0.2: json-schema "0.4.0" verror "1.10.0" -keccak@^3.0.0, keccak@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" - integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - kruptein@^2.0.4: version "2.2.3" resolved "https://registry.yarnpkg.com/kruptein/-/kruptein-2.2.3.tgz#e09a3942b8072ac71728d10fe089293e0b5e7d42" @@ -2619,32 +1786,47 @@ kruptein@^2.0.4: dependencies: asn1.js "^5.4.1" -"langchain@>=0.2.3 <0.3.0 || >=0.3.4 <0.4.0", langchain@^0.3.19: - version "0.3.19" - resolved "https://registry.yarnpkg.com/langchain/-/langchain-0.3.19.tgz#a0329036c4c870018897b91af2ac442c1f07294b" - integrity sha512-aGhoTvTBS5ulatA67RHbJ4bcV5zcYRYdm5IH+hpX99RYSFXG24XF3ghSjhYi6sxW+SUnEQ99fJhA5kroVpKNhw== +kuler@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" + integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== + +langchain@^0.1.21: + version "0.1.37" + resolved "https://registry.yarnpkg.com/langchain/-/langchain-0.1.37.tgz#15db8ca5c24afc39e61773cab69e216dfb38e1bb" + integrity sha512-rpaLEJtRrLYhAViEp7/aHfSkxbgSqHJ5n10tXv3o4kHP/wOin85RpTgewwvGjEaKc3797jOg+sLSk6a7e0UlMg== dependencies: - "@langchain/openai" ">=0.1.0 <0.5.0" - "@langchain/textsplitters" ">=0.0.0 <0.2.0" - js-tiktoken "^1.0.12" + "@anthropic-ai/sdk" "^0.9.1" + "@langchain/community" "~0.0.47" + "@langchain/core" "~0.1.60" + "@langchain/openai" "~0.0.28" + "@langchain/textsplitters" "~0.0.0" + binary-extensions "^2.2.0" + js-tiktoken "^1.0.7" js-yaml "^4.1.0" jsonpointer "^5.0.1" - langsmith ">=0.2.8 <0.4.0" + langchainhub "~0.0.8" + langsmith "~0.1.7" + ml-distance "^4.0.0" openapi-types "^12.1.3" p-retry "4" - uuid "^10.0.0" + uuid "^9.0.0" yaml "^2.2.1" zod "^3.22.4" zod-to-json-schema "^3.22.3" -"langsmith@>=0.2.8 <0.4.0": - version "0.3.10" - resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.3.10.tgz#c9bda0442fb815603312ed23a66690b174f56995" - integrity sha512-V6SnJhxKt9AbdVfl86OrEBl8uGwO0/WE2qqDcRXxHxzdCDnj+sV7nstr5VL0a6zxZmyMaw6eBbYwB4PTYKRvvQ== +langchainhub@~0.0.8: + version "0.0.11" + resolved "https://registry.yarnpkg.com/langchainhub/-/langchainhub-0.0.11.tgz#2ce22def9c84699dcbd4fd4b78270d34bd2a9ae9" + integrity sha512-WnKI4g9kU2bHQP136orXr2bcRdgz9iiTBpTN0jWt9IlScUKnJBoD0aa2HOzHURQKeQDnt2JwqVmQ6Depf5uDLQ== + +langsmith@^0.1.43, langsmith@^0.1.56-rc.1, langsmith@~0.1.1, langsmith@~0.1.7: + version "0.1.68" + resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.1.68.tgz#848332e822fe5e6734a07f1c36b6530cc1798afb" + integrity sha512-otmiysWtVAqzMx3CJ4PrtUBhWRG5Co8Z4o7hSZENPjlit9/j3/vm3TSvbaxpDYakZxtMjhkcJTqrdYFipISEiQ== dependencies: "@types/uuid" "^10.0.0" - chalk "^4.1.2" - console-table-printer "^2.12.1" + commander "^10.0.1" p-queue "^6.6.2" p-retry "4" semver "^7.6.3" @@ -2682,42 +1864,22 @@ linkify-it@5.0.0: dependencies: uc.micro "^2.0.0" -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== - -lodash@^4.17.11, lodash@^4.17.15: +lodash@^4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== +logform@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" + integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -loupe@^2.3.1: - version "2.3.7" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" - integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== - dependencies: - get-func-name "^2.0.1" - -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + "@colors/colors" "1.6.0" + "@types/triple-beam" "^1.3.2" + fecha "^4.2.0" + ms "^2.1.1" + safe-stable-stringify "^2.3.1" + triple-beam "^1.3.0" mailparser@^3.7.2: version "3.7.2" @@ -2749,25 +1911,20 @@ math-intrinsics@^1.1.0: resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== - merge-descriptors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" @@ -2795,16 +1952,11 @@ mime@1.6.0, mime@^1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: +minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -2812,52 +1964,48 @@ minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1, minimatch@^5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== +ml-array-mean@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/ml-array-mean/-/ml-array-mean-1.1.6.tgz#d951a700dc8e3a17b3e0a583c2c64abd0c619c56" + integrity sha512-MIdf7Zc8HznwIisyiJGRH9tRigg3Yf4FldW8DxKxpCCv/g5CafTw0RRu51nojVEOXuCQC7DRVVu5c7XXO/5joQ== dependencies: - brace-expansion "^2.0.1" + ml-array-sum "^1.1.6" -mnemonist@^0.38.0: - version "0.38.5" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" - integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== +ml-array-sum@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/ml-array-sum/-/ml-array-sum-1.1.6.tgz#d1d89c20793cd29c37b09d40e85681aa4515a955" + integrity sha512-29mAh2GwH7ZmiRnup4UyibQZB9+ZLyMShvt4cH4eTK+cL2oEMIZFnSyB3SS8MlsTh6q/w/yh48KmqLxmovN4Dw== dependencies: - obliterator "^2.0.0" + is-any-array "^2.0.0" -mocha@^10.0.0: - version "10.8.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" - integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg== +ml-distance-euclidean@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ml-distance-euclidean/-/ml-distance-euclidean-2.0.0.tgz#3a668d236649d1b8fec96380b9435c6f42c9a817" + integrity sha512-yC9/2o8QF0A3m/0IXqCTXCzz2pNEzvmcE/9HFKOZGnTjatvBbsn4lWYJkxENkA4Ug2fnYl7PXQxnPi21sgMy/Q== + +ml-distance@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/ml-distance/-/ml-distance-4.0.1.tgz#4741d17a1735888c5388823762271dfe604bd019" + integrity sha512-feZ5ziXs01zhyFUUUeZV5hwc0f5JW0Sh0ckU1koZe/wdVkJdGxcP06KNQuF0WBTj8FttQUzcvQcpcrOp/XrlEw== dependencies: - ansi-colors "^4.1.3" - browser-stdout "^1.3.1" - chokidar "^3.5.3" - debug "^4.3.5" - diff "^5.2.0" - escape-string-regexp "^4.0.0" - find-up "^5.0.0" - glob "^8.1.0" - he "^1.2.0" - js-yaml "^4.1.0" - log-symbols "^4.1.0" - minimatch "^5.1.6" - ms "^2.1.3" - serialize-javascript "^6.0.2" - strip-json-comments "^3.1.1" - supports-color "^8.1.1" - workerpool "^6.5.1" - yargs "^16.2.0" - yargs-parser "^20.2.9" - yargs-unparser "^2.0.0" + ml-array-mean "^1.1.6" + ml-distance-euclidean "^2.0.0" + ml-tree-similarity "^1.0.0" + +ml-tree-similarity@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ml-tree-similarity/-/ml-tree-similarity-1.0.0.tgz#24705a107e32829e24d945e87219e892159c53f0" + integrity sha512-XJUyYqjSuUQkNQHMscr6tcjldsOoAekxADTplt40QKfwW6nd++1wHWV9AArl0Zvw/TIHgNaZZNvr8QGvE8wLRg== + dependencies: + binary-search "^1.3.5" + num-sort "^2.0.0" ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -2872,15 +2020,10 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -node-addon-api@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" - integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== - -node-addon-api@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" - integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== +node-addon-api@^8.0.0: + version "8.3.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.3.1.tgz#53bc8a4f8dbde3de787b9828059da94ba9fd4eed" + integrity sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA== node-domexception@1.0.0: version "1.0.0" @@ -2894,15 +2037,10 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-gyp-build@^4.2.0: - version "4.8.4" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" - integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== - -node-telegram-bot-api@^0.66.0: - version "0.66.0" - resolved "https://registry.yarnpkg.com/node-telegram-bot-api/-/node-telegram-bot-api-0.66.0.tgz#9ad27e357b30fd3a89a37365ed95a82a70ac9f94" - integrity sha512-s4Hrg5q+VPl4/tJVG++pImxF6eb8tNJNj4KnDqAOKL6zGU34lo9RXmyAN158njwGN+v8hdNf8s9fWIYW9hPb5A== +node-telegram-bot-api@^0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/node-telegram-bot-api/-/node-telegram-bot-api-0.64.0.tgz#2f21f4095aaa1bb61705af8e1206008c19a045fe" + integrity sha512-/gxCuaEDUyWMBiHInP0ufopUkaaKprXiv3lyP9MMZdPy2KPfYKNYNKfd1Ph7o9KhfURDtOYowPZCi4UCr+2caw== dependencies: "@cypress/request" "^3.0.1" "@cypress/request-promise" "^5.0.0" @@ -2919,23 +2057,23 @@ nodemailer@6.9.16: resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.16.tgz#3ebdf6c6f477c571c0facb0727b33892635e0b8b" integrity sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ== -nodemailer@^6.10.0: +nodemailer@^6.9.9: version "6.10.0" resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.10.0.tgz#1f24c9de94ad79c6206f66d132776b6503003912" integrity sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA== -nodemon@^3.1.0: - version "3.1.9" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.9.tgz#df502cdc3b120e1c3c0c6e4152349019efa7387b" - integrity sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg== +nodemon@^2.0.22: + version "2.0.22" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.22.tgz#182c45c3a78da486f673d6c1702e00728daf5258" + integrity sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ== dependencies: chokidar "^3.5.2" - debug "^4" + debug "^3.2.7" ignore-by-default "^1.0.1" minimatch "^3.1.2" pstree.remy "^1.1.8" - semver "^7.5.3" - simple-update-notifier "^2.0.0" + semver "^5.7.1" + simple-update-notifier "^1.0.7" supports-color "^5.5.0" touch "^3.1.0" undefsafe "^2.0.5" @@ -2945,6 +2083,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +num-sort@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/num-sort/-/num-sort-2.1.0.tgz#1cbb37aed071329fdf41151258bc011898577a9b" + integrity sha512-1MQz1Ed8z2yckoBeSfkQHHO9K1yDRxxtotKSJ9yvcTUUxSvfvzEq5GwBrjjHEpMlq/k5gvXdmJ1SbYxWtpNoVg== + object-assign@^4, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -2972,15 +2115,10 @@ object.assign@^4.1.7: has-symbols "^1.1.0" object-keys "^1.1.1" -obliterator@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.5.tgz#031e0145354b0c18840336ae51d41e7d6d2c76aa" - integrity sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw== - ollama@^0.5.12: - version "0.5.13" - resolved "https://registry.yarnpkg.com/ollama/-/ollama-0.5.13.tgz#19599ab8977be1bc15d5554671651904cb8db14a" - integrity sha512-qK3eE2GjMYjCiTknEJfAHjbUzUqgVtf9qtzjxWrkwBZgBG7kOB6Z4+Ov4fbvDjmKKHv+rpuTsWFg4jZvVjNBtQ== + version "0.5.14" + resolved "https://registry.yarnpkg.com/ollama/-/ollama-0.5.14.tgz#bf1b72998491636ee89766bb0e3163e3c50a6970" + integrity sha512-pvOuEYa2WkkAumxzJP0RdEYHkbZ64AYyyUszXVX7ruLvk5L+EiO2G71da2GqEQ4IAk4j6eLoUbGk5arzFT1wJA== dependencies: whatwg-fetch "^3.6.20" @@ -2996,17 +2134,24 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" -openai@^4.77.0, openai@^4.85.2: - version "4.85.4" - resolved "https://registry.yarnpkg.com/openai/-/openai-4.85.4.tgz#fdf9d3228967b87221a112993501fa33a98f5d18" - integrity sha512-Nki51PBSu+Aryo7WKbdXvfm0X/iKkQS2fq3O0Uqb/O3b4exOZFid2te1BZ52bbO5UwxQZ5eeHJDCTqtrJLPw0w== +one-time@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" + integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== + dependencies: + fn.name "1.x.x" + +openai@^4.41.1: + version "4.86.1" + resolved "https://registry.yarnpkg.com/openai/-/openai-4.86.1.tgz#4147252d5e6255e2ae716ea59b1d4e54a1c1472a" + integrity sha512-x3iCLyaC3yegFVZaxOmrYJjitKxZ9hpVbLi+ZlT5UHuHTMlEQEbKXkGOM78z9qm2T5GF+XRUZCP2/aV4UPFPJQ== dependencies: "@types/node" "^18.11.18" "@types/node-fetch" "^2.6.4" @@ -3021,16 +2166,6 @@ openapi-types@^12.1.3: resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3" integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== -ordinal@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ordinal/-/ordinal-1.0.3.tgz#1a3c7726a61728112f50944ad7c35c06ae3a0d4d" - integrity sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ== - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - own-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" @@ -3045,27 +2180,6 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - p-queue@^6.6.2: version "6.6.2" resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" @@ -3102,37 +2216,11 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - path-to-regexp@0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -pbkdf2@^3.0.17: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - peberminta@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/peberminta/-/peberminta-0.9.0.tgz#8ec9bc0eb84b7d368126e71ce9033501dca2a352" @@ -3179,7 +2267,7 @@ pg-types@^2.1.0: postgres-date "~1.0.4" postgres-interval "^1.1.0" -pg@^8.13.3: +pg@^8.10.0, pg@^8.12.0: version "8.13.3" resolved "https://registry.yarnpkg.com/pg/-/pg-8.13.3.tgz#19cd021d1f9e9d26d860b80cd450f109a8652738" integrity sha512-P6tPt9jXbL9HVu/SSRERNYaYG++MjnscnegFh9pPHihfoBSujsrka0hyuymMzeJKFWrcG8wvCKy8rCe8e5nDUQ== @@ -3199,26 +2287,11 @@ pgpass@1.x: dependencies: split2 "^4.1.0" -pgvector@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/pgvector/-/pgvector-0.2.0.tgz#3d10f8e7084b4fc849db9acef0930fbbef75d322" - integrity sha512-ef9SggYLzgshzpsFHAha77ghSOucf1ebXcuvokgTQK6V01uihqGJv6i0+U+yjEgiDsiVtTdojDrqOHRcSmcECw== - -picocolors@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - picomatch@^2.0.4, picomatch@^2.2.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - possible-typed-array-names@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" @@ -3289,7 +2362,7 @@ punycode.js@2.3.1: resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== -punycode@^2.1.1, punycode@^2.3.1: +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -3318,19 +2391,12 @@ random-bytes@~1.0.0: resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.2, raw-body@^2.4.1: +raw-body@2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== @@ -3363,7 +2429,7 @@ readable-stream@^2.3.5: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.6.0: +readable-stream@^3.4.0, readable-stream@^3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -3372,11 +2438,6 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" - integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -3417,23 +2478,11 @@ request-promise-core@1.1.3: dependencies: lodash "^4.17.15" -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== -resolve@1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -3444,20 +2493,10 @@ retry@^0.13.1: resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.2.3: - version "2.2.7" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" - integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== - dependencies: - bn.js "^5.2.0" +rndm@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c" + integrity sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw== safe-array-concat@^1.1.3: version "1.1.3" @@ -3470,7 +2509,7 @@ safe-array-concat@^1.1.3: has-symbols "^1.1.0" isarray "^2.0.5" -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -3497,25 +2536,16 @@ safe-regex-test@^1.1.0: es-errors "^1.3.0" is-regex "^1.2.1" +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -scrypt-js@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - -secp256k1@^4.0.1, secp256k1@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.1.tgz#dc2c86187d48ff2da756f0f7e96417ee03c414b1" - integrity sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA== - dependencies: - elliptic "^6.5.7" - node-addon-api "^5.0.0" - node-gyp-build "^4.2.0" - selderee@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/selderee/-/selderee-0.11.0.tgz#6af0c7983e073ad3e35787ffe20cefd9daf0ec8a" @@ -3523,17 +2553,12 @@ selderee@^0.11.0: dependencies: parseley "^0.12.0" -semver@^5.5.0: +semver@^5.7.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.3.0: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.3, semver@^7.6.3: +semver@^7.6.3: version "7.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== @@ -3543,6 +2568,11 @@ semver@~5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw== +semver@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + send@0.19.0: version "0.19.0" resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" @@ -3562,13 +2592,6 @@ send@0.19.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - serve-static@1.16.2: version "1.16.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" @@ -3622,24 +2645,16 @@ set-proto@^1.0.0: es-errors "^1.3.0" es-object-atoms "^1.0.0" -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - side-channel-list@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" @@ -3685,51 +2700,29 @@ signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -simple-update-notifier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" - integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: - semver "^7.5.3" + is-arrayish "^0.3.1" -simple-wcswidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz#8ab18ac0ae342f9d9b629604e54d2aa1ecb018b2" - integrity sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg== - -siwe@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/siwe/-/siwe-3.0.0.tgz#0508c3fca521c476a07d907a9b5b96a03c27c0f2" - integrity sha512-P2/ry7dHYJA6JJ5+veS//Gn2XDwNb3JMvuD6xiXX8L/PJ1SNVD4a3a8xqEbmANx+7kNQcD8YAh1B9bNKKvRy/g== +simple-update-notifier@^1.0.7: + version "1.1.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" + integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== dependencies: - "@spruceid/siwe-parser" "^3.0.0" + semver "~7.0.0" + +siwe@^2.1.4: + version "2.3.2" + resolved "https://registry.yarnpkg.com/siwe/-/siwe-2.3.2.tgz#0794ae25f734f3068de0ab093ddd2f7867bc2d67" + integrity sha512-aSf+6+Latyttbj5nMu6GF3doMfv2UYj83hhwZgUF20ky6fTS83uVhkQABdIVnEuS8y1bBdk7p6ltb9SmlhTTlA== + dependencies: + "@spruceid/siwe-parser" "^2.1.2" "@stablelib/random" "^1.0.1" - -solc@0.8.26: - version "0.8.26" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" - integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== - dependencies: - command-exists "^1.2.8" - commander "^8.1.0" - follow-redirects "^1.12.1" - js-sha3 "0.8.0" - memorystream "^0.3.1" - semver "^5.5.0" - tmp "0.0.33" - -source-map-support@^0.5.13: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + uri-js "^4.4.1" + valid-url "^1.0.9" split2@^4.1.0: version "4.2.0" @@ -3751,32 +2744,26 @@ sshpk@^1.18.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -stacktrace-parser@^0.1.10: - version "0.1.11" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz#c7c08f9b29ef566b9a6f7b255d7db572f66fabc4" - integrity sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg== - dependencies: - type-fest "^0.7.1" +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +"statuses@>= 1.5.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string.prototype.trim@^1.2.10: version "1.2.10" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" @@ -3828,25 +2815,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-hex-prefix@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== - dependencies: - is-hex-prefixed "1.0.0" - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -3854,51 +2822,27 @@ supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -tinyglobby@^0.2.6: - version "0.2.12" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.12.tgz#ac941a42e0c5773bd0b5d08f32de82e74a1a61b5" - integrity sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww== - dependencies: - fdir "^6.4.3" - picomatch "^4.0.2" +text-hex@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== tlds@1.255.0: version "1.255.0" resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.255.0.tgz#53c2571766c10da95928c716c48dfcf141341e3f" integrity sha512-tcwMRIioTcF/FcxLev8MJWxCp+GUALRhFEqbDoZrnowmKSGqPrl5pqS+Sut2m8BgJ6S4FExCSSpGffZ0Tks6Aw== -tldts-core@^6.1.78: - version "6.1.78" - resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.78.tgz#47b477d9742870daa01dbd5ff9a598a48379728c" - integrity sha512-jS0svNsB99jR6AJBmfmEWuKIgz91Haya91Z43PATaeHJ24BkMoNRb/jlaD37VYjb0mYf6gRL/HOnvS1zEnYBiw== +tldts-core@^6.1.82: + version "6.1.82" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.82.tgz#b93e0312378f67cfc15ea1da9bc1b699ec621ae9" + integrity sha512-Jabl32m21tt/d/PbDO88R43F8aY98Piiz6BVH9ShUlOAiiAELhEqwrAmBocjAqnCfoUeIsRU+h3IEzZd318F3w== tldts@^6.1.32: - version "6.1.78" - resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.78.tgz#ee94576653a60d421ff94162c4e9060f2e62467b" - integrity sha512-fSgYrW0ITH0SR/CqKMXIruYIPpNu5aDgUp22UhYoSrnUQwc7SBqifEBFNce7AAcygUPBo6a/gbtcguWdmko4RQ== + version "6.1.82" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.82.tgz#1c06e884bcdbcccbaf73bd552e2f188ad670a4a9" + integrity sha512-KCTjNL9F7j8MzxgfTgjT+v21oYH38OidFty7dH00maWANAI2IsLw2AnThtTJi9HKALHZKQQWnNebYheadacD+g== dependencies: - tldts-core "^6.1.78" - -tmp@0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" + tldts-core "^6.1.82" to-regex-range@^5.0.1: version "5.0.1" @@ -3907,6 +2851,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -3928,9 +2877,9 @@ tough-cookie@^4.1.3: url-parse "^1.5.3" tough-cookie@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-5.1.1.tgz#4641c1fdbf024927e29c5532edb7b6e5377ea1f2" - integrity sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA== + version "5.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-5.1.2.tgz#66d774b4a1d9e12dc75089725af3ac75ec31bed7" + integrity sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A== dependencies: tldts "^6.1.32" @@ -3939,20 +2888,20 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +triple-beam@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" + integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== + tslib@2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== -tslib@^1.9.3: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tsort@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" - integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== +tsscmp@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" + integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== tunnel-agent@^0.6.0: version "0.6.0" @@ -3961,41 +2910,11 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tweetnacl-util@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" - integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== - tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== -tweetnacl@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" - integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== - -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.1.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" - integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -4061,7 +2980,7 @@ uc.micro@^2.0.0: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== -uid-safe@~2.1.5: +uid-safe@2.1.5, uid-safe@~2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== @@ -4098,13 +3017,6 @@ undici-types@~6.20.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== -undici@^5.14.0: - version "5.28.5" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.5.tgz#b2b94b6bf8f1d919bc5a6f31f2c01deb02e54d4b" - integrity sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA== - dependencies: - "@fastify/busboy" "^2.0.0" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -4120,6 +3032,13 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +uri-js@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" @@ -4155,6 +3074,16 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +valid-url@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" + integrity sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -4174,6 +3103,11 @@ web-streams-polyfill@4.0.0-beta.3: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== +web-streams-polyfill@^3.2.1: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -4244,26 +3178,31 @@ which-typed-array@^1.1.16, which-typed-array@^1.1.18: gopd "^1.2.0" has-tostringtag "^1.0.2" -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== +winston-transport@^4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" + integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== dependencies: - string-width "^4.0.0" + logform "^2.7.0" + readable-stream "^3.6.2" + triple-beam "^1.3.0" -workerpool@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" - integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== +winston@^3.17.0: + version "3.17.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.17.0.tgz#74b8665ce9b4ea7b29d0922cfccf852a08a11423" + integrity sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw== dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + "@colors/colors" "^1.6.0" + "@dabh/diagnostics" "^2.0.2" + async "^3.2.3" + is-stream "^2.0.0" + logform "^2.7.0" + one-time "^1.0.0" + readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.9.0" wrappy@1: version "1.0.2" @@ -4285,59 +3224,16 @@ ws@8.17.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== -ws@^7.4.6: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== - xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - yaml@^2.2.1: version "2.7.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== -yargs-parser@^20.2.2, yargs-parser@^20.2.9: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-unparser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - zod-to-json-schema@^3.22.3, zod-to-json-schema@^3.22.5, zod-to-json-schema@^3.24.1: version "3.24.3" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.3.tgz#5958ba111d681f8d01c5b6b647425c9b8a6059e7"