From 6b20fc8b62a5f55cd7dd28979b26468e6c0cca1b Mon Sep 17 00:00:00 2001 From: mtyszczak Date: Thu, 18 Dec 2025 17:16:51 +0100 Subject: [PATCH 1/2] Remove dhive --- .github/copilot-instructions.md | 146 +++ Dockerfile | 1 - apps/blog/README.md | 2 +- .../features/account-settings/lib/utils.ts | 36 +- apps/blog/features/post-editor/lib/utils.ts | 40 +- apps/blog/next.config.js | 1 + apps/wallet/next.config.js | 3 + packages/common-hiveio-packages/.eslintrc.js | 4 + .../common-hiveio-packages/.prettierrc.js | 3 + packages/common-hiveio-packages/package.json | 24 + .../src/hb-auth/hbauth-service.ts | 121 ++ .../src/hb-auth/index.ts | 1 + packages/common-hiveio-packages/src/index.ts | 2 + .../src/wax/app-types.ts | 86 ++ .../src/wax/extended-hive.chain.ts | 1151 +++++++++++++++++ .../src/wax/hive-chain-service.ts | 193 +++ .../common-hiveio-packages/src/wax/index.ts | 3 + packages/common-hiveio-packages/tsconfig.json | 9 + packages/middleware/lib/auth-proof-cookie.ts | 2 +- .../auth/methods/safestorage-key-update.tsx | 2 +- .../components/auth/methods/safestorage.tsx | 2 +- .../smart-signer/components/login-form.tsx | 2 +- .../smart-signer/components/password-form.tsx | 2 +- .../lib/api-handlers/auth/login.ts | 2 +- packages/smart-signer/lib/hbauth-service.ts | 101 +- packages/smart-signer/lib/hive-auth-utils.ts | 62 +- .../smart-signer/lib/signer/get-signer.ts | 10 +- .../smart-signer/lib/signer/signer-hbauth.ts | 37 +- .../lib/signer/signer-hiveauth.ts | 2 +- .../lib/signer/signer-keychain.ts | 27 +- .../smart-signer/lib/signer/signer-wif.ts | 110 +- packages/smart-signer/lib/signer/signer.ts | 18 +- packages/smart-signer/lib/use-signer.ts | 8 - packages/smart-signer/lib/utils.ts | 172 --- .../lib/validators/validate-wif-key.ts | 22 +- .../lib/verify-login-challenge.ts | 4 +- packages/smart-signer/lib/verify-signature.ts | 29 +- packages/smart-signer/package.json | 3 +- packages/transaction/lib/app-types.ts | 2 + packages/transaction/lib/chain.ts | 3 +- .../transaction/lib/extended-hive.chain.ts | 13 +- packages/transaction/lib/hive-api.ts | 12 +- .../transaction/lib/hive-chain-service.ts | 168 +-- packages/transaction/package.json | 3 +- pnpm-lock.yaml | 605 +-------- pnpm-workspace.yaml | 2 +- 46 files changed, 2006 insertions(+), 1245 deletions(-) create mode 100644 .github/copilot-instructions.md create mode 100644 packages/common-hiveio-packages/.eslintrc.js create mode 100644 packages/common-hiveio-packages/.prettierrc.js create mode 100644 packages/common-hiveio-packages/package.json create mode 100644 packages/common-hiveio-packages/src/hb-auth/hbauth-service.ts create mode 100644 packages/common-hiveio-packages/src/hb-auth/index.ts create mode 100644 packages/common-hiveio-packages/src/index.ts create mode 100644 packages/common-hiveio-packages/src/wax/app-types.ts create mode 100644 packages/common-hiveio-packages/src/wax/extended-hive.chain.ts create mode 100644 packages/common-hiveio-packages/src/wax/hive-chain-service.ts create mode 100644 packages/common-hiveio-packages/src/wax/index.ts create mode 100644 packages/common-hiveio-packages/tsconfig.json diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..e1216067f --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,146 @@ +# Denser - Hive Blockchain Frontend + +Decentralized social media app for Hive Blockchain. Successor to hive/condenser (hive.blog). + +## Architecture + +### Monorepo Structure (pnpm + Turbo) +- **apps/blog** - Main social media frontend (blog.hive.blog, port 3000) +- **apps/wallet** - Wallet interface (wallet.hive.blog, port 4000) +- **apps/auth** - Legacy auth app (obsolete, but code referenced for patterns) +- **packages/** - Shared workspace packages used across apps + - `smart-signer` - Hive authentication SDK (HiveAuth/Hivesigner integration) + - `ui` - Common UI components (Radix UI based) + - `transaction` - Hive blockchain transaction utilities + - `renderer` - Content rendering (markdown, etc.) + - `middleware` - Next.js middleware utilities +- **haf/** - Hive Application Framework (C++ blockchain backend, separate project) + +### Tech Stack +- Next.js (standalone output, app and pages router mix) +- TypeScript, React 18 +- Tailwind CSS +- TanStack Query (React Query) for data fetching +- Zustand for app state +- Playwright for E2E testing +- Node 20.11.1 (pinned via Volta) + +### Hive Blockchain Integration +Apps consume Hive blockchain data via: +- **@hiveio/wax** - Primary API client for Hive (installed as `catalog:hiveio-toolset`) +- **@hiveio/hb-auth** - Authentication web worker (copied to `public/auth/` during build) +- Environment variables: `REACT_APP_API_ENDPOINT` (Hive API) and `REACT_APP_IMAGES_ENDPOINT` +- HAF (Hive Application Framework) provides blockchain data via PostgreSQL (see `haf/` directory for backend) + +## Critical Workflows + +### Development +```bash +pnpm install +pnpm run dev:blog # Port 3000 +pnpm run dev:wallet # Port 4000 +``` +Version info is written to `version.json` before each dev/build command via `scripts/write-version.sh`. + +### Building & Starting +```bash +pnpm run build:blog && pnpm run start:blog +pnpm run build:wallet && pnpm run start:wallet +``` +Builds use `output: 'standalone'` mode. Post-build copies HiveAuth worker to `public/auth/`. + +### Testing +```bash +pnpm run all:pw:test:local # Both apps +pnpm run blog:pw:test:local # Blog only +pnpm run blog:mir:pw:test:mir:chromium # Against mirrornet test env +``` +Multiple Playwright configs exist for different environments (local, mirrornet, stack deployments). + +### Docker Deployment +Build individual app images: +```bash +./scripts/build_instance.sh --app-scope='@hive/blog' --app-path='/apps/blog' --app-name='blog' "$(pwd)" +BASE_PATH=/blog ./scripts/build_instance.sh ... # For subdirectory deployments +``` +Use `docker/docker-compose.yml` or `stack/compose.*.yml` for orchestration. + +## Project Conventions + +### Environment Variables (Runtime) +Use **@beam-australia/react-env** for runtime env vars (not build-time). Variables are injected when server starts, not at build time. Prefix with `REACT_APP_` for exposure to client. + +### Base Path Support +Apps support deployment at root (`/`) or subdirectory (`/blog`, `/wallet`): +- Set `NEXT_PUBLIC_BASE_PATH` env var at build time +- `basePath` and `assetPrefix` in `next.config.js` are configured accordingly +- Blog middleware redirects `/` → `/trending` + +### Package Dependencies +- Monorepo packages use `workspace:*` protocol +- External Hive tools use `catalog:hiveio-toolset` (defined in pnpm workspace) +- `transpilePackages` in next.config includes all workspace packages +- `neverBuiltDependencies`: `secp256k1`, `core-js` (defined in root package.json) + +### Authentication Flow +1. HiveAuth worker copied from `@hiveio/hb-auth/dist/worker.js` to `public/auth/` +2. Middleware (`middleware.ts`) sets login challenge cookies +3. Login API endpoints: `/api/auth/login`, `/api/auth/logout`, `/api/users/me` +4. Use hooks from `@hive/smart-signer/lib/auth/` (e.g., `use-logout.ts`, `use-user-client.ts`) +5. Forms in `packages/smart-signer/components/auth/` + +### Localization +- Use `next-i18next` with `localePath: './public/locales'` +- Copy locale files via CopyPlugin during build (both app and package locales) +- Gitignore `public/locales/` in apps + +### Code Organization +- **apps/*/pages/** - Next.js page routes +- **apps/*/app/** - Next.js App Router routes (hybrid router usage) +- **apps/*/features/** - Feature-specific components and logic +- **apps/*/lib/** - App-specific utilities +- **apps/*/store/** - Zustand stores +- **packages/** - Reusable cross-app code + +### Turbo Configuration +Tasks in `turbo.json`: +- `dev`, `devssl` - Persistent, no cache +- `build` - Depends on `^build`, outputs `.next/**` +- `start` - Depends on `^build` + +## Integration Points + +### HAF Backend +HAF (Hive Application Framework) is the blockchain data layer: +- C++/PostgreSQL based backend (see `haf/` directory) +- Provides blockchain data via sql_serializer plugin +- Apps typically consume via Wax API client pointing to HAF-powered API endpoints +- HAF handles fork resolution automatically + +### Blockchain APIs +Apps consume Hive data via `REACT_APP_API_ENDPOINT`: +- Production: `https://api.hive.blog` +- Test: Mirrornet environments (`*.bc.fqdn.pl:8083`) +- Local: Point to local HAF instance + +### Stack Deployment +`stack/` contains Docker Compose files for full-stack deployment: +- `compose.stack.yml` - HAF backend services +- `compose.blog.yml`, `compose.wallet.yml` - Frontend apps +- `compose.caddy.yml` - Reverse proxy (Caddy) +- Uses registry.gitlab.syncad.com for images + +### PWA Support +Both apps use `next-pwa`: +- Service worker: `public/sw.js` +- Cache-Control headers prevent caching of workers +- Disabled in development mode + +## Key Files + +- `turbo.json` - Monorepo task orchestration +- `pnpm-workspace.yaml` - Workspace package definitions +- `apps/*/next.config.js` - Next.js config with basePath, rewrites, transpilePackages +- `packages/smart-signer/README.md` - Comprehensive auth integration guide +- `scripts/build_instance.sh` - Docker image build script +- `haf/README.md` - HAF backend architecture documentation diff --git a/Dockerfile b/Dockerfile index fcffdea15..40cfd7e57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,6 @@ COPY . . RUN pnpm dlx turbo prune --scope=${TURBO_APP_SCOPE} --docker # Add lockfile and package.json's of isolated subworkspace -# TODO: Remove python3 installation after getting rid of dhive FROM base AS installer ARG TURBO_APP_SCOPE ARG BASE_PATH diff --git a/apps/blog/README.md b/apps/blog/README.md index d5b2d9290..14275f771 100644 --- a/apps/blog/README.md +++ b/apps/blog/README.md @@ -14,7 +14,7 @@ - Linting with [ESLint](https://eslint.org) - Static Types with [TypeScript](https://typescriptlang.org) - UI Component library [Radix UI](https://www.radix-ui.com/) -- Javascript library for talking to Hive API [DHive](https://gitlab.syncad.com/hive/dhive) +- Javascript library for talking to Hive API [Wax](https://hive.pages.syncad.com/wax-doc/) - [Hivesigner](https://hivesigner.com/) option for authentication ## Getting Started diff --git a/apps/blog/features/account-settings/lib/utils.ts b/apps/blog/features/account-settings/lib/utils.ts index 0f2d4196c..9e25804a1 100644 --- a/apps/blog/features/account-settings/lib/utils.ts +++ b/apps/blog/features/account-settings/lib/utils.ts @@ -69,30 +69,32 @@ export function validation(values: Settings, t: TFunction<'common_blog'>) { export const uploadImg = async (file: File, username: string, signer: Signer): Promise => { try { - let data; + if (!file) + throw new Error("No file provided"); - if (file) { + const data = await new Promise((resolve) => { const reader = new FileReader(); - - data = new Promise((resolve) => { - reader.addEventListener('load', () => { - const result = Buffer.from(reader.result!.toString(), 'binary'); - resolve(result); - }); - reader.readAsBinaryString(file); + reader.addEventListener('load', () => { + // reader.result is an ArrayBuffer + resolve(new Uint8Array(reader.result as ArrayBuffer)); }); - } + reader.readAsArrayBuffer(file); + }); const formData = new FormData(); - if (file) { - formData.append('file', file); - } + formData.append('file', file); + + // 3. Create the prefix as a Uint8Array + const encoder = new TextEncoder(); + const prefix = encoder.encode('ImageSigningChallenge'); - data = await data; - const prefix = Buffer.from('ImageSigningChallenge'); - // @ts-ignore - const buf = Buffer.concat([prefix, data as unknown as Uint8Array]); + // 4. Concatenate without Buffer.concat + // We create a new array of the total length and "set" the parts into it + const buf = new Uint8Array(prefix.length + data.length); + buf.set(prefix); + buf.set(data, prefix.length); + // 5. Sign (Works natively with Uint8Array) const sig = await signer.signChallenge({ message: buf, password: '' diff --git a/apps/blog/features/post-editor/lib/utils.ts b/apps/blog/features/post-editor/lib/utils.ts index 68c3775f8..e4d266ee2 100644 --- a/apps/blog/features/post-editor/lib/utils.ts +++ b/apps/blog/features/post-editor/lib/utils.ts @@ -106,32 +106,32 @@ export function maxAcceptedPayout(customValue: number | string | undefined, maxP */ const uploadImg = async (file: File, username: string, signer: Signer): Promise => { try { - let data; + if (!file) + throw new Error("No file provided"); - if (file) { + const fileData = await new Promise((resolve) => { const reader = new FileReader(); - - data = new Promise((resolve) => { - reader.addEventListener('load', () => { - const result = Buffer.from(reader.result!.toString(), 'binary'); - resolve(result); - }); - reader.readAsBinaryString(file); + reader.addEventListener('load', () => { + // reader.result is an ArrayBuffer; convert to Uint8Array immediately + resolve(new Uint8Array(reader.result as ArrayBuffer)); }); - } + reader.readAsArrayBuffer(file); + }); const formData = new FormData(); - if (file) { - formData.append('file', file); - } + formData.append('file', file); + + // 3. Create prefix using TextEncoder (Native alternative to Buffer.from) + const encoder = new TextEncoder(); + const prefix = encoder.encode('ImageSigningChallenge'); + + // 4. Standardized Concatenation + // Create a container of the total size + const buf = new Uint8Array(prefix.length + fileData.length); - data = await data; - const prefix = Buffer.from('ImageSigningChallenge'); - const dataBuf = data as Buffer; // ensure Buffer - const combined = new Uint8Array(prefix.length + dataBuf.length); - combined.set(prefix, 0); - combined.set(dataBuf, prefix.length); - const buf = Buffer.from(combined); + // Copy prefix to the start, and fileData right after it + buf.set(prefix, 0); + buf.set(fileData, prefix.length); const sig = await signer.signChallenge({ message: buf, diff --git a/apps/blog/next.config.js b/apps/blog/next.config.js index bf5ef9641..8cfc7edbc 100644 --- a/apps/blog/next.config.js +++ b/apps/blog/next.config.js @@ -56,6 +56,7 @@ const nextConfig = { ]; }, transpilePackages: [ + '@hive/common-hiveio-packages', '@hive/smart-signer', '@hive/ui', '@hive/transaction', diff --git a/apps/wallet/next.config.js b/apps/wallet/next.config.js index c12481904..97d21d0d7 100644 --- a/apps/wallet/next.config.js +++ b/apps/wallet/next.config.js @@ -25,6 +25,9 @@ const nextConfig = { experimental: { outputFileTracingRoot: path.join(__dirname, '../..') }, + transpilePackages: [ + '@hive/common-hiveio-packages', + ], async rewrites() { return [ // Rewrite requests that incorrectly include /public in the path diff --git a/packages/common-hiveio-packages/.eslintrc.js b/packages/common-hiveio-packages/.eslintrc.js new file mode 100644 index 000000000..895847a1e --- /dev/null +++ b/packages/common-hiveio-packages/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['@hive/eslint-config-custom'] +}; diff --git a/packages/common-hiveio-packages/.prettierrc.js b/packages/common-hiveio-packages/.prettierrc.js new file mode 100644 index 000000000..a275bd3e7 --- /dev/null +++ b/packages/common-hiveio-packages/.prettierrc.js @@ -0,0 +1,3 @@ +module.exports = { + ...require("@hive/prettier-config-custom"), +}; diff --git a/packages/common-hiveio-packages/package.json b/packages/common-hiveio-packages/package.json new file mode 100644 index 000000000..9296b1047 --- /dev/null +++ b/packages/common-hiveio-packages/package.json @@ -0,0 +1,24 @@ +{ + "name": "@hive/common-hiveio-packages", + "version": "0.1.0", + "main": "./src/index.ts", + "types": "./src/index.ts", + "scripts": { + "lint": "eslint ." + }, + "dependencies": { + "@hive/ui": "workspace:*", + "@hiveio/hb-auth": "catalog:hiveio-toolset", + "@hiveio/wax": "catalog:hiveio-toolset" + }, + "exports": { + ".": "./src/index.ts", + "./package.json": "./package.json", + "./wax": "./src/wax/index.ts", + "./src/hb-auth": "./src/hb-auth/index.ts" + }, + "devDependencies": { + "@types/node": "^20.10.4", + "typescript": "5.3.3" + } +} diff --git a/packages/common-hiveio-packages/src/hb-auth/hbauth-service.ts b/packages/common-hiveio-packages/src/hb-auth/hbauth-service.ts new file mode 100644 index 000000000..dc0ffb0c8 --- /dev/null +++ b/packages/common-hiveio-packages/src/hb-auth/hbauth-service.ts @@ -0,0 +1,121 @@ +import { OnlineClient, ClientOptions, OfflineClient } from '@hiveio/hb-auth'; +import { siteConfig } from '@hive/ui/config/site'; + +import { getLogger } from '@hive/ui/lib/logging'; +import { configuredSessionTime } from '@hive/ui/config/public-vars'; +import env from '@beam-australia/react-env'; + +const logger = getLogger('app'); + +// Get the worker URL with proper basePath handling +const getWorkerUrl = (): string => { + // Only run in browser context + if (typeof window === 'undefined') { + return '/auth/worker.js'; + } + + const basePath = env('BASE_PATH') || ''; + + // For subdirectory deployments, construct the full URL to avoid path issues + if (basePath) { + // Use the current origin to construct an absolute URL + const origin = window.location.origin; + const workerUrl = `${origin}${basePath}/auth/worker.js`; + logger.debug('Worker URL (absolute) computed as: %s (basePath: %s)', workerUrl, basePath); + + return workerUrl; + } + + // For root deployments, use relative path + const workerUrl = '/auth/worker.js'; + logger.debug('Worker URL (relative) computed as: %s', workerUrl); + + return workerUrl; +}; + +const getDefaultClientOptions = (): ClientOptions => { + // I don't think this logic should be here, but for now it is easier to keep it. We have dedicated MemoryMixin (?) + let node: string | undefined = undefined; + // Check if user has selected a custom node in localStorage + if (typeof window === 'object' && window.localStorage) { + const storedNode = window.localStorage.getItem('node-endpoint'); + if (storedNode) { + try { + node = JSON.parse(storedNode); + } catch (err) { + logger.error('Error parsing stored node-endpoint from localStorage: %o', err); + } + } + } + + return { + sessionTimeout: Number(configuredSessionTime), + chainId: siteConfig.chainId, + node: node || siteConfig.endpoint, + workerUrl: getWorkerUrl() // This will be overridden in getOnlineClient + }; +}; + +let onlineClientPromise: Promise | undefined = undefined; +// This should be just a reference retrieved from the onlineClientPromise. +let onlineClient: OnlineClient | undefined = undefined; + +let offlineClientPromise: Promise | undefined = undefined; + +// This is intentionally non-async method as we don't want any race condition for onlineClientPromise !== undefined check +const setOnlineClient = (options: Partial = {}): Promise => { + const clientOptions = { + ...getDefaultClientOptions(), + ...options + }; + logger.info('Creating instance of HB-Auth OnlineClient with options: %o', clientOptions); + + onlineClientPromise = new OnlineClient(clientOptions).initialize(); + + return onlineClientPromise.then(client => onlineClient = client); +}; + +// This is intentionally non-async method as we don't want any race condition for offlineClientPromise !== undefined check +const setOfflineClient = (options: Partial = {}): Promise => { + const clientOptions = { + ...getDefaultClientOptions(), + ...options + }; + logger.info('Creating instance of HB-Auth OnlineClient with options: %o', clientOptions); + + offlineClientPromise = new OfflineClient(clientOptions).initialize(); + + return offlineClientPromise; +}; + +export const initOnlineClient = (): Promise => { + if (onlineClientPromise) + return onlineClientPromise; + + return setOnlineClient(); +} + +export const setOnlineClientRpcEndpoint = (newEndpoint: string): void => { + // Even though we are calling setOnlineClient again, we should ensure the call flow is correct (init first -> modify next) + if (!onlineClient) { + throw new Error('OnlineClient is not initialized yet. Call initOnlineClient() first.'); + } + + // XXX: This is breaking interface, but we should implement specific sync method in hb-auth to change endpointUrl as it + // can be changed without re-initialization of the entire hb-auth, just like here: + (onlineClient as any).hiveChain.api.endpointUrl = newEndpoint; +}; + +export const getOnlineClient = (): Promise => { + if (onlineClientPromise) + return onlineClientPromise; + + return setOnlineClient(); +}; + +export const getOfflineClient = (): Promise => { + if (offlineClientPromise) + return offlineClientPromise; + + return setOfflineClient(); +}; diff --git a/packages/common-hiveio-packages/src/hb-auth/index.ts b/packages/common-hiveio-packages/src/hb-auth/index.ts new file mode 100644 index 000000000..8d8d14562 --- /dev/null +++ b/packages/common-hiveio-packages/src/hb-auth/index.ts @@ -0,0 +1 @@ +export * from "./hbauth-service"; diff --git a/packages/common-hiveio-packages/src/index.ts b/packages/common-hiveio-packages/src/index.ts new file mode 100644 index 000000000..553975ea4 --- /dev/null +++ b/packages/common-hiveio-packages/src/index.ts @@ -0,0 +1,2 @@ +export * from "./wax"; +export * from "./hb-auth"; diff --git a/packages/common-hiveio-packages/src/wax/app-types.ts b/packages/common-hiveio-packages/src/wax/app-types.ts new file mode 100644 index 000000000..cf1a059ed --- /dev/null +++ b/packages/common-hiveio-packages/src/wax/app-types.ts @@ -0,0 +1,86 @@ +import { ApiAccount } from '@hiveio/wax'; +import { authority, asset } from '@hiveio/wax'; + +export type ExpApiAccount = ApiAccount; +export interface AccountProfile { + about?: string; + cover_image?: string; + location?: string; + blacklist_description?: string; + muted_list_description?: string; + name?: string; + profile_image?: string; + website?: string; + pinned?: string; + witness_description?: string; + witness_owner?: string; +} +export interface AccountFollowStats { + follower_count: number; + following_count: number; + account: string; +} +export interface FullAccount { + vesting_balance: string | asset; + name: string; + owner: authority; + active: authority; + posting: authority; + memo_key: string; + post_count: number; + created: string; + reputation: string | number; + json_metadata: string; + posting_json_metadata: string; + last_vote_time: string; + last_post: string; + reward_hbd_balance: string; + reward_vesting_hive: string; + reward_hive_balance: string; + reward_vesting_balance: string; + governance_vote_expiration_ts: string; + balance: string; + vesting_shares: string; + hbd_balance: string; + savings_balance: string; + savings_hbd_balance: string; + savings_hbd_seconds: string; + savings_hbd_last_interest_payment: string; + savings_hbd_seconds_last_update: string; + next_vesting_withdrawal: string; + delegated_vesting_shares: string; + received_vesting_shares: string; + vesting_withdraw_rate: string; + to_withdraw: number; + withdrawn: number; + witness_votes: string[]; + proxy: string; + proxied_vsf_votes: number[] | string[]; + voting_manabar: { + current_mana: string | number; + last_update_time: number; + }; + voting_power: number; + downvote_manabar: { + current_mana: string | number; + last_update_time: number; + }; + profile?: AccountProfile; + follow_stats?: AccountFollowStats; + __loaded?: true; + proxyVotes?: Array; + // Temporary properties for UI purposes + _temporary?: boolean; +} + +export interface Beneficiarie { + account: string; + weight: number; +} + +export interface Preferences { + nsfw: 'hide' | 'warn' | 'show'; + blog_rewards: '0%' | '50%' | '100%'; + comment_rewards: '0%' | '50%' | '100%'; + referral_system: 'enabled' | 'disabled'; +} diff --git a/packages/common-hiveio-packages/src/wax/extended-hive.chain.ts b/packages/common-hiveio-packages/src/wax/extended-hive.chain.ts new file mode 100644 index 000000000..70e7de42f --- /dev/null +++ b/packages/common-hiveio-packages/src/wax/extended-hive.chain.ts @@ -0,0 +1,1151 @@ +import { + TWaxApiRequest, + RcAccount, + GetDynamicGlobalPropertiesResponse, + GetDynamicGlobalPropertiesRequest, + type asset as AssetType, + NaiAsset, + transaction +} from '@hiveio/wax'; +import { AccountFollowStats, FullAccount } from './app-types'; + +export interface SearchType { + pattern: string; + sort?: string; + author?: string; + limit?: number; + observer?: string; + start_author?: string; + start_permlink?: string; +} + +export interface EntryBeneficiaryRoute { + account: string; + weight: number; +} + +export interface EntryVote { + voter: string; + rshares: number; +} + +export interface EntryStat { + flag_weight: number; + gray: boolean; + hide: boolean; + total_votes: number; + is_pinned?: boolean; + // added only when using optimistic update, not backend property + _temporary?: boolean; +} +export interface IFollowList { + name: string; + blacklist_description: string; + muted_list_description: string; + //added only when using optimistic update, not backend property + _temporary?: boolean; +} +export interface Entry { + active_votes: EntryVote[]; + author: string; + author_payout_value: string; + author_reputation: number; + author_role?: string; + author_title?: string; + beneficiaries: EntryBeneficiaryRoute[]; + blacklists: string[]; + body: string; + category: string; + children: number; + community?: string; + community_title?: string; + created: string; + total_votes?: number; + curator_payout_value: string; + depth: number; + is_paidout: boolean; + json_metadata: JsonMetadata; + max_accepted_payout: string; + net_rshares: number; + parent_author?: string; + parent_permlink?: string; + payout: number; + payout_at: string; + pending_payout_value: string; + percent_hbd: number; + permlink: string; + post_id: number; + id?: number; + promoted: string; + reblogged_by?: string[]; + replies: Array; + stats?: EntryStat; + title: string; + updated: string; + url: string; + original_entry?: Entry; + //added only when using optimistic update, not backend property + _temporary?: boolean; +} + +export interface JsonMetadata { + image: string; + links?: string[]; + flow?: { + pictures: { + caption: string; + id: number; + mime: string; + name: string; + tags: string[]; + url: string; + }[]; + tags: string[]; + }; + images: string[]; + author: string | undefined; + tags?: string[]; + description?: string | null; + app?: string; + canonical_url?: string; + format?: string; + original_author?: string; + original_permlink?: string; + summary?: string; +} + +export interface Community { + about: string; + admins?: string[]; + avatar_url: string; + created_at: string; + description: string; + flag_text: string; + id: number; + is_nsfw: boolean; + lang: string; + name: string; + num_authors: number; + num_pending: number; + subscribers: number; + sum_pending: number; + settings?: object; + team: string[][]; + title: string; + type_id: number; + context: { + role: string; + subscribed: Boolean; + title: string; + // added only when using optimistic update, not backend property + _temporary?: boolean; + }; + // added only when using optimistic update, not backend property + _temporary?: boolean; +} + +export interface JsonMetadata { + image: string; + links?: string[]; + flow?: { + pictures: { + caption: string; + id: number; + mime: string; + name: string; + tags: string[]; + url: string; + }[]; + tags: string[]; + }; + images: string[]; + author: string | undefined; + tags?: string[]; + description?: string | null; + app?: string; + canonical_url?: string; + format?: string; + original_author?: string; + original_permlink?: string; + summary?: string; +} + +export type FollowListType = 'follow_blacklist' | 'followed_muted_lists' | 'blacklisted' | 'muted'; + +export interface IMarketStatistics { + hbd_volume: string; + highest_bid: string; + hive_volume: string; + latest: string; + lowest_ask: string; + percent_change: string; +} + +export interface IWitness { + created: string; + id: number; + total_missed: number; + url: string; + props: { + account_creation_fee: string; + account_subsidy_budget: number; + maximum_block_size: number; + }; + hbd_exchange_rate: { + base: string; + quote: string; + }; + available_witness_account_subsidies: number; + running_version: string; + owner: string; + signing_key: string; + last_hbd_exchange_update: string; + votes: number; + last_confirmed_block_num: number; +} + +export interface IOrdersDataItem { + created: string; + hbd: number; + hive: number; + order_price: { + base: string; + quote: string; + }; + real_price: string; +} +export interface IOrdersData { + bids: IOrdersDataItem[]; + asks: IOrdersDataItem[]; + trading: IOrdersDataItem[]; +} + +export interface IOpenOrdersData { + id: number; + created: string; + expiration: string; + seller: string; + orderid: number; + for_sale: number; + sell_price: { + base: string; + quote: string; + }; + real_price: string; + rewarded: boolean; +} + +export interface IRecentTradesData { + date: string; + current_pays: string; + open_pays: string; +} + +export type OwnerHistory = { + account: string; + id: number; + last_valid_time: string; + previous_owner_authority: { + account_auths: unknown[]; + key_auths: [string, number][]; + weight_threshold: number; + }; +}[]; + +export interface IGetProposalsParams { + start: Array; + limit: number; + order: 'by_creator' | 'by_total_votes' | 'by_start_date' | 'by_end_date'; + order_direction: 'descending' | 'ascending'; + status: 'all' | 'inactive' | 'active' | 'votable' | 'expired'; + last_id?: number; +} + +export interface IProposal { + creator: string; + daily_pay: { + amount: string; + nai: string; + precision: number; + }; + end_date: string; + id: number; + permlink: string; + proposal_id: number; + receiver: string; + start_date: string; + status: string; + subject: string; + total_votes: string; +} + +export type SavingsWithdrawals = { + withdrawals: { + amount: AssetType; + complete: Date; + from: string; + id: number; + memo: string; + request_id: number; + to: string; + }[]; +}; + +export interface IPost { + active_votes: { + rshares: number; + voter: string; + }; + author: string; + author_payout_value: string; + author_reputation: number; + author_role: string; + author_title: string; + beneficiaries: Array; + blacklists: Array; + body: string; + category: string; + children: number; + community: string; + community_title: string; + created: string; + curator_payout_value: string; + depth: number; + is_paidout: boolean; + json_metadata: { + app: string; + description: string; + format: string; + image: [string]; + tags: string[]; + users: Array; + }; + max_accepted_payout: string; + net_rshares: number; + payout: number; + payout_at: string; + pending_payout_value: string; + percent_hbd: number; + permlink: string; + post_id: number; + promoted: string; + replies: Array; + stats: { + flag_weight: number; + gray: boolean; + hide: boolean; + total_votes: number; + }; + title: string; + updated: string; + url: string; +} + +export interface IVote { + percent: number; + reputation: number; + rshares: number; + time: string; + timestamp?: number; + voter: string; + weight: number; + reward?: number; +} + +export interface BlogEntry { + blog: string; + entry_id: number; + author: string; + permlink: string; + reblogged_on: string; +} + +export interface IWitnessSchedule { + id: number; + current_virtual_time: string; + next_shuffle_block_num: number; + current_shuffled_witnesses: string[]; + num_scheduled_witnesses: number; + top19_weight: number; + timeshare_weight: number; + miner_weight: number; + witness_pay_normalization_factor: number; + median_props: { + account_creation_fee: string; + maximum_block_size: number; + hbd_interest_rate: number; + }; + majority_version: string; + max_voted_witnesses: number; + max_miner_witnesses: number; + max_runner_witnesses: number; + hardfork_required_witnesses: number; +} + +export interface IFeedHistory { + current_median_history: { + base: NaiAsset; + quote: NaiAsset; + }; + price_history: [ + { + base: NaiAsset; + quote: NaiAsset; + } + ]; +} + +export interface IRewardFund { + recent_claims: string; + reward_balance: string; +} + +export interface WithdrawRoute { + auto_vest: boolean; + from_account: string; + id: number; + percent: number; + to_account: string; +} + +export interface IConversionRequest { + amount: string; + conversion_date: string; + id: number; + owner: string; + requestid: number; +} + +export interface SavingsWithdrawRequest { + id: number; + from: string; + to: string; + memo: string; + request_id: number; + amount: string; + complete: string; +} + +export class VerifySignaturesParams { + hash!: string; + signatures!: string[]; + required_other!: string[]; + required_active!: string[]; + required_owner!: string[]; + required_posting!: string[]; +} + +export class VerifySignaturesResponse { + public valid!: boolean; +} + +export interface IDelegatedVestingShare { + id: number; + delegatee: string; + delegator: string; + min_delegation_time: string; + vesting_shares: string; +} + +export type OpType = + | 'claim_reward_balance_operation' + | 'transfer_operation' + | 'transfer_from_savings_operation' + | 'transfer_to_savings_operation' + | 'interest_operation' + | 'cancel_transfer_from_savings_operation' + | 'fill_order_operation' + | 'transfer_to_vesting_operation' + | 'curation_reward_operation' + | 'author_reward_operation' + | 'producer_reward_operation' + | 'comment_reward_operation' + | 'comment_benefactor_reward_operation' + | 'interest_operation' + | 'proposal_pay_operation' + | 'sps_fund_operation' + | 'transfer_operation' + | 'withdraw_vesting_operation'; + +export type IAuthorReward = { + author: string; + curators_vesting_payout: string; + hbd_payout: string; + hive_payout: string; + payout_must_be_claimed: boolean; + permlink: string; + vesting_payout: string; + author_rewards?: string; + beneficiary_payout_value?: string; + curator_payout_value?: string; + payout?: string; + reward?: string; + total_payout_value?: string; + curator?: string; +}; +export type ICurationReward = { + author_rewards: string; + beneficiary_payout_value: string; + curator_payout_value: string; + payout: string; + total_payout_value: string; + reward: string; + curator: string; + author?: string; + curators_vesting_payout?: string; + hbd_payout?: string; + hive_payout?: string; + payout_must_be_claimed?: boolean; + permlink?: string; + vesting_payout?: string; +}; + +export interface HiveOperation { + block: number; + trx_id: string | null; + op_pos: number; + op_type_id: number; + timestamp: Date; + virtual_op: boolean; + operation_id: number; + trx_in_block: number; + op: { + type: string; + value: { + open_pays?: NaiAsset; + current_pays?: NaiAsset; + owner?: string; + is_saved_into_hbd_balance?: boolean; + interest: NaiAsset; + request_id?: number; + amount?: NaiAsset; + from?: string; + memo?: string; + to?: string; + account?: string; + reward_hbd?: NaiAsset; + reward_hive?: NaiAsset; + reward_vests?: NaiAsset; + vesting_shares?: string; + author?: string; + producer?: string; + curator?: string; + seller?: string; + permlink?: string; + voter?: string; + weight?: number; + body?: string; + json_metadata?: string; + parent_author?: string; + parent_permlink?: string; + title?: string; + required_posting_auths?: string[]; + required_auths?: string[]; + id?: string; + json?: string; + message?: string; + 'org-op-id'?: string; + perspective?: 'incoming' | 'outgoing'; + current_owner?: string; + reward: NaiAsset; + vesting_payout: NaiAsset; + hbd_payout: NaiAsset; + hive_payout: NaiAsset; + }; + }; +} + +export type AccountRewardsHistory = [ + number, + { + trx_id: string; + block: number; + trx_in_block: number; + op_in_trx: number; + virtual_op: boolean; + timestamp: string; + op: ['author_reward' | 'curation_reward', IAuthorReward | ICurationReward]; + } +]; + +export interface IProposalVote { + id: number; + proposal: IProposal; + voter: string; +} + +export interface IDynamicGlobalProperties { + hbd_print_rate: number; + total_vesting_fund_hive: string; + total_vesting_shares: string; + hbd_interest_rate: number; + head_block_number: number; + head_block_id: string; + vesting_reward_percent: number; + virtual_supply: string; +} + +export interface IAccountReputations { + account: string; + reputation: number; +} + +export interface IMarketCandlestickDataItem { + hive: { + high: number; + low: number; + open: number; + close: number; + volume: number; + }; + id: number; + non_hive: { + high: number; + low: number; + open: number; + close: number; + volume: number; + }; + open: string; + seconds: number; +} + +export interface ITrendingTag { + comments: number; + name: string; + top_posts: number; + total_payouts: string; +} + +export interface IFollow { + follower: string; + following: string; + what: string[]; + //added only when using optimistic update, not backend property + _temporary?: boolean; +} + +export interface ICollateralizedConversionRequest { + collateral_amount: string; + conversion_date: string; + converted_amount: string; + id: number; + owner: string; + requestid: number; +} + +interface IWitnessVote { + id: number; + witness: string; + account: string; +} + +export interface IListWitnessVotes { + votes: IWitnessVote[]; +} + +export interface IVoteListItem { + id: number; + voter: string; + author: string; + permlink: string; + weight: string; + rshares: number; + vote_percent: number; + last_update: string; + num_changes: number; + // added only when using optimistic update, not backend property + _temporary: boolean; +} + +export interface IAccountNotification { + date: string; + id?: number; + msg: string; + score: number; + type: string; + url: string; +} + +export interface IGetPostHeader { + author: string; + permlink: string; + category: string; + depth: number; +} + +export interface IAccountRelationship { + follows: boolean; + ignores: boolean; + is_blacklisted: boolean; + follows_blacklists: boolean; +} + +export interface IUnreadNotifications { + lastread: string; + unread: number; +} + +export interface EntryBeneficiaryRoute { + account: string; + weight: number; +} + +export interface EntryVote { + voter: string; + rshares: number; +} + +export interface EntryStat { + flag_weight: number; + gray: boolean; + hide: boolean; + total_votes: number; + is_pinned?: boolean; +} + +export type Badge = { + name: string; + state: string; + type: string; + id: string; + title: string; + url: string; +}; + +export interface PostsSearchParams { + q: string; + truncate?: number; + result_limit?: number; + full_posts?: number; + observer?: string; +} + +export interface PostsSimilarParams { + author: string; + permlink: string; + truncate?: number; + result_limit?: number; + full_posts?: number; + observer?: string; +} + +export interface PostsByIdsParams { + posts: Array<{ author: string; permlink: string }>; + truncate?: number; + observer?: string; +} + +export interface SimilarPostsParams { + author: string; + permlink: string; + truncate?: number; + result_limit?: number; + full_posts?: number; + observer?: string; +} + +// Stub entry type for posts with only author/permlink +export interface PostStub { + author: string; + permlink: string; +} + +// Mixed response type for new API endpoints +export type MixedPostsResponse = Array; + +export interface ApiTag { + description: string; + name: string; +} + +export interface HivesenseStatusResponse { + externalDocs: { + description: string; + url: string; + }; + info: { + description: string; + title: string; + version: string; + license: { + name: string; + url: string; + }; + }; + paths: unknown; + servers: string[]; + tags: ApiTag[]; +} + +export interface IDirectDelegation { + rc_direct_delegations: { + delegated_rc: number; + from: string; + to: string; + }[]; +} +export interface GetOperationsByAccountParams { + 'account-name'?: string; + 'observer-name'?: string; + 'operation-types'?: string; + page?: number; + 'page-size'?: number; + 'data-size-limit'?: number; + 'from-block'?: string; + 'to-block'?: string; +} + +export interface IGetOperationsByAccountResponse { + total_operations: number; + total_pages: number; + block_range: { + from: number; + to: number; + }; + operations_result: HiveOperation[]; +} + +export type ExtendedNodeApi = { + bridge: { + get_post_header: TWaxApiRequest<{ author: string; permlink: string }, IGetPostHeader>; + get_ranked_posts: TWaxApiRequest< + { + sort: string; + tag: string; + start_author: string; + start_permlink: string; + limit: number; + observer: string; + }, + Entry[] | null + >; + get_account_posts: TWaxApiRequest< + { + sort: string; + account: string; + start_author: string; + start_permlink: string; + limit: number; + observer: string; + }, + Entry[] | null + >; + get_post: TWaxApiRequest<{ author: string; permlink: string; observer: string }, Entry | null>; + account_notifications: TWaxApiRequest< + { account: string; lastId?: number; limit: number }, + IAccountNotification[] | null + >; + get_discussion: TWaxApiRequest< + { author: string; permlink: string; observer?: string }, + Record | null + >; + get_community: TWaxApiRequest<{ name: string; observer?: string }, Community | null>; + list_community_roles: TWaxApiRequest<{ community: string }, string[][] | null>; + list_communities: TWaxApiRequest< + { sort: string; query?: string | null; observer: string }, + Community[] | null + >; + normalize_post: TWaxApiRequest<{ post: Entry }, Entry | null>; + list_all_subscriptions: TWaxApiRequest<{ account: string }, string[][] | null>; + list_subscribers: TWaxApiRequest<{ community: string }, string[][] | null>; + unread_notifications: TWaxApiRequest<{ account: string }, IUnreadNotifications | null>; + get_relationship_between_accounts: TWaxApiRequest; + get_follow_list: TWaxApiRequest<{ observer: string; follow_type: FollowListType }, IFollowList[]>; + }; + condenser_api: { + get_witnesses_by_vote: TWaxApiRequest<(string | number)[], IWitness[]>; + get_ticker: TWaxApiRequest; + get_order_book: TWaxApiRequest; + get_open_orders: TWaxApiRequest; + get_trade_history: TWaxApiRequest<(string | number)[], IOrdersDataItem[]>; + get_recent_trades: TWaxApiRequest; + get_owner_history: TWaxApiRequest; + get_follow_count: TWaxApiRequest; + get_content: TWaxApiRequest; + get_market_history_buckets: TWaxApiRequest; + get_active_votes: TWaxApiRequest; + get_blog_entries: TWaxApiRequest<(string | number)[], BlogEntry[]>; + get_reblogged_by: TWaxApiRequest<[string, string], string[]>; + get_witness_schedule: TWaxApiRequest<[], IWitnessSchedule>; + get_vesting_delegations: TWaxApiRequest<(string | number)[], IDelegatedVestingShare[]>; + list_proposal_votes: TWaxApiRequest<(string | number | (string | number)[])[], IProposalVote[]>; + get_dynamic_global_properties: TWaxApiRequest<[], IDynamicGlobalProperties>; + get_accounts: TWaxApiRequest<[string[]], FullAccount[]>; + get_account_reputations: TWaxApiRequest< + { + account_lower_bound: string; + limit: number; + }, + IAccountReputations[] + >; + get_market_history: TWaxApiRequest<(string | number)[], IMarketCandlestickDataItem[]>; + get_followers: TWaxApiRequest<(string | number | null)[], IFollow[]>; + get_following: TWaxApiRequest<(string | number | null)[], IFollow[]>; + }; + rc_api: { + find_rc_accounts: TWaxApiRequest; + list_rc_direct_delegations: TWaxApiRequest<{ limit: number; start: [string, string] }, IDirectDelegation>; + }; + database_api: { + list_proposals: TWaxApiRequest, { proposals: IProposal[] }>; + find_savings_withdrawals: TWaxApiRequest<{ account: string }, SavingsWithdrawals>; + get_dynamic_global_properties: TWaxApiRequest< + GetDynamicGlobalPropertiesRequest, + GetDynamicGlobalPropertiesResponse + >; + get_feed_history: TWaxApiRequest; + lookup_accounts: TWaxApiRequest<(string | number)[], string[]>; + get_reward_fund: TWaxApiRequest; + get_withdraw_routes: TWaxApiRequest; + get_conversion_requests: TWaxApiRequest; + get_savings_withdraw_from: TWaxApiRequest; + verify_signatures: { + params: VerifySignaturesParams; + result: VerifySignaturesResponse; + }; + get_trending_tags: TWaxApiRequest<(string | number)[], ITrendingTag[]>; + get_collateralized_conversion_requests: TWaxApiRequest; + list_witness_votes: TWaxApiRequest<{ start: string[]; limit: number; order: string }, IListWitnessVotes>; + list_votes: TWaxApiRequest< + { + start: [string, string, string] | null; + limit: number; + order: 'by_comment_voter' | 'by_voter_comment'; + }, + { votes: IVoteListItem[] } + >; + }; + network_broadcast_api: { + broadcast_transaction: TWaxApiRequest; + }; + 'search-api': { + find_text: TWaxApiRequest; + }; +}; + +type TEmptyReq = {}; +export interface HivesenseEndpointsPostsSearchParams { + /** Search query text for semantic similarity, e.g. `"vector databases"` */ + q: string; + /** + * Body truncation length (0 = full content, >0 = truncate to N chars) + * @default 0 + */ + truncate?: number; + /** + * Total number of posts (full + stub) to return + * @min 1 + * @max 1000 + * @default 100 + */ + result_limit?: number; + /** + * How many of the top results should include full post data + * @min 0 + * @max 50 + * @default 10 + */ + full_posts?: number; + /** + * Hive account whose mute lists etc. will be respected + * @default "" + */ + observer?: string; +} + +export interface HivesenseEndpointsPostsSimilarParams { + /** + * Controls the length of returned post bodies in the results. When set to 0, + * returns complete post content. Any other positive value will truncate the + * post body to that many characters. Useful for generating previews or + * reducing response size. Maximum value is 65535 characters. + * @min 0 + * @max 65535 + * @default 0 + * @example 20 + */ + truncate?: number; + /** + * Total number of posts (full + stub) to return. Must be between + * 1 and 1000. The posts are returned in order of similarity, with the most + * similar posts first. Setting a lower limit can improve response times + * and reduce data transfer. + * @min 1 + * @max 1000 + * @default 100 + * @example 100 + */ + result_limit?: number; + /** + * How many of the top results should include full post data. Any + * remaining posts (up to result_limit) will be stub entries with only + * author & permlink. Set this to the size of your first page of results. + * @min 0 + * @max 50 + * @default 10 + * @example 10 + */ + full_posts?: number; + /** + * Optional Hive account name with blacklists that will be used to filter the + * results. When provided, any posts from authors in the observer + * blacklist will be excluded from the results. Leave empty to disable + * blacklist filtering. Useful for content moderation and personalization. + * @default "" + * @example "hive.blog" + */ + observer?: string; + /** + * The Hive username of the post author. This is the account name that + * created the original post for which you want to find similar content. + * Must be a valid Hive account name. + * @example "bue-witness" + */ + author: string; + /** + * The unique permlink identifier of the post. This is the URL-friendly + * version of the post title that appears in the post URL on Hive. + * Together with the author name, it uniquely identifies the post. + * @example "my-blog-post" + */ + permlink: string; +} + +export interface HivesenseEndpointsAuthorsSearchParams { + /** + * Topic or theme to search for. Authors whose posts are semantically related to this topic will be returned. + * @example "Make witness node secure against hackers attack and emergency situations" + */ + topic: string; + /** + * Maximum number of authors to return (1-100). + * @min 1 + * @max 100 + * @default 10 + * @example 10 + */ + result_limit?: number; + /** + * Observer (hive account name) whose settings (such as muted lists) are used to filter out excluded posts from the search results + * @default "" + */ + observer?: string; +} + +export interface HivesenseEndpointsPostsByIdsPayload { + /** + * Array of post identifiers. Each item must have both 'author' + * and 'permlink' fields. Maximum 50 posts per request. + * @maxItems 50 + * @minItems 1 + * @example [{"author":"bue-witness","permlink":"my-first-post"},{"author":"another-user","permlink":"interesting-topic"}] + */ + posts: { + /** The Hive username of the post author */ + author: string; + /** The unique permlink identifier of the post */ + permlink: string; + }[]; + /** + * Body truncation length. 0 returns full content, positive values + * truncate to N characters. Useful for preview mode. + * @min 0 + * @max 65535 + * @default 0 + */ + truncate?: number; + /** + * Optional Hive account whose mute lists and blacklists will be + * applied to filter results. Leave empty to disable filtering. + * @default "" + */ + observer?: string; +} + +export interface HivesenseEndpointsPostsByIdsQueryParams { + /** + * URL-encoded JSON array of post identifiers. Each object must have + * 'author' and 'permlink' fields. Maximum 10 posts for GET requests. + * @example "[{"author":"bue-witness","permlink":"my-post"}]" + */ + posts: string; + /** + * Body truncation length (0 = full content) + * @min 0 + * @max 65535 + * @default 0 + */ + truncate?: number; + /** + * Optional Hive account for filtering + * @default "" + */ + observer?: string; +} + +export interface HiveOpTypeSchema { + op_type_id: number; + operation_name: string; + is_virtual: boolean; +} + +export type ExtendedRestApi = { + 'hivesense-api': { + params: undefined; + result: HivesenseStatusResponse; + posts: { + search: { + result: MixedPostsResponse; + params: HivesenseEndpointsPostsSearchParams & TEmptyReq & {}; + }; + author: { + permlink: { + similar: { + result: Entry[]; + params: HivesenseEndpointsPostsSimilarParams & + TEmptyReq & { + /** The Hive username of the post author. This is the account name that +created the original post for which you want to find similar content. +Must be a valid Hive account name. + */ + author: string; + + /** The unique permlink identifier of the post. This is the URL-friendly +version of the post title that appears in the post URL on Hive. +Together with the author name, it uniquely identifies the post. + */ + permlink: string; + }; + }; + }; + }; + byIds: { + result: Entry[]; + params: TEmptyReq & HivesenseEndpointsPostsByIdsPayload & {}; + }; + byIdsQuery: { + result: string; + params: HivesenseEndpointsPostsByIdsQueryParams & TEmptyReq & {}; + }; + }; + authors: { + search: { + result: string; + params: HivesenseEndpointsAuthorsSearchParams & TEmptyReq & {}; + }; + }; + }; + 'hivemind-api': { + accountsOperations: { + params: GetOperationsByAccountParams; + result: IGetOperationsByAccountResponse; + }; + }; + 'hafah-api': { + 'operation-types': { + params: undefined; + result: HiveOpTypeSchema[]; + }; + }; +}; diff --git a/packages/common-hiveio-packages/src/wax/hive-chain-service.ts b/packages/common-hiveio-packages/src/wax/hive-chain-service.ts new file mode 100644 index 000000000..6461bf56a --- /dev/null +++ b/packages/common-hiveio-packages/src/wax/hive-chain-service.ts @@ -0,0 +1,193 @@ +import { createHiveChain, IWaxOptionsChain, TWaxExtended, TWaxRestExtended } from '@hiveio/wax'; +import { siteConfig } from '@hive/ui/config/site'; // Maybe move this to package specific only to config +import { ExtendedNodeApi, ExtendedRestApi } from './extended-hive.chain'; +import { setOnlineClientRpcEndpoint as setHbAuthRpcEndoint } from '../hb-auth/hbauth-service'; +import { getLogger } from '@hive/ui/lib/logging'; + +export type HiveChain = TWaxExtended>; + +const logger = getLogger('wax'); + +const getDefaultClientOptions = (): IWaxOptionsChain => { + // I don't think this logic should be here, but for now it is easier to keep it. We have dedicated MemoryMixin (?) + let jsonRpcNode: string | undefined = undefined; + let restNode: string | undefined = undefined; + // Check if user has selected a custom node in localStorage + if (typeof window === 'object' && window.localStorage) { + const storedJsonRpcEndpoint = window.localStorage.getItem('node-endpoint'); + if (storedJsonRpcEndpoint) { + try { + jsonRpcNode = JSON.parse(storedJsonRpcEndpoint); + } catch (err) { + logger.error('Error parsing stored node-endpoint from localStorage: %o', err); + } + } + + const storedRestEndpoint = window.localStorage.getItem('rest-node-endpoint'); + if (storedRestEndpoint) { + try { + restNode = JSON.parse(storedRestEndpoint); + } catch (err) { + logger.error('Error parsing stored rest-node-endpoint from localStorage: %o', err); + } + } + } + + return { + chainId: siteConfig.chainId, + apiEndpoint: jsonRpcNode || siteConfig.endpoint, + apiTimeout: 5_000, // To be adjusted + restApiEndpoint: restNode || jsonRpcNode || siteConfig.endpoint, + }; +}; + +const getAIDefaultEndpoint = (): string | undefined => { + if (typeof window === 'object' && window.localStorage) { + const storedJsonRpcNode = window.localStorage.getItem('ai-search-endpoint'); + if (storedJsonRpcNode) { + try { + return JSON.parse(storedJsonRpcNode); + } catch (err) { + logger.error('Error parsing stored ai-search-endpoint from localStorage: %o', err); + } + } + } + + return undefined; +}; + +let hiveChainPromise: Promise | undefined = undefined; +// This should be just a reference retrieved from the hiveChainPromise. +let hiveChain: HiveChain | undefined = undefined; + +export const setRpcEndpoint = (newEndpoint: string): void => { + logger.info('Changing chain.api.endpointUrl with newEndpoint: %o', newEndpoint); + + // We should ensure the call flow is correct (init first -> modify next) + if (!hiveChain) { + throw new Error('Wax Chain is not initialized yet. Call initChain() first.'); + } + + setHbAuthRpcEndoint(newEndpoint); + hiveChain.api.endpointUrl = newEndpoint; + + window.localStorage.setItem('node-endpoint', JSON.stringify(newEndpoint)); +}; + +export const setRestApiEndpoint = (newEndpoint: string): void => { + logger.info('Changing chain.restApi.endpointUrl with newEndpoint: %o', newEndpoint); + + // We should ensure the call flow is correct (init first -> modify next) + if (!hiveChain) { + throw new Error('Wax Chain is not initialized yet. Call initChain() first.'); + } + + hiveChain.restApi.endpointUrl = newEndpoint; + window.localStorage.setItem('rest-node-endpoint', JSON.stringify(newEndpoint)); +}; + +export const setAiEndpoint = (newEndpoint: string): void => { + logger.info('Changing chain.restApi["hivesense-api"].endpointUrl with newEndpoint: %o', newEndpoint); + + // We should ensure the call flow is correct (init first -> modify next) + if (!hiveChain) { + throw new Error('Wax Chain is not initialized yet. Call initChain() first.'); + } + + // Always use the same endpoint as the main API for hivesense-api + hiveChain.restApi['hivesense-api'].endpointUrl = newEndpoint; + hiveChain.api['search-api'].find_text.endpointUrl = newEndpoint; + + window.localStorage.setItem('ai-search-endpoint', JSON.stringify(newEndpoint)); +}; + +// This is intentionally non-async method as we don't want any race condition for hiveChainPromise !== undefined check +const setChainClient = (options: Partial = {}): Promise => { + const clientOptions = { + ...getDefaultClientOptions(), + ...options + }; + logger.info('Creating instance of Wax Chain with options: %o', clientOptions); + + hiveChainPromise = createHiveChain(clientOptions).then((hiveChainInitialized) => { + const extended = hiveChainInitialized.extend().extendRest({ + 'hivesense-api': { + posts: { + urlPath: "posts", + search: { + urlPath: "search", + method: "GET" + }, + author: { + urlPath: "{author}", + permlink: { + urlPath: "{permlink}", + similar: { + urlPath: "similar", + method: "GET" + } + } + }, + byIds: { + urlPath: "by-ids", + method: "POST" + }, + byIdsQuery: { + urlPath: "by-ids-query", + method: "GET" + } + }, + authors: { + urlPath: "authors", + search: { + urlPath: "search", + method: "GET" + } + }, + }, + method: "GET", + 'hivemind-api': { + "accountsOperations": { + urlPath: 'accounts/{account-name}/operations', + } + }, + 'hafah-api': { + 'operation-types': { + urlPath: 'operation-types' + } + } + }); + + hiveChain = extended; + + const aiEndpoint = getAIDefaultEndpoint(); + + // Always use the same endpoint as the main API for hivesense-api + hiveChain.restApi['hivesense-api'].endpointUrl = aiEndpoint || clientOptions.restApiEndpoint; + if (aiEndpoint) { + hiveChain.api['search-api'].find_text.endpointUrl = aiEndpoint; + } + + return hiveChain; + }); + + return hiveChainPromise; +}; + +export const initChain = (): Promise => { + if (hiveChainPromise) + return hiveChainPromise; + + return setChainClient(); +} + +export const reuseHiveChain = (): HiveChain | undefined => { + return hiveChain; +}; + +export const getChain = (): Promise => { + if (hiveChainPromise) + return hiveChainPromise; + + return initChain(); +}; diff --git a/packages/common-hiveio-packages/src/wax/index.ts b/packages/common-hiveio-packages/src/wax/index.ts new file mode 100644 index 000000000..4a795fb97 --- /dev/null +++ b/packages/common-hiveio-packages/src/wax/index.ts @@ -0,0 +1,3 @@ +export * from "./app-types"; +export * from "./extended-hive.chain"; +export * from "./hive-chain-service"; diff --git a/packages/common-hiveio-packages/tsconfig.json b/packages/common-hiveio-packages/tsconfig.json new file mode 100644 index 000000000..167fd46b2 --- /dev/null +++ b/packages/common-hiveio-packages/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@hive/tsconfig/base.json", + "compilerOptions": { + "baseUrl": ".", + "paths": {} + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/middleware/lib/auth-proof-cookie.ts b/packages/middleware/lib/auth-proof-cookie.ts index fe66ede6c..89af8f16a 100644 --- a/packages/middleware/lib/auth-proof-cookie.ts +++ b/packages/middleware/lib/auth-proof-cookie.ts @@ -17,7 +17,7 @@ async function initializeWasm() { try { // Dynamic import to avoid Edge Runtime issues - const waxModule = await import('@hiveio/wax'); + const waxModule = await import('@hiveio/wax');// XXX: Analyze if we can somehow move this import to common-hiveio-packages wax = await waxModule.createHiveChain(); custom_json = waxModule.custom_json; logger.debug('WASM authProofLoggermodules loaded successfully'); diff --git a/packages/smart-signer/components/auth/methods/safestorage-key-update.tsx b/packages/smart-signer/components/auth/methods/safestorage-key-update.tsx index ba832dbc7..45a421cad 100644 --- a/packages/smart-signer/components/auth/methods/safestorage-key-update.tsx +++ b/packages/smart-signer/components/auth/methods/safestorage-key-update.tsx @@ -59,7 +59,7 @@ function getFormSchema() { isStrict: z.boolean().default(false) }) .superRefine((val, ctx) => { - const result = validateWifKey(val.wif, (v: string) => v); + const result = validateWifKey(val.wif); if (result) { ctx.addIssue({ code: z.ZodIssueCode.custom, diff --git a/packages/smart-signer/components/auth/methods/safestorage.tsx b/packages/smart-signer/components/auth/methods/safestorage.tsx index 617472db8..c988673ce 100644 --- a/packages/smart-signer/components/auth/methods/safestorage.tsx +++ b/packages/smart-signer/components/auth/methods/safestorage.tsx @@ -52,7 +52,7 @@ function getFormSchema() { }) .superRefine((val, ctx) => { if (!val.userFound) { - const result = validateWifKey(val.wif, (v) => v); + const result = validateWifKey(val.wif); if (result) { ctx.addIssue({ code: z.ZodIssueCode.custom, diff --git a/packages/smart-signer/components/login-form.tsx b/packages/smart-signer/components/login-form.tsx index 9b35af913..d46dd06c0 100644 --- a/packages/smart-signer/components/login-form.tsx +++ b/packages/smart-signer/components/login-form.tsx @@ -23,7 +23,7 @@ type ZodLoginTypeEnum = z.infer; const passwordField = z.object({ password: z.string().superRefine((val, ctx) => { - const result = validateWifKey(val, (v) => v); + const result = validateWifKey(val); if (result) { ctx.addIssue({ code: z.ZodIssueCode.custom, diff --git a/packages/smart-signer/components/password-form.tsx b/packages/smart-signer/components/password-form.tsx index 2475b3d91..abbfe98e8 100644 --- a/packages/smart-signer/components/password-form.tsx +++ b/packages/smart-signer/components/password-form.tsx @@ -29,7 +29,7 @@ export const passwordFormDefaultValuesHbauth = { // Wif password export const passwordWif = z.string().superRefine((val, ctx) => { - const result = validateWifKey(val, (v) => v); + const result = validateWifKey(val); if (result) { ctx.addIssue({ code: z.ZodIssueCode.custom, diff --git a/packages/smart-signer/lib/api-handlers/auth/login.ts b/packages/smart-signer/lib/api-handlers/auth/login.ts index d5e205377..aa964e331 100644 --- a/packages/smart-signer/lib/api-handlers/auth/login.ts +++ b/packages/smart-signer/lib/api-handlers/auth/login.ts @@ -60,7 +60,7 @@ export const loginUser: NextApiHandler = async (req, res) => { // swallow error } } else { - result = verifyLoginChallenge(chainAccount, signatures, JSON.stringify({ loginChallenge })); + result = await verifyLoginChallenge(chainAccount, signatures, JSON.stringify({ loginChallenge })); } if (!result) { diff --git a/packages/smart-signer/lib/hbauth-service.ts b/packages/smart-signer/lib/hbauth-service.ts index e9eb968c0..71d64de72 100644 --- a/packages/smart-signer/lib/hbauth-service.ts +++ b/packages/smart-signer/lib/hbauth-service.ts @@ -1,101 +1,14 @@ -import { OnlineClient, ClientOptions } from '@hiveio/hb-auth'; -import { siteConfig } from '@ui/config/site'; -import { StorageMixin, StorageBase, StorageBaseOptions } from '@smart-signer/lib/storage-mixin'; +import type { OnlineClient } from '@hiveio/hb-auth'; -import { getLogger } from '@hive/ui/lib/logging'; -import { configuredSessionTime } from '@ui/config/public-vars'; -import env from '@beam-australia/react-env'; - -const logger = getLogger('app'); - -// Get the worker URL with proper basePath handling -const getWorkerUrl = (): string => { - // Only run in browser context - if (typeof window === 'undefined') { - return '/auth/worker.js'; - } - - const basePath = env('BASE_PATH') || ''; - - // For subdirectory deployments, construct the full URL to avoid path issues - if (basePath) { - // Use the current origin to construct an absolute URL - const origin = window.location.origin; - const workerUrl = `${origin}${basePath}/auth/worker.js`; - logger.debug('Worker URL (absolute) computed as: %s (basePath: %s)', workerUrl, basePath); - return workerUrl; - } - - // For root deployments, use relative path - const workerUrl = '/auth/worker.js'; - logger.debug('Worker URL (relative) computed as: %s', workerUrl); - return workerUrl; -}; - -const defaultClientOptions: ClientOptions = { - sessionTimeout: Number(configuredSessionTime), - chainId: 'beeab0de00000000000000000000000000000000000000000000000000000000', - node: 'https://api.hive.blog', - workerUrl: '/auth/worker.js' // This will be overridden in getOnlineClient -}; - -class HbauthService extends StorageMixin(StorageBase) { - static onlineClient: OnlineClient; - - /** - * Pending promise, returning Hbauth OnlineCLient. Intended for - * awaiting by any requests arrived when it is pending. - * - * @type {(Promise | null)} - * @memberof HbauthService - */ - onlineClientPromise: Promise | null; - - constructor(options: StorageBaseOptions) { - super(options); - this.onlineClientPromise = null; - } +import { getOnlineClient } from "@hive/common-hiveio-packages"; +class HbauthService { async getOnlineClient(): Promise { - if (!HbauthService.onlineClient) { - // If we have pending promise, return its result. - if (this.onlineClientPromise) return await this.onlineClientPromise; - - // If we haven't pending promise. let's create one. - const promise = async () => { - const storedNode = this.storage.getItem('node-endpoint'); - let node: string = storedNode ? JSON.parse(storedNode) : ''; - if (!node) { - node = siteConfig.endpoint; - } - // Set promise result in this class' static property and return - // it here as well. - await this.setOnlineClient({ - node, - chainId: siteConfig.chainId, - workerUrl: getWorkerUrl() // Use dynamic worker URL with basePath - }); - return HbauthService.onlineClient; - }; - - // Set promise to pending. - this.onlineClientPromise = promise(); - // Return the result of pending promise. - return await this.onlineClientPromise; - } - // If we have not empty existing static property, just return it. - // logger.info('Returning existing instance of HbauthService.onlineClient'); - return HbauthService.onlineClient; + return await getOnlineClient(); } - - async setOnlineClient(options: Partial) { - const clientOptions = { - ...defaultClientOptions, - ...options - }; - logger.info('Creating instance of HbauthService.onlineClient with options: %o', clientOptions); - HbauthService.onlineClient = await new OnlineClient(clientOptions).initialize(); + async getOfflineClient(): Promise { + return await getOnlineClient(); } } -export const hbauthService = new HbauthService({ storageType: 'localStorage' }); +export const hbauthService = new HbauthService(); diff --git a/packages/smart-signer/lib/hive-auth-utils.ts b/packages/smart-signer/lib/hive-auth-utils.ts index 021524294..529d513cb 100644 --- a/packages/smart-signer/lib/hive-auth-utils.ts +++ b/packages/smart-signer/lib/hive-auth-utils.ts @@ -1,6 +1,5 @@ import QRCode from 'qrcode'; import { HasClient } from 'hive-auth-client'; -import { Signature, HexBuffer, cryptoUtils, PublicKey } from '@hiveio/dhive'; import { getLogger } from '@hive/ui/lib/logging'; const logger = getLogger('app'); @@ -81,35 +80,6 @@ const setKey = (key: string) => { auth.key = key; }; -// const isLoggedInWithHiveAuth = () => { -// if (!isLoggedIn()) { -// return false; -// } - -// const now = new Date().getTime(); -// const data = localStorage.getItem('autopost2'); -// const [,,,,,,,, login_with_hiveauth, hiveauth_key, hiveauth_token, hiveauth_token_expires] = extractLoginData(data); -// return !!login_with_hiveauth -// && !!hiveauth_key -// && !!hiveauth_token -// && now < hiveauth_token_expires; -// }; - -const verifyChallenge = ( - challenge: string | Buffer, - data: { challenge: string | Buffer | HexBuffer | number[]; pubkey: string | PublicKey } -) => { - // Validate signature against account public key - - // TODO We should get public key from Hive blockchain and validate - // against it. We shouldn't trust pubkey coming in data! - - const sig = Signature.fromString(HexBuffer.from(data.challenge).toString()); - const buf = cryptoUtils.sha256(challenge); - const publicKey = PublicKey.from(data.pubkey); - return publicKey.verify(buf, sig); -}; - const updateModalMessage = (message: string) => { const instructionsContainer = document.getElementById('hiveauth-instructions'); if (instructionsContainer) { @@ -355,28 +325,16 @@ const login = async ( auth.expire = expire; logger.info('Hive Auth: user has approved the auth request', { challengeResponse, message, auth }); - const verified = verifyChallenge(challenge, challengeResponse); - - if (verified) { - logger.info('Hive Auth: challenge succeeded'); - callbackFn({ - success: true, - hiveAuthData: { - key: auth.key, - token, - expire, - uuid, - challengeHex: challengeResponse.challenge - } - }); - } else { - logger.error('Hive Auth: challenge failed'); - clearLoginInstructions(); - callbackFn({ - success: false, - error: translateFn('hiveauthservices.challengeValidationFailed') - }); - } + callbackFn({ + success: true, + hiveAuthData: { + key: auth.key, + token, + expire, + uuid, + challengeHex: challengeResponse.challenge + } + }); removeEventHandlers(); }; diff --git a/packages/smart-signer/lib/signer/get-signer.ts b/packages/smart-signer/lib/signer/get-signer.ts index e40561338..79544d042 100644 --- a/packages/smart-signer/lib/signer/get-signer.ts +++ b/packages/smart-signer/lib/signer/get-signer.ts @@ -17,21 +17,17 @@ registeredSigners[LoginType.hiveauth] = SignerHiveauth; registeredSigners[LoginType.keychain] = SignerKeychain; registeredSigners[LoginType.wif] = SignerWif; -export function signerFactory({ +function signerFactory({ username, loginType, keyType, - apiEndpoint, storageType, - chainId }: SignerOptions): SignerTool { return new registeredSigners[loginType]({ username, loginType, keyType, - apiEndpoint, storageType, - chainId }) as SignerTool; } @@ -45,9 +41,7 @@ export function signerFactory({ * 2. [Keychain](https://hive-keychain.com/), handled in SignerKeychain * class. * 3. [Hiveauth](https://hiveauth.com/), handled in SignerHiveauthclass. - * 4. So known "Wif" custom tool, based on - * [@hiveio/dhive](https://openhive-network.github.io/dhive/) and - * browser's localStorage, handled in SignerWif class. + * 4. So known "Wif" custom tool * * @export * @param {SignerOptions} options diff --git a/packages/smart-signer/lib/signer/signer-hbauth.ts b/packages/smart-signer/lib/signer/signer-hbauth.ts index 4313d975b..b816b1cab 100644 --- a/packages/smart-signer/lib/signer/signer-hbauth.ts +++ b/packages/smart-signer/lib/signer/signer-hbauth.ts @@ -1,6 +1,5 @@ -import { cryptoUtils } from '@hiveio/dhive'; import { hbauthService } from '@smart-signer/lib/hbauth-service'; -import { AuthStatus, KeyAuthorityType } from '@hiveio/hb-auth'; +import type { AuthStatus, KeyAuthorityType, OfflineClient, OnlineClient } from '@hiveio/hb-auth'; import { SignChallenge, SignTransaction, Signer, SignerOptions } from '@smart-signer/lib/signer/signer'; import { THexString, TTransactionPackType } from '@hiveio/wax'; import { PasswordDialogModalPromise } from '@smart-signer/components/password-dialog'; @@ -30,16 +29,27 @@ export class SignerHbauth extends Signer { */ passwordPromise: Promise | null; + get hbAuthClient(): Promise { + return hbauthService.getOnlineClient(); + } + constructor(signerOptions: SignerOptions, pack: TTransactionPackType = TTransactionPackType.HF_26) { super(signerOptions, pack); this.passwordPromise = null; } async destroy() { - const authClient = await hbauthService.getOnlineClient(); + const authClient = await this.hbAuthClient; await authClient.logout(this.username); } + protected getPasswordPromise(passwordFormOptions: PasswordFormOptions): Promise<{ password: string }> { + return PasswordDialogModalPromise({ + isOpen: true, + passwordFormOptions + }); + } + /** * Displays dialog and asks user to enter password for unlocking * wallet. @@ -58,10 +68,7 @@ export class SignerHbauth extends Signer { try { if (!this.passwordPromise) { - this.passwordPromise = PasswordDialogModalPromise({ - isOpen: true, - passwordFormOptions - }); + this.passwordPromise = this.getPasswordPromise(passwordFormOptions); } const { password } = await this.passwordPromise; return password; @@ -76,8 +83,14 @@ export class SignerHbauth extends Signer { singleSignKeyType?: KeyAuthorityType, requiredKeyType?: KeyAuthorityType ): Promise { - const digest = cryptoUtils.sha256(message).toString('hex'); - return this.signDigest(digest, password, singleSignKeyType, requiredKeyType); + // TODO: Temporary solution to remove legacy d hive crypto (using native solutions). But eventually we should remove this function + const msgUint8 = typeof message === "string" ? new TextEncoder().encode(message) : new Uint8Array(message as ArrayBuffer); // encode as (utf-8) ArrayBuffer | ArrayBufferView + const hashBuffer = await crypto.subtle.digest("SHA-256", msgUint8); // hash the message + const hashHex = Array.from(new Uint8Array(hashBuffer)) + .map(b => b.toString(16).padStart(2, '0')) + .join(''); // Convert ArrayBuffer to hex string. + + return this.signDigest(hashHex, password, singleSignKeyType, requiredKeyType); } async signTransaction({ digest, transaction, singleSignKeyType, requiredKeyType }: SignTransaction) { @@ -108,7 +121,7 @@ export class SignerHbauth extends Signer { throw new Error(`Unsupported keyType: ${keyType}`); } - const authClient = await hbauthService.getOnlineClient(); + const authClient = await this.hbAuthClient; const checkAuthResult = await this.checkAuth(username, keyType); if (!checkAuthResult) { @@ -194,7 +207,7 @@ export class SignerHbauth extends Signer { } async checkAuth(username: string, keyType: string): Promise { - const authClient = await hbauthService.getOnlineClient(); + const authClient = await this.hbAuthClient; const auths = await authClient.getRegisteredUsers(); logger.info('auths in safe storage %o', auths); const auth = await authClient.getRegisteredUserByUsername(username); @@ -238,7 +251,7 @@ export class SignerHbauth extends Signer { digest: string, password: string ): Promise { - const authClient = await hbauthService.getOnlineClient(); + const authClient = await this.hbAuthClient; const auths = await authClient.getRegisteredUserByUsername(username); if (!auths) throw new Error('User not found'); diff --git a/packages/smart-signer/lib/signer/signer-hiveauth.ts b/packages/smart-signer/lib/signer/signer-hiveauth.ts index eb181512b..ff57913fe 100644 --- a/packages/smart-signer/lib/signer/signer-hiveauth.ts +++ b/packages/smart-signer/lib/signer/signer-hiveauth.ts @@ -14,7 +14,7 @@ const logger = getLogger('app'); * * @export * @class SignerHiveauth - * @extends {StorageMixin(SignerHbauth)} + * @extends {StorageMixin(SignerKeychain)} */ export class SignerHiveauth extends StorageMixin(SignerKeychain) { diff --git a/packages/smart-signer/lib/signer/signer-keychain.ts b/packages/smart-signer/lib/signer/signer-keychain.ts index 24802823b..5d967828b 100644 --- a/packages/smart-signer/lib/signer/signer-keychain.ts +++ b/packages/smart-signer/lib/signer/signer-keychain.ts @@ -1,4 +1,3 @@ -import { KeychainSDK, KeychainKeyTypes } from 'keychain-sdk'; import { SignChallenge, SignTransaction, Signer, SignerOptions } from '@smart-signer/lib/signer/signer'; import { TTransactionPackType, IOnlineSignatureProvider } from '@hiveio/wax'; import KeychainProvider from '@hiveio/wax-signers-keychain'; @@ -7,7 +6,7 @@ import { getLogger } from '@hive/ui/lib/logging'; import { getChain } from '@transaction/lib/chain'; const logger = getLogger('app'); -// See https://github.com/hive-keychain/keychain-sdk +// See https://github.com/hive-keychain/hive-keychain-extension/blob/master/documentation/README.md#requestsignbuffer declare global { interface Window { @@ -39,24 +38,14 @@ export class SignerKeychain extends Signer { async signChallenge({ message }: SignChallenge): Promise { const { username, keyType } = this; logger.info('in SignerKeychain.signChallenge %o', { message, username, keyType }); - const keychain = new KeychainSDK(window, { rpc: this.apiEndpoint }); try { - if (!(await keychain.isKeychainInstalled())) { - throw new Error('Keychain is not installed'); - } - const response = await keychain.signBuffer({ - username, - message: typeof message === 'string' ? message : JSON.stringify(message), - method: KeychainKeyTypes[keyType] - }); - // There's not digest in response. - logger.info('SignerKeychain.signChallenge keychain response: %o', response); - if (response.error) { - throw new Error(`Error in SignerKeychain.SignerKeychain.signChallenge: ${response.error}`); - } - // TODO We can also return response.publicKey. This could be - // useful in signature's verification. - const signature = response.result as unknown as string; + const provider = KeychainProvider.for( + this.username, + "memo" + ); + + const signature = provider.encryptData(typeof message === "string" ? message : JSON.stringify(message), username); + logger.info('keychain', { signature }); return signature; } catch (error) { diff --git a/packages/smart-signer/lib/signer/signer-wif.ts b/packages/smart-signer/lib/signer/signer-wif.ts index 9189dbe5a..daffd23a9 100644 --- a/packages/smart-signer/lib/signer/signer-wif.ts +++ b/packages/smart-signer/lib/signer/signer-wif.ts @@ -1,69 +1,72 @@ -import { PrivateKey, cryptoUtils } from '@hiveio/dhive'; -import { SignChallenge, SignerOptions } from '@smart-signer/lib/signer/signer'; -import { KeyType } from '@smart-signer/types/common'; +import { SignerOptions } from '@smart-signer/lib/signer/signer'; import { SignerHbauth } from '@smart-signer/lib/signer/signer-hbauth'; -import { StorageMixin } from '@smart-signer/lib/storage-mixin'; -import { TTransactionPackType, THexString } from '@hiveio/wax'; -import { verifyPrivateKey } from '@smart-signer/lib/utils'; +import { TTransactionPackType, THexString, transaction } from '@hiveio/wax'; import { PasswordDialogModalPromise } from '@smart-signer/components/password-dialog'; import { PasswordFormMode, PasswordFormOptions } from '@smart-signer/components/password-form'; import { getLogger } from '@hive/ui/lib/logging'; +import { KeyAuthorityType } from '@hiveio/hb-auth'; +import { getChain } from '@hive/common-hiveio-packages'; + const logger = getLogger('app'); /** * Signs challenges (any strings or byte arrays) or Hive transactions - * with Hive private keys, using so known "Wif" custom tool, based on - * [@hiveio/dhive](https://openhive-network.github.io/dhive/) and Web - * Storage API. + * with Hive private keys. + * + * As we already have hb-auth, we can just reuse its beekeeper instance * * @export * @class SignerWif - * @extends {StorageMixin(Signer)} + * @extends {SignerHbauth} */ -export class SignerWif extends StorageMixin(SignerHbauth) { +export class SignerWif extends SignerHbauth { constructor(signerOptions: SignerOptions, pack: TTransactionPackType = TTransactionPackType.HF_26) { super(signerOptions, pack); } - async destroy() { - for (const k of Object.keys(KeyType)) { - const keyType = k as KeyType; - this.storage.removeItem(`wif.${this.username}@${KeyType[keyType]}`); + override async signDigest( + digest: THexString, + explicitPassword: string = '', + _singleSignKeyType?: KeyAuthorityType, + _requiredKeyType?: KeyAuthorityType + ) { + const { username, keyType } = this; + logger.info('signDigest #wif args: %o', { digest, username, keyType }); + + const validKeyTypes = ['posting', 'active', 'owner']; + if (!validKeyTypes.includes(keyType)) { + throw new Error(`Unsupported keyType: ${keyType}`); } - } - async signChallenge({ - message, - password = '' // WIF private key, - }: SignChallenge): Promise { - const digest: Buffer = cryptoUtils.sha256(message); - return this.signDigest(digest, password); - } + const authClient = await this.hbAuthClient; + if (!validKeyTypes.includes(this.keyType)) { + throw new Error(`Unsupported singleSignKeyType: ${this.keyType}`); + } - async signDigest(digest: THexString | Buffer, password: string) { - const { username, keyType } = this; - const args = { username, password, digest, keyType }; - logger.info('signDigest args: %o', args); try { - // Resolve WIF key - let wif = password ? password : JSON.parse(this.storage.getItem(`wif.${username}@${keyType}`) || '""'); - if (!wif) { + let wif = explicitPassword; + + const keyFromStorage = window.localStorage.getItem(this.storageKey); + if (keyFromStorage) + wif = JSON.parse(keyFromStorage); + + if (!wif) wif = await this.getPasswordFromUser(); - } - if (!wif) throw new Error('login_form.zod_error.no_wif_key'); - // Convert digest to Buffer, if it is string. - if (typeof digest === 'string') { - digest = Buffer.from(digest, 'hex'); - } + if (!wif) + throw new Error("Failed to parse private key from storage"); - // Sign digest - const privateKey = PrivateKey.fromString(wif); - const signature = privateKey.sign(digest).toString(); + const signature = await authClient.singleSign( + username, + digest, + wif, + this.keyType + ); return signature; } catch (error) { + logger.error('Error in single sign: %o', error); throw error; } } @@ -109,6 +112,10 @@ export class SignerWif extends StorageMixin(SignerHbauth) { } } + private get storageKey() { + return `wif.${this.username}@${this.keyType}`; + } + /** * Stores password (WIF key) in storage for future use. * @@ -116,12 +123,11 @@ export class SignerWif extends StorageMixin(SignerHbauth) { * @memberof SignerWif */ async storePassword(wif: '') { - const { username, keyType, apiEndpoint } = this; - const storageKey = `wif.${username}@${keyType}`; + const storageKey = this.storageKey; // Check if we have the same key already stored (means also already // verified). - const wifInStorage = this.storage.getItem(storageKey); + const wifInStorage = window.localStorage.getItem(storageKey); if (wifInStorage) { logger.info('Found key in storage under key: %s', storageKey); if (JSON.parse(wifInStorage) === wif) { @@ -138,7 +144,23 @@ export class SignerWif extends StorageMixin(SignerHbauth) { logger.info('Starting to verify wif'); let valid = false; try { - valid = await verifyPrivateKey(username, wif, keyType, apiEndpoint); + const wax = await getChain(); + + const tx = await wax.createTransaction(); + tx.pushOperation({ + custom_json_operation: { + id: 'test', + json: '{}', + required_auths: this.keyType === 'posting' ? [] : [this.username], + required_posting_auths: this.keyType === 'posting' ? [this.username] : [] + } + }); + const signature = await this.signDigest(tx.sigDigest, wif); + tx.addSignature(signature); + + const result = await wax.api.database_api.verify_authority({ pack: this.pack, trx: tx.toApiJson() }); + + valid = result.valid; } catch (error) { logger.error('Cannot verify private key: %o', error); throw error; @@ -150,7 +172,7 @@ export class SignerWif extends StorageMixin(SignerHbauth) { } // Store key if it is valid. - this.storage.setItem(storageKey, JSON.stringify(wif)); + window.localStorage.setItem(storageKey, JSON.stringify(wif)); logger.info('Stored valid wif under key: %s', storageKey); } diff --git a/packages/smart-signer/lib/signer/signer.ts b/packages/smart-signer/lib/signer/signer.ts index b109569a1..f0293f975 100644 --- a/packages/smart-signer/lib/signer/signer.ts +++ b/packages/smart-signer/lib/signer/signer.ts @@ -15,7 +15,7 @@ export interface SignTransaction { requiredKeyType?: 'owner' | 'active' | 'posting'; } export interface SignChallenge { - message: string | Buffer; + message: string | ArrayBufferView | ArrayBuffer; password?: string; // private key or password to unlock hbauth key translateFn?: (v: string) => string; } @@ -24,9 +24,7 @@ export interface SignerOptions { username: string; loginType: LoginType; keyType: KeyType; - apiEndpoint: string; storageType: StorageType; - chainId: string; authorityUsername?: string; } @@ -42,13 +40,11 @@ export abstract class Signer { username: string; loginType: LoginType; keyType: KeyType; - apiEndpoint: string; storageType: StorageType; pack: TTransactionPackType; - chainId: string; authorityUsername?: string; constructor( - { username, loginType, keyType, apiEndpoint, storageType, chainId }: SignerOptions, + { username, loginType, keyType, storageType }: SignerOptions, pack: TTransactionPackType ) { logger.info('Starting Signer constructor with options: %o and pack: %s', arguments[0], arguments[1]); @@ -72,21 +68,11 @@ export abstract class Signer { } else { throw new Error('Signer constructor: keyType must be non-empty string'); } - if (apiEndpoint) { - this.apiEndpoint = apiEndpoint; - } else { - throw new Error('Signer constructor: apiEndpoint must be non-empty string'); - } if (storageType) { this.storageType = storageType; } else { throw new Error('Signer constructor: storageType must be non-empty string'); } - if (chainId) { - this.chainId = chainId; - } else { - throw new Error('Signer constructor: chainId must be non-empty string'); - } } /** diff --git a/packages/smart-signer/lib/use-signer.ts b/packages/smart-signer/lib/use-signer.ts index 67ab29071..316d442cd 100644 --- a/packages/smart-signer/lib/use-signer.ts +++ b/packages/smart-signer/lib/use-signer.ts @@ -1,22 +1,14 @@ import { useUser } from '@smart-signer/lib/auth/use-user'; import { SignerOptions } from '@smart-signer/lib/signer/signer'; -import { useLocalStorage } from 'usehooks-ts'; -import { siteConfig } from '@ui/config/site'; export const useSigner = () => { const { user } = useUser(); const { username, loginType, keyType } = user; - const [apiEndpoint] = useLocalStorage( - 'node-endpoint', - siteConfig.endpoint - ); const signerOptions: SignerOptions = { username, loginType, keyType, - apiEndpoint, storageType: 'localStorage', - chainId: siteConfig.chainId, }; return { signerOptions }; }; diff --git a/packages/smart-signer/lib/utils.ts b/packages/smart-signer/lib/utils.ts index cf4753206..e4824759d 100644 --- a/packages/smart-signer/lib/utils.ts +++ b/packages/smart-signer/lib/utils.ts @@ -1,13 +1,4 @@ -import { operation, THexString, ITransaction, TWaxExtended } from '@hiveio/wax'; -import { fetchJson } from '@smart-signer/lib/fetch-json'; import { isBrowser } from '@ui/lib/logger'; -import { PrivateKey, cryptoUtils } from '@hiveio/dhive'; -import { KeyType } from '@smart-signer/types/common'; -import { getChain } from '@transaction/lib/chain'; -import { getLogger } from '@ui/lib/logging'; -import { VerifySignaturesParams, VerifySignaturesResponse } from '@hive/transaction/lib/extended-hive.chain'; - -const logger = getLogger('app'); const KEY_TYPES = ['active', 'posting'] as const; export type KeyAuthorityType = (typeof KEY_TYPES)[number]; @@ -66,169 +57,6 @@ export function isStorageAvailable( } } -/** - * Creates Hive blockchain transaction, if needed, and pushes - * operation into it, if it exists. Then calculates transaction's - * digest (cryptographic hash). - * - * @param {(operation | null)} [operation=null] - * @param {string} [txString=''] - * @param {*} [hiveApiUrl=this.hiveApiUrl] - * @returns {Promise<{txString: string, txApi: string, digest: - * THexString}>} - */ -export async function getTransactionDigest( - operation: operation | null = null, - txString: string = '', - hiveApiUrl = 'https://api.hive.blog' -): Promise<{ txString: string; digest: THexString }> { - const wax = await getChain(); - - let txBuilder: ITransaction; - if (txString) { - txBuilder = wax.createTransactionFromJson(JSON.parse(txString)); - } else { - // Create transaction, if it does not exist. - let dynamicGlobalProps: any; - try { - dynamicGlobalProps = await fetchJson(hiveApiUrl, { - method: 'post', - body: JSON.stringify({ - jsonrpc: '2.0', - method: 'database_api.get_dynamic_global_properties', - id: 1 - }) - }); - } catch (error) { - logger.error('Error in getTransactionDigest: %o', error); - throw error; - } - const { result: globalProps } = dynamicGlobalProps; - txBuilder = wax.createTransactionWithTaPoS(globalProps.head_block_id, '+1m'); - } - - // Pass operation to transaction, if it exists. - if (operation) { - txBuilder.pushOperation(operation); - } - - logger.info('tx.toString(): %s', txBuilder.toString()); - - return { - txString: txBuilder.toString(), - digest: txBuilder.sigDigest - }; -} - - -const DatabaseApiExtensions = { - database_api: { - verify_signatures: { - params: VerifySignaturesParams, - result: VerifySignaturesResponse - } - } -}; - -/** - * Verifies signature of transaction or only signature of digest. - * Uses "@hiveio/wax" package to create digest nad Hive API - * database_api.verify_signatures endpoint. - * - * @param {string} username - * @param {THexString} digest - * @param {string} signature - * @param {KeyAuthorityType} keyType - * @param {string} [txString=''] - * @param {*} [hiveApiUrl=this.hiveApiUrl] - * @returns {Promise} - */ -export async function verifySignature( - username: string, - digest: THexString, - signature: string, - keyType: KeyAuthorityType, - txString: string = '', - hiveApiUrl = 'https://api.hive.blog' -): Promise { - // Create transaction's digest and compare it with argument `digest`. - if (txString) { - const result = await getTransactionDigest(null, txString, hiveApiUrl); - if (result.digest !== digest) { - logger.info('Digest do not match'); - return false; - } - } - - const params: VerifySignaturesParams = { - hash: digest, - signatures: [signature], - required_other: [], - required_active: [], - required_owner: [], - required_posting: [] - }; - - if (keyType === 'posting') { - params.required_posting.push(username); - } else { - params.required_active.push(username); - } - - const hiveChain = await getChain(); - - const { valid } = await hiveChain.api.database_api.verify_signatures(params); - - if (!valid) { - logger.info('Signature is invalid'); - } - - return valid; -} - -export async function verifyPrivateKey( - username: string, - wif: string, - keyType: KeyType, - apiEndpoint: string, - strict: boolean = false -): Promise { - // Generate public key and sign random string. - const privateKey = PrivateKey.fromString(wif); - const digestBuf = cryptoUtils.sha256(crypto.randomUUID()); - const signature = privateKey.sign(digestBuf).toString(); - const publicKey = privateKey.createPublic('STM'); - logger.info('verifyPrivateKey generated public key: %s', publicKey.toString()); - - // Verify signature. - const valid: boolean = await verifySignature( - username, - digestBuf.toString('hex'), - signature, - keyType, - '', - apiEndpoint - ); - - // Return false when signature is not valid. - if (!valid) return valid; - // No other checks when `strict` is false. - if (!strict) return valid; - - // Check whether username directly signed the string. - const hiveChain = await getChain(); - - const [referencedAccounts] = ( - await hiveChain.api.account_by_key_api.get_key_references({ keys: [publicKey.toString()] }) - ).accounts; - logger.info('verifyPrivateKey referencedAccounts: %o', referencedAccounts); - if (referencedAccounts.includes(username)) { - return true; - } - - return false; -} - /** * Returns true if page is loaded in iframe, false otherwise. * diff --git a/packages/smart-signer/lib/validators/validate-wif-key.ts b/packages/smart-signer/lib/validators/validate-wif-key.ts index b933a05b8..5082aa469 100644 --- a/packages/smart-signer/lib/validators/validate-wif-key.ts +++ b/packages/smart-signer/lib/validators/validate-wif-key.ts @@ -1,23 +1,19 @@ -import { cryptoUtils } from '@hiveio/dhive'; +import { reuseHiveChain } from "@hive/common-hiveio-packages"; export function validateWifKey( password: string, - translateFn: (v: string) => string = (v) => v ): string | null { if (!password) { return 'WIF should not be empty.'; } - // A Hive generated password is a WIF prefixed with a P. - // It is possible to login directly with a WIF. - const wif = /^P/.test(password) ? password.substring(1) : password; - - if (!/^5[HJK].{45,}/i.test(wif)) { - // 51 is the wif length. - // TODO So why do we check for string length 47 or more? - return 'Invalid WIF format.'; - } - if (!cryptoUtils.isWif(wif)) { - return 'Invalid WIF checksum.'; + // XXX: Take this as a parameter + const hiveChain = reuseHiveChain(); + let validWif = false; + try { + validWif = !!hiveChain?.calculatePublicKey(password); + } catch {} + if (!validWif) { + return 'Invalid WIF key.'; } return null; } diff --git a/packages/smart-signer/lib/verify-login-challenge.ts b/packages/smart-signer/lib/verify-login-challenge.ts index 5cc52e23c..7b94386c2 100644 --- a/packages/smart-signer/lib/verify-login-challenge.ts +++ b/packages/smart-signer/lib/verify-login-challenge.ts @@ -17,7 +17,7 @@ const logger = getLogger('app'); * @param {('posting' | 'active')} [keyType='posting'] * @returns */ -export function verifyLoginChallenge( +export async function verifyLoginChallenge( chainAccount: FullAccount, signatures: Signatures, message: string = '', @@ -37,7 +37,7 @@ export function verifyLoginChallenge( ); } - return verifySignature( + return await verifySignature( signatures[keyType] || '', pubkey, message diff --git a/packages/smart-signer/lib/verify-signature.ts b/packages/smart-signer/lib/verify-signature.ts index c13ad87f5..a8d49c03f 100644 --- a/packages/smart-signer/lib/verify-signature.ts +++ b/packages/smart-signer/lib/verify-signature.ts @@ -1,8 +1,4 @@ -import { cryptoUtils, PublicKey, Signature } from '@hiveio/dhive'; - -import { getLogger } from '@hive/ui/lib/logging'; -const logger = getLogger('app'); - +import { getChain } from '@hive/common-hiveio-packages'; /** * Verify signature when you know message and algorithm used to hash @@ -10,23 +6,20 @@ const logger = getLogger('app'); * * @export * @param {string} signature - * @param {(string | PublicKey)} pubkey + * @param {(string)} pubkey * @param {string} message - * @param {('sha256' | 'doubleSha256' | 'ripemd160')} - * [hashFunction='sha256'] * @returns */ -export function verifySignature( +export async function verifySignature( signature: string, - pubkey: string | PublicKey, // take this from trusted party - message: string, // this string was signed - hashFunction: 'sha256' | 'doubleSha256' | 'ripemd160' = 'sha256' + pubkey: string, + message: string, ) { if (!signature) return false; - const hashFn = cryptoUtils[hashFunction]; - const messageHash = hashFn(message); - const sig = Signature.fromString(signature); - const publicKey = PublicKey.from(pubkey); - const verified = publicKey.verify(messageHash, sig); - return verified; + + const wax = await getChain(); + + const pkDeduced = wax.getPublicKeyFromSignature(message, signature); + + return pkDeduced === pubkey; }; diff --git a/packages/smart-signer/package.json b/packages/smart-signer/package.json index 23e1f2db1..df71037af 100644 --- a/packages/smart-signer/package.json +++ b/packages/smart-signer/package.json @@ -7,8 +7,8 @@ "lint": "eslint ." }, "dependencies": { + "@hive/common-hiveio-packages": "workspace:*", "@hive/ui": "workspace:*", - "@hiveio/dhive": "^1.3.0", "@hiveio/hb-auth": "catalog:hiveio-toolset", "@hiveio/wax": "catalog:hiveio-toolset", "@hiveio/wax-signers-keychain": "catalog:hiveio-toolset", @@ -18,7 +18,6 @@ "hive-auth-client": "^0.1.5", "http-errors": "^2.0.0", "iron-session": "^8.0.1", - "keychain-sdk": "^0.6.1", "next": "^14.2.5", "oidc-provider": "^8.4.2", "qrcode": "^1.5.3", diff --git a/packages/transaction/lib/app-types.ts b/packages/transaction/lib/app-types.ts index cf1a059ed..367a14902 100644 --- a/packages/transaction/lib/app-types.ts +++ b/packages/transaction/lib/app-types.ts @@ -1,3 +1,5 @@ +// TODO: Next iteration - Remove this file and change references to @hive/common-hiveio-packages + import { ApiAccount } from '@hiveio/wax'; import { authority, asset } from '@hiveio/wax'; diff --git a/packages/transaction/lib/chain.ts b/packages/transaction/lib/chain.ts index 36b6fe6a3..7eb1f0789 100644 --- a/packages/transaction/lib/chain.ts +++ b/packages/transaction/lib/chain.ts @@ -3,6 +3,7 @@ import { getHiveChainService } from './hive-chain-service'; import { TWaxExtended, TWaxRestExtended } from '@hiveio/wax'; import { wrapChainWithLogging } from './chain-proxy'; import pLimit from 'p-limit'; +import type { HiveChain } from '@hive/common-hiveio-packages'; let chain: TWaxExtended> | undefined = undefined; @@ -12,7 +13,7 @@ let chain: TWaxExtended> | un // out of bounds" errors. const wasmLock = pLimit(1); -export async function getChain() { +export async function getChain(): Promise { return wasmLock(async () => { if (!chain) { const service = getHiveChainService(); diff --git a/packages/transaction/lib/extended-hive.chain.ts b/packages/transaction/lib/extended-hive.chain.ts index fa13bac1e..b26223ed6 100644 --- a/packages/transaction/lib/extended-hive.chain.ts +++ b/packages/transaction/lib/extended-hive.chain.ts @@ -1,3 +1,5 @@ +// TODO: Next iteration - Remove this file and change references to @hive/common-hiveio-packages + import { TWaxApiRequest, RcAccount, @@ -8,7 +10,16 @@ import { transaction } from '@hiveio/wax'; import { AccountFollowStats, FullAccount } from './app-types'; -import { SearchType } from './hive-api'; + +export interface SearchType { + pattern: string; + sort?: string; + author?: string; + limit?: number; + observer?: string; + start_author?: string; + start_permlink?: string; +} export interface EntryBeneficiaryRoute { account: string; diff --git a/packages/transaction/lib/hive-api.ts b/packages/transaction/lib/hive-api.ts index 9b7e3ab1a..5b1f3399e 100644 --- a/packages/transaction/lib/hive-api.ts +++ b/packages/transaction/lib/hive-api.ts @@ -290,7 +290,8 @@ export const getByText = async ({ observer, start_author = '', start_permlink = '' -}: SearchType): Promise => { +}: Parameters>['api']['search-api']['find_text']>[0] // Temporary solution +): Promise => { return (await getChain()).api['search-api'].find_text({ pattern, sort, @@ -301,15 +302,6 @@ export const getByText = async ({ start_permlink }); }; -export interface SearchType { - pattern: string; - sort?: string; - author?: string; - limit?: number; - observer?: string; - start_author?: string; - start_permlink?: string; -} export const getActiveVotes = async (author: string, permlink: string): Promise => { return (await getChain()).api.condenser_api.get_active_votes([author, permlink]); diff --git a/packages/transaction/lib/hive-chain-service.ts b/packages/transaction/lib/hive-chain-service.ts index 22cf42ab0..262371a6a 100644 --- a/packages/transaction/lib/hive-chain-service.ts +++ b/packages/transaction/lib/hive-chain-service.ts @@ -1,160 +1,22 @@ -import { createHiveChain, IWaxOptionsChain, TWaxExtended, TWaxRestExtended } from '@hiveio/wax'; -import { siteConfig } from '@ui/config/site'; -import { StorageType, StorageBaseOptions } from '@smart-signer/lib/storage-mixin'; -import { isStorageAvailable } from '@smart-signer/lib/utils'; -import { memoryStorage } from '@smart-signer/lib/memory-storage'; -import { getLogger } from '@ui/lib/logging'; -import { ExtendedNodeApi, ExtendedRestApi } from './extended-hive.chain'; -import { hbauthService } from '@smart-signer/lib/hbauth-service'; +import { getChain, reuseHiveChain, HiveChain, setAiEndpoint, setRpcEndpoint } from "@hive/common-hiveio-packages"; -const logger = getLogger('app'); - -export type HiveChain = TWaxExtended>; +export type { HiveChain }; export class HiveChainService { - static hiveChain: HiveChain; - - storage: Storage; - storageType: StorageType; - - /** - * Pending promise, returning Hbauth OnlineCLient. Intended for - * awaiting by any requests arrived when it is pending. - * - * @type {(Promise> | null)} - * @memberof HiveChainService - */ - hiveChainPromise: Promise | null; - - constructor({ storageType = 'localStorage' }: StorageBaseOptions) { - this.hiveChainPromise = null; - this.storageType = storageType; - - // SSR-safe: check if running in browser before accessing window - if (typeof window === 'undefined') { - // Server-side: always use memoryStorage - this.storageType = 'memoryStorage'; - this.storage = memoryStorage; - } else { - // Client-side: check storage availability - if (this.storageType === 'localStorage' && isStorageAvailable(this.storageType, true)) { - this.storage = window.localStorage; - } else if (this.storageType === 'sessionStorage' && isStorageAvailable(this.storageType, true)) { - this.storage = window.sessionStorage; - } else { - this.storageType = 'memoryStorage'; - this.storage = memoryStorage; - } - } + public getHiveChain(): Promise { + return getChain(); } - async getHiveChain(): Promise { - if (!HiveChainService.hiveChain) { - // If we have pending promise, return its result. - if (this.hiveChainPromise) return await this.hiveChainPromise; - - // If we haven't pending promise, let's create one. - const promise = async () => { - const storedApiEndpoint = this.storage.getItem('node-endpoint'); - let apiEndpoint: string = storedApiEndpoint ? JSON.parse(storedApiEndpoint) : ''; - if (!apiEndpoint) { - apiEndpoint = siteConfig.endpoint; - } - // Set promise result in this class' static property and return - // it here as well. - await this.setHiveChain({ apiEndpoint, chainId: siteConfig.chainId, restApiEndpoint: apiEndpoint }); - return HiveChainService.hiveChain; - }; - - // Set promise to pending. - this.hiveChainPromise = promise(); - // Return the result of pending promise. - return await this.hiveChainPromise; - } - // If we have not empty existing static property, just return it. - // logger.info('Returning existing instance of HiveChainService.HiveChain'); - return HiveChainService.hiveChain; + public reuseHiveChain(): HiveChain | undefined { + return reuseHiveChain(); } - reuseHiveChain(): HiveChain | undefined{ - if (HiveChainService.hiveChain) return HiveChainService.hiveChain; - return undefined; + public async setHiveChainEndpoint(newEndpoint: string) { + setRpcEndpoint(newEndpoint); } - async setHiveChain(options?: Partial) { - logger.info('Creating instance of HiveChainService.hiveChain with options: %o', options); - const hiveChain = await createHiveChain(options); - HiveChainService.hiveChain = hiveChain.extend().extendRest({ - 'hivesense-api': { - posts: { - urlPath: "posts", - search: { - urlPath: "search", - method: "GET" - }, - author: { - urlPath: "{author}", - permlink: { - urlPath: "{permlink}", - similar: { - urlPath: "similar", - method: "GET" - } - } - }, - byIds: { - urlPath: "by-ids", - method: "POST" - }, - byIdsQuery: { - urlPath: "by-ids-query", - method: "GET" - } - }, - authors: { - urlPath: "authors", - search: { - urlPath: "search", - method: "GET" - } - }, - }, - method: "GET", - 'hivemind-api': { - "accountsOperations": { - urlPath: 'accounts/{account-name}/operations', - } - }, - 'hafah-api': { - 'operation-types': { - urlPath: 'operation-types' - } - } - }); - const storedAiSearchEndpoint = this.storage.getItem('ai-search-endpoint'); - let apiEndpoint: string = storedAiSearchEndpoint ? JSON.parse(storedAiSearchEndpoint) : ''; - if (!apiEndpoint) { - apiEndpoint = siteConfig.endpoint; - } - // Always use the same endpoint as the main API for hivesense-api - HiveChainService.hiveChain.restApi['hivesense-api'].endpointUrl = apiEndpoint || siteConfig.endpoint; - if (storedAiSearchEndpoint) { - HiveChainService.hiveChain.api['search-api'].find_text.endpointUrl = apiEndpoint; - } - } - - async setHiveChainEndpoint(newEndpoint: string) { - logger.info('Changing HiveChainService.HiveChain.endpointUrl with newEndpoint: %o', newEndpoint); - HiveChainService.hiveChain.endpointUrl = newEndpoint; - this.storage.setItem('node-endpoint', JSON.stringify(newEndpoint)); - await hbauthService.setOnlineClient({ node: newEndpoint }); - } - - async setAiSearchEndpoint(newEndpoint: string) { - logger.info('Changing AI search with newEndpoint: %o', newEndpoint); - HiveChainService.hiveChain.restApi['hivesense-api'].endpointUrl = newEndpoint; - HiveChainService.hiveChain.api['search-api'].find_text.endpointUrl = newEndpoint; - this.storage.setItem('ai-search-endpoint', JSON.stringify(newEndpoint)); + public async setAiSearchEndpoint(newEndpoint: string) { + setAiEndpoint(newEndpoint); } } @@ -165,17 +27,13 @@ let _hiveChainServiceInstance: HiveChainService | undefined; * Get or create HiveChainService instance. * SSR-safe: Creates instance with appropriate storage based on environment. * - * @param options - Optional storage type override * @returns HiveChainService instance */ -export function getHiveChainService(options?: StorageBaseOptions): HiveChainService { +export function getHiveChainService(): HiveChainService { if (!_hiveChainServiceInstance) { - // Determine storage type based on environment - const storageType = - typeof window === 'undefined' ? 'memoryStorage' : options?.storageType || 'localStorage'; - - _hiveChainServiceInstance = new HiveChainService({ storageType }); + _hiveChainServiceInstance = new HiveChainService(); } + return _hiveChainServiceInstance; } diff --git a/packages/transaction/package.json b/packages/transaction/package.json index ab2603183..82e10f16e 100644 --- a/packages/transaction/package.json +++ b/packages/transaction/package.json @@ -7,6 +7,8 @@ "lint": "eslint ." }, "dependencies": { + "bs58": "6.0.0", + "@hive/common-hiveio-packages": "workspace:*", "@hive/smart-signer": "workspace:*", "@hiveio/wax": "catalog:hiveio-toolset", "@hiveio/workerbee": "catalog:hiveio-toolset", @@ -16,7 +18,6 @@ "speakingurl": "^14.0.1" }, "devDependencies": { - "@types/bs58": "^4.0.4", "@types/node": "^20.10.4", "@types/secure-random": "^1.1.3", "@types/speakingurl": "^13.0.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3d68b04b..f5c7f2c88 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -351,6 +351,25 @@ importers: specifier: 5.3.3 version: 5.3.3 + packages/common-hiveio-packages: + dependencies: + '@hive/ui': + specifier: workspace:* + version: link:../ui + '@hiveio/hb-auth': + specifier: catalog:hiveio-toolset + version: 1.28.4-rc0 + '@hiveio/wax': + specifier: 1.28.4-rc0-251216100519 + version: 1.28.4-rc0-251216100519 + devDependencies: + '@types/node': + specifier: ^20.10.4 + version: 20.14.10 + typescript: + specifier: 5.3.3 + version: 5.3.3 + packages/eslint-config-custom: dependencies: '@hive/prettier-config-custom': @@ -563,12 +582,12 @@ importers: packages/smart-signer: dependencies: + '@hive/common-hiveio-packages': + specifier: workspace:* + version: link:../common-hiveio-packages '@hive/ui': specifier: workspace:* version: link:../ui - '@hiveio/dhive': - specifier: ^1.3.0 - version: 1.3.2 '@hiveio/hb-auth': specifier: catalog:hiveio-toolset version: 1.28.4-rc0 @@ -596,9 +615,6 @@ importers: iron-session: specifier: ^8.0.1 version: 8.0.4 - keychain-sdk: - specifier: ^0.6.1 - version: 0.6.2 next: specifier: ^14.2.5 version: 14.2.23(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.0(react@18.3.0))(react@18.3.0) @@ -672,6 +688,9 @@ importers: packages/transaction: dependencies: + '@hive/common-hiveio-packages': + specifier: workspace:* + version: link:../common-hiveio-packages '@hive/smart-signer': specifier: workspace:* version: link:../smart-signer @@ -681,6 +700,9 @@ importers: '@hiveio/workerbee': specifier: catalog:hiveio-toolset version: 1.28.4-rc0 + bs58: + specifier: 6.0.0 + version: 6.0.0 p-limit: specifier: ^3.1.0 version: 3.1.0 @@ -694,9 +716,6 @@ importers: specifier: ^14.0.1 version: 14.0.1 devDependencies: - '@types/bs58': - specifier: ^4.0.4 - version: 4.0.4 '@types/node': specifier: ^20.10.4 version: 20.10.4 @@ -1524,10 +1543,6 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@colors/colors@1.6.0': - resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} - engines: {node: '>=0.1.90'} - '@commitlint/cli@19.3.0': resolution: {integrity: sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g==} engines: {node: '>=v18'} @@ -1629,9 +1644,6 @@ packages: resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} engines: {node: '>=18'} - '@dabh/diagnostics@2.0.3': - resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} - '@devexpress/bin-v8-flags-filter@1.3.0': resolution: {integrity: sha512-LWLNfYGwVJKYpmHUDoODltnlqxdEAl5Qmw7ha1+TSpsABeF94NKSWkQTTV1TB4CM02j2pZyqn36nHgaFl8z7qw==} @@ -1642,10 +1654,6 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - '@ecency/bytebuffer@6.0.0': - resolution: {integrity: sha512-rGPjzD7a7cPtMHjpJEtLMt/RmqX8XK25tN5qjuu9iaDMK/Ril86CecU5DN/TXEMUQMY1p6b2cVvKBLTdFMr2DA==} - engines: {node: '>=6'} - '@electron/asar@3.2.18': resolution: {integrity: sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==} engines: {node: '>=10.12.0'} @@ -1708,9 +1716,6 @@ packages: '@floating-ui/utils@0.2.9': resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} - '@hiveio/dhive@1.3.2': - resolution: {integrity: sha512-kJjp3TbpIlODxjJX4BWwvOf+cMxT8CFH/mNQ40RRjR2LP0a4baSWae1G+U/q/NtgjsIQz6Ja40tvnw6KF12I+g==, tarball: https://registry.npmjs.org/@hiveio/dhive/-/dhive-1.3.2.tgz} - '@hiveio/hb-auth@1.28.4-rc0': resolution: {integrity: sha1-BSdkPZskmAIgG4ndYkCjIhjjjy8=, tarball: https://gitlab.syncad.com/api/v4/projects/429/packages/npm/@hiveio/hb-auth/-/@hiveio/hb-auth-1.28.4-rc0.tgz} engines: {node: ^20.11 || >= 21.2} @@ -3020,9 +3025,6 @@ packages: '@types/body-parser@1.19.5': resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - '@types/bs58@4.0.4': - resolution: {integrity: sha512-0IEpMFXXQi2zXaXl9GJ3sRwQo0uEkD+yFOv+FnAU5lkPtcu6h61xb7jc2CFPEZ5BUOaiP13ThuGc9HD4R8lR5g==} - '@types/chai@4.3.16': resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} @@ -3149,9 +3151,6 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - '@types/node@18.19.70': - resolution: {integrity: sha512-RE+K0+KZoEpDUbGGctnGdkrLFwi1eYKTlIHNl2Um98mUkGsm1u2Ff6Ltd0e8DktTtC98uy7rSj+hO8t/QuLoVQ==} - '@types/node@20.10.4': resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==} @@ -3230,9 +3229,6 @@ packages: '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/triple-beam@1.3.5': - resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} - '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -3761,10 +3757,6 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} - assert-plus@1.0.0: - resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} - engines: {node: '>=0.8'} - assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} @@ -3814,9 +3806,6 @@ packages: resolution: {integrity: sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==} engines: {node: '>=4'} - axios@1.7.9: - resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} - axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -3878,8 +3867,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - base-x@3.0.10: - resolution: {integrity: sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==} + base-x@5.0.1: + resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -3904,25 +3893,13 @@ packages: big.js@6.2.2: resolution: {integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==} - bigi@1.4.2: - resolution: {integrity: sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - - bip66@1.1.5: - resolution: {integrity: sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==} - bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - bn.js@4.12.1: - resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -3945,15 +3922,9 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - browserify-aes@1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} - browserslist@4.24.4: resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -3969,8 +3940,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + bs58@6.0.0: + resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==} buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} @@ -3978,9 +3949,6 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - buffer-xor@1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} - buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -4140,10 +4108,6 @@ packages: ci-info@1.6.0: resolution: {integrity: sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==} - cipher-base@1.0.6: - resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} - engines: {node: '>= 0.10'} - class-variance-authority@0.6.1: resolution: {integrity: sha512-eurOEGc7YVx3majOrOb099PNKgO3KnKSApOprXI4BTq6bcfbqbQXPN2u+rPPmIJ2di23bMwhk0SxCCthBmszEQ==} @@ -4239,18 +4203,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - - color@3.2.1: - resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} - colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - colorspace@1.1.4: - resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} - combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -4391,9 +4346,6 @@ packages: core-js@3.40.0: resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==} - core-util-is@1.0.2: - resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} - core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -4418,18 +4370,9 @@ packages: typescript: optional: true - create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} - - create-hmac@1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - cross-fetch@3.2.0: - resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} - cross-spawn@6.0.6: resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} engines: {node: '>=4.8'} @@ -4775,10 +4718,6 @@ packages: resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} engines: {node: '>=10'} - drbg.js@1.0.1: - resolution: {integrity: sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==} - engines: {node: '>=0.10'} - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -4792,9 +4731,6 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - ecurve@1.0.6: - resolution: {integrity: sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==} - ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -4813,9 +4749,6 @@ packages: resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} engines: {node: '>=0.10.0'} - elliptic@6.6.1: - resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} - email-validator@2.0.4: resolution: {integrity: sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==} engines: {node: '>4.0'} @@ -4837,9 +4770,6 @@ packages: resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} engines: {node: '>= 4'} - enabled@2.0.0: - resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} - encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -5179,9 +5109,6 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - evp_bytestokey@1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} - execa@3.4.0: resolution: {integrity: sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==} engines: {node: ^8.12.0 || >=9.7.0} @@ -5209,10 +5136,6 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} - extsprintf@1.4.1: - resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==} - engines: {'0': node >=0.6.0} - fast-content-type-parse@2.0.1: resolution: {integrity: sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==} @@ -5269,9 +5192,6 @@ packages: picomatch: optional: true - fecha@4.2.3: - resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} - figures@2.0.0: resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} engines: {node: '>=4'} @@ -5288,12 +5208,6 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} - file-stream-rotator@0.6.1: - resolution: {integrity: sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==} - - file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} @@ -5355,18 +5269,6 @@ packages: flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - fn.name@1.1.0: - resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} - - follow-redirects@1.15.9: - resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - for-each@0.3.5: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} @@ -5679,13 +5581,6 @@ packages: resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} engines: {node: '>= 0.4.0'} - hash-base@3.1.0: - resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} - engines: {node: '>=4'} - - hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - hasha@5.2.2: resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} engines: {node: '>=8'} @@ -5755,12 +5650,6 @@ packages: hive-auth-client@0.1.5: resolution: {integrity: sha512-RN1vh2RK9vW9q8aMzyUwTNtIa/J5NX5pMeiVBDoy6ya8z9ea6fGhOWTKRoDsIrKwrPZO/SspSRCF2pwUK7eLVQ==} - hive-keychain-commons@1.3.2: - resolution: {integrity: sha512-8XJmLrhJqWxbr6iz1C0nRWvlvVR92m1Uoo5a9eX+hr41tEAF8T5MekcaNXPDfJpjj6lBLsLfivH7yskA9zyiZQ==} - - hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -5830,9 +5719,6 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - https@1.0.0: - resolution: {integrity: sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==} - human-signals@1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} @@ -6008,9 +5894,6 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - is-async-function@2.1.0: resolution: {integrity: sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==} engines: {node: '>= 0.4'} @@ -6372,9 +6255,6 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsbi@3.2.5: - resolution: {integrity: sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==} - jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} @@ -6445,9 +6325,6 @@ packages: jszip@3.10.1: resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} - keychain-sdk@0.6.2: - resolution: {integrity: sha512-UnfI7bwq0fajh1TcBNlzwzvVEqbGEVgT+a3segyzwFe8U7K58jkt6/DZ5TDvXYgraAy9xpl4skcMiyRFpwYQxA==} - keygrip@1.1.0: resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==} engines: {node: '>= 0.6'} @@ -6479,9 +6356,6 @@ packages: resolution: {integrity: sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==} engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} - kuler@2.0.0: - resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} - language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -6626,14 +6500,6 @@ packages: log-update-async-hook@2.0.7: resolution: {integrity: sha512-V9KpD1AZUBd/oiZ+/Xsgd5rRP9awhgtRiDv5Am4VQCixiDnAbXMdt/yKz41kCzYZtVbwC6YCxnWEF3zjNEwktA==} - logform@2.7.0: - resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} - engines: {node: '>= 12.0.0'} - - long@3.2.0: - resolution: {integrity: sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==} - engines: {node: '>=0.6'} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -6715,9 +6581,6 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} - mdast-util-definitions@5.1.2: resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} @@ -6907,9 +6770,6 @@ packages: minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -6986,9 +6846,6 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nan@2.22.0: - resolution: {integrity: sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==} - nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -7082,15 +6939,6 @@ packages: resolution: {integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==} engines: {node: '>=18'} - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - node-plop@0.26.3: resolution: {integrity: sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==} engines: {node: '>=8.9.4'} @@ -7231,10 +7079,6 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-hash@2.2.0: - resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} - engines: {node: '>= 6'} - object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -7285,9 +7129,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - one-time@1.0.0: - resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} - onetime@2.0.1: resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} engines: {node: '>=4'} @@ -8330,9 +8171,6 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - ripemd160@2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} - rollup-plugin-terser@7.0.2: resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser @@ -8437,10 +8275,6 @@ packages: scriptjs@2.5.9: resolution: {integrity: sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg==} - secp256k1@3.8.1: - resolution: {integrity: sha512-tArjQw2P0RTdY7QmkNehgp6TVvQXq6ulIhxv8gaH6YubKG/wxxAoNKcbuXjDhybbc+b2Ihc7e0xxiGN744UIiQ==} - engines: {node: '>=4.0.0'} - secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} @@ -8520,10 +8354,6 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - sha.js@2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true - shallow-clone@3.0.1: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} @@ -8574,9 +8404,6 @@ packages: resolution: {integrity: sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==} engines: {node: '>=6'} - simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - simple-zustand-devtools@1.1.0: resolution: {integrity: sha512-Axfcfr9L3YL3kto7aschCQLY2VUlXXMnIVtaTe9Y0qWbNmPsX/y7KsNprmxBZoB0pww5ZGs1u/ohcrvQ3tE6jA==} peerDependencies: @@ -8696,9 +8523,6 @@ packages: stable-hash@0.0.4: resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} - stack-trace@0.0.10: - resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} - stackframe@1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} @@ -9004,9 +8828,6 @@ packages: resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} engines: {node: '>=8'} - text-hex@1.0.0: - resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} - text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -9081,9 +8902,6 @@ packages: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} @@ -9102,10 +8920,6 @@ packages: trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - triple-beam@1.4.1: - resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} - engines: {node: '>= 14.0.0'} - trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} @@ -9494,10 +9308,6 @@ packages: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - uuid@9.0.1: - resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} - hasBin: true - uvu@0.5.6: resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} engines: {node: '>=8'} @@ -9524,10 +9334,6 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - verror@1.10.1: - resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} - engines: {node: '>=0.6.0'} - vfile-location@4.1.0: resolution: {integrity: sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==} @@ -9562,9 +9368,6 @@ packages: web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} @@ -9637,9 +9440,6 @@ packages: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} - whatwg-fetch@3.6.20: - resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} - whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} @@ -9648,9 +9448,6 @@ packages: resolution: {integrity: sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==} engines: {node: '>=18'} - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} @@ -9692,20 +9489,6 @@ packages: resolution: {integrity: sha512-NMD00arvqcq2nwqc5Q6KtrSRHK+fVD31erE5FEMahAw5PmVCgD7MUXodq3pdZSUkqA9Cda2iWx6s1XYwiJWRmw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - winston-daily-rotate-file@4.7.1: - resolution: {integrity: sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==} - engines: {node: '>=8'} - peerDependencies: - winston: ^3 - - winston-transport@4.9.0: - resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} - engines: {node: '>= 12.0.0'} - - winston@3.17.0: - resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==} - engines: {node: '>= 12.0.0'} - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -10787,8 +10570,6 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@colors/colors@1.6.0': {} - '@commitlint/cli@19.3.0(@types/node@20.14.10)(typescript@5.5.3)': dependencies: '@commitlint/format': 19.5.0 @@ -10923,12 +10704,6 @@ snapshots: '@csstools/css-tokenizer@3.0.3': {} - '@dabh/diagnostics@2.0.3': - dependencies: - colorspace: 1.1.4 - enabled: 2.0.0 - kuler: 2.0.0 - '@devexpress/bin-v8-flags-filter@1.3.0': {} '@devexpress/callsite-record@4.1.7': @@ -10943,10 +10718,6 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} - '@ecency/bytebuffer@6.0.0': - dependencies: - long: 3.2.0 - '@electron/asar@3.2.18': dependencies: commander: 5.1.0 @@ -11036,24 +10807,6 @@ snapshots: '@floating-ui/utils@0.2.9': {} - '@hiveio/dhive@1.3.2': - dependencies: - '@ecency/bytebuffer': 6.0.0 - bigi: 1.4.2 - bs58: 4.0.1 - core-js: 3.40.0 - cross-fetch: 3.2.0 - ecurve: 1.0.6 - https: 1.0.0 - jsbi: 3.2.5 - node-fetch: 2.7.0 - ripemd160: 2.0.2 - secp256k1: 3.8.1 - verror: 1.10.1 - whatwg-fetch: 3.6.20 - transitivePeerDependencies: - - encoding - '@hiveio/hb-auth@1.28.4-rc0': dependencies: '@hiveio/wax': 1.28.4-rc0-251216100519 @@ -12508,11 +12261,6 @@ snapshots: '@types/connect': 3.4.38 '@types/node': 20.14.10 - '@types/bs58@4.0.4': - dependencies: - '@types/node': 20.14.10 - base-x: 3.0.10 - '@types/chai@4.3.16': {} '@types/connect@3.4.38': @@ -12657,10 +12405,6 @@ snapshots: '@types/ms@0.7.34': {} - '@types/node@18.19.70': - dependencies: - undici-types: 5.26.5 - '@types/node@20.10.4': dependencies: undici-types: 5.26.5 @@ -12744,8 +12488,6 @@ snapshots: '@types/tough-cookie@4.0.5': {} - '@types/triple-beam@1.3.5': {} - '@types/trusted-types@2.0.7': {} '@types/unist@2.0.11': {} @@ -13468,8 +13210,6 @@ snapshots: get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 - assert-plus@1.0.0: {} - assertion-error@1.1.0: {} ast-types-flow@0.0.8: {} @@ -13510,14 +13250,6 @@ snapshots: axe-core@4.10.2: {} - axios@1.7.9: - dependencies: - follow-redirects: 1.15.9 - form-data: 4.0.1 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - axobject-query@4.1.0: {} babel-loader@8.4.1(@babel/core@7.26.0)(webpack@5.97.1): @@ -13593,9 +13325,7 @@ snapshots: balanced-match@1.0.2: {} - base-x@3.0.10: - dependencies: - safe-buffer: 5.2.1 + base-x@5.0.1: {} base64-js@1.5.1: {} @@ -13611,26 +13341,14 @@ snapshots: big.js@6.2.2: {} - bigi@1.4.2: {} - binary-extensions@2.3.0: {} - bindings@1.5.0: - dependencies: - file-uri-to-path: 1.0.0 - - bip66@1.1.5: - dependencies: - safe-buffer: 5.2.1 - bl@4.1.0: dependencies: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 - bn.js@4.12.1: {} - boolbase@1.0.0: {} bottleneck@2.19.5: {} @@ -13652,19 +13370,8 @@ snapshots: dependencies: fill-range: 7.1.1 - brorand@1.1.0: {} - browser-stdout@1.3.1: {} - browserify-aes@1.2.0: - dependencies: - buffer-xor: 1.0.3 - cipher-base: 1.0.6 - create-hash: 1.2.0 - evp_bytestokey: 1.0.3 - inherits: 2.0.4 - safe-buffer: 5.2.1 - browserslist@4.24.4: dependencies: caniuse-lite: 1.0.30001692 @@ -13688,16 +13395,14 @@ snapshots: node-releases: 2.0.27 update-browserslist-db: 1.2.2(browserslist@4.28.1) - bs58@4.0.1: + bs58@6.0.0: dependencies: - base-x: 3.0.10 + base-x: 5.0.1 buffer-crc32@0.2.13: {} buffer-from@1.1.2: {} - buffer-xor@1.0.3: {} - buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -13900,11 +13605,6 @@ snapshots: ci-info@1.6.0: {} - cipher-base@1.0.6: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - class-variance-authority@0.6.1: dependencies: clsx: 1.2.1 @@ -13999,23 +13699,8 @@ snapshots: color-name@1.1.4: {} - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - - color@3.2.1: - dependencies: - color-convert: 1.9.3 - color-string: 1.9.1 - colorette@2.0.20: {} - colorspace@1.1.4: - dependencies: - color: 3.2.1 - text-hex: 1.0.0 - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -14145,8 +13830,6 @@ snapshots: core-js@3.40.0: {} - core-util-is@1.0.2: {} - core-util-is@1.0.3: {} cors@2.8.5: @@ -14170,31 +13853,8 @@ snapshots: optionalDependencies: typescript: 5.5.3 - create-hash@1.2.0: - dependencies: - cipher-base: 1.0.6 - inherits: 2.0.4 - md5.js: 1.3.5 - ripemd160: 2.0.2 - sha.js: 2.4.11 - - create-hmac@1.1.7: - dependencies: - cipher-base: 1.0.6 - create-hash: 1.2.0 - inherits: 2.0.4 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - create-require@1.1.1: {} - cross-fetch@3.2.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - cross-spawn@6.0.6: dependencies: nice-try: 1.0.5 @@ -14509,12 +14169,6 @@ snapshots: dotenv@8.6.0: {} - drbg.js@1.0.1: - dependencies: - browserify-aes: 1.2.0 - create-hash: 1.2.0 - create-hmac: 1.1.7 - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.1 @@ -14529,11 +14183,6 @@ snapshots: eastasianwidth@0.2.0: {} - ecurve@1.0.6: - dependencies: - bigi: 1.4.2 - safe-buffer: 5.2.1 - ee-first@1.1.1: {} ejs@3.1.10: @@ -14546,16 +14195,6 @@ snapshots: elegant-spinner@1.0.1: {} - elliptic@6.6.1: - dependencies: - bn.js: 4.12.1 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - email-validator@2.0.4: {} emittery@0.4.1: {} @@ -14568,8 +14207,6 @@ snapshots: emojis-list@3.0.0: {} - enabled@2.0.0: {} - encodeurl@1.0.2: {} end-of-stream@1.4.4: @@ -15108,11 +14745,6 @@ snapshots: events@3.3.0: {} - evp_bytestokey@1.0.3: - dependencies: - md5.js: 1.3.5 - safe-buffer: 5.2.1 - execa@3.4.0: dependencies: cross-spawn: 7.0.6 @@ -15185,8 +14817,6 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 - extsprintf@1.4.1: {} - fast-content-type-parse@2.0.1: {} fast-copy@3.0.2: {} @@ -15233,8 +14863,6 @@ snapshots: optionalDependencies: picomatch: 4.0.3 - fecha@4.2.3: {} - figures@2.0.0: dependencies: escape-string-regexp: 1.0.5 @@ -15251,12 +14879,6 @@ snapshots: dependencies: flat-cache: 3.2.0 - file-stream-rotator@0.6.1: - dependencies: - moment: 2.30.1 - - file-uri-to-path@1.0.0: {} - filelist@1.0.4: dependencies: minimatch: 5.1.6 @@ -15326,10 +14948,6 @@ snapshots: flatted@3.3.2: {} - fn.name@1.1.0: {} - - follow-redirects@1.15.9: {} - for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -15703,17 +15321,6 @@ snapshots: has@1.0.4: {} - hash-base@3.1.0: - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.2 - safe-buffer: 5.2.1 - - hash.js@1.1.7: - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - hasha@5.2.2: dependencies: is-stream: 2.0.1 @@ -15845,21 +15452,6 @@ snapshots: crypto-js: 4.2.0 lodash: 4.17.21 - hive-keychain-commons@1.3.2: - dependencies: - '@hiveio/dhive': 1.3.2 - moment: 2.30.1 - winston: 3.17.0 - winston-daily-rotate-file: 4.7.1(winston@3.17.0) - transitivePeerDependencies: - - encoding - - hmac-drbg@1.0.1: - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - hoist-non-react-statics@3.3.2: dependencies: react-is: 16.13.1 @@ -15944,8 +15536,6 @@ snapshots: transitivePeerDependencies: - supports-color - https@1.0.0: {} - human-signals@1.1.1: {} human-signals@2.1.0: {} @@ -16124,8 +15714,6 @@ snapshots: is-arrayish@0.2.1: {} - is-arrayish@0.3.2: {} - is-async-function@2.1.0: dependencies: call-bound: 1.0.4 @@ -16455,8 +16043,6 @@ snapshots: dependencies: argparse: 2.0.1 - jsbi@3.2.5: {} - jsbn@1.1.0: {} jsdom@24.1.0: @@ -16535,16 +16121,6 @@ snapshots: readable-stream: 2.3.8 setimmediate: 1.0.5 - keychain-sdk@0.6.2: - dependencies: - '@types/node': 18.19.70 - axios: 1.7.9 - hive-keychain-commons: 1.3.2 - uuid: 9.0.1 - transitivePeerDependencies: - - debug - - encoding - keygrip@1.1.0: dependencies: tsscmp: 1.0.6 @@ -16594,8 +16170,6 @@ snapshots: transitivePeerDependencies: - supports-color - kuler@2.0.0: {} - language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -16720,17 +16294,6 @@ snapshots: onetime: 2.0.1 wrap-ansi: 7.0.0 - logform@2.7.0: - dependencies: - '@colors/colors': 1.6.0 - '@types/triple-beam': 1.3.5 - fecha: 4.2.3 - ms: 2.1.3 - safe-stable-stringify: 2.5.0 - triple-beam: 1.4.1 - - long@3.2.0: {} - longest-streak@3.1.0: {} loose-envify@1.4.0: @@ -16804,12 +16367,6 @@ snapshots: math-intrinsics@1.1.0: {} - md5.js@1.3.5: - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - safe-buffer: 5.2.1 - mdast-util-definitions@5.1.2: dependencies: '@types/mdast': 3.0.15 @@ -17147,8 +16704,6 @@ snapshots: minimalistic-assert@1.0.1: {} - minimalistic-crypto-utils@1.0.1: {} - minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -17232,8 +16787,6 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nan@2.22.0: {} - nanoid@3.3.11: {} nanoid@3.3.8: {} @@ -17342,10 +16895,6 @@ snapshots: emojilib: 2.4.0 skin-tone: 2.0.0 - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - node-plop@0.26.3: dependencies: '@babel/runtime-corejs3': 7.26.0 @@ -17443,8 +16992,6 @@ snapshots: object-assign@4.1.1: {} - object-hash@2.2.0: {} - object-hash@3.0.0: {} object-inspect@1.13.4: {} @@ -17517,10 +17064,6 @@ snapshots: dependencies: wrappy: 1.0.2 - one-time@1.0.0: - dependencies: - fn.name: 1.1.0 - onetime@2.0.1: dependencies: mimic-fn: 1.2.0 @@ -18570,11 +18113,6 @@ snapshots: dependencies: glob: 7.2.3 - ripemd160@2.0.2: - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - rollup-plugin-terser@7.0.2(rollup@2.79.2): dependencies: '@babel/code-frame': 7.26.2 @@ -18708,17 +18246,6 @@ snapshots: scriptjs@2.5.9: {} - secp256k1@3.8.1: - dependencies: - bindings: 1.5.0 - bip66: 1.1.5 - bn.js: 4.12.1 - create-hash: 1.2.0 - drbg.js: 1.0.1 - elliptic: 6.6.1 - nan: 2.22.0 - safe-buffer: 5.2.1 - secure-json-parse@2.7.0: {} secure-random@1.1.2: {} @@ -18821,11 +18348,6 @@ snapshots: setprototypeof@1.2.0: {} - sha.js@2.4.11: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - shallow-clone@3.0.1: dependencies: kind-of: 6.0.3 @@ -18882,10 +18404,6 @@ snapshots: figures: 2.0.0 pkg-conf: 2.1.0 - simple-swizzle@0.2.2: - dependencies: - is-arrayish: 0.3.2 - simple-zustand-devtools@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.0)(react-dom@18.3.0(react@18.3.0))(react@18.3.0)(zustand@4.5.6(@types/react@18.3.0)(react@18.3.0)): dependencies: '@types/react': 18.3.0 @@ -18995,8 +18513,6 @@ snapshots: stable-hash@0.0.4: {} - stack-trace@0.0.10: {} - stackframe@1.3.4: {} statuses@1.5.0: {} @@ -19523,8 +19039,6 @@ snapshots: text-extensions@2.4.0: {} - text-hex@1.0.0: {} - text-table@0.2.0: {} thenify-all@1.6.0: @@ -19603,8 +19117,6 @@ snapshots: universalify: 0.2.0 url-parse: 1.5.10 - tr46@0.0.3: {} - tr46@1.0.1: dependencies: punycode: 2.3.1 @@ -19619,8 +19131,6 @@ snapshots: trim-lines@3.0.1: {} - triple-beam@1.4.1: {} - trough@2.2.0: {} truncate-utf8-bytes@1.0.2: @@ -20009,8 +19519,6 @@ snapshots: uuid@8.3.2: {} - uuid@9.0.1: {} - uvu@0.5.6: dependencies: dequal: 2.0.3 @@ -20033,12 +19541,6 @@ snapshots: vary@1.1.2: {} - verror@1.10.1: - dependencies: - assert-plus: 1.0.0 - core-util-is: 1.0.2 - extsprintf: 1.4.1 - vfile-location@4.1.0: dependencies: '@types/unist': 2.0.11 @@ -20095,8 +19597,6 @@ snapshots: web-namespaces@2.0.1: {} - webidl-conversions@3.0.1: {} - webidl-conversions@4.0.2: {} webidl-conversions@7.0.0: {} @@ -20227,8 +19727,6 @@ snapshots: dependencies: iconv-lite: 0.6.3 - whatwg-fetch@3.6.20: {} - whatwg-mimetype@4.0.0: {} whatwg-url@14.1.0: @@ -20236,11 +19734,6 @@ snapshots: tr46: 5.0.0 webidl-conversions: 7.0.0 - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - whatwg-url@7.1.0: dependencies: lodash.sortby: 4.7.0 @@ -20310,34 +19803,6 @@ snapshots: dependencies: execa: 5.1.1 - winston-daily-rotate-file@4.7.1(winston@3.17.0): - dependencies: - file-stream-rotator: 0.6.1 - object-hash: 2.2.0 - triple-beam: 1.4.1 - winston: 3.17.0 - winston-transport: 4.9.0 - - winston-transport@4.9.0: - dependencies: - logform: 2.7.0 - readable-stream: 3.6.2 - triple-beam: 1.4.1 - - winston@3.17.0: - dependencies: - '@colors/colors': 1.6.0 - '@dabh/diagnostics': 2.0.3 - async: 3.2.6 - is-stream: 2.0.1 - logform: 2.7.0 - one-time: 1.0.0 - readable-stream: 3.6.2 - safe-stable-stringify: 2.5.0 - stack-trace: 0.0.10 - triple-beam: 1.4.1 - winston-transport: 4.9.0 - word-wrap@1.2.5: {} wordwrap@1.0.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ff891dc65..027c8a583 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -7,7 +7,7 @@ catalogs: # NOTE: @hiveio/wax uses dev build (1.28.4-rc0-251216100519) via pnpm.overrides in package.json # This gets latest wax fixes while waiting for official release. Remove override when wax releases new tag. hiveio-toolset: - '@hiveio/beekeeper': 1.28.4-rc0 + # '@hiveio/beekeeper': 1.28.4-rc0 '@hiveio/wax': 1.28.4-rc0-251216100519 '@hiveio/wax-signers-keychain': 1.28.4-rc0 '@hiveio/workerbee': 1.28.4-rc0 -- GitLab From 2c98c29e663a1cc9ca5ce28be020a20fe2429d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Kociubi=C5=84ski?= Date: Fri, 19 Dec 2025 12:00:06 +0100 Subject: [PATCH 2/2] improve tests validating warning message for wrong wif key --- apps/blog/playwright/tests/e2e/loginSignUp.spec.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/blog/playwright/tests/e2e/loginSignUp.spec.ts b/apps/blog/playwright/tests/e2e/loginSignUp.spec.ts index 908045d1f..c8eb3c015 100644 --- a/apps/blog/playwright/tests/e2e/loginSignUp.spec.ts +++ b/apps/blog/playwright/tests/e2e/loginSignUp.spec.ts @@ -252,7 +252,7 @@ test.describe('Login and Sign Up tests', () =>{ }); // WIF should not be empty. - Wrong WIF (needs username) - // Invalid WIF format. - Wrong WIF (needs username) + // Invalid WIF key. - Wrong WIF (needs username) test('Validate the error message for wrong WIF format', async ({page}) =>{ const loginForm = new LoginForm(page); @@ -262,7 +262,8 @@ test.describe('Login and Sign Up tests', () =>{ await loginForm.usernameInput.fill(user.username); // Type wrong WIF format to the input await loginForm.wifInput.fill('wrongWif'); - await expect(loginForm.wifInputErrorMessage).toHaveText('Invalid WIF format.'); + // `Invalid WIF format.` message changed to `Invalid WIF key.` + await expect(loginForm.wifInputErrorMessage).toHaveText('Invalid WIF key.'); // Type empty string to the WIF input await loginForm.wifInput.fill(''); await expect(loginForm.wifInputErrorMessage).toHaveText('WIF should not be empty.'); @@ -290,7 +291,7 @@ test.describe('Login and Sign Up tests', () =>{ await expect(loginForm.errorToastContentMessage).toHaveText('Error: No WIF key from user'); }); - // Invalid WIF checksum. - in Enter your WIF key + // Invalid WIF key. - in Enter your WIF key test('Validate Invalid WIF checksum in the Enter your WIF form', async ({page}) =>{ const loginForm = new LoginForm(page); @@ -306,7 +307,8 @@ test.describe('Login and Sign Up tests', () =>{ await loginForm.validateEnterYourWifKeyFormIsLoaded(); await loginForm.postingPrivateKeyInput.fill(user.keys[0].private + '1'); // wrong wif await loginForm.postingPrivateKeySubmitButton.click(); - await expect(loginForm.passwordErrorMessageEnterYourWifKey).toHaveText('Invalid WIF checksum.'); + // `Invalid WIF checksum.` message changed to `Invalid WIF key.` + await expect(loginForm.passwordErrorMessageEnterYourWifKey).toHaveText('Invalid WIF key.'); await loginForm.closeDialog.last().click(); // Validate other sign in options form with error message is loaded await loginForm.validateOtherSignInOptionsFormWithUsernameIsLoaded(user.username); -- GitLab