Skip to content

OneKey supports Sui - #217

Merged
hippocampusSK merged 20 commits into
developfrom
feature/onekey-sui-support
Nov 4, 2026
Merged

hippocampusSK merged 20 commits into
developfrom
feature/onekey-sui-support

Conversation

@hippocampusSK

@hippocampusSK hippocampusSK commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

OneKey users can connect Sui and send or swap on it.
Signatures returned by the wallet are checked to make sure they cover exactly the transaction the user was asked to sign.
Kept separate until it can be tested with the OneKey extension; it builds on the OneKey networks update.

Linear: API-3831

hippocampusSK and others added 18 commits October 28, 2026 17:54
Connect each chain through the provider the OneKey extension injects,
checked against OneKey's own provider and background sources. Bitcoin
moves to the Unisat-style $onekey.btc API and Solana to $onekey.solana:
the previous sats-connect and $onekey.sol paths never matched what the
extension exposes, so both chains failed to connect.

Sui, TRON and Stellar signatures are checked against the requested
transaction before they are returned. NEAR and TON can only sign and
send, so they go through the toolbox's sign-and-send path. The unused
EVM signer is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
…nd OneKey

Both wallets talk to the same TON Connect bridge, so the connect, send
and transfer logic moves to one helper. Each wallet passes its own
provider and errors, so OKX keeps its existing error keys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
…tichain-support

# Conflicts:
#	bun.lock
#	packages/wallet-extensions/package.json
…cels

OneKey queues every pending approval, so requesting all networks at once
kept opening windows after the user cancelled one. Networks are now
requested in order; a cancel stops the loop and keeps the ones already
approved, as OKX does. Other failures skip that network with a warning.

The TON Connect helper keeps the wallet's error code on a rejected
connection, so a manifest error is no longer mistaken for a cancel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
… test

The test left a manifestUrl in the shared config, so the OKX test that
expects no manifest failed whenever it ran afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
…d tronWeb

When a site was already connected, tron_requestAccounts answered at once
but the injected tronWeb still had no default address, so TRON reported
a user rejection and stopped the whole connection. The address now comes
from tron_accounts and signing goes through the provider's sign method.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
Sui cannot be tested against the OneKey extension yet, so it leaves this
change and returns in a follow-up. The rejection test now uses Stellar
as the chain that must not be requested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
Connect Sui through the provider the OneKey extension injects and sign
with its signTransaction. The signed bytes are compared with the
requested transaction before the signature is returned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
Signing hangs in OneKey's confirmation screen, so Cardano leaves this
change until that is resolved and returns in a follow-up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
…ctions

Cancelling the EVM approval now stops the remaining approval windows:
ethers reports OneKey's rejection as ACTION_REJECTED, which was not
recognised. TRON and TON only count a declined approval as a rejection
and skip the chain on any other failure. The TON Connect helper decides
this itself, so OKX also reports manifest errors as connection failures.

TON moves into the OneKey helpers and EVM chains are matched with
EVMChains instead of a separate list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
…out its sign()

OneKey can answer 4000 to tron_requestAccounts right after the user
approves, so the connected account from tron_accounts now decides whether
TRON connected. Signing calls tron_signTransaction directly: OneKey's
injected sign() calls a tronWeb.utils.isString its TronWeb no longer has,
which made every TRON signature fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
…requested

OneKey received the same transaction object the check and the result
used, so a provider that rewrote it in place passed the check. It now
gets a copy, and the txID check and the returned transaction come from
the requested one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QKkbKMCDEvXWUuh6hv
…tichain-support

# Conflicts:
#	bun.lock
#	packages/wallet-extensions/package.json
Base automatically changed from feature/onekey-multichain-support to develop November 3, 2026 17:05
Resolves the conflicts left by the squash-merge of the OneKey networks
update and its release: keeps the Sui connector and its tests on top of
the released helpers and drops the already published changeset.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QNFUSnoUdjpgbvcx2V
@hippocampusSK
hippocampusSK marked this pull request as ready for review November 4, 2026 17:13
@hippocampusSK

Copy link
Copy Markdown
Contributor Author

/dominion review

@ai-reviewer-towan

ai-reviewer-towan Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

PR review · published

Outcome: inconclusive. 1 finding: 1 low.

Open the published review for the TL;DR, findings and fixes.

Gate Model Status
logic codex-cli gpt-6.1-sol ✅ passed
adversarial codex-cli gpt-6.1-sol ⚠️ error
code-style-complexity claude-code claude-opus-5-5 ✅ passed
Run details

@ai-reviewer-towan ai-reviewer-towan Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

TL;DR

This PR adds Sui connect, send and swap support for OneKey, and checks that signatures cover the requested transaction. The main issue is minor: the Sui signature check takes a needless base64 round-trip that can throw a raw decode error. The adversarial lane errored and its sandbox experiments produced no meaningful evidence, so that evidence is missing. Compatibility with the real OneKey extension is also untested.

This review is inconclusive. Some evidence is missing or failed, so it does not establish that the change is safe. 1 finding: 1 low.

  • adversarial did not complete: assess adversarial experiments: adversarial experiments did not establish meaningful behavior and test-quality evidence

Low

Sui signature check uses a needless base64 round-trip

packages/wallet-extensions/src/onekey/helpers.ts:109 · code-style-complexity

The check that OneKey signed the requested Sui transaction is written as base64.encode(base64.decode(result.bytes)) !== serialized. The base64 decoder in @scure/base is strict, so any input it accepts re-encodes to the same string. The round-trip therefore adds no tolerance over a direct string comparison. Its only extra effect is a second, hidden failure path: malformed bytes throws a raw decode error instead of the OneKey signingError used everywhere else in this file. It also makes readers work out why the value is re-encoded, which hides the simple rule that the wallet's bytes must equal the requested bytes. The Tron and Stellar signers express the same check directly (txID !== requested.txID, signed.hash().equals(...)).

Fix: Compare the strings directly: if (result.bytes !== serialized) throw signingError(Chain.Sui, "OneKey signed a different transaction than the one requested");. Malformed and mismatched bytes then raise the same SwapKit signing error. The existing tests still cover the match and mismatch cases.

Review coverage and raw evidence

Reviewed head 56d26d124536688393ee6ba6c303d73ea447119d against base 15a8aad354f57b568673aebf35989edc9123b53c. Run 134c820d-1977-457b-92e3-7236b3e0ba8a.

logic — passed (0 findings)

Reviewed all five changed files, connection/error handling, signing integration, exports and test preservation. No concrete regressions found; no existing tests or guards were removed or weakened. Graph context was available but limited for dynamic/external dependencies; Argus coverage was partial. Tests were not executed, and real OneKey extension compatibility remains unverified.

adversarial — error (0 findings)

assess adversarial experiments: adversarial experiments did not establish meaningful behavior and test-quality evidence

Experiment probe-1 (behavior): passed, exit 0, 1948 ms.

Experiment probe-2 (test-quality): violated, exit 1, 1706 ms.

code-style-complexity — passed (1 findings)

I reviewed every changed file in the patch: the changeset, the OneKey Sui tests, helpers.ts, index.ts and types.ts. I compared the new Sui signer with the existing OneKey Tron, Stellar, Bitcoin and Near signers in helpers.ts. The Sui addition follows the file's existing pattern: a per-chain getXWalletMethods function, getProvider, a lazy toolbox import, connectionRejectedError/signingError, and a switch case in getWalletMethods. I found one simplification, a needless base64 round-trip in the signature check. The SUI_MAINNET constant also sits apart from the file's other constant, TRON_USER_REJECTED, but that is too minor to report. The Argus/Jev advisory pass was partial (coverage_incomplete): it produced no candidates, did not evaluate the .changeset markdown file, and omitted 173 reference files. Its gaps did not limit this review, because I read the needed source directly from the checkout.

Original specialist findings

F1 · low · code-style-complexity · packages/wallet-extensions/src/onekey/helpers.ts:109

Issue: The check that OneKey signed the requested Sui transaction is written as base64.encode(base64.decode(result.bytes)) !== serialized. @​scure/base's base64 decoder is strict, so any input it accepts re-encodes to the same string. The round-trip therefore adds no tolerance over comparing the strings directly. Its only extra effect is a second, hidden failure path: malformed bytes throws a raw decode error instead of the OneKey signingError used everywhere else in this file. Readers have to work out why the value is being re-encoded, which hides the simple rule that the wallet's bytes must equal the requested bytes. The Tron and Stellar signers express the same check directly (txID !== requested.txID, signed.hash().equals(...)).

Solution: Compare the strings directly: if (result.bytes !== serialized) throw signingError(Chain.Sui, "OneKey signed a different transaction than the one requested");. Malformed or mismatched bytes then both produce the same SwapKit signing error, and the existing tests still cover the match and mismatch cases.

The base64 decoder is strict, so decoding and re-encoding the wallet's
bytes could only ever return the same string or throw a raw decode
error. A direct comparison keeps the same check and reports malformed
bytes through the OneKey signing error like the other signers.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7T5QNFUSnoUdjpgbvcx2V
@hippocampusSK
hippocampusSK merged commit ae15331 into develop Nov 4, 2026
1 check passed
@hippocampusSK
hippocampusSK deleted the feature/onekey-sui-support branch November 4, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant