| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import 'package:dio/dio.dart';
- import '../config/app_config.dart';
- /// Tron FullNode HTTP API(与 Web TronWeb transactionBuilder 调用的 REST 一致)
- class TronFullNodeClient {
- TronFullNodeClient._();
- static Dio _dio(String rpcBase) {
- final base = _normalizeBase(rpcBase);
- final headers = <String, String>{
- 'accept': 'application/json',
- 'content-type': 'application/json',
- };
- final key = AppConfig.tronGridApiKey.trim();
- if (key.isNotEmpty) {
- headers['TRON-PRO-API-KEY'] = key;
- }
- return Dio(
- BaseOptions(
- baseUrl: base,
- connectTimeout: const Duration(seconds: 25),
- receiveTimeout: const Duration(seconds: 25),
- headers: headers,
- ),
- );
- }
- static String _normalizeBase(String rpcUrl) {
- var u = rpcUrl.trim();
- if (u.endsWith('/')) {
- u = u.substring(0, u.length - 1);
- }
- return u;
- }
- /// POST `/wallet/triggersmartcontract`
- static Future<Map<String, dynamic>> triggerSmartContract({
- required String rpcBase,
- required String ownerAddressBase58,
- required String contractAddressBase58,
- required String functionSelector,
- required String parameterHex,
- int feeLimitSun = 150000000,
- }) async {
- final dio = _dio(rpcBase);
- final res = await dio.post<dynamic>(
- '/wallet/triggersmartcontract',
- data: <String, dynamic>{
- 'owner_address': ownerAddressBase58,
- 'contract_address': contractAddressBase58,
- 'function_selector': functionSelector,
- 'parameter': parameterHex,
- 'fee_limit': feeLimitSun,
- 'call_value': 0,
- 'visible': true,
- },
- );
- final body = res.data;
- if (body is! Map) {
- throw StateError(' triggersmartcontract 响应无效');
- }
- final map = Map<String, dynamic>.from(body);
- final result = map['result'];
- if (result is Map && result['result'] != true) {
- throw StateError(
- result['message']?.toString() ?? '构建 TRC20 交易失败',
- );
- }
- final tx = map['transaction'];
- if (tx is! Map) {
- throw StateError('无 transaction 字段');
- }
- // 与 Reown AppKit 示例一致:WalletConnect `tron_signTransaction` 的 `transaction`
- // 常期望为 triggersmartcontract 整段 JSON(含 result / transaction 等),不单是内层 tx。
- return map;
- }
- /// POST `/wallet/createtransaction`(原生 TRX)
- static Future<Map<String, dynamic>> createTrxTransaction({
- required String rpcBase,
- required String ownerAddressBase58,
- required String toAddressBase58,
- required int amountSun,
- }) async {
- final dio = _dio(rpcBase);
- final res = await dio.post<dynamic>(
- '/wallet/createtransaction',
- data: <String, dynamic>{
- 'owner_address': ownerAddressBase58,
- 'to_address': toAddressBase58,
- 'amount': amountSun,
- 'visible': true,
- },
- );
- final body = res.data;
- if (body is! Map) {
- throw StateError('createtransaction 响应无效');
- }
- return Map<String, dynamic>.from(body);
- }
- /// POST `/wallet/broadcasttransaction`
- static Future<String> broadcastTransaction({
- required String rpcBase,
- required Map<String, dynamic> signed,
- }) async {
- final dio = _dio(rpcBase);
- final res = await dio.post<dynamic>(
- '/wallet/broadcasttransaction',
- data: signed,
- );
- final body = res.data;
- if (body is! Map) {
- throw StateError('broadcast 响应无效');
- }
- final map = Map<String, dynamic>.from(body);
- final ok = map['result'] == true;
- final txid = map['txid']?.toString();
- if (!ok || txid == null || txid.isEmpty) {
- throw StateError(map['message']?.toString() ?? '广播交易失败');
- }
- return txid;
- }
- }
|