diff --git a/.env.example b/.env.example index f119fc5ed301992416892f395fb0df50f0364761..d3d79b44f640f7c42b9cf2fc3f3316b216b6a8b2 100644 --- a/.env.example +++ b/.env.example @@ -17,5 +17,20 @@ NUXT_PUBLIC_HIVE_CHAIN_ID= NUXT_GOOGLE_APPLICATION_CREDENTIALS_JSON= # Your Google Wallet Issuer ID. You can find it on Google Pay and Wallet Console -> Google Wallet API, as IssuerID NUXT_GOOGLE_WALLET_ISSUER_ID= + +# Google Drive Integration +# Get these from https://console.cloud.google.com/ +# 1. Enable Google Drive API in APIs & Services -> Library +# 2. Go to APIs & Services -> Credentials -> Create Credentials -> OAuth client ID +NUXT_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com +NUXT_GOOGLE_CLIENT_SECRET=your-client-secret +# 3. Go to APIs & Services -> Credentials -> Create Credentials -> API key +NUXT_GOOGLE_API_KEY=your-api-key +# This is the filename used to store data in the user's Google Drive App Data folder +NUXT_GOOGLE_DRIVE_STORAGE_FILE=profile_data.json + +# App URL (for OAuth callbacks) +NUXT_PUBLIC_APP_URL=http://localhost:3000 + # For development, you can set a mock server URL # NUXT_PUBLIC_CTOKENS_API_URL=http://localhost:8080/mock-ctokens-api diff --git a/README.md b/README.md index ea265a3a76c5a35fe1e71d961c91b61830c6929f..fb80cbb48426041ed0df98ac9134355686cd7765 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,139 @@ # @hiveio/wallet-dapp -Metamask Wallet dApp +A Nuxt-based wallet dApp for Hive blockchain with MetaMask Snap integration and Google Wallet/Drive support. -## Running +## Overview -1. Install and configure [Metamask](https://metamask.io/download). In case of producing another (not yet accepted) version of snap, you will need to use a [Metamask Flask](https://docs.metamask.io/snaps/get-started/install-flask/). **REMEMBER TO DISABLE STANDARD METAMASK BEFORE TESTING** -1. Install project: `git clone --recurse-submodules https://gitlab.syncad.com/hive/wallet-dapp.git` -1. Install dependencies: `pnpm install` -1. Start development server: `pnpm start` -1. Navigate to [http://localhost:5173](http://localhost:5173) and authorize to test +This application provides a modern web interface for managing Hive blockchain wallets with multiple authentication methods. -> If you want to see metamask snap logs on Chrome, go to: [chrome://extensions](chrome://extensions) Details of "MetaMask Flask DEVELOPMENT BUILD" and inspect `offscreen.html` console +## Prerequisites -## Regenerating ctokens api spec +- **Node.js**: `^20.18.1` or `>= 21.2` +- **pnpm**: `10.0.0` or higher +- **MetaMask**: [MetaMask](https://metamask.io/download) or [MetaMask Flask](https://docs.metamask.io/snaps/get-started/install-flask/) for development + +## Setup + +### 1. Clone the Repository + +```bash +git clone https://gitlab.syncad.com/hive/wallet-dapp.git +cd wallet-dapp +``` + +### 2. Install Dependencies ```bash -pnpm regenerate-ctokens-api http://192.168.6.7/ +pnpm install +``` + +### 3. Configure Environment Variables + +Copy `.env.example` to `.env` and configure the required variables (see [Google Integration Setup](#google-integration-setup) for details). + +```bash +cp .env.example .env +``` + +### 4. Start Development Server + +```bash +pnpm start +# or +pnpm dev +``` + +The application will be available at [http://localhost:3000](http://localhost:3000). + +## Development Notes + +> **MetaMask Snap Logs**: To view MetaMask Snap logs in Chrome, navigate to [chrome://extensions](chrome://extensions), find "MetaMask Flask DEVELOPMENT BUILD", click Details, and inspect the `offscreen.html` console. + +> **MetaMask Flask**: When developing a new version of the Snap (not yet accepted), use [MetaMask Flask](https://docs.metamask.io/snaps/get-started/install-flask/). **Remember to disable standard MetaMask before testing.** + + +## Google Integration Setup + +To enable Google Wallet and Google Drive integration, you need to configure a Google Cloud Project and the Google Pay & Wallet Console. + +### 1. Google Cloud Console Configuration + +1. **Create a Project**: Go to [Google Cloud Console](https://console.cloud.google.com/) and create a new project. +2. **Enable APIs**: + * Navigate to **APIs & Services > Library**. + * Search for and enable **Google Wallet API**. + * Search for and enable **Google Drive API**. +3. **Configure OAuth Consent Screen**: + * Go to **APIs & Services > OAuth consent screen**. + * Select **External** (or Internal if you are in a Google Workspace organization). + * Fill in the required application details. + * Add the following scopes: + * `https://www.googleapis.com/auth/drive.appdata` + * `https://www.googleapis.com/auth/userinfo.profile` + * `https://www.googleapis.com/auth/userinfo.email` + * Add test users if your app is in "Testing" mode. +4. **Create OAuth Credentials**: + * Go to **APIs & Services > Credentials**. + * Click **Create Credentials > OAuth client ID**. + * Application type: **Web application**. + * **Authorized redirect URIs**: Add your callback URL. For local development, this is usually: + `http://localhost:3000/api/auth/google/callback` + (Adjust the port if you are not running on 3000). + * Note down the **Client ID** and **Client Secret**. +5. **Create Service Account (for Wallet)**: + * Go to **APIs & Services > Credentials**. + * Click **Create Credentials > Service account**. + * Name it (e.g., "wallet-issuer"). + * Grant it the **Owner** or **Editor** role (or a specific role if you know exactly what is needed, but for Wallet API, basic access is often sufficient for the service account itself, as permissions are handled in the Pay Console). + * After creation, click on the service account email, go to the **Keys** tab. + * Click **Add Key > Create new key > JSON**. + * Save the downloaded JSON file. You will need the contents of this file for `NUXT_GOOGLE_APPLICATION_CREDENTIALS_JSON`. + +### 2. Google Pay & Wallet Console Configuration + +1. Go to [Google Pay & Wallet Console](https://pay.google.com/business/console). +2. Create a business profile if you don't have one. +3. Request access to the **Google Wallet API**. +4. **Create an Issuer Account**: + * Once access is granted, create an Issuer Account. + * Note down your **Issuer ID**. +5. **Link Service Account**: + * In the Google Pay & Wallet Console, go to **Users**. + * Click **Invite a user**. + * Enter the **email address of the Service Account** you created in the Google Cloud Console (e.g., `wallet-issuer@your-project.iam.gserviceaccount.com`). + * Grant it **Developer** or **Admin** access. This is crucial for the API to work. + +### 3. Environment Variables Configuration + +Create a `.env` file in the root directory (copy from `.env.example`) and configure the following variables: + +```ini +# Google Drive Integration (OAuth) +GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com +GOOGLE_CLIENT_SECRET=your-client-secret +# API Key is optional for some flows but good to have if using client-side libraries +GOOGLE_API_KEY=your-api-key +GOOGLE_DRIVE_STORAGE_FILE=profile_data.json + +# Google Wallet Integration +# Your Issuer ID from Google Pay & Wallet Console +NUXT_GOOGLE_WALLET_ISSUER_ID=1234567890 + +# Service Account Credentials for Wallet API +# You can paste the entire JSON content here as a single line string. +# The application will automatically parse it. +NUXT_GOOGLE_APPLICATION_CREDENTIALS_JSON='{"type": "service_account", "project_id": "...", ...}' +``` + +**Note on `NUXT_GOOGLE_APPLICATION_CREDENTIALS_JSON`**: +This variable expects the content of the Service Account JSON key file. +- You can paste the raw JSON string (ensure it is properly escaped if needed, though single quotes usually work for shells). +- Alternatively, in a production environment (like Vercel or Docker), you can set this variable to the JSON string value. + +### 4. Application Configuration + +Ensure your `nuxt.config.ts` or runtime environment has the correct `NUXT_PUBLIC_APP_URL` set, as this is used for OAuth redirects. + +```ini +NUXT_PUBLIC_APP_URL=http://localhost:3000 ``` diff --git a/nuxt.config.ts b/nuxt.config.ts index ea17f4d7888d9bfea76ee61470ffff1abb01e014..b48a58bc5d49d8953c37349c32f1afd0e7acd891 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -40,12 +40,10 @@ export default defineNuxtConfig({ middleware: 'src/middleware', plugins: 'src/plugins' }, - modules: [ - '@nuxtjs/tailwindcss', - '@nuxtjs/color-mode', - '@nuxt/eslint', - '@pinia/nuxt' - ], + imports: { + dirs: ['src/composables'] + }, + modules: ['@nuxtjs/tailwindcss', '@nuxtjs/color-mode', '@nuxt/eslint', '@pinia/nuxt'], alias: { '@': path.resolve(import.meta.dirname, './src') }, @@ -60,9 +58,14 @@ export default defineNuxtConfig({ hiveNodeEndpoint: 'https://api.hive.blog', hiveChainId: '', snapOrigin: '', - snapVersion: '' + snapVersion: '', + appUrl: process.env.NUXT_PUBLIC_APP_URL || 'http://localhost:3000' }, googleApplicationCredentialsJson: {}, - googleWalletIssuerId: '' + googleWalletIssuerId: process.env.GOOGLE_WALLET_ISSUER_ID || '', + googleClientId: process.env.GOOGLE_CLIENT_ID || '', + googleClientSecret: process.env.GOOGLE_CLIENT_SECRET || '', + googleApiKey: process.env.GOOGLE_API_KEY || '', + googleDriveStorageFile: process.env.GOOGLE_DRIVE_STORAGE_FILE || 'profile_data.json' } }); diff --git a/package.json b/package.json index 01b79f7038cfcffa59eda172a98febdd9729ef15..8e1d3ee9338108bd32ea8a9aecf82307b5dfd041 100644 --- a/package.json +++ b/package.json @@ -37,10 +37,11 @@ "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.32.0", "@hiveio/beekeeper": "1.28.4-rc0", - "@hiveio/wax": "1.28.4-rc0-stable.251125135529", - "@hiveio/wax-signers-keychain": "1.28.4-rc0-stable.251125135529", - "@hiveio/wax-signers-metamask": "1.28.4-rc0-stable.251125135529", - "@hiveio/wax-signers-peakvault": "1.28.4-rc0-stable.251125135529", + "@hiveio/wax": "1.28.4-rc0-stable.251205135508", + "@hiveio/wax-signers-external": "1.28.4-rc0-stable.251205135508", + "@hiveio/wax-signers-keychain": "1.28.4-rc0-stable.251205135508", + "@hiveio/wax-signers-metamask": "1.28.4-rc0-stable.251205135508", + "@hiveio/wax-signers-peakvault": "1.28.4-rc0-stable.251205135508", "@mdi/js": "^7.4.47", "@metamask/providers": "^16.0.0", "@mtyszczak-cargo/htm": "^1.3.0", @@ -51,6 +52,7 @@ "@pinia/nuxt": "0.11.2", "@stylistic/eslint-plugin": "^5.2.2", "@tanstack/vue-table": "^8.21.2", + "@types/google.accounts": "^0.0.14", "@types/jsonwebtoken": "^9.0.10", "@types/node": "^22.13.9", "@types/qrcode": "^1.5.6", @@ -89,6 +91,7 @@ }, "dependencies": { "google-auth-library": "^10.4.2", + "googleapis": "^140.0.0", "jsonwebtoken": "^9.0.2", "qrcode": "^1.5.4" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4969069e0e00fb8de337180cfd9a3c456f202a6e..05602fc06f8f511e83be3de00496967752fbf6f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,6 +15,9 @@ importers: google-auth-library: specifier: ^10.4.2 version: 10.4.2 + googleapis: + specifier: ^140.0.0 + version: 140.0.1 jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 @@ -35,17 +38,20 @@ importers: specifier: 1.28.4-rc0 version: 1.28.4-rc0 '@hiveio/wax': - specifier: 1.28.4-rc0-stable.251125135529 - version: 1.28.4-rc0-stable.251125135529 + specifier: 1.28.4-rc0-stable.251205135508 + version: 1.28.4-rc0-stable.251205135508 + '@hiveio/wax-signers-external': + specifier: 1.28.4-rc0-stable.251205135508 + version: 1.28.4-rc0-stable.251205135508 '@hiveio/wax-signers-keychain': - specifier: 1.28.4-rc0-stable.251125135529 - version: 1.28.4-rc0-stable.251125135529 + specifier: 1.28.4-rc0-stable.251205135508 + version: 1.28.4-rc0-stable.251205135508 '@hiveio/wax-signers-metamask': - specifier: 1.28.4-rc0-stable.251125135529 - version: 1.28.4-rc0-stable.251125135529(webextension-polyfill@0.12.0) + specifier: 1.28.4-rc0-stable.251205135508 + version: 1.28.4-rc0-stable.251205135508(webextension-polyfill@0.12.0) '@hiveio/wax-signers-peakvault': - specifier: 1.28.4-rc0-stable.251125135529 - version: 1.28.4-rc0-stable.251125135529 + specifier: 1.28.4-rc0-stable.251205135508 + version: 1.28.4-rc0-stable.251205135508 '@mdi/js': specifier: ^7.4.47 version: 7.4.47 @@ -54,7 +60,7 @@ importers: version: 16.1.0 '@mtyszczak-cargo/htm': specifier: ^1.3.0 - version: 1.3.0(@hiveio/wax@1.28.4-rc0-stable.251125135529) + version: 1.3.0(@hiveio/wax@1.28.4-rc0-stable.251205135508) '@nabla/vite-plugin-eslint': specifier: ^2.0.6 version: 2.0.6(eslint@9.32.0(jiti@2.6.1))(vite@6.2.0(@types/node@22.13.9)(jiti@2.6.1)(terser@5.39.0)(tsx@4.19.3)(yaml@2.8.1)) @@ -76,6 +82,9 @@ importers: '@tanstack/vue-table': specifier: ^8.21.2 version: 8.21.2(vue@3.5.22(typescript@5.7.3)) + '@types/google.accounts': + specifier: ^0.0.14 + version: 0.0.14 '@types/jsonwebtoken': specifier: ^9.0.10 version: 9.0.10 @@ -376,6 +385,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.0': resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} engines: {node: '>=18'} @@ -388,6 +403,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.0': resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} engines: {node: '>=18'} @@ -400,6 +421,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.0': resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} engines: {node: '>=18'} @@ -412,6 +439,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.0': resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} engines: {node: '>=18'} @@ -424,6 +457,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.0': resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} engines: {node: '>=18'} @@ -436,6 +475,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.0': resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} engines: {node: '>=18'} @@ -448,6 +493,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.0': resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} engines: {node: '>=18'} @@ -460,6 +511,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.0': resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} engines: {node: '>=18'} @@ -472,6 +529,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.0': resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} engines: {node: '>=18'} @@ -484,6 +547,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.0': resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} engines: {node: '>=18'} @@ -496,6 +565,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.0': resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} engines: {node: '>=18'} @@ -508,6 +583,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.0': resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} engines: {node: '>=18'} @@ -520,6 +601,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.0': resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} engines: {node: '>=18'} @@ -532,6 +619,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.0': resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} engines: {node: '>=18'} @@ -544,6 +637,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.0': resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} engines: {node: '>=18'} @@ -556,6 +655,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.0': resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} engines: {node: '>=18'} @@ -568,6 +673,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.0': resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} engines: {node: '>=18'} @@ -580,6 +691,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.0': resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} engines: {node: '>=18'} @@ -592,6 +709,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.0': resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} engines: {node: '>=18'} @@ -604,6 +727,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.0': resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} engines: {node: '>=18'} @@ -616,12 +745,24 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.25.11': resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.25.0': resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} engines: {node: '>=18'} @@ -634,6 +775,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.0': resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} engines: {node: '>=18'} @@ -646,6 +793,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.0': resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} engines: {node: '>=18'} @@ -658,6 +811,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.0': resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} engines: {node: '>=18'} @@ -670,6 +829,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.7.0': resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -765,17 +930,23 @@ packages: resolution: {integrity: sha1-qLgaAY/l+gXAdleuIeyaMAo6wxA=, tarball: https://gitlab.syncad.com/api/v4/projects/198/packages/npm/@hiveio/beekeeper/-/@hiveio/beekeeper-1.28.4-rc0.tgz} engines: {node: ^20.11 || >= 21.2} - '@hiveio/wax-signers-keychain@1.28.4-rc0-stable.251125135529': - resolution: {integrity: sha1-0hRtPo0ZtQqLB0o2dOr9KUkTGeU=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax-signers-keychain/-/@hiveio/wax-signers-keychain-1.28.4-rc0-stable.251125135529.tgz} + '@hiveio/wax-signers-beekeeper@1.28.4-rc0-stable.251205135508': + resolution: {integrity: sha1-GBh6iokvhQiKQ0s1OSzupl/ig8U=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax-signers-beekeeper/-/@hiveio/wax-signers-beekeeper-1.28.4-rc0-stable.251205135508.tgz} - '@hiveio/wax-signers-metamask@1.28.4-rc0-stable.251125135529': - resolution: {integrity: sha1-KFCegjZwvUVDIXe8vpE9t60fLME=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax-signers-metamask/-/@hiveio/wax-signers-metamask-1.28.4-rc0-stable.251125135529.tgz} + '@hiveio/wax-signers-external@1.28.4-rc0-stable.251205135508': + resolution: {integrity: sha1-WwDy4UUhFOT4w+uZsqUbDJsKEjA=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax-signers-external/-/@hiveio/wax-signers-external-1.28.4-rc0-stable.251205135508.tgz} - '@hiveio/wax-signers-peakvault@1.28.4-rc0-stable.251125135529': - resolution: {integrity: sha1-+tq4uF74VA9UOIHFNIQFKzbV+CY=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax-signers-peakvault/-/@hiveio/wax-signers-peakvault-1.28.4-rc0-stable.251125135529.tgz} + '@hiveio/wax-signers-keychain@1.28.4-rc0-stable.251205135508': + resolution: {integrity: sha1-VteTW4a9gRs7uTOQH7IqrNyPQGg=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax-signers-keychain/-/@hiveio/wax-signers-keychain-1.28.4-rc0-stable.251205135508.tgz} - '@hiveio/wax@1.28.4-rc0-stable.251125135529': - resolution: {integrity: sha1-OE6212Rtqq77FgAGyR3BU2uqIcQ=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax/-/@hiveio/wax-1.28.4-rc0-stable.251125135529.tgz} + '@hiveio/wax-signers-metamask@1.28.4-rc0-stable.251205135508': + resolution: {integrity: sha1-/j6uhZKmq53gcGIjYG/Hxt7esMk=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax-signers-metamask/-/@hiveio/wax-signers-metamask-1.28.4-rc0-stable.251205135508.tgz} + + '@hiveio/wax-signers-peakvault@1.28.4-rc0-stable.251205135508': + resolution: {integrity: sha1-+HTICd96cwP9iBL+GjEy0llSuLo=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax-signers-peakvault/-/@hiveio/wax-signers-peakvault-1.28.4-rc0-stable.251205135508.tgz} + + '@hiveio/wax@1.28.4-rc0-stable.251205135508': + resolution: {integrity: sha1-2bz6ZqjlKXgtf+e0gFMLLvCorTw=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax/-/@hiveio/wax-1.28.4-rc0-stable.251205135508.tgz} engines: {node: ^20.11 || >= 21.2} '@humanfs/core@0.19.1': @@ -869,8 +1040,8 @@ packages: '@mdi/js@7.4.47': resolution: {integrity: sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==} - '@metamask/json-rpc-engine@10.0.3': - resolution: {integrity: sha512-p01QhlLIiTFXivEJCRx0LXEvPUaUPCedI9A8qV9jcLGGNSj1UTWM9GeifoeTweOMdmpIk5Rxg10H9f0JPUC9Ig==} + '@metamask/json-rpc-engine@10.2.0': + resolution: {integrity: sha512-/aJrBeT3RblRRpESgNjHqXMLZPFPl14g6oVJnek5F1yW6iA7n/eeCd0smgKOJ95uYlFtGNzyxzX7Qy3IlpBv5w==} engines: {node: ^18.18 || >=20} '@metamask/json-rpc-engine@8.0.2': @@ -881,8 +1052,8 @@ packages: resolution: {integrity: sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==} engines: {node: '>=16.0.0'} - '@metamask/json-rpc-middleware-stream@8.0.7': - resolution: {integrity: sha512-s7ugj+b4QYkQ+3VjRDdsp8GfKOKrxvI6HzaZg4TJrfSV+SO/Ky4TGo4Aib1gtv3/8muCPYAPGtjFVYWVAVJ6jw==} + '@metamask/json-rpc-middleware-stream@8.0.8': + resolution: {integrity: sha512-GeYc3tfRvEMhKzNcRSN1m1XIQs2SPaCpzgljoDlYyvnYeftGqteSSXu9ZXRGSdgtOzoS7gUJntj+JYxticGoYg==} engines: {node: ^18.18 || >=20} '@metamask/object-multiplex@2.1.0': @@ -903,8 +1074,8 @@ packages: resolution: {integrity: sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==} engines: {node: '>=16.0.0'} - '@metamask/rpc-errors@7.0.2': - resolution: {integrity: sha512-YYYHsVYd46XwY2QZzpGeU4PSdRhHdxnzkB8piWGvJW2xbikZ3R+epAYEL4q/K8bh9JPTucsUdwRFnACor1aOYw==} + '@metamask/rpc-errors@7.0.3': + resolution: {integrity: sha512-nrEaeBawm8yFU7hetJKok/CUs0tQsWtTqp3OLbFhPUMXYqU7uI5LAV5vi9o7rTjFkUyof7Nzbw5bea5+1ou+dg==} engines: {node: ^18.20 || ^20.17 || >=22} '@metamask/safe-event-emitter@3.1.2': @@ -915,8 +1086,12 @@ packages: resolution: {integrity: sha512-N08M56HdOgBfRKkrgCMZvQppkZGcArEop3kixNEtVbJKm6P9Cfg0YkI6X0s1g78sNrj2fWUwvJADdZuzJgFttA==} engines: {node: '>=16.0.0'} - '@metamask/utils@11.3.0': - resolution: {integrity: sha512-E2TxOE0IG4iLN8C7GK0q6NGWDI2YKG+HHA8HPO4vbVdF4S2d10u7CWAdW0z3VoQadOaz15L4Qig122Vn0PI39w==} + '@metamask/superstruct@3.2.1': + resolution: {integrity: sha512-fLgJnDOXFmuVlB38rUN5SmU7hAFQcCjrg3Vrxz67KTY7YHFnSNEKvX4avmEBdOI0yTCxZjwMCFEqsC8k2+Wd3g==} + engines: {node: '>=16.0.0'} + + '@metamask/utils@11.8.1': + resolution: {integrity: sha512-DIbsNUyqWLFgqJlZxi1OOCMYvI23GqFCvNJAtzv8/WXWzJfnJnvp1M24j7VvUe3URBi3S86UgQ7+7aWU9p/cnQ==} engines: {node: ^18.18 || ^20.14 || >=22} '@metamask/utils@8.5.0': @@ -956,6 +1131,10 @@ packages: resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} engines: {node: ^14.21.3 || >=16} + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1770,6 +1949,9 @@ packages: '@scure/base@1.2.4': resolution: {integrity: sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==} + '@scure/base@1.2.6': + resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} + '@scure/bip32@1.4.0': resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} @@ -1892,8 +2074,8 @@ packages: peerDependencies: vue: 3.5.22 - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} @@ -1910,6 +2092,9 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/deep-freeze-strict@1.1.2': + resolution: {integrity: sha512-VvMETBojHvhX4f+ocYTySQlXMZfxKV3Jyb7iCWlWaC+exbedkv6Iv2bZZqI736qXjVguH6IH7bzwMBMfTT+zuQ==} + '@types/eslint@9.6.1': resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} @@ -1919,6 +2104,9 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/google.accounts@0.0.14': + resolution: {integrity: sha512-HqIVkVzpiLWhlajhQQd4rIV7czanFvXblJI2J1fSrL+VKQuQwwZ63m35D/mI0flsqKE6p/hNrAG0Yn4FD6JvNA==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -1928,6 +2116,9 @@ packages: '@types/jsonwebtoken@9.0.10': resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==} + '@types/lodash@4.17.21': + resolution: {integrity: sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -2907,6 +3098,9 @@ packages: deep-equal@1.0.1: resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} + deep-freeze-strict@1.1.1: + resolution: {integrity: sha512-QemROZMM2IvhAcCFvahdX2Vbm4S/txeq5rFYU9fh4mQP79WTMW5c/HkQ2ICl1zuzcDZdPZ6zarDxQeQMsVYoNA==} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -3111,6 +3305,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -3482,10 +3681,18 @@ packages: resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} engines: {node: '>=10'} + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + gaxios@7.1.2: resolution: {integrity: sha512-/Szrn8nr+2TsQT1Gp8iIe/BEytJmbyfrbFh419DfGQSkEgNEhbPi7JRJuughjkTzPWgU9gBQf5AVu3DbHt0OXA==} engines: {node: '>=18'} + gcp-metadata@6.1.1: + resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} + engines: {node: '>=14'} + gcp-metadata@8.1.1: resolution: {integrity: sha512-dTCcAe9fRQf06ELwel6lWWFrEbstwjUBYEhr5VRGoC+iPDZQucHppCowaIp8b8v92tU1G4X4H3b/Y6zXZxkMsQ==} engines: {node: '>=18'} @@ -3578,10 +3785,26 @@ packages: resolution: {integrity: sha512-EKiQasw6aEdxSovPEf1oBxCEvxjFamZ6MPaVOSPXZMnqKFLo+rrYjHyjKlFfZcXiKi9qAH6cutr5WRqqa1jKhg==} engines: {node: '>=18'} + google-auth-library@9.15.1: + resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} + engines: {node: '>=14'} + + google-logging-utils@0.0.2: + resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} + engines: {node: '>=14'} + google-logging-utils@1.1.1: resolution: {integrity: sha512-rcX58I7nqpu4mbKztFeOAObbomBbHU2oIb/d3tJfF3dizGSApqtSwYJigGCooHdnMyQBIw8BrWyK96w3YXgr6A==} engines: {node: '>=14'} + googleapis-common@7.2.0: + resolution: {integrity: sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==} + engines: {node: '>=14.0.0'} + + googleapis@140.0.1: + resolution: {integrity: sha512-ZGvBX4mQcFXO9ACnVNg6Aqy3KtBPB5zTuue43YVLxwn8HSv8jB7w+uDKoIPSoWuxGROgnj2kbng6acXncOQRNA==} + engines: {node: '>=14.0.0'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -3592,6 +3815,10 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + gtoken@8.0.0: resolution: {integrity: sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==} engines: {node: '>=18'} @@ -4918,6 +5145,10 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} @@ -5678,6 +5909,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-template@2.0.8: + resolution: {integrity: sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -6067,6 +6301,9 @@ packages: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} + zod@4.1.13: + resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} + snapshots: '@alloc/quick-lru@5.2.0': {} @@ -6331,153 +6568,231 @@ snapshots: '@esbuild/aix-ppc64@0.25.11': optional: true + '@esbuild/aix-ppc64@0.25.12': + optional: true + '@esbuild/android-arm64@0.25.0': optional: true '@esbuild/android-arm64@0.25.11': optional: true + '@esbuild/android-arm64@0.25.12': + optional: true + '@esbuild/android-arm@0.25.0': optional: true '@esbuild/android-arm@0.25.11': optional: true + '@esbuild/android-arm@0.25.12': + optional: true + '@esbuild/android-x64@0.25.0': optional: true '@esbuild/android-x64@0.25.11': optional: true + '@esbuild/android-x64@0.25.12': + optional: true + '@esbuild/darwin-arm64@0.25.0': optional: true '@esbuild/darwin-arm64@0.25.11': optional: true + '@esbuild/darwin-arm64@0.25.12': + optional: true + '@esbuild/darwin-x64@0.25.0': optional: true '@esbuild/darwin-x64@0.25.11': optional: true + '@esbuild/darwin-x64@0.25.12': + optional: true + '@esbuild/freebsd-arm64@0.25.0': optional: true '@esbuild/freebsd-arm64@0.25.11': optional: true + '@esbuild/freebsd-arm64@0.25.12': + optional: true + '@esbuild/freebsd-x64@0.25.0': optional: true '@esbuild/freebsd-x64@0.25.11': optional: true + '@esbuild/freebsd-x64@0.25.12': + optional: true + '@esbuild/linux-arm64@0.25.0': optional: true '@esbuild/linux-arm64@0.25.11': optional: true + '@esbuild/linux-arm64@0.25.12': + optional: true + '@esbuild/linux-arm@0.25.0': optional: true '@esbuild/linux-arm@0.25.11': optional: true + '@esbuild/linux-arm@0.25.12': + optional: true + '@esbuild/linux-ia32@0.25.0': optional: true '@esbuild/linux-ia32@0.25.11': optional: true + '@esbuild/linux-ia32@0.25.12': + optional: true + '@esbuild/linux-loong64@0.25.0': optional: true '@esbuild/linux-loong64@0.25.11': optional: true + '@esbuild/linux-loong64@0.25.12': + optional: true + '@esbuild/linux-mips64el@0.25.0': optional: true '@esbuild/linux-mips64el@0.25.11': optional: true + '@esbuild/linux-mips64el@0.25.12': + optional: true + '@esbuild/linux-ppc64@0.25.0': optional: true '@esbuild/linux-ppc64@0.25.11': optional: true + '@esbuild/linux-ppc64@0.25.12': + optional: true + '@esbuild/linux-riscv64@0.25.0': optional: true '@esbuild/linux-riscv64@0.25.11': optional: true + '@esbuild/linux-riscv64@0.25.12': + optional: true + '@esbuild/linux-s390x@0.25.0': optional: true '@esbuild/linux-s390x@0.25.11': optional: true + '@esbuild/linux-s390x@0.25.12': + optional: true + '@esbuild/linux-x64@0.25.0': optional: true '@esbuild/linux-x64@0.25.11': optional: true + '@esbuild/linux-x64@0.25.12': + optional: true + '@esbuild/netbsd-arm64@0.25.0': optional: true '@esbuild/netbsd-arm64@0.25.11': optional: true + '@esbuild/netbsd-arm64@0.25.12': + optional: true + '@esbuild/netbsd-x64@0.25.0': optional: true '@esbuild/netbsd-x64@0.25.11': optional: true + '@esbuild/netbsd-x64@0.25.12': + optional: true + '@esbuild/openbsd-arm64@0.25.0': optional: true '@esbuild/openbsd-arm64@0.25.11': optional: true + '@esbuild/openbsd-arm64@0.25.12': + optional: true + '@esbuild/openbsd-x64@0.25.0': optional: true '@esbuild/openbsd-x64@0.25.11': optional: true + '@esbuild/openbsd-x64@0.25.12': + optional: true + '@esbuild/openharmony-arm64@0.25.11': optional: true + '@esbuild/openharmony-arm64@0.25.12': + optional: true + '@esbuild/sunos-x64@0.25.0': optional: true '@esbuild/sunos-x64@0.25.11': optional: true + '@esbuild/sunos-x64@0.25.12': + optional: true + '@esbuild/win32-arm64@0.25.0': optional: true '@esbuild/win32-arm64@0.25.11': optional: true + '@esbuild/win32-arm64@0.25.12': + optional: true + '@esbuild/win32-ia32@0.25.0': optional: true '@esbuild/win32-ia32@0.25.11': optional: true + '@esbuild/win32-ia32@0.25.12': + optional: true + '@esbuild/win32-x64@0.25.0': optional: true '@esbuild/win32-x64@0.25.11': optional: true + '@esbuild/win32-x64@0.25.12': + optional: true + '@eslint-community/eslint-utils@4.7.0(eslint@9.32.0(jiti@2.6.1))': dependencies: eslint: 9.32.0(jiti@2.6.1) @@ -6598,23 +6913,35 @@ snapshots: '@hiveio/beekeeper@1.28.4-rc0': {} - '@hiveio/wax-signers-keychain@1.28.4-rc0-stable.251125135529': + '@hiveio/wax-signers-beekeeper@1.28.4-rc0-stable.251205135508': + dependencies: + '@hiveio/beekeeper': 1.28.4-rc0 + '@hiveio/wax': 1.28.4-rc0-stable.251205135508 + + '@hiveio/wax-signers-external@1.28.4-rc0-stable.251205135508': + dependencies: + '@hiveio/beekeeper': 1.28.4-rc0 + '@hiveio/wax': 1.28.4-rc0-stable.251205135508 + '@hiveio/wax-signers-beekeeper': 1.28.4-rc0-stable.251205135508 + zod: 4.1.13 + + '@hiveio/wax-signers-keychain@1.28.4-rc0-stable.251205135508': dependencies: - '@hiveio/wax': 1.28.4-rc0-stable.251125135529 + '@hiveio/wax': 1.28.4-rc0-stable.251205135508 - '@hiveio/wax-signers-metamask@1.28.4-rc0-stable.251125135529(webextension-polyfill@0.12.0)': + '@hiveio/wax-signers-metamask@1.28.4-rc0-stable.251205135508(webextension-polyfill@0.12.0)': dependencies: - '@hiveio/wax': 1.28.4-rc0-stable.251125135529 + '@hiveio/wax': 1.28.4-rc0-stable.251205135508 '@metamask/providers': 21.0.0(webextension-polyfill@0.12.0) transitivePeerDependencies: - supports-color - webextension-polyfill - '@hiveio/wax-signers-peakvault@1.28.4-rc0-stable.251125135529': + '@hiveio/wax-signers-peakvault@1.28.4-rc0-stable.251205135508': dependencies: - '@hiveio/wax': 1.28.4-rc0-stable.251125135529 + '@hiveio/wax': 1.28.4-rc0-stable.251205135508 - '@hiveio/wax@1.28.4-rc0-stable.251125135529': + '@hiveio/wax@1.28.4-rc0-stable.251205135508': dependencies: events: 3.3.0 @@ -6732,11 +7059,14 @@ snapshots: '@mdi/js@7.4.47': {} - '@metamask/json-rpc-engine@10.0.3': + '@metamask/json-rpc-engine@10.2.0': dependencies: - '@metamask/rpc-errors': 7.0.2 + '@metamask/rpc-errors': 7.0.3 '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 11.3.0 + '@metamask/utils': 11.8.1 + '@types/deep-freeze-strict': 1.1.2 + deep-freeze-strict: 1.1.1 + klona: 2.0.6 transitivePeerDependencies: - supports-color @@ -6757,11 +7087,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/json-rpc-middleware-stream@8.0.7': + '@metamask/json-rpc-middleware-stream@8.0.8': dependencies: - '@metamask/json-rpc-engine': 10.0.3 + '@metamask/json-rpc-engine': 10.2.0 '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 11.3.0 + '@metamask/utils': 11.8.1 readable-stream: 3.6.2 transitivePeerDependencies: - supports-color @@ -6790,12 +7120,12 @@ snapshots: '@metamask/providers@21.0.0(webextension-polyfill@0.12.0)': dependencies: - '@metamask/json-rpc-engine': 10.0.3 - '@metamask/json-rpc-middleware-stream': 8.0.7 + '@metamask/json-rpc-engine': 10.2.0 + '@metamask/json-rpc-middleware-stream': 8.0.8 '@metamask/object-multiplex': 2.1.0 - '@metamask/rpc-errors': 7.0.2 + '@metamask/rpc-errors': 7.0.3 '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 11.3.0 + '@metamask/utils': 11.8.1 detect-browser: 5.3.0 extension-port-stream: 4.2.0(webextension-polyfill@0.12.0) fast-deep-equal: 3.1.3 @@ -6812,9 +7142,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/rpc-errors@7.0.2': + '@metamask/rpc-errors@7.0.3': dependencies: - '@metamask/utils': 11.3.0 + '@metamask/utils': 11.8.1 fast-safe-stringify: 2.1.1 transitivePeerDependencies: - supports-color @@ -6823,14 +7153,18 @@ snapshots: '@metamask/superstruct@3.1.0': {} - '@metamask/utils@11.3.0': + '@metamask/superstruct@3.2.1': {} + + '@metamask/utils@11.8.1': dependencies: '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.1.0 - '@noble/hashes': 1.7.1 - '@scure/base': 1.2.4 + '@metamask/superstruct': 3.2.1 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 '@types/debug': 4.1.12 + '@types/lodash': 4.17.21 debug: 4.4.3 + lodash: 4.17.21 pony-cause: 2.1.11 semver: 7.7.3 uuid: 9.0.1 @@ -6865,9 +7199,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@mtyszczak-cargo/htm@1.3.0(@hiveio/wax@1.28.4-rc0-stable.251125135529)': + '@mtyszczak-cargo/htm@1.3.0(@hiveio/wax@1.28.4-rc0-stable.251205135508)': dependencies: - '@hiveio/wax': 1.28.4-rc0-stable.251125135529 + '@hiveio/wax': 1.28.4-rc0-stable.251205135508 protobufjs: 7.2.5 '@nabla/vite-plugin-eslint@2.0.6(eslint@9.32.0(jiti@2.6.1))(vite@6.2.0(@types/node@22.13.9)(jiti@2.6.1)(terser@5.39.0)(tsx@4.19.3)(yaml@2.8.1))': @@ -6902,6 +7236,8 @@ snapshots: '@noble/hashes@1.7.1': {} + '@noble/hashes@1.8.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -7770,6 +8106,8 @@ snapshots: '@scure/base@1.2.4': {} + '@scure/base@1.2.6': {} + '@scure/bip32@1.4.0': dependencies: '@noble/curves': 1.4.2 @@ -7872,7 +8210,7 @@ snapshots: '@tanstack/virtual-core': 3.13.2 vue: 3.5.22(typescript@5.7.3) - '@tsconfig/node10@1.0.11': + '@tsconfig/node10@1.0.12': optional: true '@tsconfig/node12@1.0.11': @@ -7893,6 +8231,8 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/deep-freeze-strict@1.1.2': {} + '@types/eslint@9.6.1': dependencies: '@types/estree': 1.0.6 @@ -7902,6 +8242,8 @@ snapshots: '@types/estree@1.0.8': {} + '@types/google.accounts@0.0.14': {} + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} @@ -7911,6 +8253,8 @@ snapshots: '@types/ms': 2.1.0 '@types/node': 22.13.9 + '@types/lodash@4.17.21': {} + '@types/ms@2.1.0': {} '@types/node@22.13.9': @@ -9010,6 +9354,8 @@ snapshots: deep-equal@1.0.1: {} + deep-freeze-strict@1.1.1: {} + deep-is@0.1.4: {} deepmerge@4.3.1: {} @@ -9275,6 +9621,36 @@ snapshots: '@esbuild/win32-ia32': 0.25.11 '@esbuild/win32-x64': 0.25.11 + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + optional: true + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -9722,6 +10098,17 @@ snapshots: fuse.js@7.1.0: {} + gaxios@6.7.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + gaxios@7.1.2: dependencies: extend: 3.0.2 @@ -9730,6 +10117,15 @@ snapshots: transitivePeerDependencies: - supports-color + gcp-metadata@6.1.1: + dependencies: + gaxios: 6.7.1 + google-logging-utils: 0.0.2 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + gcp-metadata@8.1.1: dependencies: gaxios: 7.1.2 @@ -9867,14 +10263,56 @@ snapshots: transitivePeerDependencies: - supports-color + google-auth-library@9.15.1: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1 + gcp-metadata: 6.1.1 + gtoken: 7.1.0 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + google-logging-utils@0.0.2: {} + google-logging-utils@1.1.1: {} + googleapis-common@7.2.0: + dependencies: + extend: 3.0.2 + gaxios: 6.7.1 + google-auth-library: 9.15.1 + qs: 6.14.0 + url-template: 2.0.8 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + googleapis@140.0.1: + dependencies: + google-auth-library: 9.15.1 + googleapis-common: 7.2.0 + transitivePeerDependencies: + - encoding + - supports-color + gopd@1.2.0: {} graceful-fs@4.2.11: {} graphemer@1.4.0: {} + gtoken@7.1.0: + dependencies: + gaxios: 6.7.1 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + gtoken@8.0.0: dependencies: gaxios: 7.1.2 @@ -11404,6 +11842,10 @@ snapshots: pngjs: 5.0.0 yargs: 15.4.1 + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + quansync@0.2.11: {} queue-microtask@1.2.3: {} @@ -12059,7 +12501,7 @@ snapshots: ts-node@10.9.2(@swc/core@1.3.78(@swc/helpers@0.5.15))(@types/node@22.13.9)(typescript@5.7.3): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 + '@tsconfig/node10': 1.0.12 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 @@ -12090,7 +12532,7 @@ snapshots: tsx@4.19.3: dependencies: - esbuild: 0.25.11 + esbuild: 0.25.12 get-tsconfig: 4.13.0 optionalDependencies: fsevents: 2.3.3 @@ -12342,6 +12784,8 @@ snapshots: dependencies: punycode: 2.3.1 + url-template@2.0.8: {} + util-deprecate@1.0.2: {} uuid@9.0.1: {} @@ -12689,3 +13133,5 @@ snapshots: archiver-utils: 5.0.2 compress-commons: 6.0.2 readable-stream: 4.7.0 + + zod@4.1.13: {} diff --git a/server/api/auth/google/callback.get.ts b/server/api/auth/google/callback.get.ts new file mode 100644 index 0000000000000000000000000000000000000000..9239cf8a984f90168d54c5b041931521c7b199a3 --- /dev/null +++ b/server/api/auth/google/callback.get.ts @@ -0,0 +1,86 @@ +import { google } from 'googleapis'; + +/** + * GET /api/auth/google/callback + * Handle Google OAuth callback + */ + +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig(); + const query = getQuery(event); + + const code = query.code as string; + const error = query.error as string; + const returnUrl = (query.state as string) || '/'; + + if (error) + return sendRedirect(event, `${config.public.appUrl}${returnUrl}?error=${encodeURIComponent(error)}`); + + + if (!code) + return sendRedirect(event, `${config.public.appUrl}${returnUrl}?error=no_code`); + + + try { + const oauth2Client = new google.auth.OAuth2( + config.googleClientId, + config.googleClientSecret, + `${config.public.appUrl}/api/auth/google/callback` + ); + + // Exchange code for tokens + const { tokens } = await oauth2Client.getToken(code); + + if (!tokens.access_token) + throw new Error('No access token received'); + + + // Set credentials + oauth2Client.setCredentials(tokens); + + // Get user info + const oauth2 = google.oauth2({ version: 'v2', auth: oauth2Client }); + const userInfo = await oauth2.userinfo.get(); + + // Store tokens in httpOnly cookies + setCookie(event, 'google_access_token', tokens.access_token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 7 // 7 days + }); + + if (tokens.refresh_token) { + setCookie(event, 'google_refresh_token', tokens.refresh_token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 30 // 30 days + }); + } else { + // If no refresh token in response, check if we have an old one + // This can happen when user re-authenticates without revoking access + const existingRefreshToken = getCookie(event, 'google_refresh_token'); + if (!existingRefreshToken) + console.warn('No refresh token received and no existing refresh token found'); + } + + // Store user info in a readable cookie (not sensitive) + setCookie(event, 'google_user', JSON.stringify({ + name: userInfo.data.name, + email: userInfo.data.email, + picture: userInfo.data.picture + }), { + httpOnly: false, // Readable by client + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 7 + }); + + // Redirect back to the page user was on + return sendRedirect(event, `${config.public.appUrl}${returnUrl}?auth=success`); + } catch (err) { + console.error('OAuth callback error:', err); + return sendRedirect(event, `${config.public.appUrl}${returnUrl}?error=auth_failed`); + } +}); diff --git a/server/api/auth/google/login.get.ts b/server/api/auth/google/login.get.ts new file mode 100644 index 0000000000000000000000000000000000000000..a0e97b8ddcca55210b3b5b9718590cdfb588fb39 --- /dev/null +++ b/server/api/auth/google/login.get.ts @@ -0,0 +1,33 @@ +import { google } from 'googleapis'; + +/** + * GET /api/auth/google/login + * Initiate Google OAuth flow + */ + +export default defineEventHandler((event) => { + const config = useRuntimeConfig(); + const query = getQuery(event); + const returnUrl = (query.returnUrl as string) || '/'; + + const oauth2Client = new google.auth.OAuth2( + config.googleClientId, + config.googleClientSecret, + `${config.public.appUrl}/api/auth/google/callback` + ); + + // Generate the URL to redirect to for Google OAuth + const authUrl = oauth2Client.generateAuthUrl({ + access_type: 'offline', // Get refresh token + scope: [ + 'https://www.googleapis.com/auth/drive.appdata', + 'https://www.googleapis.com/auth/userinfo.profile', + 'https://www.googleapis.com/auth/userinfo.email' + ], + prompt: 'consent', // Force consent screen to always get refresh token + include_granted_scopes: true, + state: returnUrl // Pass returnUrl through OAuth flow + }); + + return sendRedirect(event, authUrl); +}); diff --git a/server/api/auth/google/logout.post.ts b/server/api/auth/google/logout.post.ts new file mode 100644 index 0000000000000000000000000000000000000000..2db012ae65ff6e3bc7d13e88d5a6f0b3f6c0cf5d --- /dev/null +++ b/server/api/auth/google/logout.post.ts @@ -0,0 +1,41 @@ +import { google } from 'googleapis'; + +/** + * POST /api/auth/google/logout + * Logout from Google and clear session + */ + +export default defineEventHandler(async (event) => { + try { + const accessToken = getCookie(event, 'google_access_token'); + + // Revoke Google token if exists + if (accessToken) { + try { + const oauth2Client = new google.auth.OAuth2(); + oauth2Client.setCredentials({ access_token: accessToken }); + await oauth2Client.revokeCredentials(); + } catch (err) { + console.error('Error revoking Google token:', err); + // Continue with logout even if revoke fails + } + } + + // Clear all cookies + deleteCookie(event, 'google_access_token'); + deleteCookie(event, 'google_refresh_token'); + deleteCookie(event, 'google_user'); + + return { + success: true, + message: 'Logged out successfully' + }; + } catch (error) { + console.error('Logout error:', error); + + throw createError({ + statusCode: 500, + message: 'Failed to logout' + }); + } +}); diff --git a/server/api/auth/google/status.get.ts b/server/api/auth/google/status.get.ts new file mode 100644 index 0000000000000000000000000000000000000000..cecc691d92bdbb749553d4d2e7ebe7967ad8fafd --- /dev/null +++ b/server/api/auth/google/status.get.ts @@ -0,0 +1,30 @@ +/** + * GET /api/auth/google/status + * Check Google authentication status + */ + +export default defineEventHandler((event) => { + const accessToken = getCookie(event, 'google_access_token'); + const userCookie = getCookie(event, 'google_user'); + + if (!accessToken) { + return { + authenticated: false, + user: null + }; + } + + let user = null; + if (userCookie) { + try { + user = JSON.parse(userCookie); + } catch (err) { + console.error('Error parsing user cookie:', err); + } + } + + return { + authenticated: true, + user + }; +}); diff --git a/server/api/google-drive/check-wallet-file.get.ts b/server/api/google-drive/check-wallet-file.get.ts new file mode 100644 index 0000000000000000000000000000000000000000..b7f7d3644ca049d5244ec0b17e2a5d36afac9353 --- /dev/null +++ b/server/api/google-drive/check-wallet-file.get.ts @@ -0,0 +1,88 @@ +import { google } from 'googleapis'; + +/** + * GET /api/google-drive/check-wallet-file + * Check if wallet file exists on Google Drive without loading it + */ +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig(); + + const accessToken = getCookie(event, 'google_access_token'); + const refreshToken = getCookie(event, 'google_refresh_token'); + + if (!accessToken) { + throw createError({ + statusCode: 401, + statusMessage: 'GOOGLE_AUTH_EXPIRED', + message: 'Not authenticated with Google' + }); + } + + try { + // Setup OAuth2 client + const oauth2Client = new google.auth.OAuth2( + config.googleClientId, + config.googleClientSecret, + `${config.public.appUrl}/api/auth/google/callback` + ); + + oauth2Client.setCredentials({ + access_token: accessToken, + refresh_token: refreshToken + }); + + // Handle token refresh - update cookies with new tokens + oauth2Client.on('tokens', (tokens) => { + if (tokens.access_token) { + setCookie(event, 'google_access_token', tokens.access_token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 7 + }); + } + if (tokens.refresh_token) { + setCookie(event, 'google_refresh_token', tokens.refresh_token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 30 + }); + } + }); + + const drive = google.drive({ version: 'v3', auth: oauth2Client }); + + // Search for wallet file in appDataFolder + const response = await drive.files.list({ + q: 'name=\'hivebridge_wallet.json\' and trashed=false', + spaces: 'appDataFolder', + fields: 'files(id, name)' + }); + + const files = response.data.files || []; + const walletExists = files.length > 0; + + return { + exists: walletExists, + fileId: walletExists ? files[0]?.id : null + }; + } catch (error) { + const err = error as { code?: number; message?: string }; + + // If we get 401 or 403, authentication is invalid/expired + if (err.code === 401 || err.code === 403) { + throw createError({ + statusCode: 401, + statusMessage: 'GOOGLE_AUTH_EXPIRED', + message: 'Google authentication has expired or is invalid' + }); + } + + // Other errors + throw createError({ + statusCode: 500, + message: err.message || 'Failed to check wallet file' + }); + } +}); diff --git a/server/api/google-drive/delete-wallet.delete.ts b/server/api/google-drive/delete-wallet.delete.ts new file mode 100644 index 0000000000000000000000000000000000000000..c27613b0e75c73780584681697a69165db49d589 --- /dev/null +++ b/server/api/google-drive/delete-wallet.delete.ts @@ -0,0 +1,72 @@ +import { google } from 'googleapis'; + +/** + * DELETE /api/google-drive/delete-wallet + * Delete the encrypted wallet file from Google Drive + * Requires Google authentication + */ +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig(); + + const accessToken = getCookie(event, 'google_access_token'); + const refreshToken = getCookie(event, 'google_refresh_token'); + + if (!accessToken) { + throw createError({ + statusCode: 401, + message: 'Not authenticated with Google' + }); + } + + try { + // Setup OAuth2 client + const oauth2Client = new google.auth.OAuth2( + config.googleClientId, + config.googleClientSecret, + `${config.public.appUrl}/api/auth/google/callback` + ); + + oauth2Client.setCredentials({ + access_token: accessToken, + refresh_token: refreshToken + }); + + const drive = google.drive({ version: 'v3', auth: oauth2Client }); + + // Search for the wallet file + const response = await drive.files.list({ + q: 'name=\'hivebridge_wallet.json\' and trashed=false', + fields: 'files(id, name)', + spaces: 'appDataFolder' + }); + + const files = response.data.files; + + if (!files || files.length === 0) { + return { + success: true, + message: 'No wallet file found to delete' + }; + } + + // Delete the file + const fileId = files[0].id; + if (fileId) { + await drive.files.delete({ + fileId + }); + } + + return { + success: true, + message: 'Wallet file deleted successfully' + }; + } catch (error) { + const err = error as { statusCode?: number; message?: string }; + + throw createError({ + statusCode: err.statusCode || 500, + message: err.message || 'Failed to delete wallet file' + }); + } +}); diff --git a/server/api/google-drive/token.get.ts b/server/api/google-drive/token.get.ts new file mode 100644 index 0000000000000000000000000000000000000000..8764750a499a8286d8886a813e1e42f1c130cf53 --- /dev/null +++ b/server/api/google-drive/token.get.ts @@ -0,0 +1,75 @@ +import { google } from 'googleapis'; + +/** + * GET /api/google-drive/token + * Get fresh Google access token for Google Drive operations + * This endpoint handles token refresh automatically + */ +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig(); + + const accessToken = getCookie(event, 'google_access_token'); + const refreshToken = getCookie(event, 'google_refresh_token'); + + if (!accessToken) { + throw createError({ + statusCode: 401, + message: 'Not authenticated with Google' + }); + } + + try { + // Setup OAuth2 client with token refresh capability + const oauth2Client = new google.auth.OAuth2( + config.googleClientId, + config.googleClientSecret, + `${config.public.appUrl}/api/auth/google/callback` + ); + + oauth2Client.setCredentials({ + access_token: accessToken, + refresh_token: refreshToken + }); + + // Handle token refresh - update cookies with new tokens + oauth2Client.on('tokens', (tokens) => { + if (tokens.access_token) { + setCookie(event, 'google_access_token', tokens.access_token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 7 + }); + } + if (tokens.refresh_token) { + setCookie(event, 'google_refresh_token', tokens.refresh_token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 30 + }); + } + }); + + // This will trigger token refresh if needed + const currentToken = oauth2Client.credentials.access_token; + + if (!currentToken) { + throw createError({ + statusCode: 401, + message: 'Failed to get valid access token' + }); + } + + return { + success: true, + token: currentToken + }; + } catch (error) { + const err = error as { statusCode?: number; message?: string }; + throw createError({ + statusCode: err.statusCode || 500, + message: err.message || 'Failed to get access token' + }); + } +}); diff --git a/server/api/google-drive/verify-auth.get.ts b/server/api/google-drive/verify-auth.get.ts new file mode 100644 index 0000000000000000000000000000000000000000..a90b3ce7a63d236ebe4780fab2af530bbc5b66e0 --- /dev/null +++ b/server/api/google-drive/verify-auth.get.ts @@ -0,0 +1,92 @@ +import { google } from 'googleapis'; + +/** + * GET /api/google-drive/verify-auth + * Verify Google authentication by making a test request to Google Drive API + * Returns 401 if authentication has expired or is invalid + */ +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig(); + + const accessToken = getCookie(event, 'google_access_token'); + const refreshToken = getCookie(event, 'google_refresh_token'); + + if (!accessToken) { + throw createError({ + statusCode: 401, + statusMessage: 'GOOGLE_AUTH_EXPIRED', + message: 'Not authenticated with Google' + }); + } + + try { + // Setup OAuth2 client + const oauth2Client = new google.auth.OAuth2( + config.googleClientId, + config.googleClientSecret, + `${config.public.appUrl}/api/auth/google/callback` + ); + + oauth2Client.setCredentials({ + access_token: accessToken, + refresh_token: refreshToken + }); + + // Handle token refresh - update cookies with new tokens + oauth2Client.on('tokens', (tokens) => { + if (tokens.access_token) { + setCookie(event, 'google_access_token', tokens.access_token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 7 + }); + } + if (tokens.refresh_token) { + setCookie(event, 'google_refresh_token', tokens.refresh_token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 30 + }); + } + }); + + // Make a test request to Google Drive API to verify authentication + const drive = google.drive({ version: 'v3', auth: oauth2Client }); + + // Simple test request - just get info about user's Drive + await drive.about.get({ fields: 'user' }); + + return { + authenticated: true, + valid: true + }; + } catch (error) { + const err = error as { code?: number; message?: string }; + + // Check for invalid_grant error (refresh token expired or revoked) + if (err.message?.includes('invalid_grant')) { + throw createError({ + statusCode: 401, + statusMessage: 'GOOGLE_AUTH_EXPIRED', + message: 'Google authentication has expired or been revoked. Please reconnect your account.' + }); + } + + // If we get 401 or 403, authentication is invalid/expired + if (err.code === 401 || err.code === 403) { + throw createError({ + statusCode: 401, + statusMessage: 'GOOGLE_AUTH_EXPIRED', + message: 'Google authentication has expired or is invalid' + }); + } + + // Other errors + throw createError({ + statusCode: 500, + message: err.message || 'Failed to verify Google authentication' + }); + } +}); diff --git a/src/assets/icons/wallets/google-drive.svg b/src/assets/icons/wallets/google-drive.svg new file mode 100644 index 0000000000000000000000000000000000000000..34c92d499bdc9c1bddd737e91376c923502b5d61 --- /dev/null +++ b/src/assets/icons/wallets/google-drive.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/components/AccountNamePromptDialog.vue b/src/components/AccountNamePromptDialog.vue new file mode 100644 index 0000000000000000000000000000000000000000..7d1c966df2363e5133f8136a4352ba06d1688e9f --- /dev/null +++ b/src/components/AccountNamePromptDialog.vue @@ -0,0 +1,103 @@ + + + diff --git a/src/components/RecoveryPasswordDialog.vue b/src/components/RecoveryPasswordDialog.vue new file mode 100644 index 0000000000000000000000000000000000000000..b861118642b4cd0764d75ffc296acd7767e690de --- /dev/null +++ b/src/components/RecoveryPasswordDialog.vue @@ -0,0 +1,137 @@ + + + diff --git a/src/components/navigation/AccountSwitcher.vue b/src/components/navigation/AccountSwitcher.vue index 0461051d98fcdf8e5dec283ae3f5016dc7c560f4..4e829aa18c8f12662e99df5947c80e585e6a0d5a 100644 --- a/src/components/navigation/AccountSwitcher.vue +++ b/src/components/navigation/AccountSwitcher.vue @@ -8,12 +8,13 @@ import cTokensLogoUrl from '@/assets/icons/wallets/ctokens.svg'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Button } from '@/components/ui/button'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; -import { useSettingsStore } from '@/stores/settings.store'; +import { useSettingsStore, UsedWallet } from '@/stores/settings.store'; import { useTokensStore } from '@/stores/tokens.store'; import { useUserStore } from '@/stores/user.store'; import { useWalletStore } from '@/stores/wallet.store'; import { toastError } from '@/utils/parse-error'; import CTokensProvider from '@/utils/wallet/ctokens/signer'; +import GoogleDriveWalletProvider from '@/utils/wallet/google-drive/provider'; const settingsStore = useSettingsStore(); const walletStore = useWalletStore(); @@ -34,6 +35,11 @@ const hasHiveAccount = computed(() => // HTM account data const hasHTMAccount = computed(() => tokensStore.wallet !== undefined); +// Check if current Hive account uses Google Drive wallet +const isGoogleDriveWallet = computed(() => + hasHiveAccount.value && settingsStore.settings.wallet === UsedWallet.GOOGLE_DRIVE +); + const htmUserMetadata = ref<{ displayName: string; about?: string; @@ -104,7 +110,10 @@ const connectToHTM = async () => { // Disconnect from Hive const disconnectFromHive = async () => { try { - settingsStore.resetSettings(); + // If Google Drive wallet, logout from Google + if (isGoogleDriveWallet.value) + await GoogleDriveWalletProvider.logout(); + walletStore.resetWallet(); userStore.resetSettings(); // If only Hive was connected, also reset tokens diff --git a/src/components/navigation/AppSidebar.vue b/src/components/navigation/AppSidebar.vue index dc01cfcc6d4a376aed2ba010939f814bcd2ccea5..3a5ef08e6813158ba34f9eb23c01817df35088a3 100644 --- a/src/components/navigation/AppSidebar.vue +++ b/src/components/navigation/AppSidebar.vue @@ -1,5 +1,5 @@ diff --git a/src/pages/index.vue b/src/pages/index.vue index 8484ccb89ea78af5d554ccbcc8d63e37dae6339d..e7008879a941685ebf02359c5ffbd7eab0e10244 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -5,9 +5,11 @@ import AccountBalanceCard from '@/components/utilcards/AccountBalanceCard.vue'; import AccountDetails from '@/components/utilcards/AccountDetailsCard.vue'; import ConnectWalletCard from '@/components/utilcards/ConnectWalletCard.vue'; import { useSettingsStore } from '@/stores/settings.store'; +import { useUserStore } from '@/stores/user.store'; const settingsStore = useSettingsStore(); -const hasUser = computed(() => settingsStore.settings.account !== undefined); +const userStore = useUserStore(); +const hasUser = computed(() => settingsStore.settings.account !== undefined && userStore.isReady);