Skip to content

feat(tron): initial groundwork for full TRON integration#2425

Merged
shamardy merged 20 commits intodevfrom
feat-tron
May 10, 2025
Merged

feat(tron): initial groundwork for full TRON integration#2425
shamardy merged 20 commits intodevfrom
feat-tron

Conversation

@shamardy
Copy link
Copy Markdown
Collaborator

@shamardy shamardy commented Apr 24, 2025

This PR establishes the foundation for native TRON (TRX) support alongside EVM chains using EthCoin implementation. The focus is on minimal, incremental changes that enable clear chain distinction, future extensibility for both EVM and TRON protocols.

What’s Included

ChainSpec Addition

Unified ChainSpec enum for EVM and TRON; moved chain_id into protocol data; updated all logic and config.

TRON Address Handling

Added Tron Address Struct with validation and parsing.

What’s Not Included (Yet)

  • No functional TRON RPC/client logic, transaction signing, fee handling, or coin activation is implemented at this stage.
  • No TRON wallet or swap support; only foundational structures are in place.

Next Step

The following should be addressed in the next PR:

  • Abstraction over both EVM addresses and Tron Addresses in EthHDWallet and EthDerivationMethod
  • Minimal gRPC client to fetch balance and any calls needed for activating the coin.
  • Activation of Tron platform coin using v2 enable methods

First part of #1542

…RON (step 1)

- Add `ChainSpec` enum (Evm/Tron) to EthCoinImpl and related activation logic.
- Always use Evm chain spec for now; Tron support is not implemented yet.
- Add `tron.rs` with minimal placeholder types for future TRON integration.
- Return user error if TRON protocol is attempted (not yet supported).
- Mark all TODOs for future TRON and TRC20/10/NFT work.
- No behavioral change for EVM, ERC20, or NFT coins.
…d remove legacy config patching

- Refactor `CoinProtocol::ETH` and `CoinProtocol::TRX` to structured variants holding `chain_id` and `network` respectively.
- Update all activation, address, and coininit logic to use new protocol structure.
- Pass `ChainSpec` explicitly to eth activation and token activation functions.
- Remove legacy `update_coins_config` and related CLI/config patching code.
- Update all tests, helpers, and address generation to the new protocol and chain spec structure.
- Add TODOs for TRON address generation and further TRON/chain_id cleanup.
- Refactor all ETH protocol configs to store `chain_id` inside `protocol_data`, not as a top-level field.
- Add utility method to `ChainSpec` for safe access to `chain_id`.
- Remove `chain_id` field from `EthCoinImpl`, always use `ChainSpec` for chain identification.
- Update all code, tests, and helpers to use new protocol structure and `ChainSpec`.
- Enforce presence of `chain_id` for EVM coins and propagate errors for missing/invalid chain IDs.
- Add explicit TODOs for future Tron (TRX) support and chain abstraction.
- Add eth/tron/address.rs: implements TRON Address struct with base58 and hex parsing, validation, and serde support.
- Remove obsolete placeholder Address wrapper in tron.rs.

No behavioral change yet; this is a foundation for full TRON integration.
Copy link
Copy Markdown

@laruh laruh left a comment

Choose a reason for hiding this comment

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

Seems like there is no need in it right, but could be useful to have TryFrom and AsRef traits impl in the future

impl TryFrom<[u8; ADDRESS_BYTES_LEN]> for Address {
    type Error = String;

    fn try_from(bytes: [u8; ADDRESS_BYTES_LEN]) -> Result<Self, Self::Error> { Self::from_bytes(bytes) }
}

impl AsRef<[u8]> for Address {
    fn as_ref(&self) -> &[u8] { &self.inner }
}

Copy link
Copy Markdown
Collaborator

@mariocynicys mariocynicys left a comment

Choose a reason for hiding this comment

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

Thanks! Pretty neat.

some nits ans suggestions. my only request now is dismantling the chain_spec thingy inside the coin_type so not to have multiple discrimanatory fields (which some combinations of them aren't valid and would need runtime validation with every usage [e.g. CoinType::ERC20 paired with ChainSpec::TRX]). let's do it early on if it makes sense.

Comment on lines +113 to +122
if s.len() == ADDRESS_BASE58_LEN && s.starts_with(ADDRESS_BASE58_PREFIX) {
return Self::from_base58(s);
}

// Check for hex format (with or without 0x prefix)
if (s.len() == ADDRESS_HEX_LEN && s.starts_with(&format!("{:x}", ADDRESS_HEX_PREFIX)))
|| (s.len() == ADDRESS_HEX_LEN + 2 && s.starts_with(&format!("0x{:x}", ADDRESS_HEX_PREFIX)))
{
return Self::from_hex(s);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: if not for perf reasons. i think this is simpler:

        Self::from_base58(s)
            .or_else(|_| Self::from_hex(s))
            .map_err(|_| {
                format!(
                    "Invalid TRON address '{}': must be Base58 (34 chars starting with 'T') or hex (42 chars starting with '41' or '0x41')",
                    s
                )
            });

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Your suggestions doesn't check address length and allows bad addresses, no?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it's checked inside from_base58 and from_hex. the perf downside is that if the address was hex, it will attempt base58 serialisation then fail.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

it's checked inside from_base58 and from_hex

Right, thought it used from implementations from an external lib but it's my own implementations 😅
I think your code makes sense and I should use the most popular format first to avoid this perf downside as much as possible. On the other hand, patterns like this scare me as we had instances of parsing addresses that are not valid in the past and I would prefer to keep it simple which what the current implementation does.

"rpcport": 80,
"mm2": 1,
"chain_id": 137,
"chain_id": MATIC_CHAIN_ID,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

shouldn't we remove this now?
other instance also in the same file

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

so v1 activation still uses higher level chain-id while v2 activation uses the new one we introduced here?
why worry about v1 backward compat that much but not v2? or am i missing something?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Tokens activation is not tied to platform coin in v1 so there is no way to get it from platform coin (there can be a way by accessing config json directly, I can check it). Also, same method that is used for activation of platform coin is used for tokens, so can't also remove it for platform coin config, although I can check if it's in protocol_data first and if it's not look elsewhere. Let me work on making this part better.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

2b44429 waiting for CI to run tests and fix anything that fails

"name": "ethereum",
"fname": "Ethereum",
"chain_id": 1337,
"chain_id": ETH_SEPOLIA_CHAIN_ID,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

and this one

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Again, leaving all these for backward compatibility for now.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Comment on lines +839 to +840
/// Specifies the underlying blockchain (EVM or TRON).
pub chain_spec: ChainSpec,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nitty nit: feels like this field could be integrated into coin_type?

EthCoinType::Eth { chain_id: u64 }
EthCoinType::TRX { network }
and later ...
EthCoinType::TRC20 { network, token_address }

Copy link
Copy Markdown
Collaborator Author

@shamardy shamardy Apr 27, 2025

Choose a reason for hiding this comment

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

This was the first solution I considered ofcourse, I opted for chain_spec since I think this will require the least amount of code changes, it will be more clear in subsequent stages where I might refactor this if needed, now to the explanation on why I opted for chain_spec.

What is different between EVMs and Tron are actually the chain specs not coin types, so Tron platform coin and it's tokens have the same characteristics as EVM coins and tokens. If we were to use your suggested coin_type, swaps code will need more changing than with having ChainSpec, just take a look at all the matching for EthCoinType in eth.rs file, here is an example function https://github.com/KomodoPlatform/komodo-defi-framework/blob/af4867b7086ac716bd6c49107dbc0994e07208ca/mm2src/coins/eth.rs#L3824 since etmoic swap contracts work with Tron without any changes (I tested them, the spend function needs more checks but I think it works, all others are tested completely), this function will require no changes if we abstracted approve, allowance,wait_for_required_allowance and sign_and_send_transaction over both chain types. Actually only sign_and_send_transaction will require changes and the other 3 will probably just use the Tron RPC instead so they will use an abstraction over both RPC types.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

aha i see ur point. if ERC20 is so close to TRC20 to the point that we can replace the latter with the former, then we only have one discriminator which is the chain-spec. 👍

(p.s. same for Eth & TRX)

Copy link
Copy Markdown
Collaborator Author

@shamardy shamardy Apr 29, 2025

Choose a reason for hiding this comment

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

After this PR I will look into if just adding EthCoinType::TRX { network } is better and using EthCoinType::ERC20 with both platform coin types. So the abstraction becomes over the platform coin like how lightning is implemented, but I still think chain_spec is better. All will be revealed while working on web3 RPC and signing methods.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

unresolved it, as we sometimes come back to this thread to re-read

@@ -845,7 +845,10 @@ fn eth_conf(coin: &str) -> Json {
"chain_id": 1337,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

redundant chain_id?
also found in other places in this file.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Not redundant as this config can be used for either v1 or v2 tests.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

"type": "ERC20",
"protocol_data": {
"platform": "ETH",
"chain_id": ETH_SEPOLIA_CHAIN_ID,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looking at it. this actually used to look better (having chain_id in the protocol specific discriminator instead of the higher level)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This was wrongly placed and not used actually, chain_id is kept at the higher level for backward compatibility for v1 methods, but ERC20 tokens take the chain_id from platform coin in v2 activations. So in time chain_id shouldn't be in ERC20 tokens configs at all, which makes the most sense.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

}

Err(format!(
"Invalid TRON address '{}': must be Base58 (34 chars starting with 'T') or hex (42 chars starting with '41' or '0x41')",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we return such detail error descriptions?
(I think it's a task for GUI as it is multilingual. I guess for API it's always better to return errors as codes)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I guess for API it's always better to return errors as codes

I agree ref. codes but we don't have the implementation for this yet to adopt it here. With codes, there should be an english description too IMHO, or good documentation for what each code means since GUIs or API users don't know the internals of why this error happened or what the code means.

shamardy added 2 commits May 5, 2025 20:30
Reordered derive attributes in tron.rs to maintain alphabetical order, following project conventions.
@shamardy
Copy link
Copy Markdown
Collaborator Author

shamardy commented May 5, 2025

Seems like there is no need in it right, but could be useful to have TryFrom and AsRef traits impl in the future

impl TryFrom<[u8; ADDRESS_BYTES_LEN]> for Address {
    type Error = String;

    fn try_from(bytes: [u8; ADDRESS_BYTES_LEN]) -> Result<Self, Self::Error> { Self::from_bytes(bytes) }
}

impl AsRef<[u8]> for Address {
    fn as_ref(&self) -> &[u8] { &self.inner }
}

@laruh done here bfce81d

laruh
laruh previously approved these changes May 8, 2025
Copy link
Copy Markdown

@laruh laruh left a comment

Choose a reason for hiding this comment

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

LGTM! Thank you for handling the Tron init

…p-level `chain_id`

Refactor v1 ETH/ERC20/NFT activation to extract `chain_id` from protocol config instead of top-level coin config. Improves config consistency.
borngraced
borngraced previously approved these changes May 9, 2025
Copy link
Copy Markdown

@borngraced borngraced left a comment

Choose a reason for hiding this comment

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

Great work as always!

Comment on lines +6481 to +6482
let (coin_type, decimals, chain_id) = match protocol {
CoinProtocol::ETH { chain_id } => (EthCoinType::Eth, ETH_DECIMALS, chain_id),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ummm, missed that.
does this mean this was never backward compatible to begin with (since we are extracting protocol info, whose format has changed).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yep, we needed to add chain_id in it's new place but keep the old one as well. Now we don't need the old one.

"protocol_data": {
"chain_id": 1337,
}
},
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

for e.g., before this commit, did such a config work?
i see we have no defaults or json mutations to handle such config.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yep, all tests passed, so it worked. Why wouldn't it?

mariocynicys
mariocynicys previously approved these changes May 9, 2025
Copy link
Copy Markdown
Collaborator

@mariocynicys mariocynicys left a comment

Choose a reason for hiding this comment

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

LGTM!
thanks

@shamardy shamardy merged commit ee6bdd7 into dev May 10, 2025
40 of 48 checks passed
@shamardy shamardy deleted the feat-tron branch May 10, 2025 01:58
@laruh
Copy link
Copy Markdown

laruh commented May 12, 2025

@shamardy could you tell did you notify qa team that coins conf should be updated?

dimxy pushed a commit to dimxy/komodo-defi-framework that referenced this pull request May 13, 2025
* dev: (26 commits)
  chore(deps): remove base58 and replace it completely with bs58 (GLEECBTC#2427)
  feat(tron): initial groundwork for full TRON integration (GLEECBTC#2425)
  fix(UTXO): improve tx fee calculation and min relay fee handling (GLEECBTC#2316)
  deps(timed-map): bump to 1.3.1 (GLEECBTC#2413)
  improvement(tendermint): safer IBC channel handler (GLEECBTC#2298)
  chore(release): complete v2.4.0-beta changelogs  (GLEECBTC#2436)
  fix(event-streaming): initial addresses registration in utxo balance streaming (GLEECBTC#2431)
  improvement(watchers): re-write use-watchers handling (GLEECBTC#2430)
  fix(evm): make withdraw_nft work in HD mode (GLEECBTC#2424)
  feat(taproot): support parsing taproot output address types
  chore(RPC): use consistent param name for QTUM delegation (GLEECBTC#2419)
  fix(makerbot): add LiveCoinWatch price provider (GLEECBTC#2416)
  chore(release): add changelog entries for v2.4.0-beta (GLEECBTC#2415)
  fix(wallets): prevent path traversal in `wallet_file_path` and update file extension (GLEECBTC#2400)
  fix(nft): make `update_nft` work with hd wallets using the enabled address (GLEECBTC#2386)
  fix(wasm): unify error handling for mm2_main (GLEECBTC#2389)
  fix(tx-history): token information and query (GLEECBTC#2404)
  test(electrums): fix failing test_one_unavailable_electrum_proto_version (GLEECBTC#2412)
  improvement(network): remove static IPs from seed lists (GLEECBTC#2407)
  improvement(best-orders): return an rpc error when we can't find best orders (GLEECBTC#2318)
  ...
dimxy pushed a commit that referenced this pull request May 28, 2025
* dev: (29 commits)
  fix(p2pk): validate expected pubkey correctly for p2pk inputs (#2408)
  chore(docs): update old urls referencing atomicdex or old docs pages (#2428)
  improvement(p2p): remove hardcoded seeds (#2439)
  fix(evm-api): find enabled erc20 token using platform ticker (#2445)
  chore(docs): add DeepWiki badge to README (#2463)
  chore(core): organize deps using workspace.dependencies (#2449)
  feat(db-arch): more dbdir to address_dir replacements (#2398)
  chore(build-artifacts): remove duplicated mm2 build artifacts (#2448)
  feat(pubkey-banning): expirable bans (#2455)
  fix(eth-balance-events): serialize eth address using AddrToString (#2440)
  chore(deps): remove base58 and replace it completely with bs58 (#2427)
  feat(tron): initial groundwork for full TRON integration (#2425)
  fix(UTXO): improve tx fee calculation and min relay fee handling (#2316)
  deps(timed-map): bump to 1.3.1 (#2413)
  improvement(tendermint): safer IBC channel handler (#2298)
  chore(release): complete v2.4.0-beta changelogs  (#2436)
  fix(event-streaming): initial addresses registration in utxo balance streaming (#2431)
  improvement(watchers): re-write use-watchers handling (#2430)
  fix(evm): make withdraw_nft work in HD mode (#2424)
  feat(taproot): support parsing taproot output address types
  ...
mariocynicys added a commit that referenced this pull request May 29, 2025
since we now reintroduced Trx variant into coin_type (as per discussion
in the prev PR by omar, that shouldn't have been the way) we should now
merge chain_spec into coin_type. that makes the most sense.

refere to #2425 (comment)
for the original disc
dimxy pushed a commit to dimxy/komodo-defi-framework that referenced this pull request Jun 8, 2025
* lr-swap-wip: (37 commits)
  fix custom token error name
  fix getting chain_id from protocol_data
  refactor (review): use dedicated large error cfg, add new fn to FromApiValueError, fix TODO, use experimental namespace for lr rpc, more Ticker alias
  feat(walletconnect): add WalletConnect v2 support for EVM and Cosmos (GLEECBTC#2223)
  feat(ibc-routing-part-1): supporting entire Cosmos network for swaps (GLEECBTC#2459)
  fix(test): fix HD Wallet message signing tests (GLEECBTC#2474)
  improvement(builds): enable static CRT linking for MSVC builds (GLEECBTC#2464)
  feat(wallet): implement HD multi-address support for message signing (GLEECBTC#2432)
  fix(p2pk): validate expected pubkey correctly for p2pk inputs (GLEECBTC#2408)
  chore(docs): update old urls referencing atomicdex or old docs pages (GLEECBTC#2428)
  improvement(p2p): remove hardcoded seeds (GLEECBTC#2439)
  fix(evm-api): find enabled erc20 token using platform ticker (GLEECBTC#2445)
  chore(docs): add DeepWiki badge to README (GLEECBTC#2463)
  chore(core): organize deps using workspace.dependencies (GLEECBTC#2449)
  feat(db-arch): more dbdir to address_dir replacements (GLEECBTC#2398)
  chore(build-artifacts): remove duplicated mm2 build artifacts (GLEECBTC#2448)
  feat(pubkey-banning): expirable bans (GLEECBTC#2455)
  fix(eth-balance-events): serialize eth address using AddrToString (GLEECBTC#2440)
  chore(deps): remove base58 and replace it completely with bs58 (GLEECBTC#2427)
  feat(tron): initial groundwork for full TRON integration (GLEECBTC#2425)
  ...
shamardy added a commit that referenced this pull request Mar 6, 2026
Add transaction signing, fee estimation, and the full withdraw pipeline for TRX native and TRC20 token transfers. Fourth PR in the TRON integration series (#2425, #2467, #2712).

New modules under coins/eth/tron/:
- proto.rs: minimal TRON protobuf types (prost::Message derive)
- tx_builder.rs: unsigned transaction builders with TAPOS reference block
- sign.rs: SHA256 + secp256k1 signing with 65-byte r||s||v signatures
- fee.rs: bandwidth/energy fee estimation with chain price lookup
- withdraw.rs: TRX (with iterative max-send convergence) and TRC20
  (with cross-asset TRX balance verification) withdraw flows

Key changes:
- Chain-dispatched broadcast: TRON protobuf → /wallet/broadcasthex,
  EVM RLP → eth_sendRawTransaction
- New TxFeeDetails::Tron variant with bandwidth_used, energy_used,
  bandwidth_fee, energy_fee, total_fee
- TxFeeDetails extracted from lp_coins.rs into its own module
- Optional expiration_seconds on WithdrawRequest (default 60s)
- get_account_resource and broadcast_hex RPC methods on TronApiClient
- 7 withdraw integration tests against Nile testnet
- 24 unit tests converted to cross_test! for WASM compatibility

Partially addresses #1542 and #1698.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants