Skip to content

Broadcast mode in SDK#764

Merged
feruzm merged 4 commits into
developfrom
broadcastmode
Apr 22, 2026
Merged

Broadcast mode in SDK#764
feruzm merged 4 commits into
developfrom
broadcastmode

Conversation

@feruzm
Copy link
Copy Markdown
Member

@feruzm feruzm commented Apr 22, 2026

Summary by CodeRabbit

  • New Features
    • Detects and supports multiple Hive browser wallet extensions (Hive Keeper, Hive Keychain, Peak Vault).
    • New sign-in flow: informational modal when no extension is found and a selection dialog when multiple are detected.
    • Extension icons appear on the login button for clearer identification.
    • remembers chosen extension for faster, seamless future sign-ins.
    • Added localized titles and descriptions for extension choices (English).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0133319e-cd1a-4d5d-9c0c-7c6fcb2f78b4

📥 Commits

Reviewing files that changed from the base of the PR and between 09fb22b and 3f9145e.

⛔ Files ignored due to path filters (7)
  • packages/sdk/dist/browser/index.d.ts is excluded by !**/dist/**
  • packages/sdk/dist/browser/index.js is excluded by !**/dist/**
  • packages/sdk/dist/browser/index.js.map is excluded by !**/dist/**, !**/*.map
  • packages/sdk/dist/node/index.cjs is excluded by !**/dist/**
  • packages/sdk/dist/node/index.cjs.map is excluded by !**/dist/**, !**/*.map
  • packages/sdk/dist/node/index.mjs is excluded by !**/dist/**
  • packages/sdk/dist/node/index.mjs.map is excluded by !**/dist/**, !**/*.map
📒 Files selected for processing (6)
  • apps/web/src/features/shared/login/login.tsx
  • apps/web/src/utils/hive-extensions.ts
  • packages/sdk/CHANGELOG.md
  • packages/sdk/package.json
  • packages/wallets/CHANGELOG.md
  • packages/wallets/package.json

📝 Walkthrough

Walkthrough

Adds Hive Unified Wallet Protocol support and user-preferred extension selection to web login; threads an optional broadcastMode parameter through many SDK mutation hooks, with some hooks adjusting cache invalidation timing for async broadcasts.

Changes

Cohort / File(s) Summary
Hive Extension i18n
apps/web/src/features/i18n/locales/en-US.json
Added localization strings for extension info, multi-extension selection, and three specific extensions (Hive Keeper, Hive Keychain, Peak Vault).
Login UI
apps/web/src/features/shared/login/login.tsx
Always render extension button; add modal/state for extension info/selection; persist preferred extension; handle selection to trigger keychain login and update button/icon/disabled states.
Extension utilities
apps/web/src/utils/hive-extensions.ts
Detect providers via window.hive.providers[] (RDNS mapping) with legacy global fallback; add preferred-extension localStorage getters/setters; route signBufferWithExtension and broadcastWithExtension via preferredId or auto-detection; tighten Peak Vault owner restrictions.
SDK hooks — BroadcastMode plumbing
packages/sdk/src/modules/**/mutations/use-*.ts (≈40 files, e.g., accounts, communities, market, posts, wallet, witnesses, promotions, proposals, notifications)
Added optional broadcastMode?: BroadcastMode parameter to many mutation hooks; forward { broadcastMode } into useBroadcastMutation; preserve prior defaults when omitted; several hooks conditionally defer cache invalidation for async mode.
SDK package bump & changelogs
packages/sdk/CHANGELOG.md, packages/sdk/package.json, packages/wallets/CHANGELOG.md, packages/wallets/package.json
Bumped @ecency/sdk to 2.2.6 and packages/wallets to 4.0.4; added changelog entries reflecting broadcast-mode changes.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant LoginUI as Login Component
    participant ExtDetect as Extension Detector
    participant Modal as Extension Modal
    participant Storage as localStorage
    participant Extension as Wallet Extension

    User->>LoginUI: Click "extension" login
    LoginUI->>ExtDetect: getDetectedExtensions()
    ExtDetect-->>LoginUI: detectedExtensions[]
    alt none or multiple without preferred
        LoginUI->>Modal: open extensions info / selection
        Modal-->>User: show options or links
        User->>Modal: select extId
        Modal->>Storage: setPreferredExtensionId(extId)
        Storage-->>Modal: saved
        Modal->>LoginUI: handleSelectExtension(extId)
    end
    LoginUI->>Extension: signBufferWithExtension(preferredId)
    Extension-->>LoginUI: signed response
    LoginUI-->>User: Complete login
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I found small wallets in a row,

I hop and pick the one you know,
I tuck its id in tiny store,
then sign a buffer, hop once more,
and send the broadcast — thump! — lets go.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Broadcast mode in SDK' accurately reflects the main objective of this changeset, which adds optional broadcastMode parameters across multiple SDK mutation hooks and extends extension-selection logic in the login flow.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch broadcastmode

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/src/utils/hive-extensions.ts (1)

153-235: ⚠️ Potential issue | 🟡 Minor

Silent fallback when the preferred extension is unavailable.

In both signBufferWithExtension and broadcastWithExtension, if preferredId (or the persisted value) resolves but the corresponding instance is currently null (e.g., user disabled/uninstalled the extension after saving the preference), the code silently falls through to getKeychainLikeInstance() / getPeakVaultInstance() auto-detection. The user who explicitly picked Peak Vault may suddenly be prompted by Keychain instead, with no indication why.

Consider either rejecting explicitly with a clear "preferred extension no longer available" error, or at minimum clearing the stored preference (setPreferredExtensionId(null)) when the preferred instance can't be resolved, so the selector reopens on the next attempt.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/utils/hive-extensions.ts` around lines 153 - 235, When a
user-selected extension (extId from getPreferredExtensionId() or preferredId)
resolves to null, clear the persisted preference instead of silently falling
back: inside signBufferWithExtension and broadcastWithExtension, after
determining extId and calling getPeakVaultInstance(), getHiveKeeperInstance(),
or getKeychainInstance() and finding the instance is null, call
setPreferredExtensionId(null) (and then continue with the existing
fallback/autodetect logic or return a clear rejection if you prefer). Update
both functions (referencing signBufferWithExtension, broadcastWithExtension,
getPeakVaultInstance, getHiveKeeperInstance, getKeychainInstance,
getKeychainLikeInstance, setPreferredExtensionId, preferredId,
getPreferredExtensionId) so the stored preference is cleared when the desired
extension is unavailable to force the selector to reopen on next attempt.
🧹 Nitpick comments (2)
apps/web/src/utils/hive-extensions.ts (1)

203-234: Minor duplication of the Peak Vault owner-key guard.

The owner-key rejection lives both in the preferred-branch (line 207) and in the legacy auto-detect path (lines 226–228). Consider hoisting it to a single guard at the top of broadcastWithExtension when the resolved extension ends up being Peak Vault, or extracting a helper. Not blocking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/utils/hive-extensions.ts` around lines 203 - 234, The duplicate
Peak Vault owner-key check should be consolidated: in broadcastWithExtension
resolve the target extension once (use extId/preferredId logic and
getPeakVaultInstance()) and then perform a single guard that rejects if the
resolved extension is Peak Vault and keyType === "owner"; after that dispatch to
broadcastViaPeakVault or broadcastViaKeychain as appropriate. Alternatively
extract a small helper (e.g., isPeakVault(instance) or
rejectIfPeakVaultOwner(instance, keyType)) and replace both checks in the
branches (references: extId, preferredId, getPeakVaultInstance, keyType,
broadcastViaPeakVault, broadcastViaKeychain).
apps/web/src/features/shared/login/login.tsx (1)

62-67: Simplify extensionLabel.

The outer and inner else branches both return i18next.t("login.extensions"), so the ternary collapses to:

Proposed change
-  const extensionLabel = detectedExtensions.length > 0
-    ? i18next.t("login.extensions")
-    : hasExtensions
-      ? i18next.t("login.keychain-mobile")
-      : i18next.t("login.extensions");
+  const extensionLabel =
+    detectedExtensions.length === 0 && useKeychainMobile
+      ? i18next.t("login.keychain-mobile")
+      : i18next.t("login.extensions");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/features/shared/login/login.tsx` around lines 62 - 67, The
nested ternary assigning extensionLabel is redundant because both the outer and
inner else return i18next.t("login.extensions"); simplify by computing
extensionLabel from detectedExtensions.length and useKeychainMobile directly:
check detectedExtensions.length first (return i18next.t("login.extensions") if
>0), otherwise return i18next.t("login.keychain-mobile") only when
useKeychainMobile is true, else return i18next.t("login.extensions"); update the
expression around the symbols extensionLabel, detectedExtensions,
useKeychainMobile and the i18next.t calls accordingly to remove the duplicate
branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/features/shared/login/login.tsx`:
- Around line 189-223: The extension Button is incorrectly gated by username
which prevents opening the install-info modal when no username is entered;
update the Button so its disabled prop only depends on isLoginByKeychainPending
(remove !username) and change its onClick handler to call handleExtensionLogin()
when username is present but otherwise open the install/info modal (e.g., call a
showInstallInfoModal or handleShowInstallInfo function). Locate the Button, its
onClick, disabled and icon usage as well as the handleExtensionLogin,
detectedExtensions and extensionLabel symbols and implement the conditional
click routing so the info modal is accessible even without a username while
preserving the login flow when a username exists.

---

Outside diff comments:
In `@apps/web/src/utils/hive-extensions.ts`:
- Around line 153-235: When a user-selected extension (extId from
getPreferredExtensionId() or preferredId) resolves to null, clear the persisted
preference instead of silently falling back: inside signBufferWithExtension and
broadcastWithExtension, after determining extId and calling
getPeakVaultInstance(), getHiveKeeperInstance(), or getKeychainInstance() and
finding the instance is null, call setPreferredExtensionId(null) (and then
continue with the existing fallback/autodetect logic or return a clear rejection
if you prefer). Update both functions (referencing signBufferWithExtension,
broadcastWithExtension, getPeakVaultInstance, getHiveKeeperInstance,
getKeychainInstance, getKeychainLikeInstance, setPreferredExtensionId,
preferredId, getPreferredExtensionId) so the stored preference is cleared when
the desired extension is unavailable to force the selector to reopen on next
attempt.

---

Nitpick comments:
In `@apps/web/src/features/shared/login/login.tsx`:
- Around line 62-67: The nested ternary assigning extensionLabel is redundant
because both the outer and inner else return i18next.t("login.extensions");
simplify by computing extensionLabel from detectedExtensions.length and
useKeychainMobile directly: check detectedExtensions.length first (return
i18next.t("login.extensions") if >0), otherwise return
i18next.t("login.keychain-mobile") only when useKeychainMobile is true, else
return i18next.t("login.extensions"); update the expression around the symbols
extensionLabel, detectedExtensions, useKeychainMobile and the i18next.t calls
accordingly to remove the duplicate branch.

In `@apps/web/src/utils/hive-extensions.ts`:
- Around line 203-234: The duplicate Peak Vault owner-key check should be
consolidated: in broadcastWithExtension resolve the target extension once (use
extId/preferredId logic and getPeakVaultInstance()) and then perform a single
guard that rejects if the resolved extension is Peak Vault and keyType ===
"owner"; after that dispatch to broadcastViaPeakVault or broadcastViaKeychain as
appropriate. Alternatively extract a small helper (e.g., isPeakVault(instance)
or rejectIfPeakVaultOwner(instance, keyType)) and replace both checks in the
branches (references: extId, preferredId, getPeakVaultInstance, keyType,
broadcastViaPeakVault, broadcastViaKeychain).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9df0ee65-2d1e-4694-a6a4-0e40ec6e9aae

📥 Commits

Reviewing files that changed from the base of the PR and between 65c75b5 and 09fb22b.

📒 Files selected for processing (9)
  • apps/web/src/features/shared/login/login.tsx
  • apps/web/src/utils/hive-extensions.ts
  • packages/sdk/src/modules/accounts/mutations/use-claim-account.ts
  • packages/sdk/src/modules/posts/mutations/use-comment.ts
  • packages/sdk/src/modules/posts/mutations/use-reblog.ts
  • packages/sdk/src/modules/posts/mutations/use-update-reply.ts
  • packages/sdk/src/modules/posts/mutations/use-vote.ts
  • packages/sdk/src/modules/wallet/mutations/use-claim-engine-rewards.ts
  • packages/sdk/src/modules/wallet/mutations/use-transfer-to-savings.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/sdk/src/modules/posts/mutations/use-comment.ts
  • packages/sdk/src/modules/wallet/mutations/use-transfer-to-savings.ts
  • packages/sdk/src/modules/posts/mutations/use-update-reply.ts
  • packages/sdk/src/modules/posts/mutations/use-vote.ts
  • packages/sdk/src/modules/wallet/mutations/use-claim-engine-rewards.ts
  • packages/sdk/src/modules/accounts/mutations/use-claim-account.ts
  • packages/sdk/src/modules/posts/mutations/use-reblog.ts

Comment thread apps/web/src/features/shared/login/login.tsx
@feruzm feruzm added the patch Bug fixes and patches (1.0.0 → 1.0.1), add this only if any packages/ have patch changes in PR label Apr 22, 2026
@feruzm feruzm merged commit 1f21af8 into develop Apr 22, 2026
1 check was pending
@feruzm feruzm deleted the broadcastmode branch April 22, 2026 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch Bug fixes and patches (1.0.0 → 1.0.1), add this only if any packages/ have patch changes in PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant