From 56d0ee733e8f83e4c50712088ca350758c85e735 Mon Sep 17 00:00:00 2001 From: thunkar Date: Mon, 13 Apr 2026 09:57:00 +0200 Subject: [PATCH 1/5] update and refactor --- .../{build.yml => build-artifacts.yml} | 51 +- .github/workflows/ci.yml | 52 +- .github/workflows/deploy-web.yml | 68 +- .github/workflows/release.yml | 43 +- .github/workflows/update-nightly.yml | 79 -- .gitignore | 3 +- app/.eslintrc.json | 16 - app/eslint.config.js | 34 - app/forge.config.ts | 30 +- app/package.json | 45 +- app/scripts/buildNativeHost.js | 13 +- app/scripts/copyBB.js | 18 +- app/src/ipc/preload.ts | 15 +- app/src/ipc/wallet-internal-proxy.ts | 11 +- app/src/main.ts | 36 +- app/src/native-host/index.ts | 5 +- app/src/native-host/ipc-client.ts | 4 +- app/src/native-host/stdio.ts | 4 +- app/src/native-messaging.ts | 102 +-- app/src/ui/utils/wallet-api.ts | 13 +- app/src/utils/logger.ts | 16 +- app/src/workers/wallet-worker.ts | 115 +-- app/tsconfig.json | 2 +- app/vite.main.config.ts | 12 +- app/vite.renderer.config.ts | 17 +- app/wallet-api.d.ts | 6 +- eslint.config.js | 57 ++ extension/entrypoints/background.ts | 36 +- extension/entrypoints/content.ts | 3 +- extension/entrypoints/popup/App.tsx | 70 +- extension/entrypoints/popup/main.tsx | 10 +- extension/package.json | 2 +- extension/yarn.lock | 444 ++++----- package.json | 19 + prettier.config.js | 4 + scripts/toggle-local-aztec.js | 40 +- scripts/update.js | 19 +- shared/package.json | 24 +- shared/src/config/networks.ts | 5 +- shared/src/ipc/wallet-internal-interface.ts | 223 ++--- shared/src/ui/App.tsx | 99 +- shared/src/ui/components/NetworkSelector.tsx | 21 +- .../AuthorizeAccountsContent.tsx | 38 +- .../AuthorizeAddressBookContent.tsx | 28 +- .../AuthorizeCapabilitiesContent.tsx | 277 +++--- .../AuthorizeContractClassMetadataContent.tsx | 29 +- .../AuthorizeContractContent.tsx | 11 +- .../AuthorizeContractMetadataContent.tsx | 25 +- .../AuthorizeCreateAuthWitContent.tsx | 22 +- .../AuthorizePrivateEventsContent.tsx | 21 +- .../authorization/AuthorizeSendTxContent.tsx | 21 +- .../authorization/AuthorizeSenderContent.tsx | 11 +- .../AuthorizeSimulateTxContent.tsx | 10 +- .../AccountsCapabilityDetails.tsx | 9 +- .../capabilities/DataCapabilityDetails.tsx | 10 +- .../SimulationCapabilityDetails.tsx | 32 +- .../TransactionCapabilityDetails.tsx | 22 +- .../authorization/capabilities/helpers.tsx | 13 +- .../authorization/capabilities/types.ts | 5 +- .../dialogs/AuthorizationDialog.tsx | 97 +- .../EditAccountAuthorizationDialog.tsx | 45 +- .../EditAddressBookAuthorizationDialog.tsx | 41 +- .../dialogs/ExecutionTraceDialog.tsx | 13 +- .../dialogs/ProofDebugExportDialog.tsx | 27 +- .../accounts/components/AccountBox.tsx | 6 +- .../ui/components/sections/accounts/index.tsx | 33 +- .../components/AppAuthorizationCard.tsx | 139 ++- .../sections/authorized-apps/index.tsx | 16 +- .../contacts/components/ContactBox.tsx | 3 - .../ui/components/sections/contacts/index.tsx | 7 +- .../sections/interactions/index.tsx | 91 +- .../shared/ExecutionEventDisplay.tsx | 12 +- .../shared/ExecutionTraceDisplay.tsx | 52 +- .../components/shared/FunctionCallDisplay.tsx | 100 +- .../ui/components/shared/PhaseTimeline.tsx | 41 +- .../components/shared/PrivateCallDisplay.tsx | 11 +- .../components/shared/TxProgressTimeline.tsx | 85 +- shared/src/ui/contexts/NetworkContext.tsx | 12 +- shared/src/ui/renderer.tsx | 7 +- shared/src/wallet/core/base-native-wallet.ts | 360 -------- shared/src/wallet/core/demo-wallet.ts | 272 ++++++ shared/src/wallet/core/external-wallet.ts | 114 +-- shared/src/wallet/core/index.ts | 2 +- shared/src/wallet/core/internal-wallet.ts | 134 +-- .../database/wallet-db-authorization.test.ts | 103 ++- shared/src/wallet/database/wallet-db.ts | 286 ++---- .../decoding/call-authorization-formatter.ts | 43 +- shared/src/wallet/decoding/decoding-cache.ts | 31 +- .../wallet/decoding/tx-callstack-decoder.ts | 140 +-- .../wallet/decoding/tx-decoding-service.ts | 30 +- shared/src/wallet/decoding/utils.ts | 4 +- .../managers/authorization-manager.test.ts | 86 +- .../wallet/managers/authorization-manager.ts | 34 +- .../wallet/managers/interaction-manager.ts | 12 +- .../src/wallet/operations/base-operation.ts | 35 +- .../operations/create-authwit-operation.ts | 43 +- .../operations/get-accounts-operation.ts | 23 +- .../operations/get-address-book-operation.ts | 23 +- .../get-contract-class-metadata-operation.ts | 25 +- .../get-contract-metadata-operation.ts | 23 +- .../get-private-events-operation.ts | 30 +- .../operations/register-contract-operation.ts | 48 +- .../operations/register-sender-operation.ts | 36 +- .../request-capabilities-operation.ts | 80 +- .../wallet/operations/send-tx-operation.ts | 100 +- .../operations/simulate-tx-operation.ts | 255 +----- .../operations/simulate-utility-operation.ts | 41 +- shared/src/wallet/types/wallet-interaction.ts | 8 +- shared/src/wallet/utils/simulation-utils.ts | 8 +- shared/src/wallet/utils/sponsored-fpc.ts | 34 - turbo.json | 24 + web/package.json | 26 +- web/src/ui/IframeShell.tsx | 51 +- web/src/ui/StandaloneShell.tsx | 8 +- web/src/ui/components/PinDialog.tsx | 7 +- web/src/ui/utils/wallet-api.ts | 27 +- web/src/wallet/sync-cookies.ts | 24 +- web/src/wallet/wallet-service.ts | 65 +- web/vite.config.ts | 11 +- yarn.lock | 864 ++++++++---------- 120 files changed, 2698 insertions(+), 4180 deletions(-) rename .github/workflows/{build.yml => build-artifacts.yml} (79%) delete mode 100644 .github/workflows/update-nightly.yml delete mode 100644 app/.eslintrc.json delete mode 100644 app/eslint.config.js create mode 100644 eslint.config.js create mode 100644 prettier.config.js delete mode 100644 shared/src/wallet/core/base-native-wallet.ts create mode 100644 shared/src/wallet/core/demo-wallet.ts delete mode 100644 shared/src/wallet/utils/sponsored-fpc.ts create mode 100644 turbo.json diff --git a/.github/workflows/build.yml b/.github/workflows/build-artifacts.yml similarity index 79% rename from .github/workflows/build.yml rename to .github/workflows/build-artifacts.yml index eab1538..bcc4b77 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build-artifacts.yml @@ -1,4 +1,4 @@ -name: Build +name: Build Artifacts on: workflow_call: @@ -22,50 +22,45 @@ jobs: chrome-extension-id: ${{ steps.get-chrome-id.outputs.extension-id }} steps: - - name: Checkout code - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 + - uses: actions/setup-node@v4 with: node-version: "22" - - name: Corepack enable - run: corepack enable + - run: corepack enable - - name: Install dependencies + # Extension has its own lockfile and package manager — install separately + - name: Install extension dependencies working-directory: ./extension run: yarn install --immutable - name: Build Chrome extension (development) if: ${{ !inputs.release-mode }} working-directory: ./extension - run: yarn run build + run: yarn build - name: Build Firefox extension (development) if: ${{ !inputs.release-mode }} working-directory: ./extension - run: yarn run build:firefox + run: yarn build:firefox - - name: Zip Chrome extension (release mode) + - name: Zip Chrome extension (release) if: ${{ inputs.release-mode }} working-directory: ./extension - run: yarn run zip + run: yarn zip - - name: Zip Firefox extension (release mode) + - name: Zip Firefox extension (release) if: ${{ inputs.release-mode }} working-directory: ./extension - run: yarn run zip:firefox + run: yarn zip:firefox - name: Get Chrome extension ID id: get-chrome-id working-directory: ./extension run: | - # Read the extension key from manifest.json and compute the ID - # Chrome extension ID is derived from the "key" field in manifest.json MANIFEST_PATH=".output/chrome-mv3/manifest.json" if [ -f "$MANIFEST_PATH" ]; then - # Extract the key and compute the extension ID KEY=$(jq -r '.key // empty' "$MANIFEST_PATH") if [ -n "$KEY" ]; then # Decode base64 key, hash with SHA256, take first 32 chars, map to a-p @@ -73,11 +68,9 @@ jobs: echo "extension-id=$EXTENSION_ID" >> $GITHUB_OUTPUT echo "Chrome extension ID: $EXTENSION_ID" else - echo "No key found in manifest, extension ID will be empty" echo "extension-id=" >> $GITHUB_OUTPUT fi else - echo "Manifest not found at $MANIFEST_PATH" echo "extension-id=" >> $GITHUB_OUTPUT fi @@ -114,7 +107,7 @@ jobs: retention-days: ${{ inputs.retention-days }} build-electron: - name: Build Electron App + name: Build Electron App (${{ matrix.os }}) runs-on: ${{ matrix.os }} needs: build-extension @@ -123,25 +116,22 @@ jobs: os: [ubuntu-latest, macos-latest] steps: - - name: Checkout code - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 + - uses: actions/setup-node@v4 with: node-version: "22" - - name: Corepack enable - run: corepack enable + - run: corepack enable + # Install from root so the shared workspace package is available to the app - name: Install dependencies - working-directory: ./app run: yarn install --immutable - name: Build Electron app (development) if: ${{ !inputs.release-mode }} working-directory: ./app - run: yarn run package + run: yarn package env: NODE_ENV: production NODE_OPTIONS: --max-old-space-size=4096 @@ -151,7 +141,7 @@ jobs: - name: Build Electron app (release) if: ${{ inputs.release-mode }} working-directory: ./app - run: yarn run make + run: yarn make env: NODE_ENV: production NODE_OPTIONS: --max-old-space-size=4096 @@ -171,6 +161,5 @@ jobs: uses: actions/upload-artifact@v4 with: name: electron-release-${{ matrix.os }} - path: | - app/out/make/**/* + path: app/out/make/**/* retention-days: ${{ inputs.retention-days }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37388ae..82c7e34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,18 +1,62 @@ -name: CI Build +name: CI on: - pull_request: + push: branches: - main - next - push: + pull_request_target: branches: - main - next + workflow_dispatch: + +permissions: + contents: read + pull-requests: write jobs: + lint: + name: Lint & Typecheck + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - uses: actions/setup-node@v4 + with: + node-version: "22" + + - run: corepack enable + + - name: Install dependencies + run: yarn install --immutable + + - name: Lint + run: yarn lint + + - name: Typecheck + run: yarn typecheck + build: - uses: ./.github/workflows/build.yml + name: Build Artifacts + needs: lint + uses: ./.github/workflows/build-artifacts.yml with: release-mode: false retention-days: 7 + + deploy-web: + name: Deploy Web Wallet + needs: lint + uses: ./.github/workflows/deploy-web.yml + with: + production: false + ref: ${{ github.event.pull_request.head.sha || github.sha }} + pr-number: ${{ github.event.pull_request.number || 0 }} + secrets: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} diff --git a/.github/workflows/deploy-web.yml b/.github/workflows/deploy-web.yml index a33c9bc..d30a2ea 100644 --- a/.github/workflows/deploy-web.yml +++ b/.github/workflows/deploy-web.yml @@ -1,38 +1,50 @@ -name: Deploy Web Wallet to Vercel +name: Deploy Web Wallet on: - push: - branches: - - main - pull_request: - branches: - - main - - next - workflow_dispatch: + workflow_call: + inputs: + production: + description: "Deploy to production (true) or preview (false)" + required: false + type: boolean + default: false + ref: + description: "Git ref to check out" + required: false + type: string + default: "" + pr-number: + description: "PR number to comment on (omit to skip comment)" + required: false + type: number + default: 0 + secrets: + VERCEL_TOKEN: + required: true + VERCEL_ORG_ID: + required: true + VERCEL_PROJECT_ID: + required: true env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} -permissions: - contents: read - pull-requests: write - jobs: - deploy-web: + deploy: + name: ${{ inputs.production && 'Deploy (production)' || 'Deploy (preview)' }} runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.sha }} - - name: Set up Node.js - uses: actions/setup-node@v4 + - uses: actions/setup-node@v4 with: - node-version: '22' + node-version: "22" - - name: Enable Corepack - run: corepack enable + - run: corepack enable - name: Install dependencies run: yarn install --immutable @@ -40,15 +52,15 @@ jobs: - name: Install Vercel CLI run: npm install --global vercel@latest - - name: Pull Vercel Environment Information + - name: Pull Vercel environment working-directory: ./web run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} - - name: Build and deploy to Vercel + - name: Build and deploy id: deploy working-directory: ./web run: | - if [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == "refs/heads/main" ]; then + if [ "${{ inputs.production }}" == "true" ]; then vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} DEPLOY_URL=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz --yes) else @@ -57,14 +69,14 @@ jobs: fi echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT - - name: Comment deployment URL on PR - if: github.event_name == 'pull_request' + - name: Comment preview URL on PR + if: ${{ inputs.pr-number != 0 }} uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ - issue_number: context.issue.number, + issue_number: ${{ inputs.pr-number }}, owner: context.repo.owner, repo: context.repo.repo, - body: '🚀 Web wallet deployed to Vercel!\n\n**Preview URL:** ${{ steps.deploy.outputs.url }}' + body: '🚀 Web wallet deployed!\n\n**Preview URL:** ${{ steps.deploy.outputs.url }}' }) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c6abace..de79bf1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,8 +9,32 @@ on: type: string jobs: + lint: + name: Lint & Typecheck + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "22" + + - run: corepack enable + + - name: Install dependencies + run: yarn install --immutable + + - name: Lint + run: yarn lint + + - name: Typecheck + run: yarn typecheck + build: - uses: ./.github/workflows/build.yml + name: Build Artifacts + needs: lint + uses: ./.github/workflows/build-artifacts.yml with: release-mode: true retention-days: 30 @@ -28,9 +52,6 @@ jobs: with: path: release-artifacts - - name: Display structure of downloaded files - run: ls -R release-artifacts - - name: Create Release uses: softprops/action-gh-release@v2 with: @@ -38,7 +59,17 @@ jobs: name: Release ${{ inputs.version }} draft: true generate_release_notes: true - files: | - release-artifacts/**/* + files: release-artifacts/**/* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + deploy-web: + name: Deploy Web Wallet + needs: build + uses: ./.github/workflows/deploy-web.yml + with: + production: true + secrets: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} diff --git a/.github/workflows/update-nightly.yml b/.github/workflows/update-nightly.yml deleted file mode 100644 index fd6ec81..0000000 --- a/.github/workflows/update-nightly.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Update to Latest Nightly - -on: - schedule: - # Run daily at 6 AM UTC (after nextnet deploys at 5 AM) - - cron: '0 6 * * *' - workflow_dispatch: - inputs: - version: - description: 'Nightly version (e.g., 4.0.0-nightly.20260206)' - required: false - type: string - rollup_version: - description: 'Rollup version for nextnet (e.g., 3863723750)' - required: false - type: string - -permissions: - contents: write - pull-requests: write - -jobs: - update-nightly: - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/next' - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - ref: next - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '24' - - - name: Enable Corepack - run: corepack enable - - - name: Run update script - env: - CI: 1 - run: | - ARGS="" - - if [ -n "${{ inputs.version }}" ]; then - ARGS="$ARGS --version ${{ inputs.version }}" - fi - - if [ -n "${{ inputs.rollup_version }}" ]; then - ARGS="$ARGS --rollup-version ${{ inputs.rollup_version }}" - fi - - node scripts/update-to-nightly.js $ARGS - - - name: Get updated version - id: version - run: | - VERSION=$(node -e "const p = JSON.parse(require('fs').readFileSync('app/package.json','utf-8')); console.log(p.dependencies['@aztec/wallet-sdk'])") - echo "version=$VERSION" >> $GITHUB_OUTPUT - - - name: Create Pull Request - uses: peter-evans/create-pull-request@v7 - with: - commit-message: "chore: update to ${{ steps.version.outputs.version }}" - title: "chore: update to ${{ steps.version.outputs.version }}" - body: | - Automated update to Aztec nightly version ${{ steps.version.outputs.version }} - - **Changes:** - - Updated all @aztec/* dependencies in app/package.json - - Updated @aztec/wallet-sdk in extension/package.json - - Updated nextnet rollup version (auto-fetched from nextnet node) - - **Note:** This PR was created automatically by the update-nightly workflow. - branch: automated-nightly-update-${{ steps.version.outputs.version }} - delete-branch: true - base: next diff --git a/.gitignore b/.gitignore index 59565bc..c8f56ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .local-aztec-path node_modules .vercel -.yarn/install-state.gz \ No newline at end of file +.yarn/install-state.gz +.turbo \ No newline at end of file diff --git a/app/.eslintrc.json b/app/.eslintrc.json deleted file mode 100644 index 2d7aa60..0000000 --- a/app/.eslintrc.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "env": { - "browser": true, - "es6": true, - "node": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "plugin:import/recommended", - "plugin:import/electron", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser" -} diff --git a/app/eslint.config.js b/app/eslint.config.js deleted file mode 100644 index 80a979d..0000000 --- a/app/eslint.config.js +++ /dev/null @@ -1,34 +0,0 @@ -import js from "@eslint/js"; -import globals from "globals"; -import reactHooks from "eslint-plugin-react-hooks"; -import reactRefresh from "eslint-plugin-react-refresh"; -import tseslint from "typescript-eslint"; -import eslintConfigPrettier from "eslint-config-prettier/flat"; - -export default tseslint.config( - { ignores: ["dist"] }, - { - extends: [ - js.configs.recommended, - ...tseslint.configs.recommended, - eslintConfigPrettier, - ], - files: ["**/*.{ts,tsx}"], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - plugins: { - "react-hooks": reactHooks, - "react-refresh": reactRefresh, - }, - rules: { - ...reactHooks.configs.recommended.rules, - "react-refresh/only-export-components": [ - "warn", - { allowConstantExport: true }, - ], - '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], - }, - } -); diff --git a/app/forge.config.ts b/app/forge.config.ts index d93b1d4..37ef2f4 100644 --- a/app/forge.config.ts +++ b/app/forge.config.ts @@ -18,10 +18,7 @@ type CopyClass = { type CustomWalker = CopyClass & { modules: Module[]; - walkDependenciesForModule: ( - moduleRoot: string, - depType: DepType, - ) => Promise; + walkDependenciesForModule: (moduleRoot: string, depType: DepType) => Promise; }; const externalDependencies = ["@aztec/kv-store", "@aztec/bb.js"]; @@ -55,32 +52,22 @@ const config: ForgeConfig = { console.log(`External dependencies: ${externalDependencies.join(", ")}`); for (const dep of externalDependencies) { - const walker = new Walker( - path.join(sourceNodeModulesPath, dep), - ) as unknown as CustomWalker; + const walker = new Walker(path.join(sourceNodeModulesPath, dep)) as unknown as CustomWalker; - await walker.walkDependenciesForModule( - path.join(sourceNodeModulesPath, dep), - DepType.PROD, - ); + await walker.walkDependenciesForModule(path.join(sourceNodeModulesPath, dep), DepType.PROD); walker.modules.forEach((treeDep) => { depsToCopy.add(treeDep.name); }); } - console.log( - `Total packages to copy (including transitive): ${depsToCopy.size}`, - ); + console.log(`Total packages to copy (including transitive): ${depsToCopy.size}`); await Promise.all( Array.from(depsToCopy.values()).map(async (packageName) => { // Use mapped source if available, otherwise use the original package name const sourcePackageName = dependencyMap[packageName] || packageName; - const sourcePath = path.join( - sourceNodeModulesPath, - sourcePackageName, - ); + const sourcePath = path.join(sourceNodeModulesPath, sourcePackageName); const destPath = path.join(destNodeModulesPath, packageName); // Check if source exists (handles hoisted/symlinked deps that may not resolve) @@ -103,12 +90,7 @@ const config: ForgeConfig = { }, }, rebuildConfig: {}, - makers: [ - new MakerSquirrel({}), - new MakerZIP({}, ["darwin"]), - new MakerRpm({}), - new MakerDeb({}), - ], + makers: [new MakerSquirrel({}), new MakerZIP({}, ["darwin"]), new MakerRpm({}), new MakerDeb({})], plugins: [ new AutoUnpackNativesPlugin({}), new VitePlugin({ diff --git a/app/package.json b/app/package.json index da231ff..cda982e 100644 --- a/app/package.json +++ b/app/package.json @@ -3,6 +3,7 @@ "productName": "app", "version": "1.0.0", "description": "My Electron application description", + "type": "module", "main": ".vite/build/main.js", "scripts": { "start": "yarn run prebuild && electron-forge start", @@ -11,7 +12,8 @@ "package:test": "yarn run package && ./out/app-darwin-arm64/app.app/Contents/MacOS/app", "make": "yarn run prebuild && yarn run build:native-host && NODE_ENV=production electron-forge make", "publish": "electron-forge publish", - "lint": "eslint --ext .ts,.tsx .", + "lint": "yarn exec eslint .", + "typecheck": "yarn exec tsc --noEmit", "build:native-host": "node scripts/buildNativeHost.js", "build:native-host:all": "node scripts/buildNativeHost.js --all" }, @@ -32,46 +34,39 @@ "@electron-forge/plugin-vite": "^7.9.0", "@electron/fuses": "^1.8.0", "@types/electron-squirrel-startup": "^1.0.2", - "@typescript-eslint/eslint-plugin": "^5.62.0", - "@typescript-eslint/parser": "^5.62.0", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.1", "@vitejs/plugin-react-swc": "^3.5.0", "@yao-pkg/pkg": "^5.15.0", "electron": "38.1.0", - "eslint": "^9.17.0", - "eslint-config-prettier": "^10.1.3", - "eslint-plugin-import": "^2.32.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", "glob": "^11.0.2", "json-stringify-deterministic": "^1.0.12", "lodash.chunk": "^4.2.0", "lodash.isequal": "^4.5.0", "lodash.times": "^4.3.2", "msgpackr": "^1.11.0", - "prettier": "^3.6.2", "sha3": "^2.1.4", "typescript": "~5.6.2", - "typescript-eslint": "^8.32.0", "vite": "^5.4.20", "vite-plugin-node-polyfills": "^0.24.0", "vite-plugin-static-copy": "^3.1.2" }, "dependencies": { - "@aztec/accounts": "v4.2.0-aztecnr-rc.2", - "@aztec/aztec.js": "v4.2.0-aztecnr-rc.2", - "@aztec/bb.js": "v4.2.0-aztecnr-rc.2", - "@aztec/blob-lib": "v4.2.0-aztecnr-rc.2", - "@aztec/constants": "v4.2.0-aztecnr-rc.2", - "@aztec/entrypoints": "v4.2.0-aztecnr-rc.2", - "@aztec/ethereum": "v4.2.0-aztecnr-rc.2", - "@aztec/foundation": "v4.2.0-aztecnr-rc.2", - "@aztec/kv-store": "v4.2.0-aztecnr-rc.2", - "@aztec/noir-contracts.js": "v4.2.0-aztecnr-rc.2", - "@aztec/noir-noirc_abi": "v4.2.0-aztecnr-rc.2", - "@aztec/protocol-contracts": "v4.2.0-aztecnr-rc.2", - "@aztec/pxe": "v4.2.0-aztecnr-rc.2", - "@aztec/stdlib": "v4.2.0-aztecnr-rc.2", - "@aztec/wallet-sdk": "v4.2.0-aztecnr-rc.2", + "@aztec/accounts": "v4.2.0-nightly.20260412", + "@aztec/aztec.js": "v4.2.0-nightly.20260412", + "@aztec/bb.js": "v4.2.0-nightly.20260412", + "@aztec/blob-lib": "v4.2.0-nightly.20260412", + "@aztec/constants": "v4.2.0-nightly.20260412", + "@aztec/entrypoints": "v4.2.0-nightly.20260412", + "@aztec/ethereum": "v4.2.0-nightly.20260412", + "@aztec/foundation": "v4.2.0-nightly.20260412", + "@aztec/kv-store": "v4.2.0-nightly.20260412", + "@aztec/noir-contracts.js": "v4.2.0-nightly.20260412", + "@aztec/noir-noirc_abi": "v4.2.0-nightly.20260412", + "@aztec/protocol-contracts": "v4.2.0-nightly.20260412", + "@aztec/pxe": "v4.2.0-nightly.20260412", + "@aztec/stdlib": "v4.2.0-nightly.20260412", + "@aztec/wallet-sdk": "v4.2.0-nightly.20260412", "@demo-wallet/shared": "workspace:*", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", diff --git a/app/scripts/buildNativeHost.js b/app/scripts/buildNativeHost.js index 1c4cea2..ccf2a74 100644 --- a/app/scripts/buildNativeHost.js +++ b/app/scripts/buildNativeHost.js @@ -53,7 +53,7 @@ function buildBundle() { { cwd: ROOT_DIR, stdio: "inherit", - } + }, ); console.log(`Bundle created: ${BUNDLE_PATH}`); @@ -76,13 +76,10 @@ function buildBinary(target) { console.log(`Building binary for ${target}...`); try { - execSync( - `npx pkg "${BUNDLE_PATH}" --target ${pkgTarget} --output "${outputPath}"`, - { - cwd: ROOT_DIR, - stdio: "inherit", - } - ); + execSync(`npx pkg "${BUNDLE_PATH}" --target ${pkgTarget} --output "${outputPath}"`, { + cwd: ROOT_DIR, + stdio: "inherit", + }); // Make executable on Unix if (!target.startsWith("win32")) { diff --git a/app/scripts/copyBB.js b/app/scripts/copyBB.js index f14a697..373c973 100644 --- a/app/scripts/copyBB.js +++ b/app/scripts/copyBB.js @@ -36,9 +36,7 @@ function getPlatformArch() { } else if (arch === "arm64") { return "arm64-linux"; } - console.error( - `✗ Unsupported Linux architecture: ${arch}. Only x64 and ARM64 are supported.`, - ); + console.error(`✗ Unsupported Linux architecture: ${arch}. Only x64 and ARM64 are supported.`); process.exit(1); case "win32": console.error(`✗ Windows builds are not available for Barretenberg.`); @@ -48,9 +46,7 @@ function getPlatformArch() { process.exit(1); } - console.error( - `✗ Unsupported architecture: ${arch} for platform: ${platform}`, - ); + console.error(`✗ Unsupported architecture: ${arch} for platform: ${platform}`); process.exit(1); } @@ -63,14 +59,8 @@ async function main() { BB_FOLDER, "dest/node/barretenberg_wasm/barretenberg-threads.wasm.gz", ); - const BB_NAPI_SOURCE = path.join( - BB_FOLDER, - `build/${getPlatformArch()}/nodejs_module.node`, - ); - const BB_BINARY_SOURCE = path.join( - BB_FOLDER, - `build/${getPlatformArch()}/bb`, - ); + const BB_NAPI_SOURCE = path.join(BB_FOLDER, `build/${getPlatformArch()}/nodejs_module.node`); + const BB_BINARY_SOURCE = path.join(BB_FOLDER, `build/${getPlatformArch()}/bb`); // Destination directory - will be packaged with the app const RESOURCES_DIR = path.join(__dirname, ".."); diff --git a/app/src/ipc/preload.ts b/app/src/ipc/preload.ts index c6d2d55..b1805be 100644 --- a/app/src/ipc/preload.ts +++ b/app/src/ipc/preload.ts @@ -2,10 +2,7 @@ import type { Aliased } from "@aztec/aztec.js/wallet"; import type { AztecAddress } from "@aztec/aztec.js/addresses"; import { contextBridge, ipcRenderer } from "electron"; import type { TxHash, TxReceipt } from "@aztec/stdlib/tx"; -import type { - WalletInteraction, - WalletInteractionType, -} from "@demo-wallet/shared/core"; +import type { WalletInteraction, WalletInteractionType } from "@demo-wallet/shared/core"; contextBridge.exposeInMainWorld("walletAPI", { getTxReceipt(stringifiedArgs: string): Promise { @@ -26,9 +23,7 @@ contextBridge.exposeInMainWorld("walletAPI", { deployAccount(stringifiedArgs: string): Promise { return ipcRenderer.invoke("deployAccount", stringifiedArgs); }, - getInteractions( - stringifiedArgs: string - ): Promise[]> { + getInteractions(stringifiedArgs: string): Promise[]> { return ipcRenderer.invoke("getInteractions", stringifiedArgs); }, getExecutionTrace(stringifiedArgs: string): Promise { @@ -80,13 +75,11 @@ contextBridge.exposeInMainWorld("walletAPI", { }, // Proof debug export saveProofDebugData( - base64Data: string + base64Data: string, ): Promise<{ success: boolean; canceled?: boolean; filePath?: string; error?: string }> { return ipcRenderer.invoke("saveProofDebugData", base64Data); }, onProofDebugExportRequest(callback) { - return ipcRenderer.on("proof-debug-export-request", (_event, eventData) => - callback(eventData) - ); + return ipcRenderer.on("proof-debug-export-request", (_event, eventData) => callback(eventData)); }, }); diff --git a/app/src/ipc/wallet-internal-proxy.ts b/app/src/ipc/wallet-internal-proxy.ts index e594336..369e689 100644 --- a/app/src/ipc/wallet-internal-proxy.ts +++ b/app/src/ipc/wallet-internal-proxy.ts @@ -1,7 +1,4 @@ -import { - promiseWithResolvers, - type PromiseWithResolvers, -} from "@aztec/foundation/promise"; +import { promiseWithResolvers, type PromiseWithResolvers } from "@aztec/foundation/promise"; import { schemaHasMethod } from "@aztec/foundation/schemas"; import type { MessagePortMain } from "electron/main"; import { @@ -13,7 +10,7 @@ import { } from "@demo-wallet/shared/core"; type FunctionsOf = { - [K in keyof T as T[K] extends Function ? K : never]: T[K]; + [K in keyof T as T[K] extends (...args: unknown[]) => unknown ? K : never]: T[K]; }; export class WalletInternalProxy { @@ -32,9 +29,7 @@ export class WalletInternalProxy { this.authRequestCallback = callback; } - public onProofDebugExportRequest( - callback: OnProofDebugExportRequestListener - ) { + public onProofDebugExportRequest(callback: OnProofDebugExportRequestListener) { this.proofDebugExportCallback = callback; } diff --git a/app/src/main.ts b/app/src/main.ts index 1862eb8..d7c269e 100644 --- a/app/src/main.ts +++ b/app/src/main.ts @@ -8,10 +8,7 @@ import fs, { mkdirSync, writeFile } from "node:fs"; import os from "node:os"; import { createServer, type Socket, type Server } from "node:net"; import { WALLET_DATA_DIR, getSocketPath } from "./shared/paths"; -import { - checkSystemWideManifest, - installNativeMessagingManifests, -} from "./native-messaging"; +import { checkSystemWideManifest, installNativeMessagingManifests } from "./native-messaging"; // Setup logging to file for debugging mkdirSync(WALLET_DATA_DIR, { recursive: true }); @@ -52,36 +49,34 @@ if (app.isPackaged) { if (process.env.BB_WASM_PATH?.includes("__RESOURCES_PATH__")) { process.env.BB_WASM_PATH = process.env.BB_WASM_PATH.replace( "__RESOURCES_PATH__", - resourcesPath + resourcesPath, ); } if (process.env.BB_BINARY_PATH?.includes("__RESOURCES_PATH__")) { process.env.BB_BINARY_PATH = process.env.BB_BINARY_PATH.replace( "__RESOURCES_PATH__", - resourcesPath + resourcesPath, ); } if (process.env.BB_NAPI_PATH?.includes("__RESOURCES_PATH__")) { process.env.BB_NAPI_PATH = process.env.BB_NAPI_PATH.replace( "__RESOURCES_PATH__", - resourcesPath + resourcesPath, ); } if (process.env.NATIVE_HOST_PATH?.includes("__RESOURCES_PATH__")) { process.env.NATIVE_HOST_PATH = process.env.NATIVE_HOST_PATH.replace( "__RESOURCES_PATH__", - resourcesPath + resourcesPath, ); } // Verify binary exists and is executable try { const stats = fs.statSync(process.env.BB_BINARY_PATH!); - console.log( - `BB binary found: ${stats.size} bytes, mode: ${stats.mode.toString(8)}` - ); + console.log(`BB binary found: ${stats.size} bytes, mode: ${stats.mode.toString(8)}`); } catch (error: any) { console.error("BB binary check failed:", error.message); } @@ -272,9 +267,7 @@ const createWindow = () => { if (MAIN_WINDOW_VITE_DEV_SERVER_URL) { mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL); } else { - mainWindow.loadFile( - join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`) - ); + mainWindow.loadFile(join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`)); } // Open the DevTools. @@ -298,12 +291,9 @@ app.on("ready", async () => { installNativeMessagingManifests(nativeHostPath, chromeExtensionId); createWindow(); - const { port1: externalPort1, port2: externalPort2 } = - new MessageChannelMain(); - const { port1: internalPort1, port2: internalPort2 } = - new MessageChannelMain(); - const { port1: walletLogPort1, port2: walletLogPort2 } = - new MessageChannelMain(); + const { port1: externalPort1, port2: externalPort2 } = new MessageChannelMain(); + const { port1: internalPort1, port2: internalPort2 } = new MessageChannelMain(); + const { port1: walletLogPort1, port2: walletLogPort2 } = new MessageChannelMain(); // Create IPC server for native messaging host communication const ipcServer = createIpcServer(externalPort1); @@ -324,11 +314,7 @@ app.on("ready", async () => { env: filteredEnv, }); - wallet.postMessage({ type: "ports" }, [ - externalPort2, - internalPort1, - walletLogPort1, - ]); + wallet.postMessage({ type: "ports" }, [externalPort2, internalPort1, walletLogPort1]); wallet.on("exit", () => { console.error("wallet process died"); diff --git a/app/src/native-host/index.ts b/app/src/native-host/index.ts index 93b90f2..06316af 100644 --- a/app/src/native-host/index.ts +++ b/app/src/native-host/index.ts @@ -45,10 +45,7 @@ async function main(): Promise { status: "connected", }); } catch (err) { - const errorMsg = - err instanceof Error - ? err.message - : "Failed to connect to Demo Wallet app"; + const errorMsg = err instanceof Error ? err.message : "Failed to connect to Demo Wallet app"; log(`Failed to connect: ${errorMsg}`); // Send error back to extension before exiting stdio.send({ diff --git a/app/src/native-host/ipc-client.ts b/app/src/native-host/ipc-client.ts index bab227f..ca27d71 100644 --- a/app/src/native-host/ipc-client.ts +++ b/app/src/native-host/ipc-client.ts @@ -84,8 +84,8 @@ export class IpcClient { } else { reject( new Error( - `Failed to connect to Electron app after ${this.maxReconnectAttempts} attempts` - ) + `Failed to connect to Electron app after ${this.maxReconnectAttempts} attempts`, + ), ); } } else { diff --git a/app/src/native-host/stdio.ts b/app/src/native-host/stdio.ts index a78e720..6efb4a8 100644 --- a/app/src/native-host/stdio.ts +++ b/app/src/native-host/stdio.ts @@ -76,7 +76,9 @@ export class StdioTransport { chunks.push(json.slice(i, i + effectiveChunkSize)); } - console.error(`Chunking message: ${json.length} bytes into ${chunks.length} chunks (id: ${chunkId})`); + console.error( + `Chunking message: ${json.length} bytes into ${chunks.length} chunks (id: ${chunkId})`, + ); // Send each chunk for (let i = 0; i < chunks.length; i++) { diff --git a/app/src/native-messaging.ts b/app/src/native-messaging.ts index 458b215..10d7075 100644 --- a/app/src/native-messaging.ts +++ b/app/src/native-messaging.ts @@ -8,6 +8,7 @@ */ import { app } from "electron"; +import { execSync } from "node:child_process"; import fs from "node:fs"; import os from "node:os"; import { join } from "node:path"; @@ -16,7 +17,6 @@ import { join } from "node:path"; export const NATIVE_HOST_NAME = "com.aztec.keychain"; const FIREFOX_EXTENSION_ID = "aztec-keychain@aztec.network"; - /** * Get the system-wide native messaging manifest path for Chrome. * This is the location Chrome checks when running with a custom --user-data-dir @@ -65,46 +65,46 @@ export function checkSystemWideManifest(nativeHostPath: string, chromeExtensionI allowed_origins: [`chrome-extension://${extensionId}/`], }, null, - 2 + 2, ); console.error(""); console.error( - "╔══════════════════════════════════════════════════════════════════════════════╗" + "╔══════════════════════════════════════════════════════════════════════════════╗", ); console.error( - "║ ║" + "║ ║", ); console.error( - "║ ⚠️ NATIVE MESSAGING MANIFEST NOT FOUND IN SYSTEM-WIDE LOCATION ⚠️ ║" + "║ ⚠️ NATIVE MESSAGING MANIFEST NOT FOUND IN SYSTEM-WIDE LOCATION ⚠️ ║", ); console.error( - "║ ║" + "║ ║", ); console.error( - "║ When using WXT dev mode, Chrome runs with a custom --user-data-dir and ║" + "║ When using WXT dev mode, Chrome runs with a custom --user-data-dir and ║", ); console.error( - "║ only checks the SYSTEM-WIDE location for native messaging hosts. ║" + "║ only checks the SYSTEM-WIDE location for native messaging hosts. ║", ); console.error( - "║ ║" + "║ ║", ); console.error( - "║ The manifest must be installed at: ║" + "║ The manifest must be installed at: ║", ); console.error(`║ ${manifestPath.padEnd(72)}║`); console.error( - "║ ║" + "║ ║", ); console.error( - "║ Run the command below to install it. ║" + "║ Run the command below to install it. ║", ); console.error( - "║ ║" + "║ ║", ); console.error( - "╚══════════════════════════════════════════════════════════════════════════════╝" + "╚══════════════════════════════════════════════════════════════════════════════╝", ); console.error(""); console.error("Copy and paste this command:"); @@ -130,34 +130,26 @@ function getManifestPaths(): { firefox: string[]; chrome: string[] } { switch (process.platform) { case "darwin": - paths.firefox.push( - join(home, "Library/Application Support/Mozilla/NativeMessagingHosts") - ); - paths.chrome.push( - join( - home, - "Library/Application Support/Google/Chrome/NativeMessagingHosts" - ) - ); + paths.firefox.push(join(home, "Library/Application Support/Mozilla/NativeMessagingHosts")); paths.chrome.push( - join(home, "Library/Application Support/Chromium/NativeMessagingHosts") + join(home, "Library/Application Support/Google/Chrome/NativeMessagingHosts"), ); + paths.chrome.push(join(home, "Library/Application Support/Chromium/NativeMessagingHosts")); break; case "linux": paths.firefox.push(join(home, ".mozilla/native-messaging-hosts")); - paths.chrome.push( - join(home, ".config/google-chrome/NativeMessagingHosts") - ); + paths.chrome.push(join(home, ".config/google-chrome/NativeMessagingHosts")); paths.chrome.push(join(home, ".config/chromium/NativeMessagingHosts")); break; - case "win32": + case "win32": { // Windows manifests go in AppData, registry points to them const appData = join(home, "AppData", "Local", "AztecKeychain"); paths.firefox.push(appData); paths.chrome.push(appData); break; + } } return paths; @@ -179,10 +171,7 @@ function createFirefoxManifest(nativeHostPath: string): object { /** * Create Chrome native messaging manifest. */ -function createChromeManifest( - nativeHostPath: string, - extensionId: string -): object { +function createChromeManifest(nativeHostPath: string, extensionId: string): object { return { name: NATIVE_HOST_NAME, description: "Demo Wallet Native Messaging Host", @@ -195,21 +184,13 @@ function createChromeManifest( /** * Install Windows registry keys for native messaging. */ -function installWindowsRegistryKeys(paths: { - firefox: string[]; - chrome: string[]; -}): void { - const { execSync } = require("child_process"); - +function installWindowsRegistryKeys(paths: { firefox: string[]; chrome: string[] }): void { // Firefox registry key - const firefoxManifestPath = join( - paths.firefox[0], - `${NATIVE_HOST_NAME}.json` - ); + const firefoxManifestPath = join(paths.firefox[0], `${NATIVE_HOST_NAME}.json`); try { execSync( `reg add "HKCU\\Software\\Mozilla\\NativeMessagingHosts\\${NATIVE_HOST_NAME}" /ve /t REG_SZ /d "${firefoxManifestPath}" /f`, - { stdio: "pipe" } + { stdio: "pipe" }, ); console.log("Installed Firefox registry key"); } catch (err: any) { @@ -218,14 +199,11 @@ function installWindowsRegistryKeys(paths: { // Chrome registry key if (process.env.CHROME_EXTENSION_ID) { - const chromeManifestPath = join( - paths.chrome[0], - `${NATIVE_HOST_NAME}.json` - ); + const chromeManifestPath = join(paths.chrome[0], `${NATIVE_HOST_NAME}.json`); try { execSync( `reg add "HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${NATIVE_HOST_NAME}" /ve /t REG_SZ /d "${chromeManifestPath}" /f`, - { stdio: "pipe" } + { stdio: "pipe" }, ); console.log("Installed Chrome registry key"); } catch (err: any) { @@ -238,7 +216,10 @@ function installWindowsRegistryKeys(paths: { * Install native messaging manifests for all supported browsers. * Called on app startup to ensure the extension can communicate with the app. */ -export function installNativeMessagingManifests(nativeHostPath: string, chromeExtensionId: string): void { +export function installNativeMessagingManifests( + nativeHostPath: string, + chromeExtensionId: string, +): void { // Verify native host binary exists if (!fs.existsSync(nativeHostPath)) { console.error(`Native host binary not found: ${nativeHostPath}`); @@ -262,19 +243,13 @@ export function installNativeMessagingManifests(nativeHostPath: string, chromeEx fs.writeFileSync(manifestPath, JSON.stringify(firefoxManifest, null, 2)); console.log(`Installed Firefox manifest: ${manifestPath}`); } catch (err: any) { - console.error( - `Failed to install Firefox manifest to ${dir}:`, - err.message - ); + console.error(`Failed to install Firefox manifest to ${dir}:`, err.message); } } // Install Chrome manifests (if extension ID is configured) if (chromeExtensionId) { - const chromeManifest = createChromeManifest( - nativeHostPath, - chromeExtensionId - ); + const chromeManifest = createChromeManifest(nativeHostPath, chromeExtensionId); for (const dir of paths.chrome) { try { if (!fs.existsSync(dir)) { @@ -284,19 +259,12 @@ export function installNativeMessagingManifests(nativeHostPath: string, chromeEx fs.writeFileSync(manifestPath, JSON.stringify(chromeManifest, null, 2)); console.log(`Installed Chrome manifest: ${manifestPath}`); } catch (err: any) { - console.error( - `Failed to install Chrome manifest to ${dir}:`, - err.message - ); + console.error(`Failed to install Chrome manifest to ${dir}:`, err.message); } } } else { - console.log( - "Chrome extension ID not configured, skipping Chrome manifest installation." - ); - console.log( - "In production, set CHROME_EXTENSION_ID env var when building." - ); + console.log("Chrome extension ID not configured, skipping Chrome manifest installation."); + console.log("In production, set CHROME_EXTENSION_ID env var when building."); } // Windows: Add registry keys diff --git a/app/src/ui/utils/wallet-api.ts b/app/src/ui/utils/wallet-api.ts index 170bab9..8316fac 100644 --- a/app/src/ui/utils/wallet-api.ts +++ b/app/src/ui/utils/wallet-api.ts @@ -9,8 +9,7 @@ export class WalletApi { private constructor(chainId: Fr, version: Fr) { const safeCallback = (callback: any) => (eventData: any) => { if (eventData.chainInfo) { - const { chainId: eventChainId, version: eventVersion } = - eventData.chainInfo; + const { chainId: eventChainId, version: eventVersion } = eventData.chainInfo; const currentChainId = chainId.toString(); const currentVersion = version.toString(); @@ -38,9 +37,7 @@ export class WalletApi { args.unshift(chainId, version); const safeArgs = jsonStringify(args); const result = await window.walletAPI[prop](safeArgs); - return InternalWalletInterfaceSchema[ - prop.toString() as keyof InternalWalletInterface - ] + return InternalWalletInterfaceSchema[prop.toString() as keyof InternalWalletInterface] .returnType() .parseAsync(result); }; @@ -50,9 +47,7 @@ export class WalletApi { }; } else if (prop.toString() === "onAuthorizationRequest") { return (callback: any) => { - return window.walletAPI.onAuthorizationRequest( - safeCallback(callback) - ); + return window.walletAPI.onAuthorizationRequest(safeCallback(callback)); }; } else if (prop.toString() === "onProofDebugExportRequest") { return (callback: any) => { @@ -67,7 +62,7 @@ export class WalletApi { throw new Error(`Invalid method ${prop.toString()}`); } }, - } + }, ) as unknown as InternalWalletInterface; } diff --git a/app/src/utils/logger.ts b/app/src/utils/logger.ts index 94229ff..a56f7cd 100644 --- a/app/src/utils/logger.ts +++ b/app/src/utils/logger.ts @@ -2,22 +2,10 @@ import { createLogger, type Logger } from "@aztec/aztec.js/log"; import type { MessagePortMain } from "electron"; import { jsonStringify } from "@aztec/foundation/json-rpc"; -const logLevel = [ - "silent", - "fatal", - "error", - "warn", - "info", - "verbose", - "debug", - "trace", -] as const; +const logLevel = ["silent", "fatal", "error", "warn", "info", "verbose", "debug", "trace"] as const; type LogLevel = (typeof logLevel)[number]; -export function createProxyLogger( - prefix: string, - logPort: MessagePortMain -): Logger { +export function createProxyLogger(prefix: string, logPort: MessagePortMain): Logger { return new Proxy(createLogger(prefix), { get: (target, prop) => { if (logLevel.includes(prop as (typeof logLevel)[number])) { diff --git a/app/src/workers/wallet-worker.ts b/app/src/workers/wallet-worker.ts index 76fef9f..41c7164 100644 --- a/app/src/workers/wallet-worker.ts +++ b/app/src/workers/wallet-worker.ts @@ -13,10 +13,7 @@ import { getNetworkByChainId, } from "@demo-wallet/shared/core"; import { createProxyLogger } from "../utils/logger.ts"; -import type { - AuthorizationRequest, - AuthorizationResponse, -} from "@demo-wallet/shared/core"; +import type { AuthorizationRequest, AuthorizationResponse } from "@demo-wallet/shared/core"; import { createPXE, getPXEConfig, @@ -48,10 +45,7 @@ type SessionData = { db: any; pendingAuthorizations: Map; }>; - wallets: Map< - string, - Promise<{ external: ExternalWallet; internal: InternalWallet }> - >; + wallets: Map>; }; const RUNNING_SESSIONS = new Map(); @@ -62,10 +56,7 @@ async function init( internalPort: MessagePortMain, logPort: MessagePortMain, ) { - const network = getNetworkByChainId( - chainInfo.chainId.toNumber(), - chainInfo.version.toNumber(), - ); + const network = getNetworkByChainId(chainInfo.chainId.toNumber(), chainInfo.version.toNumber()); if (!network) { throw new Error( `Unknown network: chainId=${chainInfo.chainId.toNumber()}, version=${chainInfo.version.toNumber()}`, @@ -126,11 +117,7 @@ async function init( ); const db = WalletDB.init(walletDBStore, walletDBLogger); - const pxe = await createPXE( - node, - { ...getPXEConfig(), ...configOverrides }, - options, - ); + const pxe = await createPXE(node, { ...getPXEConfig(), ...configOverrides }, options); const pendingAuthorizations = new Map< string, @@ -156,14 +143,8 @@ async function init( // Now create wallet instances for this specific appId if they don't exist if (!walletExists) { const internalInit = async () => { - const externalWalletLogger = createProxyLogger( - `wallet:external:${appId}`, - logPort, - ); - const internalWalletLogger = createProxyLogger( - `wallet:internal:${appId}`, - logPort, - ); + const externalWalletLogger = createProxyLogger(`wallet:external:${appId}`, logPort); + const internalWalletLogger = createProxyLogger(`wallet:internal:${appId}`, logPort); // Create both wallet instances sharing the same db, pxe and authorization logic const externalWallet = new ExternalWallet( @@ -199,35 +180,29 @@ async function init( }); }); - wallet.addEventListener( - "authorization-request", - (event: CustomEvent) => { - internalPort.postMessage({ - origin: "wallet", - type: "authorization-request", - content: event.detail, - chainInfo: { - chainId: chainInfo.chainId.toString(), - version: chainInfo.version.toString(), - }, - }); - }, - ); + wallet.addEventListener("authorization-request", (event: CustomEvent) => { + internalPort.postMessage({ + origin: "wallet", + type: "authorization-request", + content: event.detail, + chainInfo: { + chainId: chainInfo.chainId.toString(), + version: chainInfo.version.toString(), + }, + }); + }); - wallet.addEventListener( - "proof-debug-export-request", - (event: CustomEvent) => { - internalPort.postMessage({ - origin: "wallet", - type: "proof-debug-export-request", - content: event.detail, - chainInfo: { - chainId: chainInfo.chainId.toString(), - version: chainInfo.version.toString(), - }, - }); - }, - ); + wallet.addEventListener("proof-debug-export-request", (event: CustomEvent) => { + internalPort.postMessage({ + origin: "wallet", + type: "proof-debug-export-request", + content: event.detail, + chainInfo: { + chainId: chainInfo.chainId.toString(), + version: chainInfo.version.toString(), + }, + }); + }); }; setupWalletEvents(externalWallet); @@ -256,14 +231,14 @@ const handleEvent = async ( if (!schemaHasMethod(schema, type)) { throw new Error(`Unknown method: ${type}`); } - const sanitizedArgs = await parseWithOptionals( - args, - schema[type].parameters(), - ); + const sanitizedArgs = await parseWithOptionals(args, schema[type].parameters()); let result; let error; try { - result = await wallet[type](...sanitizedArgs); + const method = (wallet as unknown as Record Promise>)[ + type + ]; + result = await method(...sanitizedArgs); } catch (err: any) { userLog.error(`Error handling ${type}: ${err.message}`); if (err.stack) { @@ -311,7 +286,7 @@ async function main() { let messageContent; try { messageContent = JSON.parse(content); - } catch (err) { + } catch { userLog.debug(`Unable to parse message ${content}`); return; } @@ -328,24 +303,10 @@ async function main() { logPort, ); // Use external wallet for external requests - handleEvent( - externalPort, - wallets.external, - WalletSchema, - type, - messageId, - args, - userLog, - ); + handleEvent(externalPort, wallets.external, WalletSchema, type, messageId, args, userLog); }); internalPort.on("message", async (event) => { - const { - type, - messageId, - args, - appId: originalAppId, - chainInfo, - } = event.data; + const { type, messageId, args, appId: originalAppId, chainInfo } = event.data; if (!messageId) { return; } @@ -376,9 +337,7 @@ async function main() { // Use internal wallet for internal requests, except when handling // resolveAuthorization (which was always originated by the external one) const wallet = - type === "resolveAuthorization" && appId !== "this" - ? wallets.external - : wallets.internal; + type === "resolveAuthorization" && appId !== "this" ? wallets.external : wallets.internal; handleEvent( internalPort, wallet, diff --git a/app/tsconfig.json b/app/tsconfig.json index 0775267..d196412 100644 --- a/app/tsconfig.json +++ b/app/tsconfig.json @@ -22,5 +22,5 @@ "allowArbitraryExtensions": true, "allowSyntheticDefaultImports": true }, - "include": ["src/**/*", "wallet-api.d.ts"] + "include": ["src/**/*", "wallet-api.d.ts", "forge.env.d.ts"] } diff --git a/app/vite.main.config.ts b/app/vite.main.config.ts index 4fe9b6b..5d67047 100644 --- a/app/vite.main.config.ts +++ b/app/vite.main.config.ts @@ -57,9 +57,7 @@ const BB_WASM_PATH = isDev ? resolve(__dirname, "./bb/barretenberg-threads.wasm.gz") : "__RESOURCES_PATH__/bb/barretenberg-threads.wasm.gz"; -const BB_BINARY_PATH = isDev - ? resolve(__dirname, "./bb/bb") - : "__RESOURCES_PATH__/bb/bb"; +const BB_BINARY_PATH = isDev ? resolve(__dirname, "./bb/bb") : "__RESOURCES_PATH__/bb/bb"; const BB_NAPI_PATH = isDev ? resolve(__dirname, "./bb/nodejs_module.node") @@ -67,14 +65,10 @@ const BB_NAPI_PATH = isDev const platform = process.platform; const arch = process.arch; -const nativeHostBinaryName = - platform === "win32" ? "native-host.exe" : "native-host"; +const nativeHostBinaryName = platform === "win32" ? "native-host.exe" : "native-host"; const NATIVE_HOST_PATH = isDev - ? resolve( - __dirname, - `./dist/native-host/${platform}-${arch}/${nativeHostBinaryName}`, - ) + ? resolve(__dirname, `./dist/native-host/${platform}-${arch}/${nativeHostBinaryName}`) : `__RESOURCES_PATH__/${platform}-${arch}/${nativeHostBinaryName}`; // https://vitejs.dev/config diff --git a/app/vite.renderer.config.ts b/app/vite.renderer.config.ts index 417d4d7..2d4855c 100644 --- a/app/vite.renderer.config.ts +++ b/app/vite.renderer.config.ts @@ -6,12 +6,9 @@ import { PolyfillOptions, nodePolyfills } from "vite-plugin-node-polyfills"; const nodePolyfillsFix = (options?: PolyfillOptions | undefined): Plugin => { return { ...nodePolyfills(options), - /* @ts-ignore */ + // @ts-expect-error - resolveId signature mismatch with vite-plugin-node-polyfills spread type resolveId(source: string) { - const m = - /^vite-plugin-node-polyfills\/shims\/(buffer|global|process)$/.exec( - source, - ); + const m = /^vite-plugin-node-polyfills\/shims\/(buffer|global|process)$/.exec(source); if (m) { return `./node_modules/vite-plugin-node-polyfills/shims/${m[1]}/dist/index.cjs`; } @@ -30,14 +27,8 @@ export default defineConfig({ // app bundle (applying the SWC/JSX transform) rather than as externals // served raw via /@fs/node_modules/. alias: { - "@demo-wallet/shared/ui": resolve( - import.meta.dirname, - "../shared/src/ui.ts", - ), - "@demo-wallet/shared/core": resolve( - import.meta.dirname, - "../shared/src/core.ts", - ), + "@demo-wallet/shared/ui": resolve(import.meta.dirname, "../shared/src/ui.ts"), + "@demo-wallet/shared/core": resolve(import.meta.dirname, "../shared/src/core.ts"), }, }, plugins: [ diff --git a/app/wallet-api.d.ts b/app/wallet-api.d.ts index cbeb84e..b94a78b 100644 --- a/app/wallet-api.d.ts +++ b/app/wallet-api.d.ts @@ -1,8 +1,4 @@ -import type { - InternalWalletInterface, - OnAuthorizationRequestListener, - OnWalletUpdateListener, -} from "./src/wallet-internal-proxy.ts"; +import type { InternalWalletInterface } from "./src/wallet-internal-proxy.ts"; declare global { interface Window { walletAPI: InternalWalletInterface; diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..f43296f --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,57 @@ +import js from "@eslint/js"; +import globals from "globals"; +import reactHooks from "eslint-plugin-react-hooks"; +import reactRefresh from "eslint-plugin-react-refresh"; +import tseslint from "typescript-eslint"; +import eslintConfigPrettier from "eslint-config-prettier/flat"; + +export default tseslint.config( + // Ignore build outputs across all packages + { ignores: ["**/dist/**", "**/out/**", "**/node_modules/**", "**/.turbo/**", "**/.vite/**"] }, + + // Base: all TypeScript files + { + extends: [js.configs.recommended, ...tseslint.configs.recommended, eslintConfigPrettier], + files: ["**/*.{ts,tsx}"], + rules: { + "@typescript-eslint/no-unused-vars": [ + "error", + { argsIgnorePattern: "^_", varsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_" }, + ], + "@typescript-eslint/no-explicit-any": "warn", + }, + }, + + // React packages (app + web + shared UI) + { + files: ["app/src/**/*.{ts,tsx}", "web/src/**/*.{ts,tsx}", "shared/src/ui/**/*.{ts,tsx}"], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + "react-hooks": reactHooks, + "react-refresh": reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], + }, + }, + + // Shared package: Node-compatible, no browser globals + { + files: ["shared/src/**/*.{ts,tsx}"], + languageOptions: { + globals: globals.node, + }, + }, + + // Worker files: Node environment + { + files: ["app/src/workers/**/*.ts", "app/src/native-host/**/*.ts"], + languageOptions: { + globals: globals.node, + }, + }, +); diff --git a/extension/entrypoints/background.ts b/extension/entrypoints/background.ts index 4a6370d..d8ad349 100644 --- a/extension/entrypoints/background.ts +++ b/extension/entrypoints/background.ts @@ -1,8 +1,5 @@ import { BackgroundConnectionHandler } from "@aztec/wallet-sdk/extension/handlers"; -import { - WalletMessageType, - type WalletResponse, -} from "@aztec/wallet-sdk/types"; +import { WalletMessageType, type WalletResponse } from "@aztec/wallet-sdk/types"; import { ChunkReassembler } from "../utils/chunk_reassembler"; // Wallet configuration @@ -60,8 +57,7 @@ export default defineBackground(async () => { return []; } const result = await browser.storage.local.get(REMEMBERED_APPS_KEY); - const apps = - (result[REMEMBERED_APPS_KEY] as RememberedApp[] | undefined) ?? []; + const apps = (result[REMEMBERED_APPS_KEY] as RememberedApp[] | undefined) ?? []; // Filter out old format entries that don't have chainId/version return apps.filter((app) => app.chainId && app.version); } @@ -134,8 +130,7 @@ export default defineBackground(async () => { }, { sendToTab: (tabId, message) => browser.tabs.sendMessage(tabId, message), - addContentListener: (handler) => - browser.runtime.onMessage.addListener(handler), + addContentListener: (handler) => browser.runtime.onMessage.addListener(handler), }, { onPendingDiscovery: (discovery) => { @@ -148,16 +143,9 @@ export default defineBackground(async () => { const version = discovery.chainInfo.version.toString(); // Check if app is remembered for this specific network - if so, auto-approve - isAppRemembered( - discovery.appId, - discovery.origin, - chainId, - version, - ).then((remembered) => { + isAppRemembered(discovery.appId, discovery.origin, chainId, version).then((remembered) => { if (remembered) { - const success = sessionHandler.approveDiscovery( - discovery.requestId, - ); + const success = sessionHandler.approveDiscovery(discovery.requestId); if (success) { console.log( `Auto-approved discovery for remembered app: ${discovery.appId} @ ${discovery.origin} (chain: ${chainId})`, @@ -382,11 +370,7 @@ export default defineBackground(async () => { // Handle messages from popup (content script messages are handled by SDK) browser.runtime.onMessage.addListener((event: any, _sender, sendResponse) => { if (event.origin === "popup") { - return handlePopupMessage( - event.type as PopupMessageType, - event, - sendResponse, - ); + return handlePopupMessage(event.type as PopupMessageType, event, sendResponse); } }); @@ -412,9 +396,7 @@ export default defineBackground(async () => { const sessionId = pendingRequests.get(response.messageId); if (!sessionId) { - console.error( - `No pending request found for messageId ${response.messageId}`, - ); + console.error(`No pending request found for messageId ${response.messageId}`); return; } pendingRequests.delete(response.messageId); @@ -429,9 +411,7 @@ export default defineBackground(async () => { nativePort.onDisconnect.addListener(() => { const error = browser.runtime.lastError; if (error) { - console.error( - `Native host disconnected with error: ${error.message}`, - ); + console.error(`Native host disconnected with error: ${error.message}`); } else { console.log("Native host disconnected"); } diff --git a/extension/entrypoints/content.ts b/extension/entrypoints/content.ts index 93bc9cc..ebf7dbd 100644 --- a/extension/entrypoints/content.ts +++ b/extension/entrypoints/content.ts @@ -16,8 +16,7 @@ export default defineContentScript({ main() { const handler = new ContentScriptConnectionHandler({ sendToBackground: (message) => browser.runtime.sendMessage(message), - addBackgroundListener: (listener) => - browser.runtime.onMessage.addListener(listener), + addBackgroundListener: (listener) => browser.runtime.onMessage.addListener(listener), }); handler.start(); diff --git a/extension/entrypoints/popup/App.tsx b/extension/entrypoints/popup/App.tsx index 4abab10..f945b1a 100644 --- a/extension/entrypoints/popup/App.tsx +++ b/extension/entrypoints/popup/App.tsx @@ -75,18 +75,16 @@ function getHostname(origin: string): string { function EmojiGrid({ emojis }: { emojis: string }): JSX.Element { // Split emojis into array (handles multi-byte emoji correctly) const emojiArray = [...emojis]; - const rows = [ - emojiArray.slice(0, 3), - emojiArray.slice(3, 6), - emojiArray.slice(6, 9), - ]; + const rows = [emojiArray.slice(0, 3), emojiArray.slice(3, 6), emojiArray.slice(6, 9)]; return (
{rows.map((row, i) => (
{row.map((emoji, j) => ( - {emoji} + + {emoji} + ))}
))} @@ -207,7 +205,12 @@ function App() { await refreshData(); }; - const handleForgetApp = async (appId: string, appOrigin: string, chainId: string, version: string) => { + const handleForgetApp = async ( + appId: string, + appOrigin: string, + chainId: string, + version: string, + ) => { await browser.runtime.sendMessage({ origin: "popup", type: "forget-app", @@ -278,12 +281,7 @@ function App() {
- + +
{s.appId || hostname} @@ -444,10 +445,16 @@ function App() { via {hostname} )} - + Chain: {hexToDecimal(s.chainId)} - + Version: {hexToDecimal(s.version)} @@ -485,30 +492,43 @@ function App() { {rememberedApps.map((app) => { const hostname = getHostname(app.origin); const hasActiveSession = sessions.some( - (s) => s.appId === app.appId && s.origin === app.origin + (s) => s.appId === app.appId && s.origin === app.origin, ); return ( -
+
{app.appId} {hasActiveSession && ( - + + ● + )} via {hostname} - + Chain: {hexToDecimal(app.chainId)} - + Version: {hexToDecimal(app.version)}
- diff --git a/shared/src/ui/components/dialogs/EditAddressBookAuthorizationDialog.tsx b/shared/src/ui/components/dialogs/EditAddressBookAuthorizationDialog.tsx index 4629450..35eaf5c 100644 --- a/shared/src/ui/components/dialogs/EditAddressBookAuthorizationDialog.tsx +++ b/shared/src/ui/components/dialogs/EditAddressBookAuthorizationDialog.tsx @@ -57,16 +57,12 @@ export function EditAddressBookAuthorizationDialog({ const contactsWithSelection = contacts.map((contact) => { const isSelected = currentAddresses.has(contact.item.toString()); - const currentContact = currentContacts.find( - (cc) => cc.item === contact.item.toString() - ); + const currentContact = currentContacts.find((cc) => cc.item === contact.item.toString()); return { address: contact.item.toString(), originalAlias: contact.alias, - displayAlias: isSelected - ? currentContact?.alias || contact.alias - : contact.alias, + displayAlias: isSelected ? currentContact?.alias || contact.alias : contact.alias, selected: isSelected, }; }); @@ -81,16 +77,16 @@ export function EditAddressBookAuthorizationDialog({ const handleToggleContact = (address: string) => { setAllContacts((prev) => prev.map((contact) => - contact.address === address ? { ...contact, selected: !contact.selected } : contact - ) + contact.address === address ? { ...contact, selected: !contact.selected } : contact, + ), ); }; const handleAliasChange = (address: string, newAlias: string) => { setAllContacts((prev) => prev.map((contact) => - contact.address === address ? { ...contact, displayAlias: newAlias } : contact - ) + contact.address === address ? { ...contact, displayAlias: newAlias } : contact, + ), ); }; @@ -124,8 +120,7 @@ export function EditAddressBookAuthorizationDialog({ Edit Address Book Authorization for {appId} - Select which contacts this app can access and customize the aliases - shown to the app. + Select which contacts this app can access and customize the aliases shown to the app. {error && ( @@ -161,9 +156,7 @@ export function EditAddressBookAuthorizationDialog({ } label={ - - {contact.originalAlias} - + {contact.originalAlias} - handleAliasChange(contact.address, e.target.value) - } + onChange={(e) => handleAliasChange(contact.address, e.target.value)} sx={{ mt: 1, ml: 4, - '& .MuiInputBase-input': { - overflow: 'hidden', - textOverflow: 'ellipsis' - } + "& .MuiInputBase-input": { + overflow: "hidden", + textOverflow: "ellipsis", + }, }} helperText="The app will see this contact under this alias" /> @@ -209,11 +200,7 @@ export function EditAddressBookAuthorizationDialog({ - diff --git a/shared/src/ui/components/dialogs/ExecutionTraceDialog.tsx b/shared/src/ui/components/dialogs/ExecutionTraceDialog.tsx index 2942eb8..7852d8d 100644 --- a/shared/src/ui/components/dialogs/ExecutionTraceDialog.tsx +++ b/shared/src/ui/components/dialogs/ExecutionTraceDialog.tsx @@ -35,7 +35,9 @@ export function ExecutionTraceDialog({ if (!trace) return null; - const isFromZero = from === "NO_FROM" || (from && from.startsWith("0x") && AztecAddress.fromString(from).equals(AztecAddress.ZERO)); + const isFromZero = + from === "NO_FROM" || + (from && from.startsWith("0x") && AztecAddress.fromString(from).equals(AztecAddress.ZERO)); const hasEmbeddedFeePayer = !!embeddedPaymentMethodFeePayer; return ( @@ -59,18 +61,15 @@ export function ExecutionTraceDialog({ }} > Execution Trace - t.palette.grey[500] }} - > + t.palette.grey[500] }}> {isFromZero && ( - This transaction uses an external entrypoint and does not execute from any of your accounts. + This transaction uses an external entrypoint and does not execute from any of your + accounts. )} {hasEmbeddedFeePayer && ( diff --git a/shared/src/ui/components/dialogs/ProofDebugExportDialog.tsx b/shared/src/ui/components/dialogs/ProofDebugExportDialog.tsx index 78c3938..b097734 100644 --- a/shared/src/ui/components/dialogs/ProofDebugExportDialog.tsx +++ b/shared/src/ui/components/dialogs/ProofDebugExportDialog.tsx @@ -56,8 +56,8 @@ export function ProofDebugExportDialog({ - The proving process failed. You can export debug data to help the - development team investigate this issue. + The proving process failed. You can export debug data to help the development team + investigate this issue. @@ -65,8 +65,7 @@ export function ProofDebugExportDialog({ Privacy Warning - The exported file contains sensitive information{" "} - including: + The exported file contains sensitive information including:
  • @@ -75,34 +74,26 @@ export function ProofDebugExportDialog({
  • - - Circuit bytecode and verification keys - + Circuit bytecode and verification keys
  • - - Function names and execution flow - + Function names and execution flow
  • - Only share this file with trusted parties (e.g., the Aztec development - team) for debugging purposes. + Only share this file with trusted parties (e.g., the Aztec development team) for debugging + purposes. setAcknowledged(e.target.checked)} - /> + setAcknowledged(e.target.checked)} /> } label={ - I understand this file contains sensitive data and I consent to - exporting it + I understand this file contains sensitive data and I consent to exporting it } /> diff --git a/shared/src/ui/components/sections/accounts/components/AccountBox.tsx b/shared/src/ui/components/sections/accounts/components/AccountBox.tsx index 66e574a..5ceb630 100644 --- a/shared/src/ui/components/sections/accounts/components/AccountBox.tsx +++ b/shared/src/ui/components/sections/accounts/components/AccountBox.tsx @@ -96,11 +96,7 @@ export function AccountBox({ account, QRButton = false, onDeploy }: AccountBoxPr
    {!account.deployed && onDeploy && ( - onDeploy(account.item)} - color="primary" - > + onDeploy(account.item)} color="primary"> diff --git a/shared/src/ui/components/sections/accounts/index.tsx b/shared/src/ui/components/sections/accounts/index.tsx index ac08545..a4b52db 100644 --- a/shared/src/ui/components/sections/accounts/index.tsx +++ b/shared/src/ui/components/sections/accounts/index.tsx @@ -53,7 +53,7 @@ export function AccountsManager() { "ecdsasecp256r1", Fr.random(), Fr.random(), - randomBytes(32) + randomBytes(32), ); await loadAccounts(); } catch (err: any) { @@ -72,7 +72,17 @@ export function AccountsManager() { if (loading) { return ( - + Loading accounts... @@ -96,19 +106,10 @@ export function AccountsManager() { Create an account in the standalone wallet first. - + Open wallet - @@ -148,11 +149,7 @@ export function AccountsManager() { onClose={() => setError(null)} anchorOrigin={{ vertical: "bottom", horizontal: "center" }} > - setError(null)} - severity="error" - sx={{ width: "100%" }} - > + setError(null)} severity="error" sx={{ width: "100%" }}> {error} diff --git a/shared/src/ui/components/sections/authorized-apps/components/AppAuthorizationCard.tsx b/shared/src/ui/components/sections/authorized-apps/components/AppAuthorizationCard.tsx index f3cda11..a367fbe 100644 --- a/shared/src/ui/components/sections/authorized-apps/components/AppAuthorizationCard.tsx +++ b/shared/src/ui/components/sections/authorized-apps/components/AppAuthorizationCard.tsx @@ -1,26 +1,22 @@ import { useContext, useEffect, useState, useRef, useCallback } from "react"; -import { - Card, - CardContent, - Typography, - Box, - IconButton, - Tooltip, - Alert, -} from "@mui/material"; -import { - Apps as AppsIcon, - Block as RevokeIcon, -} from "@mui/icons-material"; +import { Card, CardContent, Typography, Box, IconButton, Tooltip, Alert } from "@mui/material"; +import { Apps as AppsIcon, Block as RevokeIcon } from "@mui/icons-material"; import { WalletContext } from "../../../../renderer"; -import type { GrantedCapability, AppCapabilities, CAPABILITY_VERSION, Capability } from "@aztec/aztec.js/wallet"; -import type { AuthorizationItem, RequestCapabilitiesParams } from "../../../../../wallet/types/authorization"; +import type { + GrantedCapability, + AppCapabilities, + CAPABILITY_VERSION, + Capability, +} from "@aztec/aztec.js/wallet"; +import type { + AuthorizationItem, + RequestCapabilitiesParams, +} from "../../../../../wallet/types/authorization"; import { AuthorizeCapabilitiesContent } from "../../../authorization/AuthorizeCapabilitiesContent"; interface AppAuthorizationCardProps { appId: string; onRevoke: (appId: string) => Promise; - onUpdate: () => Promise; } /** @@ -55,16 +51,13 @@ function extractContractAddresses(caps: GrantedCapability[]): string[] { return [...addresses]; } -export function AppAuthorizationCard({ - appId, - onRevoke, - onUpdate, -}: AppAuthorizationCardProps) { +export function AppAuthorizationCard({ appId, onRevoke }: AppAuthorizationCardProps) { const { walletAPI } = useContext(WalletContext); const [loading, setLoading] = useState(true); const [revoking, setRevoking] = useState(false); const [saving, setSaving] = useState(false); - const [fakeRequest, setFakeRequest] = useState | null>(null); + const [fakeRequest, setFakeRequest] = + useState | null>(null); // Track granted capabilities for diffing in handleCapabilitiesChange, but don't // use as a useEffect dependency to avoid re-render loops. const grantedRef = useRef([]); @@ -87,9 +80,8 @@ export function AppAuthorizationCard({ // Resolve contract names from all requested capabilities const addresses = extractContractAddresses(result.requested); - const resolvedNames = addresses.length > 0 - ? await walletAPI.resolveContractNames(addresses) - : {}; + const resolvedNames = + addresses.length > 0 ? await walletAPI.resolveContractNames(addresses) : {}; // Build existingGrants from currently-granted capabilities const existingGrants: Record = {}; @@ -105,9 +97,9 @@ export function AppAuthorizationCard({ // Merge granted account data into the requested capabilities so the // UI initialises checkboxes from the *currently granted* accounts // rather than from the (cumulative) requested list. - const grantedAccountsCap = result.granted.find( - (c) => c.type === "accounts", - ) as GrantedCapability & { accounts?: unknown[] } | undefined; + const grantedAccountsCap = result.granted.find((c) => c.type === "accounts") as + | (GrantedCapability & { accounts?: unknown[] }) + | undefined; const mergedCapabilities = result.requested.map((cap) => { if (cap.type === "accounts" && grantedAccountsCap) { @@ -164,57 +156,56 @@ export function AppAuthorizationCard({ } }; - const handleCapabilitiesChange = useCallback((data: { - granted: GrantedCapability[]; - mode: "strict" | "permissive"; - duration: number; - }) => { - // Clear any pending save - if (saveTimeoutRef.current) { - clearTimeout(saveTimeoutRef.current); - } + const handleCapabilitiesChange = useCallback( + (data: { granted: GrantedCapability[]; mode: "strict" | "permissive"; duration: number }) => { + // Clear any pending save + if (saveTimeoutRef.current) { + clearTimeout(saveTimeoutRef.current); + } - // Debounce: save after 500ms of no changes - saveTimeoutRef.current = setTimeout(async () => { - try { - setSaving(true); + // Debounce: save after 500ms of no changes + saveTimeoutRef.current = setTimeout(async () => { + try { + setSaving(true); - // Build old and new key sets for diffing - const oldGrantedKeys = new Set(); - for (const cap of grantedRef.current) { - const keys = await walletAPI.capabilityToStorageKeys(cap); - for (const key of keys) oldGrantedKeys.add(key); - } + // Build old and new key sets for diffing + const oldGrantedKeys = new Set(); + for (const cap of grantedRef.current) { + const keys = await walletAPI.capabilityToStorageKeys(cap); + for (const key of keys) oldGrantedKeys.add(key); + } - const newGrantedKeys = new Set(); - for (const cap of data.granted) { - const keys = await walletAPI.capabilityToStorageKeys(cap); - for (const key of keys) newGrantedKeys.add(key); - } + const newGrantedKeys = new Set(); + for (const cap of data.granted) { + const keys = await walletAPI.capabilityToStorageKeys(cap); + for (const key of keys) newGrantedKeys.add(key); + } - // Delete individual keys that were removed (not entire capabilities) - for (const key of oldGrantedKeys) { - if (!newGrantedKeys.has(key)) { - await walletAPI.revokeAuthorization(`${appId}:${key}`); + // Delete individual keys that were removed (not entire capabilities) + for (const key of oldGrantedKeys) { + if (!newGrantedKeys.has(key)) { + await walletAPI.revokeAuthorization(`${appId}:${key}`); + } } - } - // Store all newly granted capabilities (additive upsert). - // This also overwrites capability data blobs (e.g. account lists). - if (data.granted.length > 0) { - await walletAPI.storeCapabilityGrants(appId, data.granted); - } + // Store all newly granted capabilities (additive upsert). + // This also overwrites capability data blobs (e.g. account lists). + if (data.granted.length > 0) { + await walletAPI.storeCapabilityGrants(appId, data.granted); + } - // Update ref (not state — no re-render needed) - grantedRef.current = data.granted; - } catch (err) { - console.error("[AppAuthorizationCard] Failed to save capabilities:", err); - alert(`Failed to save: ${err instanceof Error ? err.message : String(err)}`); - } finally { - setSaving(false); - } - }, 500); - }, [appId, walletAPI]); + // Update ref (not state — no re-render needed) + grantedRef.current = data.granted; + } catch (err) { + console.error("[AppAuthorizationCard] Failed to save capabilities:", err); + alert(`Failed to save: ${err instanceof Error ? err.message : String(err)}`); + } finally { + setSaving(false); + } + }, 500); + }, + [appId, walletAPI], + ); return ( @@ -256,9 +247,7 @@ export function AppAuthorizationCard({ showAppId={false} /> ) : ( - - No capabilities have been requested by this app yet - + No capabilities have been requested by this app yet )} diff --git a/shared/src/ui/components/sections/authorized-apps/index.tsx b/shared/src/ui/components/sections/authorized-apps/index.tsx index 73b8a57..9b9676b 100644 --- a/shared/src/ui/components/sections/authorized-apps/index.tsx +++ b/shared/src/ui/components/sections/authorized-apps/index.tsx @@ -40,11 +40,6 @@ export function AuthorizedApps() { } }; - const handleUpdate = async () => { - // Reload apps after updating - await loadApps(); - }; - if (loading) { return ( - No apps have been authorized yet. When you grant persistent - authorizations to external applications, they will appear here. + No apps have been authorized yet. When you grant persistent authorizations to external + applications, they will appear here. ); @@ -89,12 +84,7 @@ export function AuthorizedApps() { {apps.map((appId) => ( - + ))} diff --git a/shared/src/ui/components/sections/contacts/components/ContactBox.tsx b/shared/src/ui/components/sections/contacts/components/ContactBox.tsx index 1902d74..e82673e 100644 --- a/shared/src/ui/components/sections/contacts/components/ContactBox.tsx +++ b/shared/src/ui/components/sections/contacts/components/ContactBox.tsx @@ -1,12 +1,9 @@ -import Button from "@mui/material/Button"; import Typography from "@mui/material/Typography"; import Box from "@mui/material/Box"; import Card from "@mui/material/Card"; -import ArrowDropDown from "@mui/icons-material/ArrowDropDown"; import ContentCopyIcon from "@mui/icons-material/ContentCopy"; import CheckIcon from "@mui/icons-material/Check"; -import { addressToShortStr, keyToShortStr } from "../../../../utils/format"; import IconButton from "@mui/material/IconButton"; import { useState } from "react"; import QrCode from "@mui/icons-material/QrCode"; diff --git a/shared/src/ui/components/sections/contacts/index.tsx b/shared/src/ui/components/sections/contacts/index.tsx index fc539d0..d8f893e 100644 --- a/shared/src/ui/components/sections/contacts/index.tsx +++ b/shared/src/ui/components/sections/contacts/index.tsx @@ -73,12 +73,7 @@ export function ContactsManager() { setAddDialogOpen(true)} /> {/* Add Contact Dialog */} - setAddDialogOpen(false)} - maxWidth="sm" - fullWidth - > + setAddDialogOpen(false)} maxWidth="sm" fullWidth> Add New Contact diff --git a/shared/src/ui/components/sections/interactions/index.tsx b/shared/src/ui/components/sections/interactions/index.tsx index 70d67c7..56d9ecc 100644 --- a/shared/src/ui/components/sections/interactions/index.tsx +++ b/shared/src/ui/components/sections/interactions/index.tsx @@ -30,7 +30,13 @@ import type { ExecutionStats } from "../../shared/PhaseTimeline"; import { TxProgressTimeline } from "../../shared/TxProgressTimeline"; import { WalletContext } from "../../../renderer"; -const TX_TYPES: WalletInteractionType[] = ["sendTx", "simulateTx", "simulateUtility", "createAccount", "deployAccount"]; +const TX_TYPES: WalletInteractionType[] = [ + "sendTx", + "simulateTx", + "simulateUtility", + "createAccount", + "deployAccount", +]; interface InteractionsListProps { interactions: WalletInteraction[]; @@ -64,8 +70,7 @@ const shimmer = keyframes` `; const getStatusIcon = (status: string, complete: boolean) => { - if (status.includes("ERROR") || status.includes("FAIL")) - return ; + if (status.includes("ERROR") || status.includes("FAIL")) return ; if (complete) return ; return ; }; @@ -150,17 +155,16 @@ export function InteractionsList({ phaseStartsRef, }: InteractionsListProps) { const { walletAPI } = useContext(WalletContext); - const [selectedTrace, setSelectedTrace] = - useState(null); + const [selectedTrace, setSelectedTrace] = useState(null); const [selectedStats, setSelectedStats] = useState(null); const [selectedFrom, setSelectedFrom] = useState(null); const [selectedFeePayer, setSelectedFeePayer] = useState(null); const [traceDialogOpen, setTraceDialogOpen] = useState(false); // Lazy-loaded stats for completed tx interactions (for the inline timeline) - const [completedTimings, setCompletedTimings] = useState< - Map - >(new Map()); + const [completedTimings, setCompletedTimings] = useState>( + new Map(), + ); // Evict completed timings for interactions that are running again (same id, re-run). useEffect(() => { @@ -179,37 +183,36 @@ export function InteractionsList({ // Guard: don't fire while any TX interaction is still active — concurrent PXE DB // reads (via decodeTransaction → decodingCache) can corrupt in-flight IDB transactions. useEffect(() => { - const hasActiveTx = interactions.some( - (i) => !i.complete && TX_TYPES.includes(i.type) - ); + const hasActiveTx = interactions.some((i) => !i.complete && TX_TYPES.includes(i.type)); if (hasActiveTx) return; const completedTxInteractions = interactions.filter( - (i) => i.complete && TX_TYPES.includes(i.type) && !completedTimings.has(i.id) + (i) => i.complete && TX_TYPES.includes(i.type) && !completedTimings.has(i.id), ); if (completedTxInteractions.length === 0) return; for (const interaction of completedTxInteractions) { - walletAPI.getExecutionTrace(interaction.id).then((result) => { - setCompletedTimings((prev) => { - const next = new Map(prev); - next.set(interaction.id, { stats: result?.stats as ExecutionStats | undefined }); - return next; - }); - }).catch(() => { - // Mark as attempted so we don't retry - setCompletedTimings((prev) => { - const next = new Map(prev); - next.set(interaction.id, {}); - return next; + walletAPI + .getExecutionTrace(interaction.id) + .then((result) => { + setCompletedTimings((prev) => { + const next = new Map(prev); + next.set(interaction.id, { stats: result?.stats as ExecutionStats | undefined }); + return next; + }); + }) + .catch(() => { + // Mark as attempted so we don't retry + setCompletedTimings((prev) => { + const next = new Map(prev); + next.set(interaction.id, {}); + return next; + }); }); - }); } }, [interactions]); - const handleInteractionClick = async ( - interaction: WalletInteraction - ) => { + const handleInteractionClick = async (interaction: WalletInteraction) => { // Only show trace for simulateTx, simulateUtility, and sendTx interactions if ( interaction.type === "simulateTx" || @@ -238,12 +241,9 @@ export function InteractionsList({ // Filter interactions based on selected types const filteredInteractions = - selectedTypes.length === 0 || - selectedTypes.length === allInteractionTypes.length + selectedTypes.length === 0 || selectedTypes.length === allInteractionTypes.length ? interactions - : interactions.filter((interaction) => - selectedTypes.includes(interaction.type) - ); + : interactions.filter((interaction) => selectedTypes.includes(interaction.type)); return ( @@ -304,9 +304,7 @@ export function InteractionsList({ }} onClick={() => handleInteractionClick(interaction)} > - + {isProvenTx(interaction.type, interaction.status) && ( @@ -382,7 +374,9 @@ export function InteractionsList({ sx={{ p: 0.25 }} onClick={(e) => { e.stopPropagation(); - navigator.clipboard.writeText(extractTxHash(interaction.description)!); + navigator.clipboard.writeText( + extractTxHash(interaction.description)!, + ); }} > @@ -434,9 +428,7 @@ export function InteractionsList({ {/* Filter Controls at Bottom */} - - Filter by Type - + Filter by Type + { const account = await this.getAccountFromAddress(from); - return account.createAuthWit(messageHashOrIntent, chainInfo); + return account.createAuthWit(messageHashOrIntent, this.chainInfo); } /** diff --git a/shared/src/wallet/core/internal-wallet.ts b/shared/src/wallet/core/internal-wallet.ts index 947e539..14258f7 100644 --- a/shared/src/wallet/core/internal-wallet.ts +++ b/shared/src/wallet/core/internal-wallet.ts @@ -169,7 +169,7 @@ export class InternalWallet extends DemoWallet { const simulationResult = await this.simulateViaEntrypoint(executionPayload, { from: opts.from, feeOptions, - additionalScopes: opts.additionalScopes, + additionalScopes: [address], skipTxValidation: true, }); @@ -210,6 +210,7 @@ export class InternalWallet extends DemoWallet { }); const sendOptions = { ...(await toSendOptions(opts)), + additionalScopes: [address], fee: { ...opts.fee, gasSettings }, }; await this.sendTx(executionPayload, sendOptions, interaction); @@ -259,7 +260,10 @@ export class InternalWallet extends DemoWallet { status: "PROVING", }), ); - const provenTx = await this.pxe.proveTx(txRequest, this.scopesFrom(opts.from)); + const provenTx = await this.pxe.proveTx( + txRequest, + this.scopesFrom(opts.from, opts.additionalScopes), + ); const provingTime = Date.now() - provingStartTime; const offchainOutput = extractOffchainOutput( @@ -339,6 +343,14 @@ export class InternalWallet extends DemoWallet { return this.db.listInteractions(); } + deleteInteraction(id: string) { + return this.db.deleteInteraction(id); + } + + clearInteractions() { + return this.db.clearInteractions(); + } + async getExecutionTrace(interactionId: string): Promise< | { trace?: DecodedExecutionTrace; diff --git a/shared/src/wallet/database/wallet-db.ts b/shared/src/wallet/database/wallet-db.ts index 4e123b8..90bafae 100644 --- a/shared/src/wallet/database/wallet-db.ts +++ b/shared/src/wallet/database/wallet-db.ts @@ -281,6 +281,16 @@ export class WalletDB { return result.sort((a, b) => b.timestamp - a.timestamp); } + async deleteInteraction(id: string) { + await this.interactions.delete(id); + } + + async clearInteractions() { + for await (const [id] of this.interactions.entriesAsync()) { + await this.interactions.delete(id); + } + } + async storePersistentAuthorization(appId: string, key: string, data: any) { const fullKey = `${appId}:${key}`; await this.authorizations.set(fullKey, Buffer.from(jsonStringify(data))); diff --git a/shared/src/wallet/operations/register-contract-operation.ts b/shared/src/wallet/operations/register-contract-operation.ts index b73e43f..b095a7d 100644 --- a/shared/src/wallet/operations/register-contract-operation.ts +++ b/shared/src/wallet/operations/register-contract-operation.ts @@ -164,7 +164,8 @@ export class RegisterContractOperation extends ExternalOperation< } async execute(executionData: RegisterContractExecutionData): Promise { - const { instance, artifact, secretKey } = executionData; + const { instance, secretKey } = executionData; + let { artifact } = executionData; const existingInstance = await this.pxe.getContractInstance(instance.address); if (existingInstance) { diff --git a/shared/src/wallet/operations/send-tx-operation.ts b/shared/src/wallet/operations/send-tx-operation.ts index d8692a1..2b99a94 100644 --- a/shared/src/wallet/operations/send-tx-operation.ts +++ b/shared/src/wallet/operations/send-tx-operation.ts @@ -284,7 +284,7 @@ export class SendTxOperation< const profileResult = await this.pxe.profileTx(executionData.txRequest, { profileMode: "execution-steps", skipProofGeneration: true, - scopes: this.scopesFrom(from), + scopes: this.scopesFrom(from, executionData.additionalScopes), }); // Serialize the execution steps to msgpack format diff --git a/shared/src/wallet/utils/index.ts b/shared/src/wallet/utils/index.ts index 0c775e5..b3ec77d 100644 --- a/shared/src/wallet/utils/index.ts +++ b/shared/src/wallet/utils/index.ts @@ -1,3 +1,2 @@ // Wallet utility exports export * from "./simulation-utils"; -export { prepareForFeePayment } from "./sponsored-fpc"; From 6d662657eef783d2b9242119836f680164a54757 Mon Sep 17 00:00:00 2001 From: thunkar Date: Mon, 13 Apr 2026 10:46:50 +0200 Subject: [PATCH 3/5] working --- shared/src/ui/App.tsx | 2 + .../dialogs/ExecutionTraceDialog.tsx | 2 +- .../components/shared/FunctionCallDisplay.tsx | 126 +++++++++--------- 3 files changed, 69 insertions(+), 61 deletions(-) diff --git a/shared/src/ui/App.tsx b/shared/src/ui/App.tsx index 9db1808..f484597 100644 --- a/shared/src/ui/App.tsx +++ b/shared/src/ui/App.tsx @@ -666,6 +666,8 @@ export function App() { interactions={interactions} selectedTypes={selectedInteractionTypes} onTypeFilterChange={setSelectedInteractionTypes} + onDismiss={handleDismissInteraction} + onClearCompleted={handleClearCompleted} phaseStartsRef={phaseStartsRef} /> diff --git a/shared/src/ui/components/dialogs/ExecutionTraceDialog.tsx b/shared/src/ui/components/dialogs/ExecutionTraceDialog.tsx index 7852d8d..4fdcdcf 100644 --- a/shared/src/ui/components/dialogs/ExecutionTraceDialog.tsx +++ b/shared/src/ui/components/dialogs/ExecutionTraceDialog.tsx @@ -65,7 +65,7 @@ export function ExecutionTraceDialog({ - + {isFromZero && ( This transaction uses an external entrypoint and does not execute from any of your diff --git a/shared/src/ui/components/shared/FunctionCallDisplay.tsx b/shared/src/ui/components/shared/FunctionCallDisplay.tsx index 9a79793..9ef10fe 100644 --- a/shared/src/ui/components/shared/FunctionCallDisplay.tsx +++ b/shared/src/ui/components/shared/FunctionCallDisplay.tsx @@ -7,7 +7,7 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Chip from "@mui/material/Chip"; import CallMadeIcon from "@mui/icons-material/CallMade"; import VpnKeyIcon from "@mui/icons-material/VpnKey"; -import type { ReactNode } from "react"; +import { useState, type ReactNode } from "react"; export interface FunctionCallDisplayProps { contractName: string; @@ -45,6 +45,7 @@ export function FunctionCallDisplay({ accordionBgColor = "rgba(0, 0, 0, 0.01)", compact = false, }: FunctionCallDisplayProps) { + const [expanded, setExpanded] = useState(false); const hasArgs = args.length > 0; const hasReturnValues = returnValues.length > 0; // In compact mode, reduce nesting indent to avoid consuming too much width @@ -60,10 +61,11 @@ export function FunctionCallDisplay({ pl: depth > 0 ? (compact ? 1 : 2) : 0, // minWidth:0 allows flex children to shrink below their content size (needed for text truncation) minWidth: 0, - overflow: "hidden", }} > setExpanded(isExpanded)} sx={{ bgcolor: accordionBgColor, boxShadow: compact ? 0 : 1, @@ -85,7 +87,12 @@ export function FunctionCallDisplay({ }, px: 1, } - : undefined + : { + "& .MuiAccordionSummary-content": { + minWidth: 0, + overflow: "hidden", + }, + } } > {contractName}.{functionName}({hasArgs ? "..." : ""}) - - {needsAuth && !compact && ( - } - label="Requires Authorization" - size="small" - color="warning" - variant="filled" - /> - )} - {needsAuth && compact && ( + > } - label="Auth" + label={typeLabel} size="small" - color="warning" - variant="filled" - sx={{ flexShrink: 0, height: 16, fontSize: "0.6rem" }} + color={typeChipColor} + variant="outlined" + sx={{ + height: compact ? 16 : undefined, + fontSize: compact ? "0.6rem" : undefined, + }} /> - )} - {isStaticCall && !compact && } - {hasReturnValues && !compact && ( - - → {returnValues.map((rv) => rv.value).join(", ")} - - )} + {needsAuth && ( + } + label={compact ? "Auth" : "Requires Authorization"} + size="small" + color="warning" + variant="filled" + sx={compact ? { height: 16, fontSize: "0.6rem" } : undefined} + /> + )} + {isStaticCall && !compact && } + {hasReturnValues && !compact && !expanded && ( + + → {returnValues.map((rv) => rv.value).join(", ")} + + )} + - + {/* Arguments (if available) - Show first as most important */} {hasArgs && ( @@ -201,6 +205,7 @@ export function FunctionCallDisplay({ gap: compact ? 0.5 : 1, columnGap: compact ? 1 : 2, alignItems: "start", + minWidth: 0, }} > {args.map((arg, i) => ( @@ -260,6 +265,7 @@ export function FunctionCallDisplay({ gap: compact ? 0.5 : 1, columnGap: compact ? 1 : 2, alignItems: "start", + minWidth: 0, }} > {returnValues.map((rv, i) => ( From dd31da2ad6e7f19cd21b02f28068c96c9f768bac Mon Sep 17 00:00:00 2001 From: thunkar Date: Mon, 13 Apr 2026 10:53:04 +0200 Subject: [PATCH 4/5] fix build --- app/package.json | 6 +++--- app/scripts/{buildNativeHost.js => buildNativeHost.cjs} | 0 app/scripts/{copyBB.js => copyBB.cjs} | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename app/scripts/{buildNativeHost.js => buildNativeHost.cjs} (100%) rename app/scripts/{copyBB.js => copyBB.cjs} (100%) diff --git a/app/package.json b/app/package.json index cda982e..71fd263 100644 --- a/app/package.json +++ b/app/package.json @@ -7,15 +7,15 @@ "main": ".vite/build/main.js", "scripts": { "start": "yarn run prebuild && electron-forge start", - "prebuild": "node scripts/copyBB.js", + "prebuild": "node scripts/copyBB.cjs", "package": "yarn run prebuild && yarn run build:native-host && NODE_ENV=production electron-forge package", "package:test": "yarn run package && ./out/app-darwin-arm64/app.app/Contents/MacOS/app", "make": "yarn run prebuild && yarn run build:native-host && NODE_ENV=production electron-forge make", "publish": "electron-forge publish", "lint": "yarn exec eslint .", "typecheck": "yarn exec tsc --noEmit", - "build:native-host": "node scripts/buildNativeHost.js", - "build:native-host:all": "node scripts/buildNativeHost.js --all" + "build:native-host": "node scripts/buildNativeHost.cjs", + "build:native-host:all": "node scripts/buildNativeHost.cjs --all" }, "keywords": [], "author": { diff --git a/app/scripts/buildNativeHost.js b/app/scripts/buildNativeHost.cjs similarity index 100% rename from app/scripts/buildNativeHost.js rename to app/scripts/buildNativeHost.cjs diff --git a/app/scripts/copyBB.js b/app/scripts/copyBB.cjs similarity index 100% rename from app/scripts/copyBB.js rename to app/scripts/copyBB.cjs From 94ba34d6c5072e17aeba114fe8be3002c02b8b1d Mon Sep 17 00:00:00 2001 From: thunkar Date: Mon, 13 Apr 2026 11:50:30 +0200 Subject: [PATCH 5/5] fixes --- app/package.json | 1 - app/src/workers/wallet-worker.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/package.json b/app/package.json index 71fd263..07e3e73 100644 --- a/app/package.json +++ b/app/package.json @@ -3,7 +3,6 @@ "productName": "app", "version": "1.0.0", "description": "My Electron application description", - "type": "module", "main": ".vite/build/main.js", "scripts": { "start": "yarn run prebuild && electron-forge start", diff --git a/app/src/workers/wallet-worker.ts b/app/src/workers/wallet-worker.ts index 41c7164..56e68f4 100644 --- a/app/src/workers/wallet-worker.ts +++ b/app/src/workers/wallet-worker.ts @@ -237,7 +237,7 @@ const handleEvent = async ( try { const method = (wallet as unknown as Record Promise>)[ type - ]; + ].bind(wallet); result = await method(...sanitizedArgs); } catch (err: any) { userLog.error(`Error handling ${type}: ${err.message}`);