Feat/ton sign data#778
Merged
ByteZhang1024 merged 18 commits intoonekeyfrom Apr 29, 2026
Merged
Conversation
Contributor
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
originalix
reviewed
Apr 28, 2026
originalix
reviewed
Apr 28, 2026
- New `tonSignData` method dispatching firmware TonSignData/TonSignedData for text/binary/cell payload signing, mirroring the TonSignProof shape. - Re-export TonSignDataType as a runtime value from @onekeyfe/hd-core so consumers can use the enum (previously only re-exported as a type, so `TonSignDataType.TEXT` threw at runtime). - Map firmware Failure_PinMismatch to new HardwareErrorCode.PinMismatch (828); surfaced only in set/change-PIN flows, so not added to the session-release list. - Regenerate hd-transport messages.ts and core messages.json from the updated firmware proto.
App-side now subscribes hardware UI events from a single hw.on(...) bus
instead of mixing connector.on('ui-event') with hw.on(UI_REQUEST.X).
LedgerAdapter forwards the connector 'ui-event' channel onto its own
emitter so the four EConnectorInteraction values (ConfirmOnDevice /
ConfirmOpenApp / UnlockDevice / InteractionComplete) reach consumers
through the same surface as REQUEST_DEVICE_PERMISSION etc. The dead
'ui-request_confirmation' → REQUEST_BUTTON path and its 'ui-request'
listener are removed.
Legacy-SDK chains (TRON today, future XRP/ADA/DOT) now go through a
single withLegacyChainCall wrapper that owns the full lifecycle:
pre-flight ensureAppOpen, ConfirmOnDevice/InteractionComplete pairing,
wrong-app retry, and symmetric UI cleanup on failure paths. TRON
handlers shrink ~40% and stop reimplementing the open-app boilerplate.
AppManager.ensureAppOpen invokes the onConfirmOnDevice callback BEFORE
issuing the blocking OpenAppCommand APDU; previously the prompt event
fired after the user had already confirmed on-device, so UI consumers
showed and immediately closed the "open app" toast. The fallback path
also closes any lingering ConfirmOpenApp prompt when ensureAppOpen
itself throws (e.g. 0x6807 app-not-installed).
mapLedgerError accepts an optional defaultAppName so DMK signer errors
(which lack appName) get a chain-bound fallback. LedgerConnectorBase
.dispatcher injects this once per call via _ctxForMethod, keeping
chain handlers' wrapError calls a single line. Downstream the App
layer's ThirdPartyAppNotInstalled toast can interpolate {appName}
across all chains, not just TRON.
Adds focused debug logs at points where, when bugs occur, no upstream
log can localize the failure: AppManager (currentApp / closeApp /
openApp statusCode / waitForApp exhausted), legacyChainCall decision
points (pre-flight failure / non-wrong-app / wrong-app retry /
retry failure / retry success), and BTC wallet template selection.
…ched labels Two independent bugs combined to make a single physical Ledger appear as two devices in the discovered list — one labelled with its real name and one labelled "Ledger". 1. LedgerAdapter.searchDevices() accumulated entries instead of replacing them. DMK assigns ephemeral UUIDs as USB device paths (which we use as connectId), so each replug produced a fresh connectId while the prior connectId still sat in the cache pointing at a device DMK no longer recognized. Fix: clear the cache before writing this round's raw result so it always reflects current discovery state. 2. LedgerConnectorBase.connect() emitted 'device-connect' with a hardcoded `name: 'Ledger'` placeholder. The adapter's deviceConnectHandler then wrote that placeholder over the real label that searchDevices() had just stored. Fix: capture the searchDevices() return value at connect entry and emit the real name found by connectId; fall back to 'Ledger' only if the device isn't in this round's discovery. Both fixes are required: clearing the cache without fixing the emit still leaves the active device's label clobbered by the placeholder; fixing the emit without clearing the cache still leaves stale connectId entries from prior plug events.
…sink
Hosts now inject a typed logger callback instead of toggling a boolean
to switch console output on/off. Makes SDK debug output flow into the
host's existing logging pipeline (e.g. defaultLogger.hardware.sdkLog).
setLogger((level, ...args) => { ... }) // host-supplied
debugLog('[X]', value) // routed through the injected sink
Removes setDebugEnabled / isDebugEnabled. SDK no longer holds a
console-output flag; not injecting a logger means the SDK is silent.
Cross-runtime note: this module's `logger` is a per-process singleton.
Hosts that span multiple runtimes (e.g. MV3 extensions where the SW
holds the adapter and an offscreen document holds the connector) must
call setLogger from each runtime — they don't share state.
Replaces the single-sink setLogger callback with a typed event bus,
matching the pattern OneKey's own hd-core uses (addHardwareGlobalEventListener).
onSdkEvent((event) => {
if (event.type === 'log') /* ... */
})
`SdkEvent` is a discriminated union — currently `{ type: 'log', level,
message }`. Future variants (firmware progress, battery state, ...)
extend the union and host adapters dispatch via the same subscription.
Why this matters for cross-runtime integration: hosts that span SW ↔
offscreen (MV3 extensions) or main ↔ renderer (Electron) wire one IPC
channel that forwards the whole `SdkEvent` payload. Adding a new event
variant doesn't require a new IPC route, a new subscriber, or a new
host-side handler — the dispatch is data-driven on `event.type`.
debugLog/debugError now `emitSdkEvent({type: 'log', ...})` internally;
hosts that want logs subscribe and route to their logger pipeline.
With no subscribers the bus skips stringification, so the SDK has zero
overhead when nobody's listening.
Removes setLogger / Logger / LogLevel exports.
…Bus comments Adds a single debugLog at each chain's signer.onInteraction site so the raw DMK interaction string (verify-address / sign-transaction / confirm-open-app / interaction-complete / unlock-device / ...) is visible in the host's SDK log scope. Without it, the entire device-side state machine between IO start and IO end is a black box — useful for diagnosing UI-event timing questions like "did verify-address actually fire on the device" or "where did app-switch insert itself". Trims redundant prose from sdkEventBus.ts and debugLog.ts that the file header / function name already conveys.
- TonSignData: restore getVersionRange(). With strictCheckDeviceSupport=true the core consults this method's version matrix; an empty range causes every device to be classified as unsupported and the TonSignData typedCall is rejected before run() ever fires. Aligned with TonSignMessage's getFixInitStateErrorVersionRange — bump when the firmware ships TonSignData. - LedgerConnectorBase.call: stop logging full call params via JSON.stringify(params). Now that debugLog flows through onSdkEvent into the host's defaultLogger pipeline, sensitive payloads (serializedTx, psbt, rawTxHex, messageHex, typed data) would propagate to telemetry / persistent stores. Replaced with summarizeCallParams() which surfaces only path, length-of-payload, and harmless flags.
- TonSignData: drop strictCheckDeviceSupport (set to false) and remove getVersionRange(). Firmware version that ships TonSignData isn't decided yet; gating now would lock out every connected device. Re-enable both once the touch/classic1s min versions are known. - LedgerConnectorBase.call: restore JSON.stringify(params) in debugLog. Log bus only feeds the host's local defaultLogger pipeline (no third-party telemetry forwarding), so full params are acceptable for now and useful for in-the-wild debugging.
9607383 to
8bcb31c
Compare
…scalation Core fix - LedgerConnectorBase subscribes to DMK getDeviceSessionState per active session and emits device-disconnect the moment DMK reports the device went to NOT_CONNECTED. Without this the upstream _sessions map kept dead entries until the next call hit DeviceSessionNotFound (the "empty connectId picks a stale session" bug after replug / process restart / abnormal teardown). - _retryWithFreshConnection: when the inner fresh-session retry still fails with disconnect/timeout, escalate to connector.reset() to drop and rebuild DMK + transport, then retry once more. Covers DMK internal state wedge that normal retry can't recover from. Diagnostic logging (validation paths) - LedgerConnectorBase.searchDevices: entry/exit logs (count, ids, paths) - LedgerConnectorBase: long-lived listenToAvailableDevices subscription that logs only (no behaviour) — used to verify that DMK proactively re-emits on USB unplug. Confirmed working in real-device repro. - LedgerDeviceManager.enumerate: include device ids in raw count log - LedgerAdapter.searchDevices: entry + return logs with cache size Dead-code purge - Drop unused batch APIs callChainBatch + evm/btc/sol/tronGetAddresses and matching interface declarations in hwk-adapter-core. Drop the now-orphan ProgressCallback type and re-export. Zero callers verified across OneKey app-monorepo and hwk-* packages.
…ecovery - User clicks app cancel UI → signal.reason carries UserAborted (10005) - Autonomous disconnect → canceller reason tags DeviceDisconnected (10101) - Chain app stuck mid-step (UnknownDeviceExchangeError) → escalate to connector.reset()
All three names from @onekeyfe/hd-transport are used in type position only (AlephiumSignedTx / AlephiumSignTx / TypedCall). Switching to `import type` clears the consistent-type-imports warning that surfaces in CI's full-repo `eslint .` scan. Pre-existing; not introduced by this branch.
Add two HardwareErrorCodes — DeviceAppStuck (10107) for a wedged chain app (e.g. Ledger BTC 0x6901) and ChainNotSupported (10108) for vendors that don't support a chain at all. LedgerConnectorBase.call now catches the stuck-app signal and rethrows as a DeviceAppStuck error so the host app can prompt the user to exit the app on-device. LedgerAdapter stops attempting silent retry-with- reset for stuck state — only manual on-device exit recovers, so the retry path was masking the real failure.
Firmware encodes the field as uint64; JS `number` loses precision on values past 2^53-1. UintType (string|number union) matches the rest of the protobuf-generated message types and lets callers pass a string when needed.
isStuckAppStateError now also matches: - _tag === 'AlreadySendingApduError': raised when a previous stuck call left DMK's IntentQueue slot held, so the next call fails synchronously. - APDU 6901 anywhere in the wrapped error chain: caller-side wrappers sometimes hide the original _tag, so we fall back to the raw status. Without these, the adapter misclassified post-stuck calls as generic errors and skipped the DeviceAppStuck escalation.
wabicai
approved these changes
Apr 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.