feat: support tron with native wallet#750
Conversation
…olana The adapter property was being shared between TRON and Solana mixins, causing the Solana adapter to overwrite the TRON adapter during initialization. This resulted in TRON addresses being derived using Solana's address format. Renamed to tronAdapter to match the pattern used by other chains (e.g., ETH uses #ethSigner).
Fixed TypeScript error where EIP-1559 and legacy transaction fields were being mixed in the same object literal. Now conditionally creates the correct transaction data type based on whether the transaction is EIP-1559 or legacy. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Changed prepublishOnly from "echo skipping build" back to "yarn clean && yarn build" to ensure packages are properly built before publishing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…ivation
Fixes Buffer stringification issue where Uint8Array.toString('hex') doesn't accept arguments.
Now properly converts to Buffer first with Buffer.from() before calling toString('hex').
The uncompressed public key format is: - Byte 0: 0x04 prefix - Bytes 1-32: X coordinate - Bytes 33-64: Y coordinate slice(2) was removing the prefix AND first byte of X, giving only 63 bytes. slice(1) correctly removes just the prefix, leaving 64 bytes (X+Y coordinates).
|
Warning Rate limit exceeded@gomesalexandre has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 21 minutes and 2 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (27)
📝 WalkthroughWalkthroughAdds full Tron support across core and native packages: new core types and exports, SLIP-44 entry, wallet type-guards, native mixins, an isolation TronAdapter (address derivation and tx signing), and integration into NativeHDWallet (describePath, init, wipe). Also bumps many package versions. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant NativeHDWallet
participant MixinNativeTronWallet
participant TronAdapter
participant CryptoOps as Crypto Operations
User->>NativeHDWallet: tronGetAddress(msg)
NativeHDWallet->>MixinNativeTronWallet: tronGetAddress(msg)
MixinNativeTronWallet->>TronAdapter: getAddress(addressNList)
TronAdapter->>CryptoOps: Derive secp256k1 key from BIP32 node
CryptoOps-->>TronAdapter: Uncompressed public key
TronAdapter->>CryptoOps: keccak256(pubkey[1:])
CryptoOps-->>TronAdapter: hash
TronAdapter->>TronAdapter: take last 20 bytes, prefix 0x41, Base58Check encode
TronAdapter-->>MixinNativeTronWallet: address
MixinNativeTronWallet-->>NativeHDWallet: address
NativeHDWallet-->>User: address
sequenceDiagram
actor User
participant NativeHDWallet
participant MixinNativeTronWallet
participant TronAdapter
participant CryptoOps as Crypto Operations
User->>NativeHDWallet: tronSignTx(msg with rawDataHex)
NativeHDWallet->>MixinNativeTronWallet: tronSignTx(msg)
MixinNativeTronWallet->>TronAdapter: signTransaction(rawDataHex, addressNList)
TronAdapter->>CryptoOps: Derive secp256k1 key from BIP32 node
CryptoOps-->>TronAdapter: private key
TronAdapter->>CryptoOps: SHA-256(rawDataHex)
CryptoOps-->>TronAdapter: digest
TronAdapter->>CryptoOps: sign digest (canonical recoverable secp256k1)
CryptoOps-->>TronAdapter: signature (64 bytes) + recovery param
TronAdapter->>TronAdapter: concat signature + recid, format hex
TronAdapter-->>MixinNativeTronWallet: signatureHex
MixinNativeTronWallet->>NativeHDWallet: TronSignedTx (serializedTx/txid)
NativeHDWallet-->>User: TronSignedTx
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
packages/hdwallet-native/src/crypto/isolation/adapters/tron.ts (1)
10-42: TRON address derivation looks correct (optional minor cleanup only).The address derivation (uncompressed pubkey without 0x04, keccak256, last 20 bytes, prepend 0x41, bs58check) matches TRON’s standard mainnet address scheme. The implementation looks good as-is; if you want, you could pass a
Uint8Arraydirectly tokeccak256to avoid the intermediate hex string, but that’s purely cosmetic.packages/hdwallet-core/src/tron.ts (1)
4-55: Core TRON types are consistent; consider documentingserializedformat.The TRON interfaces (
TronGetAddress,TronSignTx,TronSignedTx,TronWalletInfo,TronWallet) look consistent with the rest of the core API surface. Given that the native implementation buildsserializedasrawDataHex + signature, adding a short JSDoc onTronSignedTx.serializedto state the expected format would help ensure future wallet backends (Ledger, Trezor, etc.) all implement it identically.packages/hdwallet-native/src/tron.ts (2)
7-20: Avoid throwing intronNextAccountPath; returnundefinedinstead.
tronNextAccountPathcurrently throwsError("Method not implemented"). For callers that rely on theTronWalletInfocontract, this is likely unexpected—“no next path” is normally represented asundefined. SincetronGetAccountPathsalready returns a single preferred path, a safe default here is to simply returnundefined.- // eslint-disable-next-line @typescript-eslint/no-unused-vars - tronNextAccountPath(msg: core.TronAccountPath): core.TronAccountPath | undefined { - throw new Error("Method not implemented"); - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + tronNextAccountPath(msg: core.TronAccountPath): core.TronAccountPath | undefined { + return undefined; + }
39-65:tronSignTxlogic is fine; minor opportunity to avoid redundant address derivation.
tronSignTxcorrectly gates onneedsMnemonic, derives the TRON address for the given path, signs viatronAdapter, and returns{ serialized, signature }whereserializedisrawDataHex + signature. The derivedaddressis only used as a sanity check and then discarded; if you don’t plan to surface it, you could skip thetronGetAddresscall and letsignTransactionfail naturally on bad paths, or alternatively include the address in the returned object for convenience.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (8)
packages/hdwallet-core/src/index.ts(1 hunks)packages/hdwallet-core/src/tron.ts(1 hunks)packages/hdwallet-core/src/utils.ts(1 hunks)packages/hdwallet-core/src/wallet.ts(2 hunks)packages/hdwallet-native/src/crypto/isolation/adapters/index.ts(1 hunks)packages/hdwallet-native/src/crypto/isolation/adapters/tron.ts(1 hunks)packages/hdwallet-native/src/native.ts(8 hunks)packages/hdwallet-native/src/tron.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/hdwallet PR: 737
File: packages/hdwallet-trezor/src/ethereum.ts:122-138
Timestamp: 2025-11-20T11:04:44.808Z
Learning: In packages/hdwallet-trezor/src/ethereum.ts, the ethSignTypedData function correctly returns the signature from res.payload.signature without adding a "0x" prefix. This works correctly in practice and has been tested, despite appearing inconsistent with ethSignMessage which does add the prefix. The Trezor Connect ethereumSignTypedData response already provides the signature in the correct format for consumption.
📚 Learning: 2025-08-07T15:47:29.207Z
Learnt from: gomesalexandre
Repo: shapeshift/hdwallet PR: 726
File: packages/hdwallet-ledger/src/transport.ts:10-10
Timestamp: 2025-08-07T15:47:29.207Z
Learning: In the shapeshiftoss/hdwallet monorepo, ts-ignore is used instead of ts-expect-error for Ledger transport imports because the code works locally without TypeScript errors but has issues in CI environment. Using ts-expect-error would fail locally since there are no actual errors to suppress.
Applied to files:
packages/hdwallet-core/src/index.tspackages/hdwallet-native/src/crypto/isolation/adapters/index.tspackages/hdwallet-core/src/wallet.tspackages/hdwallet-native/src/tron.ts
📚 Learning: 2025-08-07T15:47:26.835Z
Learnt from: gomesalexandre
Repo: shapeshift/hdwallet PR: 726
File: packages/hdwallet-ledger-webusb/src/transport.ts:12-12
Timestamp: 2025-08-07T15:47:26.835Z
Learning: In the shapeshiftoss/hdwallet monorepo, ts-ignore is used instead of ts-expect-error for Ledger transport imports because the CI environment has different type checking behavior than local development. The code works locally without errors, but CI reports type issues, so ts-ignore is necessary to suppress the inconsistent type checking across environments.
Applied to files:
packages/hdwallet-core/src/index.tspackages/hdwallet-native/src/crypto/isolation/adapters/index.ts
📚 Learning: 2025-11-20T11:04:44.808Z
Learnt from: gomesalexandre
Repo: shapeshift/hdwallet PR: 737
File: packages/hdwallet-trezor/src/ethereum.ts:122-138
Timestamp: 2025-11-20T11:04:44.808Z
Learning: In packages/hdwallet-trezor/src/ethereum.ts, the ethSignTypedData function correctly returns the signature from res.payload.signature without adding a "0x" prefix. This works correctly in practice and has been tested, despite appearing inconsistent with ethSignMessage which does add the prefix. The Trezor Connect ethereumSignTypedData response already provides the signature in the correct format for consumption.
Applied to files:
packages/hdwallet-native/src/crypto/isolation/adapters/tron.ts
📚 Learning: 2025-10-15T23:22:26.842Z
Learnt from: gomesalexandre
Repo: shapeshift/hdwallet PR: 731
File: packages/hdwallet-gridplus/src/thormaya.ts:99-105
Timestamp: 2025-10-15T23:22:26.842Z
Learning: In packages/hdwallet-gridplus/src/thormaya.ts, the GridPlus SDK (gridplus-sdk) automatically pads the r and s signature components to 32 bytes, so explicit padding in the code may be redundant but is not required. The thorchainSignTx implementation works without explicit padding because the SDK handles it.
Applied to files:
packages/hdwallet-native/src/crypto/isolation/adapters/tron.ts
🧬 Code graph analysis (4)
packages/hdwallet-native/src/crypto/isolation/adapters/tron.ts (1)
packages/hdwallet-core/src/wallet.ts (1)
BIP32Path(21-21)
packages/hdwallet-core/src/tron.ts (2)
packages/hdwallet-core/src/wallet.ts (4)
BIP32Path(21-21)HDWalletInfo(273-329)HDWallet(331-446)PathDescription(86-96)packages/hdwallet-core/src/utils.ts (2)
addressNListToBIP32(96-98)slip44ByCoin(174-176)
packages/hdwallet-core/src/wallet.ts (1)
packages/hdwallet-core/src/tron.ts (2)
TronWallet(48-55)TronWalletInfo(33-46)
packages/hdwallet-native/src/tron.ts (3)
packages/hdwallet-core/src/tron.ts (6)
TronWalletInfo(33-46)TronGetAccountPaths(25-27)TronAccountPath(29-31)TronGetAddress(4-8)TronSignTx(10-14)TronSignedTx(16-19)packages/hdwallet-native/src/native.ts (1)
NativeHDWalletBase(91-122)packages/hdwallet-native/src/crypto/isolation/adapters/tron.ts (1)
TronAdapter(10-67)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build and Release
🔇 Additional comments (15)
packages/hdwallet-core/src/index.ts (1)
21-21: LGTM!The Tron module export follows the established pattern and maintains alphabetical ordering with other chain exports.
packages/hdwallet-native/src/crypto/isolation/adapters/index.ts (1)
9-9: LGTM!The Tron adapter export follows the established pattern for isolation adapters.
packages/hdwallet-core/src/wallet.ts (2)
19-19: LGTM!Import placement is correct and follows the existing alphabetical ordering.
261-267: LGTM!The
supportsTronandinfoTrontype guard functions follow the established pattern used by other chains (e.g.,supportsSolana,infoSolana). The property checks (_supportsTron,_supportsTronInfo) align with the interface definitions intron.ts.packages/hdwallet-native/src/native.ts (8)
21-21: LGTM!Import follows the established pattern and alphabetical ordering.
130-142: LGTM!The Tron mixin is correctly integrated into the
NativeHDWalletInfomixin chain. The nesting order follows the established pattern.
155-155: LGTM!The
core.TronWalletInfointerface is correctly added to the implements clause.
210-212: LGTM!The
describePathswitch cases for "tron" and "trx" follow the established pattern of supporting both the full chain name and ticker symbol (similar to "rune"/"thorchain", "secret"/"scrt", etc.).
225-235: LGTM!The Tron mixin is correctly integrated into the
NativeHDWalletmixin chain.
248-248: LGTM!The
core.TronWalletinterface is correctly added to the implements clause.
372-372: LGTM!Tron correctly uses
secp256k1MasterKeyfor initialization, which aligns with Tron's cryptographic design (secp256k1 curve, similar to Ethereum).
426-426: LGTM!The
tronWipe()call is correctly placed in the wipe sequence alongside other chain wipe calls.packages/hdwallet-core/src/utils.ts (1)
159-159: SLIP-44 coin type 195 for Tron is correct and verified.The entry
Tron: 195is accurate per the official SLIP-44 registry. Tron (TRX) is registered with coin_type 195 (hex 0x800000c3).packages/hdwallet-native/src/crypto/isolation/adapters/tron.ts (1)
44-66: Signing flow is sound; please confirm serialized/encoding expectations downstream.Using SHA-256 with a canonical secp256k1 recoverable signature and returning
r||s||v(64 bytes + 1-byte recovery param) as hex is consistent with how TRON transactions are typically signed. Just make sure the broadcast layer (or any TRON RPC integration) expects this exact 65‑byte hex encoding and not DER or some other representation.packages/hdwallet-core/src/tron.ts (1)
57-87: BIP44 path handling for TRON is correct and aligned with TIP‑102.
tronDescribePathandtronGetAccountPathscorrectly enforce and construct the standard TRON pathm/44'/195'/<account>'/0/0, including a hardened account index and appropriate slip44 lookup. ThePathDescriptionfields (accountIdx,wholeAccount,coin: "Tron") are set sensibly for an account‑based chain.
gomesalexandre
left a comment
There was a problem hiding this comment.
Tested with web fren - in the spirit of shipping, happy for this one to go out. Web may be another beast!
- Account 0 addy is the same as Trust for a given seed ✅
- Can swap to TRX using NEAR ✅
Although I had this sneaky guy the first time around:
And notifications server errors too
- TRX Balance updates after swap ✅
- Can self-send (well actually can't, but can from account 0 to 1) ✅
- Send status detection is happy with throttler ✅
Nothing this:
Note: Sending to a second account might not update the second account but considering the amount of work there I was seeing that as a stretch and could be done as a follow up, we could have the notion of toAccountId in the send action to be able to resolve that
And indeed, it doesn't as stated!
Reset all package.json files and lerna.json back to origin/master versions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
4dfbff1 to
5cd6b3e
Compare
gomesalexandre
left a comment
There was a problem hiding this comment.
Restamp after bump
All testing done in shapeshift/web#11217
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.