Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: keepkey/keepkey-client
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: keepkey/keepkey-client
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: develop
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 7 commits
  • 23 files changed
  • 3 contributors

Commits on Jul 18, 2026

  1. Merge pull request #128 from keepkey/master

    chore: sync master back into develop (0.0.37 drop-scripting)
    BitHighlander authored Jul 18, 2026
    Configuration menu
    Copy the full SHA
    5be0b82 View commit details
    Browse the repository at this point in the history

Commits on Jul 20, 2026

  1. feat(hive): limit_order_create / limit_order_cancel clear-sign gate (#…

    …130)
    
    * docs(hive): handoff for vault limit_order_create/cancel serializer
    
    Firmware clear-signs both ops (PR #315). Vault has no serializer for them,
    so Hive internal-market swaps still fail at hive_broadcast. Doc pins the
    byte layout the firmware parser expects.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    
    * feat(hive): allow limit_order_create / limit_order_cancel
    
    Opens the client clear-sign gate now that the vault serializer exists
    (keepkey-vault #373) and the firmware parses both ops (keepkey-firmware
    #315). Adds an approval-screen summary line for each.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
    BitHighlander and claude authored Jul 20, 2026
    Configuration menu
    Copy the full SHA
    2b191ab View commit details
    Browse the repository at this point in the history
  2. feat(bex): every page-touching MCP tool shows UI in the page (#129)

    The driving overlay fired only from showThen(), which has three callers —
    click, type and select. Every other tool that touches a page ran with no
    indication to the user at all: bex_snapshot, bex_find and bex_read_page read
    the DOM, bex_console/bex_network/bex_perf read page state, bex_storage reads
    localStorage, and bex_screenshot captures the tab. Reading and capturing a
    user's page are precisely the operations that most need to be visible.
    
    Enforce it at the dispatcher instead of per call site. executeBrowserTool()
    announces before the switch, so a tool added later is covered by construction
    rather than by remembering. Each tool is either in ANNOUNCE_CAPTIONS or in
    NO_ANNOUNCE with a stated reason; announceContract.test.ts fails the build on
    any tool that is in neither, so a silent tool cannot ship.
    
    Exempt, with reasons: bex_panel is the UI itself; bex_tabs touches no page;
    bex_navigate and bex_bring_to_front are self-evident (the user watches their
    own tab move); click/type/select are already announced page-side by showThen,
    which additionally points at the target.
    
    bex_screenshot now refuses a tab whose content script is missing. Reaching the
    content script is what proves the tab CAN show the indicator, and it is
    already required to hide the overlay out of the capture — so a capture that
    cannot be announced is no longer taken. The remedy is the page reload the
    no_content_script error already names.
    
    Banner lifetime: BANNER_IDLE_MS was 8s, so the "MCP is driving this tab"
    banner vanished during any quiet stretch — including while waiting on a
    hardware-wallet confirmation, the longest silence and the highest stakes in
    the whole flow. It now stays up until the agent says it is done (panel 'done'
    or hide), with a 5 minute safety net for an agent that dies mid-session.
    
    No new permissions. The overlay is plain DOM in the content script that is
    already declaratively injected on <all_urls>; the scripting permission dropped
    in b3e3126 was only ever for executeScript into pre-existing tabs.
    BitHighlander authored Jul 20, 2026
    Configuration menu
    Copy the full SHA
    09e4ca8 View commit details
    Browse the repository at this point in the history
  3. fix(hive): render op summaries in the approval card (#131)

    * fix(hive): render op summaries in the approval card
    
    hiveHandler built a one-line summary per operation (opSummary) into
    unsignedTx.operations and no component ever read it. Grepping
    pages/side-panel/src/approval for `.operations` returned zero hits, so a
    Hive batch fell through to the generic amount table, which has no
    destination or amount to show for an op batch and rendered "N/A" and "0".
    The summaries surfaced only inside RequestDataCard's collapsed raw-JSON
    dump.
    
    That matters most for the four ops the extension does not construct
    itself — claim_reward_balance, account_update2, limit_order_create and
    limit_order_cancel reach the device via requestBroadcast, so a dApp
    composes them and the panel was the user's only look at them before the
    device screen. The OLED is authoritative and was always correct, so this
    was never a signing hole; but the clear-sign table exists so the user can
    compare the screen against what the dApp asked for, and half of that
    comparison was an unreadable blob.
    
    RequestDetailsCard now renders the account plus one row per op, falling
    back to the op name rather than blanking a row — an unsummarized op must
    stay visible, not disappear.
    
    SUPPORTED_OPS and opSummary move to hiveOps.ts, a leaf module.
    hiveHandler.ts imports @extension/storage, which touches chrome.* at
    import time and throws under vitest ("chrome is not defined"), so the
    table was untestable where it lived. No logic changed in the move.
    
    hiveOpSummary.test.ts pins the contract the card depends on: every op in
    SUPPORTED_OPS must summarize to something other than its own bare name
    (opSummary's default arm returns `name`, which is exactly the unreadable
    render this fixes) and must carry a test payload. It also pins the
    details a user has to check against the OLED — amounts with their
    symbols, the counterparty account, the '0.000000 VESTS' sentinels that
    mean stop/remove rather than "send zero", and comment_options
    beneficiary names and percentages, since a payout redirect is the one
    thing in the table an attacker would most want unreadable.
    
    Differential-verified: deleting the limit_order_create case fails with
    "limit_order_create falls through to the default arm — add a case to
    opSummary()".
    
    121 tests pass, up from 116. type-check clean across all 15 packages.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    
    * fix(hive): show the signed payload, not a lossy render of it
    
    Review of #131 found three ways the approval could differ from what the
    device signs.
    
    custom_json rendered String(p.json). The vault serializes
    `typeof json === 'string' ? json : JSON.stringify(json ?? {})`
    (hive-ops.ts:151), so a dApp passing an object got "[object Object]" in
    the panel while the object's real contents went to the device — the
    approval showed neither the value nor that it was hiding one. Mirror the
    vault's own expression instead.
    
    Truncation at 120 chars was unmarked, so two payloads sharing a prefix
    rendered as the same string. The cut now carries the dropped length.
    
    comment_options showed only the post and its beneficiaries, omitting
    max_accepted_payout, percent_hbd, allow_votes and allow_curation_rewards.
    A declined payout, an all-HIVE split and a votes-disabled post therefore
    had identical browser approvals. Every control that differs from the Hive
    default is now named; defaults stay quiet so the common case remains a
    one-liner. percent_steem_dollars is read as the alias the vault also
    accepts (hive-ops.ts:225) — ignoring it would have shown the default
    while a non-default value was signed.
    
    unsignedTx.operations kept only {op, summary}, so the Raw tab could not
    recover what the summary elides. It now carries `params` verbatim.
    RequestDataCard renders transaction.unsignedTx and nothing else — the
    event's own `request` is never displayed in any tab — so this is the only
    surface on which the operation body appears at all.
    
    The approval also opened on the Raw tab (defaultIndex={1}), whose data
    section is useState(false) and so renders a collapsed chevron with no
    transaction facts on it. A user could approve having seen nothing. Basic
    is now the default. This affects all five chains routed to
    OtherTransaction (ripple, solana, ton, tron, hive), and is an improvement
    or a wash for each: Hive, Ripple and Tron contract-calls gain a populated
    table, and the chains that render N/A in Basic were previously landing on
    an empty panel anyway, so the cost is one click to reach Raw and no fact
    became less visible.
    
    Differential-verified: restoring String(p.json) fails with
    "expected 'follow: [object Object]' not to contain '[object Object]'";
    dropping the payout controls fails with
    "expected 'Payout options for @alice/a-post' to contain '0.000 HBD'".
    
    125 tests pass, up from 121. type-check, prettier and build clean.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
    BitHighlander and claude authored Jul 20, 2026
    Configuration menu
    Copy the full SHA
    e2a0e57 View commit details
    Browse the repository at this point in the history

Commits on Jul 31, 2026

  1. fix(injected): reject with an Error, not a bare string

    Closes #132.
    
    The background sends failures across postMessage as a plain string
    (`sendResponse({ error: formatUserError(error) })`), and every injected
    provider rejected with that string untouched. EIP-1193 requires rejecting
    with an object carrying `code` and `message`, and dApp libraries rely on it:
    wagmi/viem/ethers inspect the rejection value, `in` throws on a primitive,
    and the user gets
    
      TypeError: Cannot use 'in' operator to search for 'data' in
      KeepKey Vault is not running. Open the KeepKey Vault desktop app...
    
    instead of the instruction we wrote for exactly that situation. The message
    we most want read is the one we made unreadable.
    
    Nothing about that message is special — every error from the extension
    rejected as a primitive. It is just long enough to make the TypeError absurd.
    
    Add toProviderError() and apply it at all five reject sites: injected.ts
    (EVM), solana-provider, tron-provider, solana-wallet-standard. It keeps an
    existing Error by reference so stacks are not discarded, preserves a `code`
    when one is already set, rebuilds structured errors that lost their prototype
    crossing postMessage, and never throws — a normalizer that can fail is worse
    than the bug it fixes.
    
    Follow-up (deliberately not in this change): formatUserError() flattens
    errors to a string, so the 4900 "provider disconnected" code from
    createVaultRequiredError() is dropped before it reaches the dApp. Sending
    `{ message, code }` would preserve it — toProviderError already handles that
    shape — but it changes what every consumer of `response.error` receives and
    wants a side-panel audit first.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
    sktbrd and claude committed Jul 31, 2026
    Configuration menu
    Copy the full SHA
    8f6d961 View commit details
    Browse the repository at this point in the history

Commits on Aug 15, 2026

  1. fix(evm): fail over on Chrome network errors instead of claiming the …

    …vault is down (#134)
    
    A dApp eth_sendTransaction failed with "KeepKey Vault is not running" while
    the vault was running. Two message-text classifiers combined to turn a dead
    Ethereum RPC into a false claim about the vault:
    
      isTransientRpcError("Failed to fetch")     -> false  => failover aborts
      isVaultUnreachableError("Failed to fetch")  -> true   => "Vault not running"
    
    Chrome throws byte-identical text for an unreachable RPC and a closed vault,
    so no regex can separate them.
    
    - isTransientRpcError now covers browser connection-level wording
      (failed to fetch / load failed / err_ / aborted). It was written against
      Firefox/Node wording, so the same dead RPC failed over on Firefox and
      hard-threw on Chrome. The loop now tries the remaining URLs.
    - Collapse the two copies of the classifier (ethereumHandler + rpcFailover)
      into one export; they had already drifted.
    - Log the URL before both definitive throws. That branch was silent while the
      transient branch logged, so the failing RPC never appeared in the console —
      the single biggest reason this was misdiagnosed as a vault problem.
    - formatUserError probes localhost:1646 before blaming the vault, instead of
      inferring vault state from an arbitrary error string in a catch-all.
    
    Tests: browser error strings in rpcFailover.test.ts; utils.test.ts asserts an
    RPC-origin "Failed to fetch" does NOT produce VAULT_REQUIRED_MESSAGE when the
    vault answers.
    
    Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
    BitHighlander and claude authored Aug 15, 2026
    Configuration menu
    Copy the full SHA
    b17f979 View commit details
    Browse the repository at this point in the history

Commits on Sep 11, 2026

  1. Merge pull request #133 from sktbrd/fix/eip1193-reject-with-error

    fix(injected): reject with an Error, not a bare string
    BitHighlander authored Sep 11, 2026
    Configuration menu
    Copy the full SHA
    5596fa4 View commit details
    Browse the repository at this point in the history
Loading