diff --git a/docs/MINI_APPS.md b/docs/MINI_APPS.md new file mode 100644 index 000000000..73e5c1f76 --- /dev/null +++ b/docs/MINI_APPS.md @@ -0,0 +1,233 @@ +# Mini-Apps Plugin System + +The Superhero platform includes a powerful plugin system that allows community developers to easily create and register their own mini-apps without forking the main repository. + +## Overview + +Mini-apps are self-contained applications that integrate seamlessly into the Superhero platform. They appear in the `/apps` directory and are automatically listed on the Mini-Apps landing page. + +## Quick Start + +### 1. Create Your Mini-App Component + +Create a React component for your mini-app: + +```tsx +// src/features/my-app/MyApp.tsx +import React from 'react'; + +export default function MyApp() { + return ( +
+ {/* Your app content */} +

My Custom Mini-App

+
+ ); +} +``` + +### 2. Register Your Mini-App + +Create a plugin file and register your app: + +```tsx +// src/features/my-app/plugin.ts +import { lazy } from 'react'; +import { registerMiniApp } from '@/features/mini-apps'; + +registerMiniApp({ + metadata: { + id: 'my-app', + name: 'My App', + description: 'A cool mini-app built by the community', + icon: '๐Ÿš€', + path: '/apps/my-app', + category: 'utility', + gradient: 'from-purple-500 to-pink-500', + author: 'Your Name', + authorUrl: 'https://github.com/yourusername', + version: '1.0.0', + tags: ['utility', 'community'], + }, + route: { + path: '/apps/my-app', + component: lazy(() => import('./MyApp')), + }, +}); +``` + +### 3. Import Your Plugin + +Add your plugin import to the plugins file: + +```tsx +// src/features/mini-apps/plugins.ts +import { registerBuiltInMiniApps } from './built-in'; +import './my-app/plugin'; // Add this line +``` + +## Plugin Structure + +### Metadata + +The `metadata` object defines how your mini-app appears in the UI: + +- **id**: Unique identifier (required) +- **name**: Display name (required) +- **description**: Short description shown on the landing page (required) +- **icon**: Emoji string or React component (required) +- **path**: Route path (required, should start with `/apps/`) +- **category**: One of `'trading' | 'bridge' | 'explore' | 'community' | 'utility'` (required) +- **gradient**: Tailwind gradient classes for icon background (required) +- **author**: Your name (optional) +- **authorUrl**: Your GitHub/profile URL (optional) +- **version**: Version string (optional) +- **tags**: Array of tags for filtering (optional) +- **requiresAuth**: Whether the app requires authentication (optional) + +### Route Configuration + +The `route` object defines how your app is routed: + +- **path**: Route path pattern (required) +- **component**: Lazy-loaded React component (required) +- **layout**: Custom layout wrapper (optional, defaults to `SocialLayout`) +- **options**: Additional route options (optional) + +## Examples + +### Simple Utility App + +```tsx +import { lazy } from 'react'; +import { registerMiniApp } from '@/features/mini-apps'; + +registerMiniApp({ + metadata: { + id: 'calculator', + name: 'Calculator', + description: 'A simple calculator tool', + icon: '๐Ÿ”ข', + path: '/apps/calculator', + category: 'utility', + gradient: 'from-blue-500 to-cyan-500', + author: 'John Doe', + }, + route: { + path: '/apps/calculator', + component: lazy(() => import('./Calculator')), + }, +}); +``` + +### App with Custom Layout + +```tsx +import { lazy } from 'react'; +import { registerMiniApp } from '@/features/mini-apps'; +import CustomLayout from './CustomLayout'; + +registerMiniApp({ + metadata: { + id: 'custom-app', + name: 'Custom App', + description: 'An app with custom layout', + icon: 'โญ', + path: '/apps/custom', + category: 'community', + gradient: 'from-purple-500 to-pink-500', + }, + route: { + path: '/apps/custom', + component: lazy(() => import('./CustomApp')), + layout: CustomLayout, + }, +}); +``` + +### App with Initialization + +```tsx +import { lazy } from 'react'; +import { registerMiniApp } from '@/features/mini-apps'; + +registerMiniApp({ + metadata: { + id: 'analytics', + name: 'Analytics', + description: 'Token analytics dashboard', + icon: '๐Ÿ“Š', + path: '/apps/analytics', + category: 'explore', + gradient: 'from-green-500 to-teal-500', + }, + route: { + path: '/apps/analytics', + component: lazy(() => import('./Analytics')), + }, + initialize: () => { + // Initialize analytics tracking, etc. + console.log('Analytics app initialized'); + }, + cleanup: () => { + // Cleanup when app is unregistered + console.log('Analytics app cleaned up'); + }, +}); +``` + +## Best Practices + +1. **Use lazy loading**: Always use `lazy()` for your component imports to enable code splitting +2. **Follow naming conventions**: Use kebab-case for IDs and paths +3. **Provide good descriptions**: Help users understand what your app does +4. **Use appropriate categories**: Choose the category that best fits your app +5. **Add tags**: Tags help users discover your app +6. **Test your routes**: Make sure your route paths don't conflict with existing routes +7. **Handle errors gracefully**: Use error boundaries and proper error handling + +## Integration Points + +### Using Platform Features + +Your mini-app can access platform features through hooks and context: + +```tsx +import { useAeSdk } from '@/hooks'; +import { useToast } from '@/components/ToastProvider'; + +export default function MyApp() { + const { activeAccount, sdk } = useAeSdk(); + const toast = useToast(); + + // Use platform features +} +``` + +### Styling + +Use Tailwind CSS classes and follow the platform's design system: + +```tsx +
+ {/* Your content */} +
+``` + +## Community Guidelines + +1. **Be respectful**: Don't create apps that harm users or violate terms of service +2. **Open source**: Consider open-sourcing your mini-app for the community +3. **Documentation**: Provide clear documentation for your app +4. **Testing**: Test your app thoroughly before registering +5. **Updates**: Keep your app updated and maintain compatibility + +## Questions? + +Join our developer community: +- GitHub: https://github.com/superhero-com/superhero +- Discord: [Link to Discord] +- Documentation: [Link to docs] + + + diff --git a/index.html b/index.html index 42bc2b8c7..962d94a66 100644 --- a/index.html +++ b/index.html @@ -16,13 +16,15 @@ var theme = saved || (prefersDark ? 'dark' : 'light'); document.documentElement.setAttribute('data-theme', theme); document.documentElement.classList.add('preload'); - // Set immediate baseline colors to avoid initial black flash + // Set immediate baseline colors to avoid initial flash if (theme === 'dark') { document.documentElement.style.backgroundColor = '#0a0a0f'; document.documentElement.style.color = '#f8fafc'; + document.body.style.backgroundColor = '#0a0a0f'; } else { document.documentElement.style.backgroundColor = '#fafafa'; document.documentElement.style.color = '#1e293b'; + document.body.style.backgroundColor = '#fafafa'; } } catch (e) {} })(); @@ -30,7 +32,7 @@ Superhero.com โ€“ The Allโ€‘inโ€‘One Social + Crypto App - +
- + diff --git a/package-lock.json b/package-lock.json index 5c8efec1f..b6ff30cda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -74,6 +74,7 @@ "tailwindcss-animate": "^1.0.7", "typescript": "^5.8.3", "vite": "^5.1.3", + "vite-plugin-node-polyfills": "^0.24.0", "vite-plugin-svgr": "^4.2.0", "vitest": "^2.0.5" } @@ -3018,6 +3019,29 @@ "dev": true, "license": "MIT" }, + "node_modules/@rollup/plugin-inject": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz", + "integrity": "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/pluginutils": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", @@ -6313,6 +6337,39 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -6629,6 +6686,156 @@ "node": ">=8" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "dev": true, + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.6.1", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, "node_modules/browserslist": { "version": "4.25.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.3.tgz", @@ -6695,6 +6902,13 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT" + }, "node_modules/bufferutil": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", @@ -6708,6 +6922,13 @@ "node": ">=6.14.2" } }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "license": "MIT" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -6928,6 +7149,21 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/class-variance-authority": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", @@ -7067,6 +7303,19 @@ "node": ">=18" } }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true, + "license": "MIT" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -7127,6 +7376,13 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -7154,6 +7410,60 @@ } } }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-fetch": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", @@ -7196,6 +7506,33 @@ "node": "*" } }, + "node_modules/crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -7491,6 +7828,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/defu": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", @@ -7537,6 +7892,17 @@ "node": ">=6" } }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/destr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", @@ -7594,6 +7960,25 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, "node_modules/dijkstrajs": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", @@ -7615,6 +8000,19 @@ "license": "MIT", "peer": true }, + "node_modules/domain-browser": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", + "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", @@ -7660,6 +8058,29 @@ "devOptional": true, "license": "ISC" }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, "node_modules/embla-carousel": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", @@ -8115,6 +8536,17 @@ "node": ">=0.8.x" } }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "node_modules/expect-type": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", @@ -8466,6 +8898,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -8641,12 +9083,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "license": "MIT", - "peer": true, "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -8664,6 +9119,18 @@ "node": ">= 0.4" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -8716,6 +9183,13 @@ "node": ">= 6" } }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true, + "license": "MIT" + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -8886,8 +9360,25 @@ "url": "https://github.com/sponsors/brc-dd" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, @@ -8968,6 +9459,26 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -8981,6 +9492,23 @@ "node": ">=0.10.0" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -8998,6 +9526,25 @@ "dev": true, "license": "MIT" }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-retry-allowed": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", @@ -9044,6 +9591,16 @@ "dev": true, "license": "ISC" }, + "node_modules/isomorphic-timers-promises": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz", + "integrity": "sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/isomorphic-ws": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", @@ -9845,6 +10402,18 @@ "is-buffer": "~1.1.6" } }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -9896,6 +10465,27 @@ "node": ">=8.6" } }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -9943,8 +10533,14 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "license": "ISC", - "peer": true + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true, + "license": "MIT" }, "node_modules/minimist": { "version": "1.2.8", @@ -10132,6 +10728,77 @@ "devOptional": true, "license": "MIT" }, + "node_modules/node-stdlib-browser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.3.1.tgz", + "integrity": "sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert": "^2.0.0", + "browser-resolve": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.7.1", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "create-require": "^1.1.1", + "crypto-browserify": "^3.12.1", + "domain-browser": "4.22.0", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "isomorphic-timers-promises": "^1.0.1", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "pkg-dir": "^5.0.0", + "process": "^0.11.10", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.6.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.1", + "url": "^0.11.4", + "util": "^0.12.4", + "vm-browserify": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-stdlib-browser/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/node-stdlib-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -10189,6 +10856,54 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ofetch": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", @@ -10238,6 +10953,13 @@ "openapi": "bin/index.js" } }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true, + "license": "MIT" + }, "node_modules/ox": { "version": "0.6.9", "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", @@ -10337,6 +11059,13 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10350,6 +11079,23 @@ "node": ">=6" } }, + "node_modules/parse-asn1": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -10391,6 +11137,13 @@ "node": ">= 0.8" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -10450,6 +11203,24 @@ "node": ">= 14.16" } }, + "node_modules/pbkdf2": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -10526,6 +11297,84 @@ "node": ">= 6" } }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pngjs": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", @@ -10743,6 +11592,13 @@ "node": ">= 0.6.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, "node_modules/process-warning": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", @@ -10814,6 +11670,28 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -10863,6 +11741,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -10896,6 +11783,27 @@ "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", "license": "MIT" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -11150,6 +12058,21 @@ "pify": "^2.3.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -11303,6 +12226,83 @@ "node": ">=0.10.0" } }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ripemd160/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ripemd160/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, "node_modules/rlp": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/rlp/-/rlp-3.0.0.tgz", @@ -11450,6 +12450,24 @@ ], "license": "MIT" }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-stable-stringify": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", @@ -11606,6 +12624,13 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -11899,12 +12924,36 @@ "dev": true, "license": "MIT" }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, "node_modules/stream-chain": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", "license": "BSD-3-Clause" }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, "node_modules/stream-json": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", @@ -11914,6 +12963,16 @@ "stream-chain": "^2.2.5" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -12340,6 +13399,19 @@ "real-require": "^0.2.0" } }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -12423,9 +13495,9 @@ "license": "MIT" }, "node_modules/to-buffer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", - "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", "license": "MIT", "dependencies": { "isarray": "^2.0.5", @@ -12497,6 +13569,13 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true, + "license": "MIT" + }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", @@ -12658,6 +13737,27 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/use-callback-ref": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", @@ -12723,6 +13823,20 @@ "node": ">=6.14.2" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -13013,6 +14127,23 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite-plugin-node-polyfills": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.24.0.tgz", + "integrity": "sha512-GA9QKLH+vIM8NPaGA+o2t8PDfFUl32J8rUp1zQfMKVJQiNkOX4unE51tR6ppl6iKw5yOrDAdSH7r/UIFLCVhLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/plugin-inject": "^5.0.5", + "node-stdlib-browser": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/davidmyersdev" + }, + "peerDependencies": { + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, "node_modules/vite-plugin-svgr": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.5.0.tgz", @@ -13094,6 +14225,13 @@ } } }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true, + "license": "MIT" + }, "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", @@ -13440,6 +14578,16 @@ "node": ">=0.4.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -13552,6 +14700,19 @@ "node": ">=8" } }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", diff --git a/package.json b/package.json index 8d1e17812..9b9153968 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "postinstall": "node ./scripts/update-package-type.cjs" }, "dependencies": { - "@base-org/account": "2.4.0", "@aeternity/aepp-sdk": "^13.3.2", + "@base-org/account": "2.4.0", "@dicebear/avatars": "^4.2.5", "@dicebear/avatars-avataaars-sprites": "^4.2.5", "@ethersproject/bignumber": "^5.8.0", @@ -78,6 +78,7 @@ "tailwindcss-animate": "^1.0.7", "typescript": "^5.8.3", "vite": "^5.1.3", + "vite-plugin-node-polyfills": "^0.24.0", "vite-plugin-svgr": "^4.2.0", "vitest": "^2.0.5" }, diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 000000000..497fdc46b --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,33 @@ + + + + https://superhero.com/ + daily + 0.7 + + + https://superhero.com/trends/tokens + daily + 0.7 + + + https://superhero.com/defi/swap + daily + 0.7 + + + https://superhero.com/terms + daily + 0.7 + + + https://superhero.com/privacy + daily + 0.7 + + + https://superhero.com/faq + daily + 0.7 + + diff --git a/src/@components/Address/AddressAvatarWithChainName.tsx b/src/@components/Address/AddressAvatarWithChainName.tsx index ef5f8d542..005d701bd 100644 --- a/src/@components/Address/AddressAvatarWithChainName.tsx +++ b/src/@components/Address/AddressAvatarWithChainName.tsx @@ -47,7 +47,8 @@ export const AddressAvatarWithChainName = memo(({ // Hooks must be called unconditionally before any early returns // Use empty string as fallback to ensure hooks are always called with a valid value const { decimalBalance, aex9Balances, loadAccountData } = useAccountBalances(address || ''); - const { chainName } = useChainName(address || ''); + // Fetch chain name immediately for displayed addresses (showBalance or showAddressAndChainName) + const { chainName } = useChainName(address || '', { immediate: showBalance || showAddressAndChainName }); // Guard against undefined/null address after hooks are called if (!address) { @@ -161,14 +162,16 @@ export const AddressAvatarWithChainName = memo(({ {chainName || (hideFallbackName ? '' : 'Legend')} - - - + ) )} diff --git a/src/App.tsx b/src/App.tsx index bc55620ab..79dd21e40 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,9 +7,11 @@ import { useAeSdk, useAccount, useWalletConnect } from "./hooks"; import { routes } from "./routes"; import "./styles/genz-components.scss"; import "./styles/mobile-optimizations.scss"; +import "./styles/layout-variants.scss"; import AppHeader from "./components/layout/app-header"; import { useSuperheroChainNames } from "./hooks/useChainName"; import FeedbackButton from "./components/FeedbackButton"; +import { LayoutVariantProvider } from "./contexts/LayoutVariantContext"; const CookiesDialog = React.lazy( () => import("./components/modals/CookiesDialog") @@ -55,41 +57,83 @@ export default function App() { }, [loadAccountData]); // setup intervals for periodic data refresh + // Increased interval from 10s to 30s to reduce load + // Pauses when window is not visible to save resources useEffect(() => { if (!activeAccount) return; // Note: Initial load is handled by useAccountBalances hook when account changes // This interval is just for periodic refreshes - const interval = setInterval(() => { - loadAccountDataRef.current(); - }, 10000); - return () => clearInterval(interval); + + let interval: NodeJS.Timeout | null = null; + + const startInterval = () => { + // Clear any existing interval + if (interval) clearInterval(interval); + + // Only start interval if document is visible + if (!document.hidden) { + interval = setInterval(() => { + // Double-check visibility before fetching + if (!document.hidden) { + loadAccountDataRef.current(); + } + }, 30000); // Reduced frequency: 30s instead of 10s + } + }; + + // Start interval initially + startInterval(); + + // Handle visibility changes + const handleVisibilityChange = () => { + if (document.hidden) { + // Pause when hidden + if (interval) { + clearInterval(interval); + interval = null; + } + } else { + // Resume when visible, and immediately refresh + loadAccountDataRef.current(); + startInterval(); + } + }; + + document.addEventListener('visibilitychange', handleVisibilityChange); + + return () => { + if (interval) clearInterval(interval); + document.removeEventListener('visibilitychange', handleVisibilityChange); + }; }, [activeAccount]); return ( -
- - - -
- + +
+ + + +
+ +
+ }> + + + }> +
{useRoutes(routes as any)}
+
+
- }> - - - }> -
{useRoutes(routes as any)}
-
- -
+ ); } diff --git a/src/api/backend.ts b/src/api/backend.ts index 63d88ba9e..43eb0c03a 100644 --- a/src/api/backend.ts +++ b/src/api/backend.ts @@ -6,6 +6,13 @@ export const SuperheroApi = { const base = (CONFIG.SUPERHERO_API_URL || '').replace(/\/$/, ''); if (!base) throw new Error('SUPERHERO_API_URL not configured'); const url = `${base}${path.startsWith('/') ? '' : '/'}${path}`; + // #region agent log + const requestId = `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + const stackTrace = new Error().stack || ''; + const callerMatch = stackTrace.match(/at\s+(\w+\.\w+)/g); + const caller = callerMatch && callerMatch.length > 1 ? callerMatch[1] : 'unknown'; + fetch('http://127.0.0.1:7242/ingest/f2f932c5-966e-499b-aaa2-090a82a9b89d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'backend.ts:fetchJson',message:'API request initiated',data:{requestId,url,path,caller,method:init?.method||'GET'},timestamp:Date.now(),sessionId:'debug-session',runId:'run2',hypothesisId:'B'})}).catch(()=>{}); + // #endregion if (process.env.NODE_ENV === 'development') { console.log(`[SuperheroApi] Base URL: ${base}`); console.log(`[SuperheroApi] Fetching: ${url}`); diff --git a/src/api/generated/core/request.ts b/src/api/generated/core/request.ts index f83d71199..dabf91420 100644 --- a/src/api/generated/core/request.ts +++ b/src/api/generated/core/request.ts @@ -297,6 +297,13 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C const formData = getFormData(options); const body = getRequestBody(options); const headers = await getHeaders(config, options); + // #region agent log + const requestId = `gen_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + const stackTrace = new Error().stack || ''; + const callerMatch = stackTrace.match(/at\s+(\w+Service\.\w+)/g); + const caller = callerMatch && callerMatch.length > 1 ? callerMatch[1] : 'unknown'; + fetch('http://127.0.0.1:7242/ingest/f2f932c5-966e-499b-aaa2-090a82a9b89d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'request.ts:request',message:'Generated API request initiated',data:{requestId,url,path:options.url,method:options.method,caller},timestamp:Date.now(),sessionId:'debug-session',runId:'run2',hypothesisId:'B'})}).catch(()=>{}); + // #endregion if (!onCancel.isCancelled) { const response = await sendRequest(config, options, url, body, formData, headers, onCancel); diff --git a/src/bootstrap.ts b/src/bootstrap.ts new file mode 100644 index 000000000..abc5141a4 --- /dev/null +++ b/src/bootstrap.ts @@ -0,0 +1,16 @@ +// This file runs before the app entry (`main.tsx`). +// Some dependencies assume Node's `buffer` module default export has a `.Buffer` property (CJS-like). +// In Vite/browser polyfills, the default export is typically the Buffer constructor itself, so we add `.Buffer = Buffer`. +import BufferPolyfill from 'vite-plugin-node-polyfills/shims/buffer'; +import BufferDefault, { Buffer as BufferNamed } from 'buffer'; + +const candidates = [BufferPolyfill, BufferDefault, BufferNamed, (globalThis as any).Buffer].filter(Boolean); +for (const b of candidates) { + if (!b.Buffer) b.Buffer = b; +} +(globalThis as any).Buffer = (globalThis as any).Buffer || BufferPolyfill; + +// IMPORTANT: dynamic import so the patch runs *before* the app and its deps execute. +void import('./main'); + + diff --git a/src/components/Account/AccountPortfolio.tsx b/src/components/Account/AccountPortfolio.tsx index c51fd64e4..2a951ca0b 100644 --- a/src/components/Account/AccountPortfolio.tsx +++ b/src/components/Account/AccountPortfolio.tsx @@ -848,8 +848,8 @@ export default function AccountPortfolio({ address }: AccountPortfolioProps) { address, convertTo: convertTo as any, enabled: !!address, - staleTime: 30_000, // 30 seconds - refetchInterval: 60_000, // 1 minute + staleTime: 60_000, // 1 minute (increased from 30s) + refetchInterval: 120_000, // 2 minutes (increased from 1 minute) }); // Prepare chart data for Recharts first (needed for currentPortfolioValue extraction) diff --git a/src/components/ConnectWalletButton.tsx b/src/components/ConnectWalletButton.tsx index 6a91b57e3..b47b071b1 100644 --- a/src/components/ConnectWalletButton.tsx +++ b/src/components/ConnectWalletButton.tsx @@ -57,7 +57,7 @@ export function ConnectWalletButton({ label, block, style, className, variant = style={style} > - + {(connectingWallet ? connectingText : displayLabel).toUpperCase()} diff --git a/src/components/GlobalNewAccountEducation.tsx b/src/components/GlobalNewAccountEducation.tsx index 5e7711fef..18bdcbcc9 100644 --- a/src/components/GlobalNewAccountEducation.tsx +++ b/src/components/GlobalNewAccountEducation.tsx @@ -145,7 +145,7 @@ export default function GlobalNewAccountEducation() { {/* Action buttons */}
+ + + {sortBy === "hot" ? ( + <> + {popularWindow !== "24h" && ( + handleMobileOptionSelect("today")} + className="cursor-pointer focus:bg-white/10 focus:text-white px-4 py-2.5 text-sm" + > + Today + + )} + {popularWindow !== "7d" && ( + handleMobileOptionSelect("this-week")} + className="cursor-pointer focus:bg-white/10 focus:text-white px-4 py-2.5 text-sm" + > + This week + + )} + {popularWindow !== "all" && ( + handleMobileOptionSelect("all-time")} + className="cursor-pointer focus:bg-white/10 focus:text-white px-4 py-2.5 text-sm" + > + All time + + )} + handleMobileOptionSelect("latest")} + className="cursor-pointer focus:bg-white/10 focus:text-white px-4 py-2.5 text-sm" + > + Latest + + + ) : ( + <> + handleMobileOptionSelect("today")} + className="cursor-pointer focus:bg-white/10 focus:text-white px-4 py-2.5 text-sm" + > + Popular today + + handleMobileOptionSelect("this-week")} + className="cursor-pointer focus:bg-white/10 focus:text-white px-4 py-2.5 text-sm" + > + Hot this week + + handleMobileOptionSelect("all-time")} + className="cursor-pointer focus:bg-white/10 focus:text-white px-4 py-2.5 text-sm" + > + Popular all time + + + )} + + +
+
+ + + {/* Post Button */} +
+ +
+ + {/* Scrollable Feed Content */} +
+
{ + // Pass scroll container ref to FeedList via data attribute or context + if (el) { + (el as any).__feedScrollContainer = true; + } + }} + className="h-full overflow-y-auto overflow-x-hidden" + onScroll={(e) => { + // Prevent outer scroll when scrolling within container + const target = e.currentTarget; + if (target.scrollTop > 0 && target.scrollTop < target.scrollHeight - target.clientHeight) { + e.stopPropagation(); + } + }} + onWheel={(e) => { + // Prevent outer scroll when scrolling within container + const target = e.currentTarget; + const isAtTop = target.scrollTop === 0; + const isAtBottom = target.scrollTop + target.clientHeight >= target.scrollHeight - 1; + if ((e.deltaY > 0 && !isAtBottom) || (e.deltaY < 0 && !isAtTop)) { + e.stopPropagation(); + } + }} + > + {/* Use FeedList with standalone=false to get just the feed content */} +
+ +
+
+
+ + ); +} diff --git a/src/components/layout/LayoutSwitcher.tsx b/src/components/layout/LayoutSwitcher.tsx new file mode 100644 index 000000000..f69d9f495 --- /dev/null +++ b/src/components/layout/LayoutSwitcher.tsx @@ -0,0 +1,91 @@ +import React from 'react'; +import { useLayoutVariant, LayoutVariant } from '../../contexts/LayoutVariantContext'; +import { GlassSurface } from '../ui/GlassSurface'; + +export default function LayoutSwitcher({ mode = 'sidebar' }: { mode?: 'sidebar' | 'header' }) { + const { variant, setVariant } = useLayoutVariant(); + + const options: { id: LayoutVariant; label: string; icon: React.ReactNode }[] = [ + { + id: 'dashboard', + label: 'Default', + icon: ( + + + + + + ) + }, + { + id: 'focus', + label: 'Focus', + icon: ( + + + + + ) + }, + { + id: 'minimal', + label: 'Zen', + icon: ( + + + + ) + } + ]; + + if (mode === 'header') { + return ( + + {options.map((opt) => { + const isActive = variant === opt.id; + return ( + + ); + })} + + ); + } + + return ( + +
+ {options.map((opt) => { + const isActive = variant === opt.id; + return ( + + ); + })} +
+
+ ); +} diff --git a/src/components/layout/LeftRail.tsx b/src/components/layout/LeftRail.tsx index 23301b5f3..e15c72db4 100644 --- a/src/components/layout/LeftRail.tsx +++ b/src/components/layout/LeftRail.tsx @@ -1,687 +1,562 @@ -import React, { useEffect, useState } from "react"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useEffect, useMemo, useState } from "react"; +import { useNavigate, useLocation, useParams, Link } from "react-router-dom"; +import { useTranslation } from 'react-i18next'; +import { useQuery } from '@tanstack/react-query'; import { SuperheroApi } from "../../api/backend"; -import { useAeSdk } from "../../hooks"; -import WebSocketClient from "../../libs/WebSocketClient"; - -interface TrendingTag { - tag: string; - score: number; - source?: string; -} - -interface TokenItem { - address: string; - name: string; - symbol: string; - price: number; - market_cap: number; - holders_count: number; - sale_address?: string; - trending_score?: number; -} - -interface LiveTransaction { - sale_address: string; - token_name: string; - type: string; - created_at: string; -} - -export default function LeftRail() { - const { sdk, currentBlockHeight } = useAeSdk(); +import { useAccountBalances } from "../../hooks/useAccountBalances"; +import WalletOverviewCard from "@/components/wallet/WalletOverviewCard"; +import { useAeSdk } from "../../hooks/useAeSdk"; +import Sparkline from "../Trendminer/Sparkline"; +import { HeaderLogo, IconWallet } from "../../icons"; +import Favicon from "../../svg/favicon.svg?react"; +import { getNavigationItems } from "./app-header/navigationItems"; + +import { useWallet, useWalletConnect, useModal } from "../../hooks"; +import { useAddressByChainName } from "../../hooks/useChainName"; +import { useCurrencies } from "../../hooks/useCurrencies"; +import LayoutSwitcher from "./LayoutSwitcher"; +import TabSwitcher from "./TabSwitcher"; +import { GlassSurface } from "../ui/GlassSurface"; +import AeButton from "../AeButton"; +import { ConnectWalletButton } from "../ConnectWalletButton"; +import FooterSection from "./FooterSection"; + +export default function LeftRail({ + hidePriceSection = true, +}: { + hidePriceSection?: boolean; +}) { + const { t } = useTranslation('common'); + const { openModal } = useModal(); const navigate = useNavigate(); const location = useLocation(); - const [currentTime, setCurrentTime] = useState(new Date()); - const [isOnline, setIsOnline] = useState(navigator.onLine); - const [isRefreshing, setIsRefreshing] = useState(false); - const [showTips, setShowTips] = useState(false); - const [showLiveFeed, setShowLiveFeed] = useState(true); - const [trendingTags, setTrendingTags] = useState([]); - const [liveTransactions, setLiveTransactions] = useState( - [] + const params = useParams(); + const { activeAccount } = useAeSdk(); + const { connectWallet } = useWalletConnect(); + const { currencyRates, aeternityData } = useCurrencies(); + + // Resolve chain name if present + const isChainName = params.address?.endsWith(".chain"); + const { address: resolvedAddress } = useAddressByChainName( + isChainName ? params.address : undefined ); - const [marketStats, setMarketStats] = useState(null); - const [topTokens, setTopTokens] = useState([]); - const [priceAlerts, setPriceAlerts] = useState< - Array<{ token: string; price: number; change: number }> - >([]); - // Removed local API status (moved to footer) - - // Timer, online status, and block height - useEffect(() => { - const timer = setInterval(() => setCurrentTime(new Date()), 1000); - const handleOnline = () => setIsOnline(true); - const handleOffline = () => setIsOnline(false); - - window.addEventListener("online", handleOnline); - window.addEventListener("offline", handleOffline); + const effectiveProfileAddress = isChainName && resolvedAddress + ? resolvedAddress + : (params.address as string | undefined); + + // Check if we're on the user's own profile page + const isOwnProfile = useMemo(() => { + const isProfilePage = location.pathname.startsWith('/users/'); + if (!isProfilePage) return false; + if (!activeAccount || !effectiveProfileAddress) return false; + return effectiveProfileAddress === activeAccount; + }, [location.pathname, effectiveProfileAddress, activeAccount]); + + const [prices, setPrices] = useState(() => { + // Initialize from cache if available + try { + const cached = sessionStorage.getItem("ae_prices"); + if (cached) { + const parsed = JSON.parse(cached); + // Check if cache is recent (less than 5 minutes old) + if (parsed.timestamp && Date.now() - parsed.timestamp < 5 * 60 * 1000) { + return parsed.data; + } + } + } catch { + // Ignore cache errors + } + return null; + }); + const [selectedCurrency, setSelectedCurrency] = useState< + "usd" | "eur" | "cny" + >("usd"); + + // Use React Query for historical price to avoid duplicate requests + const { data: historicalPriceData } = useQuery({ + queryKey: ['historical-price', selectedCurrency], + queryFn: () => SuperheroApi.getHistoricalPrice(selectedCurrency, 1, 'daily'), + staleTime: 5 * 60 * 1000, // 5 minutes + refetchInterval: 30 * 1000, // 30 seconds (matching the old interval) + }); + + const [usdSpark, setUsdSpark] = useState(() => { + try { + const raw = sessionStorage.getItem("ae_spark_usd"); + if (!raw) return []; + const arr = JSON.parse(raw); + return Array.isArray(arr) ? arr.slice(-50) : []; + } catch { + return []; + } + }); + + const [eurSpark, setEurSpark] = useState(() => { + try { + const raw = sessionStorage.getItem("ae_spark_eur"); + if (!raw) return []; + const arr = JSON.parse(raw); + return Array.isArray(arr) ? arr.slice(-50) : []; + } catch { + return []; + } + }); - return () => { - clearInterval(timer); - window.removeEventListener("online", handleOnline); - window.removeEventListener("offline", handleOffline); - }; - }, []); + const address = useWallet().address; + const accountId = useMemo( + () => activeAccount || address || "", + [activeAccount, address] + ); + useAccountBalances(accountId); - // Enhanced time formatting with emoji and block height - const formatTime = (date: Date) => { - const hour = date.getHours(); - let timeEmoji = "๐ŸŒ…"; - if (hour >= 6 && hour < 12) timeEmoji = "๐ŸŒ…"; - else if (hour >= 12 && hour < 17) timeEmoji = "โ˜€๏ธ"; - else if (hour >= 17 && hour < 20) timeEmoji = "๐ŸŒ†"; - else timeEmoji = "๐ŸŒ™"; + // Note: loadAccountData() is automatically called by useAccountBalances hook + // when accountId changes, so no manual call is needed here - const timeString = date.toLocaleTimeString("en-US", { - hour12: false, - hour: "2-digit", - minute: "2-digit", - second: "2-digit", + const formatPrice = (price: number, currency: string) => { + const formatter = new Intl.NumberFormat("en-US", { + style: "currency", + currency: currency.toUpperCase(), + minimumFractionDigits: 2, + maximumFractionDigits: 6, }); + return formatter.format(price); + }; - const dateString = date.toLocaleDateString("en-US", { - weekday: "short", - month: "short", - day: "numeric", - }); + const formatMarketCap = (amount: number): string => { + if (amount >= 1000000) { + return `$${(amount / 1000000).toFixed(1)}M`; + } else if (amount >= 1000) { + return `$${(amount / 1000).toFixed(1)}K`; + } + return `$${amount.toFixed(0)}`; + }; - return { timeEmoji, timeString, dateString }; + const getPriceChangeColor = (change: number) => { + if (change > 0) return "var(--neon-green)"; + if (change < 0) return "var(--neon-pink)"; + return "#94a3b8"; }; - // Load trending data + // Update prices when currency rates, market data, or historical price data changes + // This uses data from useCurrencies hook (React Query cached) instead of making duplicate API calls useEffect(() => { - let cancelled = false; - async function loadTrendingData() { - try { - const [tagsResp, tokensResp, statsResp] = await Promise.all([ - SuperheroApi.listTrendingTags({ - orderBy: "score", - orderDirection: "DESC", - limit: 10, - }), - SuperheroApi.listTokens({ - orderBy: "market_cap", - orderDirection: "DESC", - limit: 5, - }), - SuperheroApi.fetchJson("/api/analytics/past-24-hours"), - ]); - - if (!cancelled) { - try { - const tags = Array.isArray(tagsResp?.items) ? tagsResp.items : []; - const mappedTags = tags.map((it: any) => ({ - tag: it.tag ?? it.name ?? "", - score: Number(it.score ?? it.value ?? 0), - source: it.source || it.platform || undefined, - })); - setTrendingTags(mappedTags.filter((t) => t.tag)); + // Step 1: Use historical price data from React Query (cached) + if (historicalPriceData && Array.isArray(historicalPriceData) && historicalPriceData.length > 0) { + const latestPrice = historicalPriceData[historicalPriceData.length - 1]; + if (Array.isArray(latestPrice) && latestPrice.length >= 2) { + const price = latestPrice[1]; + setPrices((prevPrices) => { + // Only update if the price actually changed + if (prevPrices?.[selectedCurrency] === price) { + return prevPrices; + } + + const quickPriceData: any = { + usd: prevPrices?.usd ?? null, + eur: prevPrices?.eur ?? null, + cny: prevPrices?.cny ?? null, + [selectedCurrency]: price, + }; + + // Preserve existing market stats + quickPriceData.change24h = prevPrices?.change24h ?? null; + quickPriceData.marketCap = prevPrices?.marketCap ?? null; + quickPriceData.volume24h = prevPrices?.volume24h ?? null; + + return quickPriceData; + }); + } + } - const tokens = tokensResp?.items ?? []; - // Ensure token data is properly formatted - const formattedTokens = tokens.map((token: any) => ({ - ...token, - price: token.price ? Number(token.price) : null, - market_cap: token.market_cap ? Number(token.market_cap) : 0, - holders_count: token.holders_count - ? Number(token.holders_count) - : 0, - })); - setTopTokens(formattedTokens); + // Step 2: Use currency rates and market data from useCurrencies hook (React Query cached) + // Update sparklines whenever rates are available (only if they changed) + if (currencyRates) { + if (currencyRates.usd != null) { + setUsdSpark((prev) => { + const newValue = Number(currencyRates.usd); + // Only update if the value actually changed + if (prev.length > 0 && prev[prev.length - 1] === newValue) { + return prev; + } + const next = [...prev, newValue].slice(-50); + sessionStorage.setItem("ae_spark_usd", JSON.stringify(next)); + return next; + }); + } - setMarketStats(statsResp); - } catch (parseError) { - console.error("Failed to parse trending data:", parseError); - // Set empty arrays as fallback - setTrendingTags([]); - setTopTokens([]); - setMarketStats(null); + if (currencyRates.eur != null) { + setEurSpark((prev) => { + const newValue = Number(currencyRates.eur); + // Only update if the value actually changed + if (prev.length > 0 && prev[prev.length - 1] === newValue) { + return prev; } - } - } catch (error) { - console.error("Failed to load trending data:", error); - // Set empty arrays as fallback - if (!cancelled) { - setTrendingTags([]); - setTopTokens([]); - setMarketStats(null); - } + const next = [...prev, newValue].slice(-50); + sessionStorage.setItem("ae_spark_eur", JSON.stringify(next)); + return next; + }); } } - loadTrendingData(); - return () => { - cancelled = true; - }; - }, []); - // Load live transactions - useEffect(() => { - let cancelled = false; - async function loadLiveTransactions() { - try { - const [txResp, createdResp] = await Promise.all([ - SuperheroApi.fetchJson("/api/transactions?limit=5"), - SuperheroApi.fetchJson( - "/api/tokens?order_by=created_at&order_direction=DESC&limit=3" - ), - ]); - - if (!cancelled) { - try { - const txItems = txResp?.items ?? []; - const createdItems = (createdResp?.items ?? []).map((t: any) => ({ - sale_address: t.sale_address || t.address || "", - token_name: t.name || "Unknown Token", - type: "CREATED", - created_at: t.created_at || new Date().toISOString(), - })); - setLiveTransactions([...createdItems, ...txItems].slice(0, 8)); - } catch (parseError) { - console.error("Failed to parse live transactions:", parseError); - setLiveTransactions([]); + // Update price data using currency rates and market data from useCurrencies hook + setPrices((prevPrices) => { + const priceData: any = { + usd: currencyRates?.usd ?? null, + eur: currencyRates?.eur ?? null, + cny: currencyRates?.cny ?? null, + }; + + // Fallback to sparkline data if API rates are null but we have sparkline data + if (!priceData.usd) { + try { + const usdSparkData = sessionStorage.getItem("ae_spark_usd"); + if (usdSparkData) { + const usdSparkArray = JSON.parse(usdSparkData); + if (Array.isArray(usdSparkArray) && usdSparkArray.length > 0) { + priceData.usd = usdSparkArray[usdSparkArray.length - 1]; + } } + } catch { + // Ignore errors reading sparkline data } - } catch (error) { - console.error("Failed to load live transactions:", error); - if (!cancelled) { - setLiveTransactions([]); + } + + if (!priceData.eur) { + try { + const eurSparkData = sessionStorage.getItem("ae_spark_eur"); + if (eurSparkData) { + const eurSparkArray = JSON.parse(eurSparkData); + if (Array.isArray(eurSparkArray) && eurSparkArray.length > 0) { + priceData.eur = eurSparkArray[eurSparkArray.length - 1]; + } + } + } catch { + // Ignore errors reading sparkline data } } - } - loadLiveTransactions(); - - // WebSocket subscriptions for real-time updates - const unsub1 = WebSocketClient.subscribeForTokenHistories("TokenTransaction", (tx) => { - setLiveTransactions((prev) => - [ - { - sale_address: tx?.sale_address || tx?.token_address || "", - token_name: tx?.token_name || "Unknown", - type: "TRADE", - created_at: new Date().toISOString(), - }, - ...prev, - ].slice(0, 8) - ); - }); - - const unsub2 = WebSocketClient.subscribeForTokenHistories("TokenCreated", (payload) => { - setLiveTransactions((prev) => - [ - { - sale_address: payload?.sale_address || payload?.address || "", - token_name: payload?.name || "New Token", - type: "CREATED", - created_at: payload?.created_at || new Date().toISOString(), - }, - ...prev, - ].slice(0, 8) - ); - }); - - return () => { - cancelled = true; - unsub1(); - unsub2(); - }; - }, []); - - // API status moved to footer - // Simulate price alerts (in real app, this would come from user preferences) - useEffect(() => { - const alerts = [ - { token: "AE", price: 0.15, change: 2.5 }, - { token: "SUPER", price: 0.08, change: -1.2 }, - { token: "MEME", price: 0.003, change: 15.7 }, - ]; - setPriceAlerts(alerts); - }, []); - - const handleQuickAction = (action: string) => { - switch (action) { - case "explore": - navigate("/pool/add-tokens"); - break; - case "bridge": - navigate("/dex"); - break; - case "nfts": - navigate("/trends"); - break; - case "trending": - navigate("/trends"); - break; - case "governance": - navigate("/voting"); - break; - case "meet": - navigate("/meet"); - break; - default: - break; - } - }; - - const handleTrendingTopic = (topic: string) => { - navigate(`/trends?q=${encodeURIComponent(topic)}`); - }; + // Update market stats from aeternityData (from useCurrencies hook) + if (aeternityData) { + priceData.change24h = aeternityData.priceChangePercentage24h || + aeternityData.price_change_percentage_24h || + null; + priceData.marketCap = aeternityData.marketCap || + aeternityData.market_cap || + null; + priceData.volume24h = aeternityData.totalVolume || + aeternityData.total_volume || + null; + } else { + // Preserve existing market stats when marketData is not available + priceData.change24h = prevPrices?.change24h ?? null; + priceData.marketCap = prevPrices?.marketCap ?? null; + priceData.volume24h = prevPrices?.volume24h ?? null; + } - const handleTokenClick = (token: TokenItem) => { - navigate(`/trends/tokens/${token.name}`); - }; + // Check if data actually changed before updating + const hasChanged = + prevPrices?.usd !== priceData.usd || + prevPrices?.eur !== priceData.eur || + prevPrices?.cny !== priceData.cny || + prevPrices?.change24h !== priceData.change24h || + prevPrices?.marketCap !== priceData.marketCap || + prevPrices?.volume24h !== priceData.volume24h; + + // Only update if we have at least one currency price AND data changed + if ((priceData.usd != null || priceData.eur != null || priceData.cny != null) && hasChanged) { + // Cache the price data + try { + sessionStorage.setItem("ae_prices", JSON.stringify({ + data: priceData, + timestamp: Date.now(), + })); + } catch { + // Ignore cache errors + } + return priceData; + } - const formatMarketCap = (amount: number): string => { - if (amount >= 1000000) { - return `$${(amount / 1000000).toFixed(1)}M`; - } else if (amount >= 1000) { - return `$${(amount / 1000).toFixed(1)}K`; - } - return `$${amount.toFixed(0)}`; + // Return previous prices if no new data available or nothing changed + return prevPrices; + }); + }, [selectedCurrency, currencyRates, aeternityData, historicalPriceData]); + + const { t: tNav } = useTranslation('navigation'); + const navigationItems = getNavigationItems(tNav); + const isDaoPath = location.pathname.startsWith('/trends/dao') || location.pathname.startsWith('/trends/daos'); + + const isActiveRoute = (path: string) => { + if (path === '/') return location.pathname === '/'; + if (path === '/trends/daos') return isDaoPath; + return location.pathname.startsWith(path); }; - const enhancedTips = [ - { - icon: "๐Ÿ’Ž", - color: "var(--neon-teal)", - text: "Use hardware wallets for large amounts", - expanded: - "Hardware wallets like Ledger or Trezor provide the highest security for storing significant amounts of cryptocurrency.", - category: "Security", - }, - { - icon: "๐Ÿ”’", - color: "var(--neon-pink)", - text: "Always verify contract addresses", - expanded: - "Double-check contract addresses before interacting. One wrong character can lead to permanent loss of funds.", - category: "Security", - }, - { - icon: "โšก", - color: "var(--neon-blue)", - text: "Keep some AE for gas fees", - expanded: - "Always maintain a small balance of AE tokens to pay for transaction fees on the รฆternity network.", - category: "Trading", - }, - { - icon: "๐Ÿ›ก๏ธ", - color: "var(--neon-yellow)", - text: "Never share your private keys", - expanded: - "Your private keys are like the password to your bank account. Never share them with anyone, including support.", - category: "Security", - }, - { - icon: "๐Ÿ“ฑ", - color: "var(--neon-purple)", - text: "Enable 2FA on exchanges", - expanded: - "Use two-factor authentication on all cryptocurrency exchanges to add an extra layer of security.", - category: "Security", - }, - { - icon: "๐Ÿš€", - color: "var(--neon-green)", - text: "Diversify your portfolio", - expanded: - "Don't put all your eggs in one basket. Spread your investments across different tokens and projects.", - category: "Investment", - }, - ]; - return ( -
- {/* Enhanced Quick Stats Dashboard */} -
-
- - ๐Ÿ“Š - -

- Live Dashboard -

-
+
+ {/* LayoutSwitcher hidden */} + {/* Navigation Bar - Tab style like LayoutSwitcher */} +
+
+ + +
- -
-
- Blockchain Status - - {isOnline ? "๐ŸŸข Connected" : "๐Ÿ”ด Offline"} + !!item && !!item.id && !item.isExternal) + .map((item: any) => ({ + id: item.id, + label: item.label, + path: item.path, + icon: item.icon, + }))} + /> +
+ + {/* Connect Wallet Card - Only show if not connected */} + {!activeAccount && ( + +
+ +
+
+ +
+ +

+ Connect Wallet +

+ +

+ Access your assets and start trading on Superhero. +

+ +
+ + +
+
+ + )} + + {/* Network & Wallet Overview - Hidden on own profile */} + {!isOwnProfile && ( + + + + )} + + {/* Enhanced Price Section (hidden by default via hidePriceSection) */} + {!hidePriceSection && ( + +
+ + ๐Ÿ“ˆ +

+ AE Price +

+
+ {(["usd", "eur", "cny"] as const).map((currency) => ( + + ))} +
- {/* Enhanced Current Time Display */} -
- {/* Animated background effect */} -
- -
- {/* Time Emoji and Label */} -
- - Current Time - - - {formatTime(currentTime).timeEmoji} - -
- - {/* Main Time Display */} -
-
- {formatTime(currentTime).timeString} +
+
+
+
+ {prices?.[selectedCurrency] + ? formatPrice(prices[selectedCurrency], selectedCurrency) + : "-"}
-
- - {/* Date Display */} -
-
- {formatTime(currentTime).dateString} +
+ {prices?.change24h && ( + + {prices.change24h > 0 ? "+" : ""} + {prices.change24h.toFixed(2)}% (24h) + + )}
- - {/* Block Height (if available) */} - {currentBlockHeight !== null && ( -
- - - Block #{currentBlockHeight.toLocaleString()} - -
- )} +
+ +
-
- {marketStats && ( -
-
-
+
+
+ Market Cap -
-
- {formatMarketCap(marketStats.total_market_cap_sum || 0)} -
+ + + {prices?.marketCap ? formatMarketCap(prices.marketCap) : "-"} +
-
-
- Total Tokens -
-
- {marketStats.total_tokens || 0} -
+
+ + 24h Volume + + + {prices?.volume24h ? formatMarketCap(prices.volume24h) : "-"} +
- )} - - {/* Network Status moved to footer */} -
-
- - {/* Enhanced Quick Actions - moved to RightRail */} - - {/* Live Trending Topics */} -
-
- ๐Ÿ”ฅ -

- Live Trending -

+
+ + )} + + {/* Enhanced Trending Section */} + {/*
+
+ ๐Ÿ”ฅ +

Trending Topics

-
-
- {trendingTags.slice(0, 6).map((tag, index) => ( -
handleTrendingTopic(tag.tag)} - onMouseEnter={(e) => { - e.currentTarget.style.background = "rgba(255,255,255,0.12)"; - e.currentTarget.style.color = "white"; - e.currentTarget.style.transform = - "translateY(-2px) scale(1.02)"; - }} - onMouseLeave={(e) => { - e.currentTarget.style.background = `rgba(255,255,255,${ - 0.03 + index * 0.02 - })`; - e.currentTarget.style.color = "#b8c5d6"; - e.currentTarget.style.transform = "translateY(0) scale(1)"; - }} - title={`Search for ${tag.tag} (Score: ${tag.score})`} - > - - #{index + 1} +
+ {topTrending.map((topic, index) => ( +
+ #{index + 1} + + {typeof topic[0] === 'string' ? topic[0] : 'Unknown Topic'} + + + {typeof topic[1] === 'number' ? `${topic[1]} mentions` : '0 mentions'} - {tag.tag}
))}
-
+
*/} - {/* Top Tokens - moved to RightRail */} - {/* Live Activity Feed - moved to RightRail */} + {/* Trading Leaderboard promo */} + +
+ ๐Ÿ† +

+ Top Traders +

+
+

+ See which wallets are leading the markets by PnL, ROI and AUM on the Trading Leaderboard. +

+ +
- {/* Price Alerts - moved to RightRail */} + {/* Quick Actions - moved to Right Rail bottom */} + +
+ โšก +

+ Quick Actions +

+
- {/* Enhanced Pro Tips */} -
-
setShowTips(!showTips)} - title="Click to expand tips" - > - ๐Ÿ’ก -

+

- +
- -
- {enhancedTips.map((tip, index) => ( -
-
{ - // Show expanded tip in a toast or modal - alert(`${tip.icon} ${tip.category}: ${tip.expanded}`); - }} - onMouseEnter={(e) => { - e.currentTarget.style.background = "rgba(255,255,255,0.05)"; - }} - onMouseLeave={(e) => { - e.currentTarget.style.background = "transparent"; - }} - title={`${tip.category}: Click for more details`} - > - - {tip.icon} - -
- - {tip.text} - -
- {tip.category} -
-
-
- {showTips && ( -
- {tip.expanded} -
- )} -
- ))} -
+ ๐Ÿš€ Tokenize Trend + + + + + + + ๐Ÿ’ฌ Open Chat +
+
+ + {/* Footer Section */} + - + + {/* Load More Button - inside scrollable container */} + {hasNextPage && ( +
+ +
+ )} +
+
+ + {/* Empty State */} + {!tokens.length && !isFetching && ( + +

No trending tokens found

+
+ )} + + {/* Loading State */} + {isFetching && !tokens.length && ( +
+
+ + + + + + + + + + + + + + + + {[...Array(5)].map((_, i) => ( + + + + + + + + + + + + ))} + +
RankTokenMarket CapPrice +
+ +
+
24h7d30dGraph
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )} +
+ ); +} + diff --git a/src/views/Explore.tsx b/src/views/Explore.tsx index bde2235ba..539c6dc7c 100644 --- a/src/views/Explore.tsx +++ b/src/views/Explore.tsx @@ -208,7 +208,7 @@ export default function ExploreRefactored() {