| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- import 'dart:typed_data';
- import 'package:bs58/bs58.dart';
- import 'package:convert/convert.dart';
- import 'package:crypto/crypto.dart';
- import 'package:decimal/decimal.dart';
- /// Tron 主网 CAIP-2(与 Web `tronRecharge.ts` / WalletConnect 一致)
- const String kTronMainnetCaip2 = 'tron:0x2b6653dc';
- /// rpcMap key(不含 tron: 前缀)
- const String kTronMainnetChainIdHex = '0x2b6653dc';
- /// Tether 波场主网 USDT TRC20 合约 Base58(与 Web 一致)
- const String kTrc20UsdtOfficialMainnet = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
- /// USDT-TRC20 精度
- const int kTrc20UsdtDecimals = 6;
- String tronMainnetCaip10Account(String base58Address) {
- return '$kTronMainnetCaip2:$base58Address';
- }
- bool isTronDepositNetwork(String protocol, String networkName) {
- final p = protocol.toLowerCase().trim();
- final n = networkName.toLowerCase().trim();
- return p.contains('tron') || n == 'trc20';
- }
- bool isTronRechargeUsdtSymbol(String coinName) {
- final u = coinName.toUpperCase().trim();
- return u == 'USDT' || u == 'TUSDT';
- }
- /// 金额字符串 → TRC20 最小单位整数字符串(与 Web `trc20AmountToMinUnits` 一致)
- String trc20AmountToMinUnits(String amountStr, int decimals) {
- final s = amountStr.trim().replaceAll(',', '');
- if (s.isEmpty) {
- throw FormatException('充值金额无效');
- }
- final d = Decimal.parse(s);
- var mult = Decimal.one;
- for (var i = 0; i < decimals; i++) {
- mult = mult * Decimal.fromInt(10);
- }
- final v = (d * mult).floor();
- return v.toBigInt().toString();
- }
- /// TRX 人类可读数量 → SUN(与 Web `trxToSunAmount` 一致)
- int trxToSunAmount(String amountStr) {
- final d =
- Decimal.parse(amountStr.trim().replaceAll(',', '')) * Decimal.fromInt(1000000);
- final n = d.floor().toBigInt().toInt();
- if (n <= 0) {
- throw FormatException('充值金额无效');
- }
- return n;
- }
- /// 将 Base58 地址编码为 triggerSmartContract 的 parameter 片段(与 Reown 示例一致)
- String tronAddressAbiWord(String base58Address) {
- final decoded = base58.decode(base58Address);
- final fullHex = hex.encode(decoded);
- if (fullHex.length < 10) {
- throw FormatException('无效的波场地址');
- }
- final bodyHex = fullHex.substring(2, fullHex.length - 8);
- return bodyHex.padLeft(64, '0');
- }
- String tronTransferTrc20ParameterHex(String toBase58, BigInt amountMinUnits) {
- final addrWord = tronAddressAbiWord(toBase58);
- final amountHex =
- amountMinUnits.toRadixString(16).padLeft(64, '0').toLowerCase();
- if (amountHex.length != 64) {
- throw FormatException('金额过大');
- }
- return '$addrWord$amountHex';
- }
- /// 兼容 `tron:<chain>:T…` / 十六进制形态;对齐 Web `parseTronCaip10Address`。
- String? parseTronCaip10Address(String accountStr) {
- final trimmed = accountStr.trim();
- if (trimmed.isEmpty) {
- return null;
- }
- final parts = trimmed.split(':').map((p) => p.trim()).toList();
- if (parts.length < 3 || parts[0].toLowerCase() != 'tron') {
- return null;
- }
- final last = parts.last;
- if (last.startsWith('T')) {
- try {
- final d = base58.decode(last);
- if (d.length >= 21) {
- return last;
- }
- } catch (_) {
- return null;
- }
- return null;
- }
- var hexBody = last;
- if (hexBody.startsWith('0x') || hexBody.startsWith('0X')) {
- hexBody = hexBody.substring(2);
- }
- if (!RegExp(r'^[a-fA-F0-9]+$').hasMatch(hexBody)) {
- return null;
- }
- if (hexBody.length == 40) {
- hexBody = '41$hexBody';
- }
- try {
- return _tronBytes21ToBase58(Uint8List.fromList(hex.decode(hexBody)));
- } catch (_) {
- return null;
- }
- }
- String _tronBytes21ToBase58(Uint8List body21) {
- if (body21.length != 21 || body21[0] != 0x41) {
- throw FormatException('invalid tron raw address');
- }
- final h1 = sha256.convert(body21);
- final h2 = sha256.convert(h1.bytes);
- final full = Uint8List(25);
- full.setRange(0, 21, body21);
- full.setRange(21, 25, h2.bytes.sublist(0, 4));
- return base58.encode(full);
- }
|