From dff8fefa4013d16e98928f5a47f4406385ed0f03 Mon Sep 17 00:00:00 2001 From: Mohsen <56779182+mrtnetwork@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:46:06 +0330 Subject: [PATCH] v4.0.0 Fix tron objects descrialization --- CHANGELOG.md | 4 + .../contract/call_with_fragment_example.dart | 2 +- .../manually/eip_1559_example.dart | 2 +- .../transaction/manually/legacy_example.dart | 2 +- ...ontract_transaction_without_fully_abi.dart | 2 +- .../smart_contract/call_contract_example.dart | 2 +- ...all_contract_with_token_value_example.dart | 3 +- ...on_smart_contract_with_tron_http_node.dart | 2 +- ...ontract_transaction_and_calculate_fee.dart | 2 +- .../send_contract_transaction_example.dart | 2 +- ...tion_contract_with_call_value_example.dart | 3 +- example/test/widget_test.dart | 21 +- lib/ethereum/src/address/evm_address.dart | 23 +- lib/ethereum/src/models/block.dart | 2 +- lib/ethereum/src/models/fee_history.dart | 2 +- lib/ethereum/src/models/log_entry.dart | 2 +- lib/ethereum/src/models/transaction.dart | 2 +- .../src/models/transaction_receipt.dart | 2 +- .../src/transaction/eth_transaction.dart | 2 +- lib/solidity/abi/abi.dart | 1 - lib/solidity/abi/core/abi.dart | 8 +- lib/solidity/abi/eip712/utils.dart | 30 +- lib/solidity/abi/exception/abi_exception.dart | 9 + lib/solidity/abi/types/address.dart | 4 +- lib/solidity/abi/utils/utils.dart | 5 +- lib/solidity/address/core.dart | 35 +- lib/solidity/contract/contract_abi.dart | 5 +- lib/solidity/contract/fragments.dart | 42 +- lib/tron/src/address/tron_address.dart | 43 +- lib/tron/src/exception/exception.dart | 20 + lib/tron/src/keys/private_key.dart | 4 +- lib/tron/src/keys/public_key.dart | 4 +- lib/tron/src/models/contract/.DS_Store | Bin 0 -> 6148 bytes .../account/{accout.dart => account.dart} | 0 .../contract/account/account_create.dart | 12 +- .../models/contract/account/account_id.dart | 8 +- .../account_permission_update_contract.dart | 18 +- .../account/account_update_contract.dart | 12 +- lib/tron/src/models/contract/account/key.dart | 13 +- .../models/contract/account/permission.dart | 36 +- .../contract/account/permission_type.dart | 13 +- .../account/set_account_id_contract.dart | 10 +- .../asset_issue_contract.dart | 63 +- .../assets_issue_contract/frozensupply.dart | 8 +- .../participate_asset_issue_contract.dart | 13 +- .../transfer_assets_contract.dart | 15 +- .../unfreez_assets_contract.dart | 5 +- .../update_asset_contract.dart | 16 +- .../contract/balance/account_identifier.dart | 5 +- .../cancel_all_unfreeze_v2_contract.dart | 5 +- .../balance/delegate_resource_contract.dart | 23 +- .../balance/freez_balance_contract.dart | 1 + .../balance/freez_balance_v2_contract.dart | 18 +- .../contract/balance/transfer_contract.dart | 15 +- .../balance/undelegate_resource_contract.dart | 3 +- .../balance/unfreez_balance_contract.dart | 1 + .../balance/unfreez_balance_v2_contract.dart | 22 +- .../balance/withdraw_balance_contract.dart | 1 + .../withdraw_expire_unfreeze_contract.dart | 5 +- .../contract/base_contract/base_contract.dart | 21 +- .../base_contract/transaction_type.dart | 5 +- lib/tron/src/models/contract/contract.dart | 2 +- .../exchange/create_exchange_contract.dart | 23 +- .../exchange/exchange_inject_contract.dart | 13 +- .../exchange_transaction_contract.dart | 16 +- .../exchange/exchange_withdraw_contract.dart | 13 +- .../market/market_cancel_order_contract.dart | 10 +- .../market/market_sell_asset_contract.dart | 19 +- .../proposal/proposal_approve_contract.dart | 14 +- .../proposal/proposal_create_contract.dart | 15 +- .../proposal/proposal_delete_contrat.dart | 9 +- .../shield/shield_transfer_contract.dart | 4 + .../contract/smart_contract/abi_types.dart | 26 +- .../smart_contract/clear_abi_contract.dart | 8 +- .../smart_contract/create_smart_contract.dart | 22 +- .../smart_contract/smart_contract.dart | 41 +- .../smart_contract/smart_contract_abi.dart | 3 +- .../smart_contract_abi_entry.dart | 35 +- .../smart_contract_abi_entry_param.dart | 12 +- .../trigger_smart_contract.dart | 24 +- .../update_energy_limit_contract.dart | 12 +- .../update_setting_contract.dart | 14 +- .../update_brokerage_contract.dart | 9 +- .../src/models/contract/transaction/any.dart | 30 +- .../contract/transaction/transaction.dart | 11 +- .../transaction/transaction_contract.dart | 19 +- .../contract/transaction/transaction_raw.dart | 88 +- .../contract/vote/vote_asset_contract.dart | 23 +- .../contract/vote/vote_witness_contract.dart | 23 +- .../vote/vote_witness_contract_vote.dart | 11 +- .../witness/update_witness_contract.dart | 13 +- .../witness/wintess_create_contract.dart | 13 +- .../parsed_contract_request.dart | 8 +- lib/tron/src/protbuf/decoder.dart | 34 +- lib/tron/src/protbuf/encoder.dart | 7 +- .../src/provider/methods/create_account.dart | 2 +- .../src/provider/methods/update_account.dart | 2 +- lib/tron/tron.dart | 1 + lib/utils/safe_cast.dart | 9 - lib/utils/utils.dart | 2 + lib/utils/{ => utils}/number_utils.dart | 0 lib/utils/utils/utils.dart | 147 +++ pubspec.yaml | 2 +- test/abi/encode_decode/contract_test.dart | 10 +- test/tron/json_buff_serialization_test.dart | 1072 +++++++++++++++++ 105 files changed, 2054 insertions(+), 476 deletions(-) create mode 100644 lib/tron/src/exception/exception.dart create mode 100644 lib/tron/src/models/contract/.DS_Store rename lib/tron/src/models/contract/account/{accout.dart => account.dart} (100%) delete mode 100644 lib/utils/safe_cast.dart create mode 100644 lib/utils/utils.dart rename lib/utils/{ => utils}/number_utils.dart (100%) create mode 100644 lib/utils/utils/utils.dart create mode 100644 test/tron/json_buff_serialization_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index d512be7e..7808e409 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.0.0 + +- Fix tron objects descrialization + ## 3.9.0 - Fix issue with Ethereum RLP encoding related to leading zero in signature S. diff --git a/example/lib/example/contract/call_with_fragment_example.dart b/example/lib/example/contract/call_with_fragment_example.dart index 0c5419f8..551e32ed 100644 --- a/example/lib/example/contract/call_with_fragment_example.dart +++ b/example/lib/example/contract/call_with_fragment_example.dart @@ -31,7 +31,7 @@ void main() async { ], "stateMutability": "pure", "type": "function" - }, false), + }), params: [ BigInt.from(12), BigInt.from(150), diff --git a/example/lib/example/ethereum/transaction/manually/eip_1559_example.dart b/example/lib/example/ethereum/transaction/manually/eip_1559_example.dart index 74e35fa2..2fca1350 100644 --- a/example/lib/example/ethereum/transaction/manually/eip_1559_example.dart +++ b/example/lib/example/ethereum/transaction/manually/eip_1559_example.dart @@ -38,7 +38,7 @@ void main() async { "name": "transfer", "stateMutability": "nonpayable", "type": "function" - }, false); + }); /// Request EIP-1559 historical fee data from the RPC service final eip1559HistoricalFee = await rpc.request(RPCGetFeeHistory( diff --git a/example/lib/example/ethereum/transaction/manually/legacy_example.dart b/example/lib/example/ethereum/transaction/manually/legacy_example.dart index d3168242..542486ed 100644 --- a/example/lib/example/ethereum/transaction/manually/legacy_example.dart +++ b/example/lib/example/ethereum/transaction/manually/legacy_example.dart @@ -38,7 +38,7 @@ void main() async { "name": "transfer", "stateMutability": "nonpayable", "type": "function" - }, false); + }); /// Request gas price from the RPC service final gasPrice = await rpc.request(RPCGetGasPrice()); diff --git a/example/lib/example/ethereum/transaction/with_builder/send_contract_transaction_without_fully_abi.dart b/example/lib/example/ethereum/transaction/with_builder/send_contract_transaction_without_fully_abi.dart index 1b8a5109..80540135 100644 --- a/example/lib/example/ethereum/transaction/with_builder/send_contract_transaction_without_fully_abi.dart +++ b/example/lib/example/ethereum/transaction/with_builder/send_contract_transaction_without_fully_abi.dart @@ -36,7 +36,7 @@ void main() async { "name": "transfer", "stateMutability": "nonpayable", "type": "function" - }, false); + }); /// Build an Ethereum transaction for a contract call (transfer) final tr = ETHTransactionBuilder.contract( diff --git a/example/lib/example/tron/transactions/smart_contract/call_contract_example.dart b/example/lib/example/tron/transactions/smart_contract/call_contract_example.dart index b0af802e..73bc1416 100644 --- a/example/lib/example/tron/transactions/smart_contract/call_contract_example.dart +++ b/example/lib/example/tron/transactions/smart_contract/call_contract_example.dart @@ -8,7 +8,7 @@ import 'tron_test_abi.dart'; void main() async { /// For Tron: If the output parameters include an address, set isTron to true. /// If it doesn't, set isTron to false to receive an ETH address instead of a Tron address. - final contract = ContractABI.fromJson(tronContract["entrys"]!, isTron: true); + final contract = ContractABI.fromJson(tronContract["entrys"]!); final rpc = EVMRPC(RPCHttpService("https://api.shasta.trongrid.io/jsonrpc")); final call1 = await rpc.request(RPCCall.fromMethod( contractAddress: diff --git a/example/lib/example/tron/transactions/smart_contract/call_contract_with_token_value_example.dart b/example/lib/example/tron/transactions/smart_contract/call_contract_with_token_value_example.dart index a5ddb049..24133e1b 100644 --- a/example/lib/example/tron/transactions/smart_contract/call_contract_with_token_value_example.dart +++ b/example/lib/example/tron/transactions/smart_contract/call_contract_with_token_value_example.dart @@ -19,8 +19,7 @@ void main() async { final rpc = TronProvider(TronHTTPProvider(url: "https://api.shasta.trongrid.io")); - final contract = - ContractABI.fromJson(payableContractTest["entrys"]!, isTron: true); + final contract = ContractABI.fromJson(payableContractTest["entrys"]!); final function = contract.functionFromName("PayWithTrc10"); diff --git a/example/lib/example/tron/transactions/smart_contract/call_tron_smart_contract_with_tron_http_node.dart b/example/lib/example/tron/transactions/smart_contract/call_tron_smart_contract_with_tron_http_node.dart index 14861780..f9b5f21d 100644 --- a/example/lib/example/tron/transactions/smart_contract/call_tron_smart_contract_with_tron_http_node.dart +++ b/example/lib/example/tron/transactions/smart_contract/call_tron_smart_contract_with_tron_http_node.dart @@ -8,7 +8,7 @@ import 'tron_test_abi.dart'; void main() async { /// For Tron: If the output parameters include an address, set isTron to true. /// If it doesn't, set isTron to false to receive an ETH address instead of a Tron address. - final contract = ContractABI.fromJson(tronContract["entrys"]!, isTron: true); + final contract = ContractABI.fromJson(tronContract["entrys"]!); final rpc = TronProvider(TronHTTPProvider(url: "https://api.shasta.trongrid.io")); final call1 = await rpc.request(TronRequestTriggerConstantContract.fromMethod( diff --git a/example/lib/example/tron/transactions/smart_contract/send_contract_transaction_and_calculate_fee.dart b/example/lib/example/tron/transactions/smart_contract/send_contract_transaction_and_calculate_fee.dart index 6357fd9a..3a240644 100644 --- a/example/lib/example/tron/transactions/smart_contract/send_contract_transaction_and_calculate_fee.dart +++ b/example/lib/example/tron/transactions/smart_contract/send_contract_transaction_and_calculate_fee.dart @@ -52,7 +52,7 @@ void main() async { int bandWidthNeed = 0; int energyNeed = 0; - final contract = ContractABI.fromJson(trc20Abi, isTron: true); + final contract = ContractABI.fromJson(trc20Abi); final function = contract.functionFromName("transfer"); diff --git a/example/lib/example/tron/transactions/smart_contract/send_contract_transaction_example.dart b/example/lib/example/tron/transactions/smart_contract/send_contract_transaction_example.dart index 5b991b8c..e7a5d6b0 100644 --- a/example/lib/example/tron/transactions/smart_contract/send_contract_transaction_example.dart +++ b/example/lib/example/tron/transactions/smart_contract/send_contract_transaction_example.dart @@ -23,7 +23,7 @@ void main() async { final rpc = TronProvider(TronHTTPProvider(url: "https://api.shasta.trongrid.io")); - final contract = ContractABI.fromJson(trc20Abi, isTron: true); + final contract = ContractABI.fromJson(trc20Abi); final function = contract.functionFromName("transfer"); diff --git a/example/lib/example/tron/transactions/smart_contract/transaction_contract_with_call_value_example.dart b/example/lib/example/tron/transactions/smart_contract/transaction_contract_with_call_value_example.dart index 6fc7f285..256d96a2 100644 --- a/example/lib/example/tron/transactions/smart_contract/transaction_contract_with_call_value_example.dart +++ b/example/lib/example/tron/transactions/smart_contract/transaction_contract_with_call_value_example.dart @@ -18,8 +18,7 @@ void main() async { final rpc = TronProvider(TronHTTPProvider(url: "https://api.shasta.trongrid.io")); - final contract = - ContractABI.fromJson(payableContractTest["entrys"]!, isTron: true); + final contract = ContractABI.fromJson(payableContractTest["entrys"]!); final function = contract.functionFromName("PayWithTRX"); diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 9fa0fb30..ab73b3a2 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -1,20 +1 @@ -void main() async { -// /// WebSocket RPC Service -// final websocketRpc = await RPCWebSocketService.connect( -// "wss://go.getblock.io/b9c91d92aaeb4e5ba2d4cca664ab708c", onEvents: (p0) { -// print("on event $p0"); -// }, onClose: (p0) {}); -// // Establish a WebSocket RPC connection to the specified endpoint for real-time updates. - -// /// Ethereum RPC -// final rpc = EVMRPC(websocketRpc); - -// final getblock = await rpc.request(RPCETHSubscribe()); -// print("block $getblock"); -// Timer.periodic(const Duration(seconds: 5), (s) async { -// // final re = await rpc.request(RPCETHSubscribe()); -// // print("re $re"); -// }); -// print("get block $getblock"); -// final changed = await Future.delayed(const Duration(seconds: 60)); -} +void main() {} diff --git a/lib/ethereum/src/address/evm_address.dart b/lib/ethereum/src/address/evm_address.dart index 0d1f30de..1b8c25f3 100644 --- a/lib/ethereum/src/address/evm_address.dart +++ b/lib/ethereum/src/address/evm_address.dart @@ -2,13 +2,19 @@ import 'package:on_chain/solidity/address/core.dart'; import 'package:blockchain_utils/bip/address/eth_addr.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; +extension ToEthereumAddress on SolidityAddress { + ETHAddress toEthereumAddress() { + if (this is ETHAddress) return this as ETHAddress; + return ETHAddress(toHex()); + } +} + /// Class representing an Ethereum address, implementing the [SolidityAddress] interface. -class ETHAddress implements SolidityAddress { - /// The Ethereum address string. +class ETHAddress extends SolidityAddress { final String address; /// Private constructor for creating an instance of [ETHAddress] with a given Ethereum address - const ETHAddress._(this.address); + const ETHAddress._(this.address) : super.unsafe(address); /// Creates an [ETHAddress] instance from a public key represented as a bytes. factory ETHAddress.fromPublicKey(List keyBytes) { @@ -39,20 +45,9 @@ class ETHAddress implements SolidityAddress { return ETHAddress(BytesUtils.toHexString(addrBytes, prefix: "0x")); } - /// convert address to bytes - @override - List toBytes() { - return BytesUtils.fromHexString(address); - } - /// Constant representing the length of the ETH address in bytes static const int lengthInBytes = 20; - @override - String toHex() { - return address; - } - @override String toString() { return address; diff --git a/lib/ethereum/src/models/block.dart b/lib/ethereum/src/models/block.dart index 0184fb83..a37058a5 100644 --- a/lib/ethereum/src/models/block.dart +++ b/lib/ethereum/src/models/block.dart @@ -1,5 +1,5 @@ import 'package:on_chain/ethereum/src/models/transaction.dart'; -import 'package:on_chain/utils/number_utils.dart'; +import 'package:on_chain/utils/utils/number_utils.dart'; /// Represents a withdrawal in the context of Ethereum block. class Withdrawal { diff --git a/lib/ethereum/src/models/fee_history.dart b/lib/ethereum/src/models/fee_history.dart index 852d11b3..34166751 100644 --- a/lib/ethereum/src/models/fee_history.dart +++ b/lib/ethereum/src/models/fee_history.dart @@ -1,4 +1,4 @@ -import 'package:on_chain/utils/number_utils.dart'; +import 'package:on_chain/utils/utils/number_utils.dart'; /// Represents the fee history in the context of Ethereum, including base fee per gas, gas used ratio, oldest block, and reward details. class FeeHistory { diff --git a/lib/ethereum/src/models/log_entry.dart b/lib/ethereum/src/models/log_entry.dart index 04ea2cd3..81fb7d58 100644 --- a/lib/ethereum/src/models/log_entry.dart +++ b/lib/ethereum/src/models/log_entry.dart @@ -1,4 +1,4 @@ -import 'package:on_chain/utils/number_utils.dart'; +import 'package:on_chain/utils/utils/number_utils.dart'; /// Represents an entry in Ethereum transaction logs. class LogEntry { diff --git a/lib/ethereum/src/models/transaction.dart b/lib/ethereum/src/models/transaction.dart index b1146882..dda30348 100644 --- a/lib/ethereum/src/models/transaction.dart +++ b/lib/ethereum/src/models/transaction.dart @@ -1,7 +1,7 @@ import 'package:on_chain/ethereum/src/address/evm_address.dart'; import 'package:on_chain/ethereum/src/models/models.dart'; import 'package:on_chain/ethereum/src/transaction/eth_transaction.dart'; -import 'package:on_chain/utils/number_utils.dart'; +import 'package:on_chain/utils/utils/number_utils.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; /// Represents information about an Ethereum transaction. diff --git a/lib/ethereum/src/models/transaction_receipt.dart b/lib/ethereum/src/models/transaction_receipt.dart index db6f8c77..1c0d86c7 100644 --- a/lib/ethereum/src/models/transaction_receipt.dart +++ b/lib/ethereum/src/models/transaction_receipt.dart @@ -1,5 +1,5 @@ import 'package:on_chain/ethereum/src/models/log_entry.dart'; -import 'package:on_chain/utils/number_utils.dart'; +import 'package:on_chain/utils/utils/number_utils.dart'; /// Represents the receipt of an Ethereum transaction. class TransactionReceipt { diff --git a/lib/ethereum/src/transaction/eth_transaction.dart b/lib/ethereum/src/transaction/eth_transaction.dart index 9ac38e22..857f2516 100644 --- a/lib/ethereum/src/transaction/eth_transaction.dart +++ b/lib/ethereum/src/transaction/eth_transaction.dart @@ -2,7 +2,7 @@ import 'package:on_chain/ethereum/src/address/evm_address.dart'; import 'package:on_chain/ethereum/src/rlp/decode.dart'; import 'package:on_chain/ethereum/src/rlp/encode.dart'; import 'package:on_chain/ethereum/src/models/access_list.dart'; -import 'package:on_chain/utils/number_utils.dart'; +import 'package:on_chain/utils/utils/number_utils.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; /// Represents the type of an Ethereum transaction. diff --git a/lib/solidity/abi/abi.dart b/lib/solidity/abi/abi.dart index 6df0d086..49d14929 100644 --- a/lib/solidity/abi/abi.dart +++ b/lib/solidity/abi/abi.dart @@ -27,7 +27,6 @@ library abi; import 'package:on_chain/solidity/address/core.dart'; -import 'package:on_chain/ethereum/src/address/evm_address.dart'; import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; diff --git a/lib/solidity/abi/core/abi.dart b/lib/solidity/abi/core/abi.dart index 460495f7..2aaf44c1 100644 --- a/lib/solidity/abi/core/abi.dart +++ b/lib/solidity/abi/core/abi.dart @@ -65,7 +65,7 @@ class AbiParameter { final String type; /// Flag indicating whether Tron types are used. - final bool tronTypes; + // final bool tronTypes; /// The base type, if applicable. final String? baseType; @@ -84,7 +84,6 @@ class AbiParameter { /// The name of the parameter. required this.name, required this.type, - this.tronTypes = false, this.baseType, this.indexed = false, this.components = const [], @@ -113,7 +112,7 @@ class AbiParameter { } /// Factory method to create an AbiParameter instance from a JSON representation. - factory AbiParameter.fromJson(Map json, bool tronTypes) { + factory AbiParameter.fromJson(Map json) { final List inputs = json["components"] ?? []; final String name = json["name"] ?? ""; return AbiParameter( @@ -121,9 +120,8 @@ class AbiParameter { type: json["type"], internalType: json["internalType"], indexed: json["indexed"] ?? false, - tronTypes: tronTypes, components: List.unmodifiable( - inputs.map((e) => AbiParameter.fromJson(e, tronTypes)).toList()), + inputs.map((e) => AbiParameter.fromJson(e)).toList()), ); } diff --git a/lib/solidity/abi/eip712/utils.dart b/lib/solidity/abi/eip712/utils.dart index 6d66d8dc..37a2ed17 100644 --- a/lib/solidity/abi/eip712/utils.dart +++ b/lib/solidity/abi/eip712/utils.dart @@ -81,11 +81,13 @@ class _EIP712Utils { } switch (type) { case "address": - if (value is TronAddress) { - return value.toAddress(); - } else { - return (value as ETHAddress).address; + if (value is String) { + return value; } + if (value is SolidityAddress) { + return value.toHex(); + } + break; case "bool": case "string": return value; @@ -100,19 +102,17 @@ class _EIP712Utils { /// If the value is a string, it is parsed to create an ETHAddress or TronAddress. /// Throws a [SolidityAbiException] for invalid input. static SolidityAddress ensureIsAddress(dynamic value) { - if (value is ETHAddress) return value; - if (value is List) { - if (value.length == TronAddress.lengthInBytes) { - return TronAddress.fromBytes(value); - } - return ETHAddress.fromBytes(value); - } else if (value is String) { - try { - return ETHAddress(value); - } catch (e) { + try { + if (value is SolidityAddress) return value; + if (value is List) { + return SolidityAddress.fromBytes(value); + } else if (value is String) { + if (StringUtils.isHexBytes(value)) { + return SolidityAddress(value); + } return TronAddress(value); } - } + } catch (_) {} throw SolidityAbiException("Invalid data provided for address codec.", details: {"input": value}); } diff --git a/lib/solidity/abi/exception/abi_exception.dart b/lib/solidity/abi/exception/abi_exception.dart index 80c0ce63..4862829a 100644 --- a/lib/solidity/abi/exception/abi_exception.dart +++ b/lib/solidity/abi/exception/abi_exception.dart @@ -8,4 +8,13 @@ class SolidityAbiException extends BlockchainUtilsException { final String message; const SolidityAbiException(this.message, {this.details}); + + @override + String toString() { + String msg = message; + if (details?.isNotEmpty ?? false) { + msg += ' Details: $details'; + } + return msg; + } } diff --git a/lib/solidity/abi/types/address.dart b/lib/solidity/abi/types/address.dart index 79703803..e20c704e 100644 --- a/lib/solidity/abi/types/address.dart +++ b/lib/solidity/abi/types/address.dart @@ -15,9 +15,7 @@ class AddressCoder implements ABICoder { final addrBytes = bytes.sublist( ABIConst.uintBytesLength - addrLength, ABIConst.uintBytesLength); return DecoderResult( - result: params.tronTypes - ? TronAddress.fromEthAddress(addrBytes) - : ETHAddress.fromBytes(addrBytes), + result: SolidityAddress.fromBytes(addrBytes), consumed: ABIConst.uintBytesLength, name: params.name); } diff --git a/lib/solidity/abi/utils/utils.dart b/lib/solidity/abi/utils/utils.dart index 05bf4da8..ee0b30fd 100644 --- a/lib/solidity/abi/utils/utils.dart +++ b/lib/solidity/abi/utils/utils.dart @@ -78,10 +78,7 @@ class _ABIUtils { } return Tuple( AbiParameter( - type: arrayParamType, - name: '', - components: abi.components, - tronTypes: abi.tronTypes), + type: arrayParamType, name: '', components: abi.components), size); } } diff --git a/lib/solidity/address/core.dart b/lib/solidity/address/core.dart index 69c77e87..d15c4ecd 100644 --- a/lib/solidity/address/core.dart +++ b/lib/solidity/address/core.dart @@ -1,3 +1,7 @@ +import 'package:blockchain_utils/bip/address/eth_addr.dart'; +import 'package:blockchain_utils/bip/coin_conf/coins_conf.dart'; +import 'package:blockchain_utils/blockchain_utils.dart'; + /// An abstract class representing a hexadecimal address in solidity smart conteract system. /// such as Ethereum and Tron (visible address). /// @@ -8,9 +12,34 @@ /// Implementations for specific blockchain addresses, such as Ethereum /// (`ETHAddress`) and Tron (`TronAddress`), will provide concrete /// implementations for these methods. -abstract class SolidityAddress { +class SolidityAddress { + final String _hexAddress; + const SolidityAddress.unsafe(this._hexAddress); + factory SolidityAddress(String address, {bool skipChecksum = true}) { + address = StringUtils.strip0x(address); + if (address.length > EthAddrConst.addrLen && + address.toLowerCase().startsWith("41")) { + address = address.substring(2); + } + EthAddrDecoder().decodeAddr( + "${CoinsConf.ethereum.params.addrPrefix}$address", + {"skip_chksum_enc": skipChecksum}); + return SolidityAddress.unsafe(EthAddrUtils.toChecksumAddress(address)); + } + factory SolidityAddress.fromBytes(List bytes, + {bool skipChecksum = true}) { + return SolidityAddress(BytesUtils.toHexString(bytes)); + } + /// Converts the hexadecimal address to a bytes. - List toBytes(); + List toBytes() { + return BytesUtils.fromHexString(_hexAddress); + } + + String toHex() => _hexAddress; - String toHex(); + @override + String toString() { + return _hexAddress; + } } diff --git a/lib/solidity/contract/contract_abi.dart b/lib/solidity/contract/contract_abi.dart index f1978687..601ed94f 100644 --- a/lib/solidity/contract/contract_abi.dart +++ b/lib/solidity/contract/contract_abi.dart @@ -12,11 +12,10 @@ class ContractABI { ContractABI._(this.fragments); /// Factory method to create a ContractABI instance from JSON. - factory ContractABI.fromJson(List> abi, - {bool isTron = false}) { + factory ContractABI.fromJson(List> abi) { try { final fragments = abi.map((e) { - return AbiBaseFragment.fromJson(e, isTron); + return AbiBaseFragment.fromJson(e); }).toList(); return ContractABI._(fragments); } catch (e) { diff --git a/lib/solidity/contract/fragments.dart b/lib/solidity/contract/fragments.dart index 096c8cc3..43ef30f8 100644 --- a/lib/solidity/contract/fragments.dart +++ b/lib/solidity/contract/fragments.dart @@ -10,22 +10,22 @@ abstract class AbiBaseFragment { abstract final FragmentTypes type; /// Creates an instance of [AbiBaseFragment] from JSON representation. - factory AbiBaseFragment.fromJson(Map json, bool tronTypes) { + factory AbiBaseFragment.fromJson(Map json) { final type = FragmentTypes.fromName(json["type"]); switch (type) { case FragmentTypes.event: - return AbiEventFragment.fromJson(json, tronTypes); + return AbiEventFragment.fromJson(json); case FragmentTypes.function: - return AbiFunctionFragment.fromJson(json, tronTypes); + return AbiFunctionFragment.fromJson(json); case FragmentTypes.receive: return AbiReceiveFragment.fromJson(json); case FragmentTypes.constructor: - return AbiConstructorFragment.fromJson(json, tronTypes); + return AbiConstructorFragment.fromJson(json); case FragmentTypes.fallback: - return AbiFallbackFragment.fromJson(json, tronTypes); + return AbiFallbackFragment.fromJson(json); case FragmentTypes.error: - return AbiErrorFragment.fromJson(json, tronTypes); + return AbiErrorFragment.fromJson(json); default: throw MessageException("unsupported fragment $type"); @@ -45,12 +45,11 @@ abstract class AbiBaseFragment { /// Class representing an ABI constructor fragment. class AbiConstructorFragment implements AbiBaseFragment { - factory AbiConstructorFragment.fromJson( - Map json, bool tronTypes) { + factory AbiConstructorFragment.fromJson(Map json) { final List inputs = json["inputs"] ?? []; return AbiConstructorFragment( stateMutability: StateMutability.fromName(json["stateMutability"])!, - inputs: inputs.map((e) => AbiParameter.fromJson(e, tronTypes)).toList(), + inputs: inputs.map((e) => AbiParameter.fromJson(e)).toList(), ); } @override @@ -71,15 +70,13 @@ class AbiConstructorFragment implements AbiBaseFragment { /// Represents a function fragment in ABI, providing methods for working with function calls. class AbiFunctionFragment implements AbiBaseFragment { /// Creates an instance of [AbiFunctionFragment] from JSON representation. - factory AbiFunctionFragment.fromJson( - Map json, bool tronTypes) { + factory AbiFunctionFragment.fromJson(Map json) { final List inputs = json["inputs"] ?? []; final List outputs = json["outputs"] ?? []; return AbiFunctionFragment( name: json["name"], - inputs: inputs.map((e) => AbiParameter.fromJson(e, tronTypes)).toList(), - outputs: - outputs.map((e) => AbiParameter.fromJson(e, tronTypes)).toList(), + inputs: inputs.map((e) => AbiParameter.fromJson(e)).toList(), + outputs: outputs.map((e) => AbiParameter.fromJson(e)).toList(), stateMutability: StateMutability.fromName(json["stateMutability"]), constant: json["constant"], payable: json["payable"]); @@ -200,15 +197,13 @@ class AbiReceiveFragment extends AbiFunctionFragment { /// Represents a fallback function fragment in ABI, providing methods for working with fallback functions. class AbiFallbackFragment implements AbiBaseFragment { /// Creates an instance of [AbiFallbackFragment] from JSON representation. - factory AbiFallbackFragment.fromJson( - Map json, bool tronTypes) { + factory AbiFallbackFragment.fromJson(Map json) { final List inputs = json["inputs"] ?? []; final List outputs = json["outputs"] ?? []; return AbiFallbackFragment( stateMutability: StateMutability.fromName(json["stateMutability"])!, - inputs: inputs.map((e) => AbiParameter.fromJson(e, tronTypes)).toList(), - outputs: - outputs.map((e) => AbiParameter.fromJson(e, tronTypes)).toList(), + inputs: inputs.map((e) => AbiParameter.fromJson(e)).toList(), + outputs: outputs.map((e) => AbiParameter.fromJson(e)).toList(), constant: json["constant"], payable: json["payable"]); } @@ -244,14 +239,13 @@ class AbiFallbackFragment implements AbiBaseFragment { /// Represents an event fragment in ABI, providing methods for decoding event data. class AbiEventFragment implements AbiBaseFragment { /// Creates an instance of [AbiEventFragment] from JSON representation. - factory AbiEventFragment.fromJson(Map json, bool tronTypes) { + factory AbiEventFragment.fromJson(Map json) { final List inputs = json["inputs"] ?? []; return AbiEventFragment( name: json["name"] ?? "", anonymous: json["anonymous"], - inputs: - inputs.map((e) => AbiParameter.fromJson(e, tronTypes)).toList()); + inputs: inputs.map((e) => AbiParameter.fromJson(e)).toList()); } /// The name of the event fragment. @@ -318,10 +312,10 @@ class AbiEventFragment implements AbiBaseFragment { /// Represents an error fragment in ABI, providing methods for decoding errors. class AbiErrorFragment implements AbiBaseFragment { /// Creates an instance of [AbiErrorFragment] from JSON representation. - factory AbiErrorFragment.fromJson(Map json, bool tronTypes) { + factory AbiErrorFragment.fromJson(Map json) { final List inputs = json["inputs"] ?? []; return AbiErrorFragment( - inputs: inputs.map((e) => AbiParameter.fromJson(e, tronTypes)).toList(), + inputs: inputs.map((e) => AbiParameter.fromJson(e)).toList(), name: json["name"]); } diff --git a/lib/tron/src/address/tron_address.dart b/lib/tron/src/address/tron_address.dart index e8214e2b..082806fe 100644 --- a/lib/tron/src/address/tron_address.dart +++ b/lib/tron/src/address/tron_address.dart @@ -1,16 +1,23 @@ import 'package:on_chain/solidity/address/core.dart'; import 'package:blockchain_utils/bip/address/trx_addr.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; -import 'package:on_chain/ethereum/src/address/evm_address.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; + +extension ToTronAddress on SolidityAddress { + TronAddress toTronAddress() { + if (this is TronAddress) return this as TronAddress; + return TronAddress.fromEthAddress(toBytes()); + } +} /// Class representing a Tron address, implementing the BaseHexAddress interface -class TronAddress implements SolidityAddress { +class TronAddress extends SolidityAddress { /// Private fields to store the address and its hexadecimal representation final String _address; - final String _hexAddress; /// Private constructor for internal use, initializing with address and hexAddress - const TronAddress._(this._address, this._hexAddress); + const TronAddress._(this._address, String hexAddress) + : super.unsafe(hexAddress); /// Factory method to create a TronAddress from a Tron public key represented as a list of integers factory TronAddress.fromPublicKey(List keyBytes) { @@ -20,7 +27,7 @@ class TronAddress implements SolidityAddress { return TronAddress._(toAddress, BytesUtils.toHexString([...TrxAddressUtils.prefix, ...decode])); } catch (e) { - throw MessageException("invalid tron public key", + throw TronPluginException("invalid tron public key", details: {"input": BytesUtils.toHexString(keyBytes)}); } } @@ -45,7 +52,7 @@ class TronAddress implements SolidityAddress { } } } catch (e) { - throw MessageException("invalid tron address", + throw TronPluginException("invalid tron address", details: {"input": address, "visible": visible}); } } @@ -63,18 +70,12 @@ class TronAddress implements SolidityAddress { return TronAddress._(addr, BytesUtils.toHexString(addrBytes)); } - /// Implementation of the toBytes method from the BaseHexAddress interface - @override - List toBytes() { - return BytesUtils.fromHexString(_hexAddress); - } - /// Method to get the Tron address as a string, with an option to visible address (base58) or hex address String toAddress([bool visible = true]) { if (visible) { return _address; } - return _hexAddress; + return super.toHex(); } /// Method to get the Tron address as a string, with an option to visible address (base58) or hex address @@ -86,20 +87,6 @@ class TronAddress implements SolidityAddress { /// Constant representing the length of the Tron address in bytes static const int lengthInBytes = 21; - /// To Ethereum address - ETHAddress toETHAddress() { - final toBytes = BytesUtils.fromHexString(_hexAddress); - - /// remove tron 0x41 prefix from bytes - return ETHAddress.fromBytes( - toBytes.sublist(toBytes.length - TronAddress.lengthInBytes)); - } - - @override - String toHex() { - return _hexAddress; - } - @override operator ==(other) { if (other is! TronAddress) return false; @@ -107,5 +94,5 @@ class TronAddress implements SolidityAddress { } @override - int get hashCode => _address.hashCode ^ _hexAddress.hashCode; + int get hashCode => _address.hashCode; } diff --git a/lib/tron/src/exception/exception.dart b/lib/tron/src/exception/exception.dart new file mode 100644 index 00000000..02808fd0 --- /dev/null +++ b/lib/tron/src/exception/exception.dart @@ -0,0 +1,20 @@ +import 'package:blockchain_utils/exception/exceptions.dart'; + +class TronPluginException extends BlockchainUtilsException { + const TronPluginException(this.message, {this.details}); + + @override + final String message; + + @override + final Map? details; + + @override + String toString() { + String msg = message; + if (details?.isNotEmpty ?? false) { + msg += ' Details: $details'; + } + return msg; + } +} diff --git a/lib/tron/src/keys/private_key.dart b/lib/tron/src/keys/private_key.dart index df5ae684..45bc118e 100644 --- a/lib/tron/src/keys/private_key.dart +++ b/lib/tron/src/keys/private_key.dart @@ -1,7 +1,7 @@ -import 'package:blockchain_utils/exception/exception.dart'; import 'package:blockchain_utils/utils/utils.dart'; import 'package:blockchain_utils/bip/ecc/keys/secp256k1_keys_ecdsa.dart'; import 'package:blockchain_utils/signer/tron/tron_signer.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; import 'public_key.dart'; @@ -26,7 +26,7 @@ class TronPrivateKey { return TronPrivateKey._(key); } catch (e) { // Throw a MessageException with details if an error occurs during the creation - throw MessageException("invalid tron private key", + throw TronPluginException("invalid tron private key", details: {"input": BytesUtils.toHexString(keyBytes)}); } } diff --git a/lib/tron/src/keys/public_key.dart b/lib/tron/src/keys/public_key.dart index 4089483e..4e828ee5 100644 --- a/lib/tron/src/keys/public_key.dart +++ b/lib/tron/src/keys/public_key.dart @@ -1,9 +1,9 @@ -import 'package:blockchain_utils/exception/exception.dart'; import 'package:blockchain_utils/signer/tron/tron_signer.dart'; import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:blockchain_utils/utils/utils.dart'; import 'package:blockchain_utils/bip/address/p2pkh_addr.dart'; import 'package:blockchain_utils/bip/ecc/keys/secp256k1_keys_ecdsa.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; /// Class representing a Tron public key class TronPublicKey { @@ -19,7 +19,7 @@ class TronPublicKey { final pubKey = Secp256k1PublicKeyEcdsa.fromBytes(keyBytes); return TronPublicKey._(pubKey); } catch (e) { - throw MessageException("invalid tron public key", + throw TronPluginException("invalid tron public key", details: {"input": BytesUtils.toHexString(keyBytes)}); } } diff --git a/lib/tron/src/models/contract/.DS_Store b/lib/tron/src/models/contract/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f87f6d899b1751fd7e442b19cbed5e73bdc47a3d GIT binary patch literal 6148 zcmeHKOHKnZ41IDJ9j0oBHFFm3!h&0H1;hn-j?HJp zNQDhT$d;1lICkQB(j+kencXg@zy!dUO;J=C5H$}@?YZ-aD0z(*=cv%&2JOH?f6=75 zA7YCdm)J1tkNh{ZRA^UM(|Og@YfJv_WtV^5l;vX8Ea*3WKHEMX-#?t}j#>UVW_|rR zuP1I15)1?b!9Xw&419|L-q|YS1HICh5l=wO#i0HQvlvryMs zLSvF+;n*2+h9VY9v{3O9LoA&3k!U7Of0*i_W7Q-wmk_XyxX&yk}% dY4b^S`W23yp{}C#98QdfKqe%*VBi-Rcm=naJIVk6 literal 0 HcmV?d00001 diff --git a/lib/tron/src/models/contract/account/accout.dart b/lib/tron/src/models/contract/account/account.dart similarity index 100% rename from lib/tron/src/models/contract/account/accout.dart rename to lib/tron/src/models/contract/account/account.dart diff --git a/lib/tron/src/models/contract/account/account_create.dart b/lib/tron/src/models/contract/account/account_create.dart index 0a310130..c9787b1a 100644 --- a/lib/tron/src/models/contract/account/account_create.dart +++ b/lib/tron/src/models/contract/account/account_create.dart @@ -2,6 +2,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/account/account_type.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Activate an account. Uses an already activated account to activate a new account. /// or just simply transfer TRX to it. @@ -9,13 +10,17 @@ class AccountCreateContract extends TronBaseContract { factory AccountCreateContract.fromJson(Map json) { return AccountCreateContract( /// Transaction initiator address - ownerAddress: TronAddress(json["owner_address"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), /// Account address to be activated - accountAddress: TronAddress(json["account_address"]), + accountAddress: OnChainUtils.parseTronAddress( + value: json["account_address"], name: "account_address"), /// Account type. The external account type is Normal, and this field will not be displayed in the return value - type: AccountType.fromName(json["type"]) ?? AccountType.normal, + type: AccountType.fromName( + OnChainUtils.parseString(value: json["type"], name: "type")) ?? + AccountType.normal, ); } factory AccountCreateContract.deserialize(List bytes) { @@ -38,6 +43,7 @@ class AccountCreateContract extends TronBaseContract { {required this.ownerAddress, required this.accountAddress, this.type}); /// Transaction initiator address + @override final TronAddress ownerAddress; /// Account address to be activated diff --git a/lib/tron/src/models/contract/account/account_id.dart b/lib/tron/src/models/contract/account/account_id.dart index cba7a44a..42171f85 100644 --- a/lib/tron/src/models/contract/account/account_id.dart +++ b/lib/tron/src/models/contract/account/account_id.dart @@ -2,14 +2,14 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; class AccountId extends TronProtocolBufferImpl { - /// final decode = TronProtocolBufferImpl.decode(bytes); - factory AccountId.fromJson(Map json) { return AccountId( - name: StringUtils.tryEncode(json["name"]), - address: TronAddress(json["address"])); + name: OnChainUtils.parseBytes(value: json["name"], name: "name"), + address: OnChainUtils.parseTronAddress( + value: json["address"], name: "address")); } factory AccountId.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); diff --git a/lib/tron/src/models/contract/account/account_permission_update_contract.dart b/lib/tron/src/models/contract/account/account_permission_update_contract.dart index dba3ba4e..4e6ec8e6 100644 --- a/lib/tron/src/models/contract/account/account_permission_update_contract.dart +++ b/lib/tron/src/models/contract/account/account_permission_update_contract.dart @@ -2,18 +2,23 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/account/permission.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Update the account's permission. class AccountPermissionUpdateContract extends TronBaseContract { /// Create a new [AccountPermissionUpdateContract] instance by parsing a JSON map. factory AccountPermissionUpdateContract.fromJson(Map json) { return AccountPermissionUpdateContract( - ownerAddress: TronAddress(json["owner_address"]), - owner: Permission.fromJson(json["owner"]), - witness: json["witness"] == null - ? null - : Permission.fromJson(json["witness"]), - actives: (json["actives"] as List?) + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + owner: Permission.fromJson(OnChainUtils.parseMap( + value: json["owner"], name: "owner", throwOnNull: true)!), + witness: + OnChainUtils.parseMap(value: json["witness"], name: "witness") == + null + ? null + : Permission.fromJson(json["witness"]), + actives: OnChainUtils.parseList(value: json["actives"], name: "actives") ?.map((e) => Permission.fromJson(e)) .toList() ?? []); @@ -42,6 +47,7 @@ class AccountPermissionUpdateContract extends TronBaseContract { : actives = List.unmodifiable(actives); /// account address + @override final TronAddress ownerAddress; /// The owner permission of the account. diff --git a/lib/tron/src/models/contract/account/account_update_contract.dart b/lib/tron/src/models/contract/account/account_update_contract.dart index cda5c9ff..a972e1bf 100644 --- a/lib/tron/src/models/contract/account/account_update_contract.dart +++ b/lib/tron/src/models/contract/account/account_update_contract.dart @@ -2,14 +2,17 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Modify account name class AccountUpdateContract extends TronBaseContract { /// Create a new [AccountUpdateContract] instance by parsing a JSON map. factory AccountUpdateContract.fromJson(Map json) { return AccountUpdateContract( - ownerAddress: TronAddress(json["owner_address"]), - accountName: StringUtils.encode(json["account_name"])); + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + accountName: OnChainUtils.parseBytes( + value: json["account_name"], name: "account_name")); } /// Factory method to create a new [AccountUpdateContract] instance with specified parameters. @@ -26,6 +29,7 @@ class AccountUpdateContract extends TronBaseContract { } /// Owner_address is the account address to be modified + @override final TronAddress ownerAddress; /// Account_name is the name of the account @@ -42,8 +46,8 @@ class AccountUpdateContract extends TronBaseContract { Map toJson() { return { "owner_address": ownerAddress.toString(), - "account_name": StringUtils.tryDecode(accountName), - }..removeWhere((key, value) => value == null); + "account_name": StringUtils.tryDecode(accountName) + }; } /// Convert the [AccountUpdateContract] object to its string representation. diff --git a/lib/tron/src/models/contract/account/key.dart b/lib/tron/src/models/contract/account/key.dart index 937dd6a7..64985245 100644 --- a/lib/tron/src/models/contract/account/key.dart +++ b/lib/tron/src/models/contract/account/key.dart @@ -1,14 +1,16 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; class TronKey extends TronProtocolBufferImpl { /// Create a new [TronKey] instance by parsing a JSON map. factory TronKey.fromJson(Map json) { return TronKey( - address: TronAddress(json["address"]), - weight: BigintUtils.parse(json["weight"])); + address: OnChainUtils.parseTronAddress( + value: json["address"], name: "address"), + weight: + OnChainUtils.parseBigInt(value: json["weight"], name: "weight")); } factory TronKey.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); @@ -48,10 +50,7 @@ class TronKey extends TronProtocolBufferImpl { /// Convert the [TronKey] object to a JSON representation. @override Map toJson() { - return { - "address": address, - "weight": weight, - }; + return {"address": address, "weight": weight}; } /// Convert the [TronKey] object to its string representation. diff --git a/lib/tron/src/models/contract/account/permission.dart b/lib/tron/src/models/contract/account/permission.dart index 7eca9e18..62593d3b 100644 --- a/lib/tron/src/models/contract/account/permission.dart +++ b/lib/tron/src/models/contract/account/permission.dart @@ -3,18 +3,27 @@ import 'package:on_chain/tron/src/models/contract/account/key.dart'; import 'package:on_chain/tron/src/models/contract/account/permission_type.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; class Permission extends TronProtocolBufferImpl { /// Create a new [Permission] instance by parsing a JSON map. factory Permission.fromJson(Map json) { return Permission( - type: PermissionType.fromName(json["type"]), - id: json["id"], - permissionName: json["permission_name"], - operations: BytesUtils.tryFromHexString(json["operations"]), - keys: (json["keys"] as List?)?.map((e) => TronKey.fromJson(e)).toList(), - parentId: json["parent_id"], - threshold: BigintUtils.tryParse(json["threshold"])); + type: PermissionType.fromName( + OnChainUtils.parseString(value: json["type"], name: "type"), + defaultPermission: PermissionType.owner), + id: OnChainUtils.parseInt(value: json["id"], name: "id"), + permissionName: OnChainUtils.parseString( + value: json["permission_name"], name: "permission_name"), + operations: OnChainUtils.parseHex( + value: json["operations"], name: "operations"), + keys: OnChainUtils.parseList(value: json["keys"], name: "keys") + ?.map((e) => TronKey.fromJson(e)) + .toList(), + parentId: + OnChainUtils.parseInt(value: json["parent_id"], name: "parent_id"), + threshold: OnChainUtils.parseBigInt( + value: json["threshold"], name: "threshold")); } /// Factory method to create a new [Permission] instance with specified parameters. @@ -75,8 +84,15 @@ class Permission extends TronProtocolBufferImpl { List get fieldIds => [1, 2, 3, 4, 5, 6, 7]; @override - List get values => - [type, id, permissionName, threshold, parentId, operations, keys]; + List get values => [ + type == PermissionType.owner ? null : type, + id, + permissionName, + threshold, + parentId, + operations, + keys, + ]; /// Convert the [Permission] object to a JSON representation. @override @@ -89,7 +105,7 @@ class Permission extends TronProtocolBufferImpl { "id": id, "parent_id": parentId, "operations": BytesUtils.tryToHexString(operations), - }; + }..removeWhere((k, v) => v == null); } /// Convert the [Permission] object to its string representation. diff --git a/lib/tron/src/models/contract/account/permission_type.dart b/lib/tron/src/models/contract/account/permission_type.dart index 0da1a47e..1b9ea8f2 100644 --- a/lib/tron/src/models/contract/account/permission_type.dart +++ b/lib/tron/src/models/contract/account/permission_type.dart @@ -1,3 +1,4 @@ +import 'package:on_chain/tron/src/exception/exception.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/common.dart'; /// Enum representing different types of permissions within a Tron account. @@ -37,8 +38,10 @@ class PermissionType implements TronEnumerate { /// Returns `null` if no match is found. static PermissionType fromName(String? name, {PermissionType? defaultPermission}) { - return values.firstWhere((element) => element.name == name, - orElse: defaultPermission == null ? null : () => defaultPermission); + return values.firstWhere((element) => element.name == name, orElse: () { + if (defaultPermission != null) return defaultPermission; + throw const TronPluginException("No permission Type is found."); + }); } /// Returns the [PermissionType] associated with the given [value]. @@ -46,7 +49,9 @@ class PermissionType implements TronEnumerate { /// Throws an error if no match is found. static PermissionType fromValue(int? value, {PermissionType? defaultPermission}) { - return values.firstWhere((element) => element.value == value, - orElse: defaultPermission == null ? null : () => defaultPermission); + return values.firstWhere((element) => element.value == value, orElse: () { + if (defaultPermission != null) return defaultPermission; + throw const TronPluginException("No permission Type is found."); + }); } } diff --git a/lib/tron/src/models/contract/account/set_account_id_contract.dart b/lib/tron/src/models/contract/account/set_account_id_contract.dart index 20009a44..7c08d969 100644 --- a/lib/tron/src/models/contract/account/set_account_id_contract.dart +++ b/lib/tron/src/models/contract/account/set_account_id_contract.dart @@ -2,13 +2,16 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class SetAccountIdContract extends TronBaseContract { /// Create a new [SetAccountIdContract] instance by parsing a JSON map. factory SetAccountIdContract.fromJson(Map json) { return SetAccountIdContract( - accountId: StringUtils.encode(json["account_id"]), - ownerAddress: TronAddress(json["owner_address"]), + accountId: OnChainUtils.parseBytes( + value: json["account_id"], name: "account_id"), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), ); } @@ -25,6 +28,7 @@ class SetAccountIdContract extends TronBaseContract { ownerAddress: TronAddress.fromBytes(decode.getField(2))); } final List accountId; + @override final TronAddress ownerAddress; @override @@ -39,7 +43,7 @@ class SetAccountIdContract extends TronBaseContract { return { "owner_address": ownerAddress.toString(), "account_id": StringUtils.decode(accountId) - }..removeWhere((key, value) => value == null); + }; } /// Convert the [SetAccountIdContract] object to its string representation. diff --git a/lib/tron/src/models/contract/assets_issue_contract/asset_issue_contract.dart b/lib/tron/src/models/contract/assets_issue_contract/asset_issue_contract.dart index 215bd1b5..e4140f59 100644 --- a/lib/tron/src/models/contract/assets_issue_contract/asset_issue_contract.dart +++ b/lib/tron/src/models/contract/assets_issue_contract/asset_issue_contract.dart @@ -3,36 +3,49 @@ import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/assets_issue_contract/frozensupply.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; class AssetIssueContract extends TronBaseContract { /// Create a new [AssetIssueContract] instance by parsing a JSON map. factory AssetIssueContract.fromJson(Map json) { return AssetIssueContract( - ownerAddress: TronAddress(json['owner_address']), - name: StringUtils.encode(json['name']), - abbr: StringUtils.encode(json['abbr']), - totalSupply: BigInt.from(json['total_supply']), - frozenSupply: (json['frozen_supply'] as List?) + ownerAddress: OnChainUtils.parseTronAddress( + value: json['owner_address'], name: "owner_address"), + name: OnChainUtils.parseBytes(value: json['name'], name: "name"), + abbr: OnChainUtils.parseBytes(value: json['abbr'], name: "abbr"), + totalSupply: OnChainUtils.parseBigInt( + value: json['total_supply'], name: "total_supply"), + frozenSupply: OnChainUtils.parseList( + value: json['frozen_supply'], name: "frozen_supply") ?.map((frozenSupplyJson) => AssetIssueContractFrozenSupply.fromJson(frozenSupplyJson)) .toList(), - trxNum: json['trx_num'], - precision: json['precision'], - num: json['num'], - startTime: BigintUtils.parse(json['start_time']), - endTime: BigintUtils.parse(json['end_time']), - order: BigintUtils.tryParse(json['order']), - voteScore: json['vote_score'], - description: StringUtils.tryEncode(json['description']), - url: StringUtils.tryEncode(json['url']), - freeAssetNetLimit: BigintUtils.tryParse(json['free_asset_netimit']), - publicFreeAssetNetLimit: - BigintUtils.tryParse(json['public_free_asset_netimit']), - publicFreeAssetNetUsage: - BigintUtils.tryParse(json['public_free_asset_net_usage']), - publicLatestFreeNetTime: - BigintUtils.tryParse(json['publicatest_free_net_time']), - id: json['id'], + trxNum: OnChainUtils.parseInt(value: json['trx_num'], name: "trx_num"), + precision: + OnChainUtils.parseInt(value: json['precision'], name: "precision"), + num: OnChainUtils.parseInt(value: json["num"], name: "num"), + startTime: OnChainUtils.parseBigInt( + value: json['start_time'], name: "start_time"), + endTime: + OnChainUtils.parseBigInt(value: json['end_time'], name: "end_time"), + order: OnChainUtils.parseBigInt(value: json['order'], name: "order"), + voteScore: + OnChainUtils.parseInt(value: json["vote_score"], name: "vote_score"), + description: OnChainUtils.parseBytes( + value: json['description'], name: "description"), + url: OnChainUtils.parseBytes(value: json['url'], name: "url"), + freeAssetNetLimit: OnChainUtils.parseBigInt( + value: json['free_asset_netimit'], name: "name"), + publicFreeAssetNetLimit: OnChainUtils.parseBigInt( + value: json['public_free_asset_netimit'], + name: "public_free_asset_netimit"), + publicFreeAssetNetUsage: OnChainUtils.parseBigInt( + value: json['public_free_asset_net_usage'], + name: "public_free_asset_net_usage"), + publicLatestFreeNetTime: OnChainUtils.parseBigInt( + value: json["publicatest_free_net_time"], + name: "publicatest_free_net_time"), + id: OnChainUtils.parseString(value: json['id'], name: "id"), ); } @@ -59,8 +72,9 @@ class AssetIssueContract extends TronBaseContract { this.id, }) : name = BytesUtils.toBytes(name, unmodifiable: true), abbr = BytesUtils.toBytes(abbr, unmodifiable: true), - frozenSupply = - frozenSupply != null ? List.unmodifiable(frozenSupply) : null, + frozenSupply = (frozenSupply?.isNotEmpty ?? false) + ? List.unmodifiable(frozenSupply!) + : null, description = BytesUtils.tryToBytes(description, unmodifiable: true), url = BytesUtils.tryToBytes(url, unmodifiable: true); @@ -92,6 +106,7 @@ class AssetIssueContract extends TronBaseContract { } /// issuer address + @override final TronAddress ownerAddress; /// token name diff --git a/lib/tron/src/models/contract/assets_issue_contract/frozensupply.dart b/lib/tron/src/models/contract/assets_issue_contract/frozensupply.dart index ec2de512..07bbee9a 100644 --- a/lib/tron/src/models/contract/assets_issue_contract/frozensupply.dart +++ b/lib/tron/src/models/contract/assets_issue_contract/frozensupply.dart @@ -1,6 +1,6 @@ import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class AssetIssueContractFrozenSupply extends TronProtocolBufferImpl { /// Create a new [AssetIssueContractFrozenSupply] instance with specified parameters. @@ -10,8 +10,10 @@ class AssetIssueContractFrozenSupply extends TronProtocolBufferImpl { /// Create a new [AssetIssueContractFrozenSupply] instance by parsing a JSON map. factory AssetIssueContractFrozenSupply.fromJson(Map json) { return AssetIssueContractFrozenSupply( - frozenAmount: BigintUtils.parse(json["frozen_amount"]), - frozenDays: BigintUtils.parse(json["frozen_days"])); + frozenAmount: OnChainUtils.parseBigInt( + value: json["frozen_amount"], name: "frozen_amount"), + frozenDays: OnChainUtils.parseBigInt( + value: json["frozen_days"], name: "frozen_days")); } factory AssetIssueContractFrozenSupply.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); diff --git a/lib/tron/src/models/contract/assets_issue_contract/participate_asset_issue_contract.dart b/lib/tron/src/models/contract/assets_issue_contract/participate_asset_issue_contract.dart index 8da65998..43e28815 100644 --- a/lib/tron/src/models/contract/assets_issue_contract/participate_asset_issue_contract.dart +++ b/lib/tron/src/models/contract/assets_issue_contract/participate_asset_issue_contract.dart @@ -2,16 +2,20 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Participate in an asset issue. class ParticipateAssetIssueContract extends TronBaseContract { /// Create a new [ParticipateAssetIssueContract] instance by parsing a JSON map. factory ParticipateAssetIssueContract.fromJson(Map json) { return ParticipateAssetIssueContract( - ownerAddress: TronAddress(json['owner_address']), - toAddress: TronAddress(json['to_address']), - assetName: StringUtils.encode(json['asset_name']), - amount: BigintUtils.parse(json['amount']), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + toAddress: OnChainUtils.parseTronAddress( + value: json["to_address"], name: "to_address"), + assetName: OnChainUtils.parseBytes( + value: json["asset_name"], name: "asset_name"), + amount: OnChainUtils.parseBigInt(value: json["amount"], name: "amount"), ); } @@ -32,6 +36,7 @@ class ParticipateAssetIssueContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Issuer's address diff --git a/lib/tron/src/models/contract/assets_issue_contract/transfer_assets_contract.dart b/lib/tron/src/models/contract/assets_issue_contract/transfer_assets_contract.dart index 1e530180..f01f6c1f 100644 --- a/lib/tron/src/models/contract/assets_issue_contract/transfer_assets_contract.dart +++ b/lib/tron/src/models/contract/assets_issue_contract/transfer_assets_contract.dart @@ -2,16 +2,20 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Transfer TRC10 token. class TransferAssetContract extends TronBaseContract { /// Create a new [TransferAssetContract] instance by parsing a JSON map. factory TransferAssetContract.fromJson(Map json) { return TransferAssetContract( - assetName: StringUtils.encode(json['asset_name']), - ownerAddress: TronAddress(json['owner_address']), - toAddress: TronAddress(json['to_address']), - amount: BigintUtils.parse(json['amount']), + assetName: OnChainUtils.parseBytes( + value: json['asset_name'], name: "asset_name"), + ownerAddress: OnChainUtils.parseTronAddress( + value: json['owner_address'], name: "owner_address"), + toAddress: OnChainUtils.parseTronAddress( + value: json['to_address'], name: "to_address"), + amount: OnChainUtils.parseBigInt(value: json['amount'], name: "amount"), ); } @@ -34,7 +38,10 @@ class TransferAssetContract extends TronBaseContract { /// Token id final List assetName; + String get assestId => StringUtils.decode(assetName); + /// Owner address + @override final TronAddress ownerAddress; /// receiving address diff --git a/lib/tron/src/models/contract/assets_issue_contract/unfreez_assets_contract.dart b/lib/tron/src/models/contract/assets_issue_contract/unfreez_assets_contract.dart index 8b16d548..ff972991 100644 --- a/lib/tron/src/models/contract/assets_issue_contract/unfreez_assets_contract.dart +++ b/lib/tron/src/models/contract/assets_issue_contract/unfreez_assets_contract.dart @@ -1,6 +1,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Unstake a token that has passed the minimum freeze duration. class UnfreezeAssetContract extends TronBaseContract { @@ -10,7 +11,8 @@ class UnfreezeAssetContract extends TronBaseContract { /// Create a new [UnfreezeAssetContract] instance by parsing a JSON map. factory UnfreezeAssetContract.fromJson(Map json) { return UnfreezeAssetContract( - ownerAddress: TronAddress(json["owner_address"])); + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address")); } factory UnfreezeAssetContract.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); @@ -19,6 +21,7 @@ class UnfreezeAssetContract extends TronBaseContract { } /// owner Address + @override final TronAddress ownerAddress; @override diff --git a/lib/tron/src/models/contract/assets_issue_contract/update_asset_contract.dart b/lib/tron/src/models/contract/assets_issue_contract/update_asset_contract.dart index fe44b3a4..7e80208d 100644 --- a/lib/tron/src/models/contract/assets_issue_contract/update_asset_contract.dart +++ b/lib/tron/src/models/contract/assets_issue_contract/update_asset_contract.dart @@ -2,17 +2,22 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Update basic TRC10 token information. class UpdateAssetContract extends TronBaseContract { /// Create a new [UpdateAssetContract] instance by parsing a JSON map. factory UpdateAssetContract.fromJson(Map json) { return UpdateAssetContract( - ownerAddress: TronAddress(json["owner_address"]), - description: StringUtils.tryEncode(json['description']), - url: StringUtils.tryEncode(json['url']), - newLimit: BigintUtils.tryParse(json['new_limit']), - newPublicLimit: BigintUtils.tryParse(json['new_public_limit']), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + description: OnChainUtils.parseBytes( + value: json["description"], name: "description"), + url: OnChainUtils.parseBytes(value: json["url"], name: "url"), + newLimit: + OnChainUtils.parseBigInt(value: json["new_limit"], name: "new_limit"), + newPublicLimit: OnChainUtils.parseBigInt( + value: json["new_public_limit"], name: "new_public_limit"), ); } @@ -36,6 +41,7 @@ class UpdateAssetContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Description diff --git a/lib/tron/src/models/contract/balance/account_identifier.dart b/lib/tron/src/models/contract/balance/account_identifier.dart index e73effb3..b799b617 100644 --- a/lib/tron/src/models/contract/balance/account_identifier.dart +++ b/lib/tron/src/models/contract/balance/account_identifier.dart @@ -1,11 +1,14 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; class AccountIdentifier extends TronProtocolBufferImpl { /// Create a new [AccountIdentifier] instance by parsing a JSON map. factory AccountIdentifier.fromJson(Map json) { - return AccountIdentifier(address: TronAddress(json["address"])); + return AccountIdentifier( + address: OnChainUtils.parseTronAddress( + value: json["address"], name: "address")); } factory AccountIdentifier.deserialize(List bytes) { diff --git a/lib/tron/src/models/contract/balance/cancel_all_unfreeze_v2_contract.dart b/lib/tron/src/models/contract/balance/cancel_all_unfreeze_v2_contract.dart index e4e190f7..b75b0c80 100644 --- a/lib/tron/src/models/contract/balance/cancel_all_unfreeze_v2_contract.dart +++ b/lib/tron/src/models/contract/balance/cancel_all_unfreeze_v2_contract.dart @@ -1,6 +1,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Cancel unstakings, all unstaked funds still in the waiting period will be re-staked, /// all unstaked funds that exceeded the 14-day waiting period will be automatically @@ -9,7 +10,8 @@ class CancelAllUnfreezeV2Contract extends TronBaseContract { /// Create a new [CancelAllUnfreezeV2Contract] instance by parsing a JSON map. factory CancelAllUnfreezeV2Contract.fromJson(Map json) { return CancelAllUnfreezeV2Contract( - ownerAddress: TronAddress(json["owner_address"])); + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address")); } /// Create a new [CancelAllUnfreezeV2Contract] instance with specified parameters. @@ -21,6 +23,7 @@ class CancelAllUnfreezeV2Contract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; @override diff --git a/lib/tron/src/models/contract/balance/delegate_resource_contract.dart b/lib/tron/src/models/contract/balance/delegate_resource_contract.dart index 3dc6181b..a050cb3d 100644 --- a/lib/tron/src/models/contract/balance/delegate_resource_contract.dart +++ b/lib/tron/src/models/contract/balance/delegate_resource_contract.dart @@ -1,19 +1,25 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Delegate bandwidth or energy resources to other accounts in Stake2.0. class DelegateResourceContract extends TronBaseContract { /// Create a new [DelegateResourceContract] instance by parsing a JSON map. factory DelegateResourceContract.fromJson(Map json) { return DelegateResourceContract( - ownerAddress: TronAddress(json["owner_address"]), - balance: BigintUtils.parse(json["balance"]), - receiverAddress: TronAddress(json["receiver_address"]), - lock: json["lock"], - resource: ResourceCode.fromName(json["resource"]), - lockPeriod: BigintUtils.tryParse(json["lock_period"])); + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + balance: + OnChainUtils.parseBigInt(value: json["balance"], name: "balance"), + receiverAddress: OnChainUtils.parseTronAddress( + value: json["receiver_address"], name: "receiver_address"), + lock: OnChainUtils.parseBoolean(value: json["lock"], name: "lock"), + resource: ResourceCode.fromName( + OnChainUtils.parseString(value: json["resource"], name: "resource"), + orElse: ResourceCode.bandWidth), + lockPeriod: OnChainUtils.parseBigInt( + value: json["lock_period"], name: "lock_period")); } factory DelegateResourceContract.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); @@ -37,6 +43,7 @@ class DelegateResourceContract extends TronBaseContract { this.lockPeriod}); /// Account address + @override final TronAddress ownerAddress; /// Resource type @@ -85,7 +92,7 @@ class DelegateResourceContract extends TronBaseContract { "lock_period": lockPeriod?.toString(), "balance": balance.toString(), "resource": resource?.name - }; + }..removeWhere((key, value) => value == null); } /// Convert the [DelegateResourceContract] object to its string representation. diff --git a/lib/tron/src/models/contract/balance/freez_balance_contract.dart b/lib/tron/src/models/contract/balance/freez_balance_contract.dart index 26cddc65..0e08b267 100644 --- a/lib/tron/src/models/contract/balance/freez_balance_contract.dart +++ b/lib/tron/src/models/contract/balance/freez_balance_contract.dart @@ -40,6 +40,7 @@ class FreezeBalanceContract extends TronBaseContract { this.receiverAddress}); /// Owner address + @override final TronAddress ownerAddress; /// TRX stake amount diff --git a/lib/tron/src/models/contract/balance/freez_balance_v2_contract.dart b/lib/tron/src/models/contract/balance/freez_balance_v2_contract.dart index e71ae909..b75e4ed2 100644 --- a/lib/tron/src/models/contract/balance/freez_balance_v2_contract.dart +++ b/lib/tron/src/models/contract/balance/freez_balance_v2_contract.dart @@ -1,7 +1,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// In Stake2.0, stake an amount of TRX to obtain bandwidth or energy, /// and obtain equivalent TRON Power(TP) according to the staked amount @@ -9,9 +9,13 @@ class FreezeBalanceV2Contract extends TronBaseContract { /// Create a new [FreezeBalanceV2Contract] instance by parsing a JSON map. factory FreezeBalanceV2Contract.fromJson(Map json) { return FreezeBalanceV2Contract( - ownerAddress: TronAddress(json["owner_address"]), - frozenBalance: BigintUtils.parse(json["frozen_balance"]), - resource: ResourceCode.fromName(json["resource"])); + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + frozenBalance: OnChainUtils.parseBigInt( + value: json["frozen_balance"], name: "frozen_balance"), + resource: ResourceCode.fromName( + OnChainUtils.parseString(value: json["resource"], name: "resource"), + orElse: ResourceCode.bandWidth)); } /// Create a new [FreezeBalanceV2Contract] instance with specified parameters. @@ -29,6 +33,7 @@ class FreezeBalanceV2Contract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// TRX stake amount, the unit is sun @@ -54,7 +59,7 @@ class FreezeBalanceV2Contract extends TronBaseContract { "owner_address": ownerAddress.toString(), "frozen_balance": frozenBalance.toString(), "resource": resource?.name - }; + }..removeWhere((key, value) => value == null); } /// Convert the [FreezeBalanceV2Contract] object to its string representation. @@ -66,4 +71,7 @@ class FreezeBalanceV2Contract extends TronBaseContract { @override TransactionContractType get contractType => TransactionContractType.freezeBalanceV2Contract; + + @override + BigInt get trxAmount => frozenBalance; } diff --git a/lib/tron/src/models/contract/balance/transfer_contract.dart b/lib/tron/src/models/contract/balance/transfer_contract.dart index 3bb2a2cb..d9f02f76 100644 --- a/lib/tron/src/models/contract/balance/transfer_contract.dart +++ b/lib/tron/src/models/contract/balance/transfer_contract.dart @@ -1,7 +1,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Create a TRX transfer transaction. If to_address does not exist, then create the account on the blockchain. class TransferContract extends TronBaseContract { @@ -14,10 +14,11 @@ class TransferContract extends TronBaseContract { /// Create a new [TransferContract] instance by parsing a JSON map. factory TransferContract.fromJson(Map json) { return TransferContract( - amount: BigintUtils.parse(json['amount']), - ownerAddress: TronAddress(json['owner_address']), - toAddress: TronAddress(json['to_address']), - ); + amount: OnChainUtils.parseBigInt(value: json['amount'], name: "amount"), + ownerAddress: OnChainUtils.parseTronAddress( + value: json['owner_address'], name: "owner_address"), + toAddress: OnChainUtils.parseTronAddress( + value: json['to_address'], name: "to_address")); } factory TransferContract.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); @@ -28,6 +29,7 @@ class TransferContract extends TronBaseContract { } /// Transaction initiator address + @override final TronAddress ownerAddress; /// Destination address @@ -61,4 +63,7 @@ class TransferContract extends TronBaseContract { @override TransactionContractType get contractType => TransactionContractType.transferContract; + + @override + BigInt get trxAmount => amount; } diff --git a/lib/tron/src/models/contract/balance/undelegate_resource_contract.dart b/lib/tron/src/models/contract/balance/undelegate_resource_contract.dart index 7ed340d7..6a2ec4fc 100644 --- a/lib/tron/src/models/contract/balance/undelegate_resource_contract.dart +++ b/lib/tron/src/models/contract/balance/undelegate_resource_contract.dart @@ -34,6 +34,7 @@ class UnDelegateResourceContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Resource type @@ -64,7 +65,7 @@ class UnDelegateResourceContract extends TronBaseContract { "receiver_address": receiverAddress.toString(), "balance": balance.toString(), "resource": resource?.name - }; + }..removeWhere((key, value) => value == null); } /// Convert the [UnDelegateResourceContract] object to its string representation. diff --git a/lib/tron/src/models/contract/balance/unfreez_balance_contract.dart b/lib/tron/src/models/contract/balance/unfreez_balance_contract.dart index e12d4e9c..2636965b 100644 --- a/lib/tron/src/models/contract/balance/unfreez_balance_contract.dart +++ b/lib/tron/src/models/contract/balance/unfreez_balance_contract.dart @@ -30,6 +30,7 @@ class UnfreezeBalanceContract extends TronBaseContract { {required this.ownerAddress, this.resource, this.receiverAddress}); /// Transaction initiator address + @override final TronAddress ownerAddress; /// Resource type diff --git a/lib/tron/src/models/contract/balance/unfreez_balance_v2_contract.dart b/lib/tron/src/models/contract/balance/unfreez_balance_v2_contract.dart index 35fd7b73..17537df9 100644 --- a/lib/tron/src/models/contract/balance/unfreez_balance_v2_contract.dart +++ b/lib/tron/src/models/contract/balance/unfreez_balance_v2_contract.dart @@ -1,7 +1,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Unstake some TRX staked in Stake2.0, /// release the corresponding amount of bandwidth or energy, @@ -10,9 +10,13 @@ class UnfreezeBalanceV2Contract extends TronBaseContract { /// Create a new [UnfreezeBalanceV2Contract] instance by parsing a JSON map. factory UnfreezeBalanceV2Contract.fromJson(Map json) { return UnfreezeBalanceV2Contract( - ownerAddress: TronAddress(json["owner_address"]), - unfreezeBalance: BigintUtils.parse(json["unfreeze_balance"]), - resource: ResourceCode.fromName(json["resource"])); + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + unfreezeBalance: OnChainUtils.parseBigInt( + value: json["unfreeze_balance"], name: "unfreeze_balance"), + resource: ResourceCode.fromName( + OnChainUtils.parseString(value: json["resource"], name: "resource"), + orElse: ResourceCode.bandWidth)); } factory UnfreezeBalanceV2Contract.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); @@ -31,6 +35,7 @@ class UnfreezeBalanceV2Contract extends TronBaseContract { this.resource}); /// Account address + @override final TronAddress ownerAddress; /// Unstake amount, unit is sun @@ -43,8 +48,11 @@ class UnfreezeBalanceV2Contract extends TronBaseContract { List get fieldIds => [1, 2, 3]; @override - List get values => - [ownerAddress, unfreezeBalance, resource?.value == 0 ? null : resource]; + List get values => [ + ownerAddress, + unfreezeBalance, + resource == ResourceCode.bandWidth ? null : resource, + ]; /// Convert the [UnfreezeBalanceV2Contract] object to a JSON representation. @override @@ -53,7 +61,7 @@ class UnfreezeBalanceV2Contract extends TronBaseContract { "owner_address": ownerAddress.toString(), "unfreeze_balance": unfreezeBalance.toString(), "resource": resource?.name - }; + }..removeWhere((key, value) => value == null); } /// Convert the [UnfreezeBalanceV2Contract] object to its string representation. diff --git a/lib/tron/src/models/contract/balance/withdraw_balance_contract.dart b/lib/tron/src/models/contract/balance/withdraw_balance_contract.dart index 21fb0cfe..f54eb7aa 100644 --- a/lib/tron/src/models/contract/balance/withdraw_balance_contract.dart +++ b/lib/tron/src/models/contract/balance/withdraw_balance_contract.dart @@ -17,6 +17,7 @@ class WithdrawBalanceContract extends TronBaseContract { return WithdrawBalanceContract( ownerAddress: TronAddress.fromBytes(decode.getField(1))); } + @override final TronAddress ownerAddress; @override diff --git a/lib/tron/src/models/contract/balance/withdraw_expire_unfreeze_contract.dart b/lib/tron/src/models/contract/balance/withdraw_expire_unfreeze_contract.dart index 10b77cac..3282cf5a 100644 --- a/lib/tron/src/models/contract/balance/withdraw_expire_unfreeze_contract.dart +++ b/lib/tron/src/models/contract/balance/withdraw_expire_unfreeze_contract.dart @@ -1,6 +1,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Withdraw unfrozen balance in Stake2.0, the user can /// call this API to get back their funds after executing /wallet/unfreezebalancev2 @@ -9,7 +10,8 @@ class WithdrawExpireUnfreezeContract extends TronBaseContract { /// Create a new [WithdrawExpireUnfreezeContract] instance by parsing a JSON map. factory WithdrawExpireUnfreezeContract.fromJson(Map json) { return WithdrawExpireUnfreezeContract( - ownerAddress: TronAddress(json["owner_address"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), ); } factory WithdrawExpireUnfreezeContract.deserialize(List bytes) { @@ -22,6 +24,7 @@ class WithdrawExpireUnfreezeContract extends TronBaseContract { WithdrawExpireUnfreezeContract({required this.ownerAddress}); /// Account address + @override final TronAddress ownerAddress; @override diff --git a/lib/tron/src/models/contract/base_contract/base_contract.dart b/lib/tron/src/models/contract/base_contract/base_contract.dart index d3b37683..62857bab 100644 --- a/lib/tron/src/models/contract/base_contract/base_contract.dart +++ b/lib/tron/src/models/contract/base_contract/base_contract.dart @@ -1,3 +1,5 @@ +import 'package:on_chain/tron/src/address/tron_address.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/common.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; @@ -19,12 +21,12 @@ abstract class TronProtocolBufferImpl { /// Converts the protocol buffer data to a byte buffer. List toBuffer() { if (values.length != fieldIds.length) { - throw MessageException( + throw TronPluginException( "The values and field IDs must have the same length.", details: { "values": values, "fieldIds": fieldIds, - "class": runtimeType.toString(), + "class": runtimeType.toString() }); } final bytes = DynamicByteTracker(); @@ -40,7 +42,6 @@ abstract class TronProtocolBufferImpl { } else { encode = ProtocolBufferEncoder.encode(tagNumber, value); } - bytes.add(encode); } return bytes.toBytes(); @@ -58,4 +59,18 @@ abstract class TronProtocolBufferImpl { abstract class TronBaseContract extends TronProtocolBufferImpl { TransactionContractType get contractType; String get typeURL => "type.googleapis.com/protocol.${contractType.name}"; + + /// the owner of contract. + TronAddress get ownerAddress; + + /// the trx amount of contract; + /// if contract need any trx amount for spending, stack, freez or .... + BigInt get trxAmount => BigInt.zero; + + T cast() { + if (this is! T) { + throw const TronPluginException("Incorrect contract casting."); + } + return this as T; + } } diff --git a/lib/tron/src/models/contract/base_contract/transaction_type.dart b/lib/tron/src/models/contract/base_contract/transaction_type.dart index 3b8581c1..b37513b7 100644 --- a/lib/tron/src/models/contract/base_contract/transaction_type.dart +++ b/lib/tron/src/models/contract/base_contract/transaction_type.dart @@ -1,3 +1,4 @@ +import 'package:on_chain/tron/src/exception/exception.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/common.dart'; /// Enum representing different types of transaction contracts on the Tron blockchain. @@ -146,7 +147,9 @@ class TransactionContractType implements TronEnumerate { /// /// Case-sensitive matching is performed. static TransactionContractType findByName(String name) { - return values.firstWhere((element) => element.name == name); + return values.firstWhere((element) => element.name == name, + orElse: () => + throw const TronPluginException("Contact does not found.")); } /// Finds and returns a [TransactionContractType] by its [value]. diff --git a/lib/tron/src/models/contract/contract.dart b/lib/tron/src/models/contract/contract.dart index 77d7b173..fa560096 100644 --- a/lib/tron/src/models/contract/contract.dart +++ b/lib/tron/src/models/contract/contract.dart @@ -1,4 +1,4 @@ -export 'account/accout.dart'; +export 'account/account.dart'; export 'assets_issue_contract/asset.dart'; export 'balance/balance.dart'; export 'base_contract/base.dart'; diff --git a/lib/tron/src/models/contract/exchange/create_exchange_contract.dart b/lib/tron/src/models/contract/exchange/create_exchange_contract.dart index 0f89d9f7..abb6d3a7 100644 --- a/lib/tron/src/models/contract/exchange/create_exchange_contract.dart +++ b/lib/tron/src/models/contract/exchange/create_exchange_contract.dart @@ -2,17 +2,23 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Creates a trading pair. class ExchangeCreateContract extends TronBaseContract { /// Create a new [ExchangeCreateContract] instance by parsing a JSON map. factory ExchangeCreateContract.fromJson(Map json) { return ExchangeCreateContract( - ownerAddress: TronAddress(json["owner_address"]), - firstTokenId: BytesUtils.tryFromHexString(json["first_token_id"]), - firstTokenBalance: BigintUtils.tryParse(json["first_token_balance"]), - secondTokenId: BytesUtils.tryFromHexString(json["second_token_id"]), - secondTokenBalance: BigintUtils.tryParse(json["second_token_balance"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + firstTokenId: OnChainUtils.parseBytes( + value: json["first_token_id"], name: "first_token_id"), + firstTokenBalance: OnChainUtils.parseBigInt( + value: json["first_token_balance"], name: "first_token_balance"), + secondTokenId: OnChainUtils.parseBytes( + value: json["second_token_id"], name: "second_token_id"), + secondTokenBalance: OnChainUtils.parseBigInt( + value: json["second_token_balance"], name: "second_token_balance"), ); } factory ExchangeCreateContract.deserialize(List bytes) { @@ -37,6 +43,7 @@ class ExchangeCreateContract extends TronBaseContract { BytesUtils.tryToBytes(secondTokenId, unmodifiable: true); /// Account address + @override final TronAddress ownerAddress; /// First token id @@ -68,11 +75,11 @@ class ExchangeCreateContract extends TronBaseContract { Map toJson() { return { "owner_address": ownerAddress.toString(), - "first_token_id": BytesUtils.tryToHexString(firstTokenId), + "first_token_id": StringUtils.tryDecode(firstTokenId), "first_token_balance": firstTokenBalance?.toString(), - "second_token_id": BytesUtils.tryToHexString(secondTokenId), + "second_token_id": StringUtils.tryDecode(secondTokenId), "second_token_balance": secondTokenBalance?.toString(), - }; + }..removeWhere((key, value) => value == null); } /// Convert the [ExchangeCreateContract] object to its string representation. diff --git a/lib/tron/src/models/contract/exchange/exchange_inject_contract.dart b/lib/tron/src/models/contract/exchange/exchange_inject_contract.dart index 0ce65eb3..fe8794d8 100644 --- a/lib/tron/src/models/contract/exchange/exchange_inject_contract.dart +++ b/lib/tron/src/models/contract/exchange/exchange_inject_contract.dart @@ -2,6 +2,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Injects capital into the transaction. /// The purpose of injecting capital into the trading pair @@ -10,10 +11,13 @@ class ExchangeInjectContract extends TronBaseContract { /// Create a new [ExchangeInjectContract] instance by parsing a JSON map. factory ExchangeInjectContract.fromJson(Map json) { return ExchangeInjectContract( - ownerAddress: TronAddress(json["owner_address"]), - exchangeId: BigintUtils.tryParse(json["exchange_id"]), - tokenId: BytesUtils.tryFromHexString(json["token_id"]), - quant: BigintUtils.tryParse(json["quant"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + exchangeId: OnChainUtils.parseBigInt( + value: json["exchange_id"], name: "exchange_id"), + tokenId: + OnChainUtils.parseBytes(value: json["token_id"], name: "token_id"), + quant: OnChainUtils.parseBigInt(value: json["quant"], name: "quant"), ); } factory ExchangeInjectContract.deserialize(List bytes) { @@ -34,6 +38,7 @@ class ExchangeInjectContract extends TronBaseContract { : tokenId = BytesUtils.tryToBytes(tokenId); /// Account address + @override final TronAddress ownerAddress; /// Exchange id diff --git a/lib/tron/src/models/contract/exchange/exchange_transaction_contract.dart b/lib/tron/src/models/contract/exchange/exchange_transaction_contract.dart index f82cca5c..0b35c3e4 100644 --- a/lib/tron/src/models/contract/exchange/exchange_transaction_contract.dart +++ b/lib/tron/src/models/contract/exchange/exchange_transaction_contract.dart @@ -2,17 +2,22 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Participate the transaction of exchange pair class ExchangeTransactionContract extends TronBaseContract { /// Create a new [ExchangeTransactionContract] instance by parsing a JSON map. factory ExchangeTransactionContract.fromJson(Map json) { return ExchangeTransactionContract( - ownerAddress: TronAddress(json["owner_address"]), - exchangeId: BigintUtils.tryParse(json["exchange_id"]), - tokenId: BytesUtils.fromHexString(json["token_id"]), - quant: BigintUtils.tryParse(json["quant"]), - expected: BigintUtils.tryParse(json["expected"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + exchangeId: OnChainUtils.parseBigInt( + value: json["exchange_id"], name: "exchange_id"), + tokenId: + OnChainUtils.parseBytes(value: json["token_id"], name: "token_id"), + quant: OnChainUtils.parseBigInt(value: json["quant"], name: "quant"), + expected: + OnChainUtils.parseBigInt(value: json["expected"], name: "expected"), ); } @@ -35,6 +40,7 @@ class ExchangeTransactionContract extends TronBaseContract { } /// Trader's wallet address + @override final TronAddress ownerAddress; /// Transaction Pair ID diff --git a/lib/tron/src/models/contract/exchange/exchange_withdraw_contract.dart b/lib/tron/src/models/contract/exchange/exchange_withdraw_contract.dart index c59e83bf..c07af351 100644 --- a/lib/tron/src/models/contract/exchange/exchange_withdraw_contract.dart +++ b/lib/tron/src/models/contract/exchange/exchange_withdraw_contract.dart @@ -2,16 +2,20 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Withdraws the transaction pair. class ExchangeWithdrawContract extends TronBaseContract { /// Create a new [ExchangeWithdrawContract] instance by parsing a JSON map. factory ExchangeWithdrawContract.fromJson(Map json) { return ExchangeWithdrawContract( - ownerAddress: TronAddress(json["owner_address"]), - exchangeId: BigintUtils.tryParse(json["exchange_id"]), - tokenId: BytesUtils.tryFromHexString(json["token_id"]), - quant: BigintUtils.tryParse(json["quant"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + exchangeId: OnChainUtils.parseBigInt( + value: json["exchange_id"], name: "exchange_id"), + tokenId: + OnChainUtils.parseBytes(value: json["token_id"], name: "token_id"), + quant: OnChainUtils.parseBigInt(value: json["quant"], name: "quant"), ); } factory ExchangeWithdrawContract.deserialize(List bytes) { @@ -32,6 +36,7 @@ class ExchangeWithdrawContract extends TronBaseContract { : tokenId = BytesUtils.tryToBytes(tokenId); /// Account address + @override final TronAddress ownerAddress; /// Exchange id diff --git a/lib/tron/src/models/contract/market/market_cancel_order_contract.dart b/lib/tron/src/models/contract/market/market_cancel_order_contract.dart index 99be6697..6fd61e63 100644 --- a/lib/tron/src/models/contract/market/market_cancel_order_contract.dart +++ b/lib/tron/src/models/contract/market/market_cancel_order_contract.dart @@ -2,13 +2,16 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class MarketCancelOrderContract extends TronBaseContract { /// Create a new [MarketCancelOrderContract] instance by parsing a JSON map. factory MarketCancelOrderContract.fromJson(Map json) { return MarketCancelOrderContract( - ownerAddress: TronAddress(json["owner_address"]), - orderId: BytesUtils.tryFromHexString(json["order_id"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + orderId: + OnChainUtils.parseBytes(value: json["order_id"], name: "order_id"), ); } @@ -23,6 +26,7 @@ class MarketCancelOrderContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; final List? orderId; @@ -38,7 +42,7 @@ class MarketCancelOrderContract extends TronBaseContract { return { "owner_address": ownerAddress.toString(), "order_id": BytesUtils.tryToHexString(orderId) - }; + }..removeWhere((k, v) => v == null); } /// Convert the [MarketCancelOrderContract] object to its string representation. diff --git a/lib/tron/src/models/contract/market/market_sell_asset_contract.dart b/lib/tron/src/models/contract/market/market_sell_asset_contract.dart index 1e473ec2..66b6f233 100644 --- a/lib/tron/src/models/contract/market/market_sell_asset_contract.dart +++ b/lib/tron/src/models/contract/market/market_sell_asset_contract.dart @@ -2,16 +2,22 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class MarketSellAssetContract extends TronBaseContract { /// Create a new [MarketSellAssetContract] instance by parsing a JSON map. factory MarketSellAssetContract.fromJson(Map json) { return MarketSellAssetContract( - ownerAddress: TronAddress(json["owner_address"]), - sellTokenId: BytesUtils.tryFromHexString(json["sell_token_id"]), - sellTokenQuantity: BigintUtils.tryParse(json["sell_token_quantity"]), - buyTokenId: BytesUtils.tryFromHexString(json["buy_token_id"]), - buyTokenQuantity: BigintUtils.tryParse(json["buy_token_quantity"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + sellTokenId: OnChainUtils.parseBytes( + value: json["sell_token_id"], name: "sell_token_id"), + sellTokenQuantity: OnChainUtils.parseBigInt( + value: json["sell_token_quantity"], name: "sell_token_quantity"), + buyTokenId: OnChainUtils.parseBytes( + value: json["buy_token_id"], name: "buy_token_id"), + buyTokenQuantity: OnChainUtils.parseBigInt( + value: json["buy_token_quantity"], name: "buy_token_quantity"), ); } @@ -35,6 +41,7 @@ class MarketSellAssetContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; final List? sellTokenId; final BigInt? sellTokenQuantity; @@ -62,7 +69,7 @@ class MarketSellAssetContract extends TronBaseContract { "sell_token_quantity": sellTokenQuantity?.toString(), "buy_token_id": BytesUtils.tryToHexString(buyTokenId), "buy_token_quantity": buyTokenQuantity?.toString(), - }; + }..removeWhere((k, v) => v == null); } /// Convert the [MarketSellAssetContract] object to its string representation. diff --git a/lib/tron/src/models/contract/proposal/proposal_approve_contract.dart b/lib/tron/src/models/contract/proposal/proposal_approve_contract.dart index 34e568ed..bddd2227 100644 --- a/lib/tron/src/models/contract/proposal/proposal_approve_contract.dart +++ b/lib/tron/src/models/contract/proposal/proposal_approve_contract.dart @@ -1,16 +1,19 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Approves proposed transaction. class ProposalApproveContract extends TronBaseContract { /// Create a new [ProposalApproveContract] instance by parsing a JSON map. factory ProposalApproveContract.fromJson(Map json) { return ProposalApproveContract( - ownerAddress: TronAddress(json["owner_address"]), - proposalId: BigintUtils.tryParse(json["proposal_id"]), - isAddApproval: json["is_add_approval"], + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + proposalId: OnChainUtils.parseBigInt( + value: json["proposal_id"], name: "proposal_id"), + isAddApproval: OnChainUtils.parseBoolean( + value: json["is_add_approval"], name: "is_add_approval"), ); } factory ProposalApproveContract.deserialize(List bytes) { @@ -26,6 +29,7 @@ class ProposalApproveContract extends TronBaseContract { {required this.ownerAddress, this.proposalId, this.isAddApproval}); /// Account address + @override final TronAddress ownerAddress; /// Proposal id @@ -47,7 +51,7 @@ class ProposalApproveContract extends TronBaseContract { "owner_address": ownerAddress.toString(), "proposal_id": proposalId?.toString(), "is_add_approval": isAddApproval, - }; + }..removeWhere((k, v) => v == null); } /// Convert the [ProposalApproveContract] object to its string representation. diff --git a/lib/tron/src/models/contract/proposal/proposal_create_contract.dart b/lib/tron/src/models/contract/proposal/proposal_create_contract.dart index 6ea7a449..0e9b8cc7 100644 --- a/lib/tron/src/models/contract/proposal/proposal_create_contract.dart +++ b/lib/tron/src/models/contract/proposal/proposal_create_contract.dart @@ -1,19 +1,23 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Creates a proposal transaction. class ProposalCreateContract extends TronBaseContract { /// Create a new [ProposalCreateContract] instance by parsing a JSON map. factory ProposalCreateContract.fromJson(Map json) { return ProposalCreateContract( - ownerAddress: TronAddress(json["owner_address"]), - parameters: json["parameters"] == null + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + parameters: OnChainUtils.parseMap( + value: json["parameters"], name: "parameters") == + null ? null : (json["parameters"] as Map).map( - (key, value) => - MapEntry(BigintUtils.parse(key), BigintUtils.parse(value)), + (key, value) => MapEntry( + OnChainUtils.parseBigInt(value: key, name: "parameters"), + OnChainUtils.parseBigInt(value: value, name: "parameters")), ), ); } @@ -32,6 +36,7 @@ class ProposalCreateContract extends TronBaseContract { : Map.unmodifiable(parameters); /// Account address + @override final TronAddress ownerAddress; /// Parameters proposed to be modified and their values diff --git a/lib/tron/src/models/contract/proposal/proposal_delete_contrat.dart b/lib/tron/src/models/contract/proposal/proposal_delete_contrat.dart index 0495b51f..7be13939 100644 --- a/lib/tron/src/models/contract/proposal/proposal_delete_contrat.dart +++ b/lib/tron/src/models/contract/proposal/proposal_delete_contrat.dart @@ -1,15 +1,17 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Deletes Proposal Transaction. class ProposalDeleteContract extends TronBaseContract { /// Create a new [ProposalDeleteContract] instance by parsing a JSON map. factory ProposalDeleteContract.fromJson(Map json) { return ProposalDeleteContract( - ownerAddress: TronAddress(json["owner_address"]), - proposalId: BigintUtils.tryParse(json["proposal_id"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + proposalId: OnChainUtils.parseBigInt( + value: json["proposal_id"], name: "proposal_id"), ); } @@ -23,6 +25,7 @@ class ProposalDeleteContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Proposal id diff --git a/lib/tron/src/models/contract/shield/shield_transfer_contract.dart b/lib/tron/src/models/contract/shield/shield_transfer_contract.dart index 385d7452..4f0d0b89 100644 --- a/lib/tron/src/models/contract/shield/shield_transfer_contract.dart +++ b/lib/tron/src/models/contract/shield/shield_transfer_contract.dart @@ -1,3 +1,4 @@ +import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/shield/receive_description.dart'; import 'package:on_chain/tron/src/models/contract/shield/spend_description.dart'; @@ -111,4 +112,7 @@ class ShieldedTransferContract extends TronBaseContract { @override TransactionContractType get contractType => TransactionContractType.shieldedTransferContract; + + @override + TronAddress get ownerAddress => throw UnimplementedError(); } diff --git a/lib/tron/src/models/contract/smart_contract/abi_types.dart b/lib/tron/src/models/contract/smart_contract/abi_types.dart index 842ece77..4c3717bc 100644 --- a/lib/tron/src/models/contract/smart_contract/abi_types.dart +++ b/lib/tron/src/models/contract/smart_contract/abi_types.dart @@ -1,3 +1,4 @@ +import 'package:on_chain/tron/src/exception/exception.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/common.dart'; /// Enum representing different types of entries in a smart contract's ABI (Application Binary Interface). @@ -66,13 +67,19 @@ class SmartContractAbiEntryType implements TronEnumerate { /// Case-insensitive matching is performed. static SmartContractAbiEntryType fromName(String name) { return values.firstWhere( - (element) => element.name.toLowerCase() == name.toLowerCase()); + (element) => element.name.toLowerCase() == name.toLowerCase(), + orElse: () => throw const TronPluginException( + "SmartContractAbiEntryType was not found."), + ); } static SmartContractAbiEntryType fromValue(int? value, {SmartContractAbiEntryType? orElese}) { - return values.firstWhere((element) => element.value == value, - orElse: orElese == null ? null : () => orElese); + return values.firstWhere((element) => element.value == value, orElse: () { + if (orElese != null) return orElese; + throw const TronPluginException( + "SmartContractAbiEntryType was not found."); + }); } @override @@ -135,13 +142,20 @@ class SmartContractAbiStateMutabilityType implements TronEnumerate { /// Case-insensitive matching is performed. static SmartContractAbiStateMutabilityType fromName(String name) { return values.firstWhere( - (element) => element.name.toLowerCase() == name.toLowerCase()); + (element) => element.name.toLowerCase() == name.toLowerCase(), + orElse: () { + throw const TronPluginException( + "SmartContractAbiStateMutabilityType was not found."); + }); } static SmartContractAbiStateMutabilityType fromValue(int? value, {SmartContractAbiStateMutabilityType? orElese}) { - return values.firstWhere((element) => element.value == value, - orElse: orElese == null ? null : () => orElese); + return values.firstWhere((element) => element.value == value, orElse: () { + if (orElese != null) return orElese; + throw const TronPluginException( + "SmartContractAbiStateMutabilityType was not found."); + }); } @override diff --git a/lib/tron/src/models/contract/smart_contract/clear_abi_contract.dart b/lib/tron/src/models/contract/smart_contract/clear_abi_contract.dart index ab99b85a..5bce504c 100644 --- a/lib/tron/src/models/contract/smart_contract/clear_abi_contract.dart +++ b/lib/tron/src/models/contract/smart_contract/clear_abi_contract.dart @@ -1,14 +1,17 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// To clear the ABI info of a smart contract. class ClearABIContract extends TronBaseContract { /// Create a new [ClearABIContract] instance by parsing a JSON map. factory ClearABIContract.fromJson(Map json) { return ClearABIContract( - ownerAddress: TronAddress(json["owner_address"]), - contractAddress: TronAddress(json["contract_address"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + contractAddress: OnChainUtils.parseTronAddress( + value: json["contract_address"], name: "contract_address"), ); } @@ -22,6 +25,7 @@ class ClearABIContract extends TronBaseContract { } /// Owner address of the smart contract + @override final TronAddress ownerAddress; /// Smart contract address diff --git a/lib/tron/src/models/contract/smart_contract/create_smart_contract.dart b/lib/tron/src/models/contract/smart_contract/create_smart_contract.dart index 67a5d700..8ca51b5f 100644 --- a/lib/tron/src/models/contract/smart_contract/create_smart_contract.dart +++ b/lib/tron/src/models/contract/smart_contract/create_smart_contract.dart @@ -1,18 +1,24 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/smart_contract/smart_contract.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; /// Deploys a contract class CreateSmartContract extends TronBaseContract { /// Create a new [CreateSmartContract] instance by parsing a JSON map. factory CreateSmartContract.fromJson(Map json) { return CreateSmartContract( - ownerAddress: TronAddress(json["owner_address"]), - newContract: SmartContract.fromJson(json["new_contract"]), - callTokenValue: BigintUtils.tryParse(json["call_token_value"]), - tokenId: BigintUtils.tryParse(json["token_id"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + newContract: SmartContract.fromJson(OnChainUtils.parseMap( + value: json["new_contract"], + name: "new_contract", + throwOnNull: true)!), + callTokenValue: OnChainUtils.parseBigInt( + value: json["call_token_value"], name: "call_token_value"), + tokenId: + OnChainUtils.parseBigInt(value: json["token_id"], name: "token_id"), ); } @@ -32,6 +38,7 @@ class CreateSmartContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Deployed contract data, the fields contained in it @@ -69,4 +76,9 @@ class CreateSmartContract extends TronBaseContract { @override TransactionContractType get contractType => TransactionContractType.createSmartContract; + + @override + BigInt get trxAmount => newContract.callValue ?? BigInt.zero; + + bool get hasTokenTransfer => callTokenValue != null && tokenId != null; } diff --git a/lib/tron/src/models/contract/smart_contract/smart_contract.dart b/lib/tron/src/models/contract/smart_contract/smart_contract.dart index fea883cd..58d58029 100644 --- a/lib/tron/src/models/contract/smart_contract/smart_contract.dart +++ b/lib/tron/src/models/contract/smart_contract/smart_contract.dart @@ -3,25 +3,36 @@ import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/smart_contract/smart_contract_abi.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class SmartContract extends TronProtocolBufferImpl { /// Create a new [SmartContract] instance by parsing a JSON map. factory SmartContract.fromJson(Map json) { return SmartContract( - originAddress: TronAddress(json["origin_address"]), - bytecode: BytesUtils.fromHexString(json["bytecode"]), - callValue: BigintUtils.tryParse(json["call_value"]), - abi: SmartContractABI.fromJson(json["abi"]), - consumeUserResourcePercent: - BigintUtils.tryParse(json["consume_user_resource_percent"]), - name: json["name"], - originEnergyLimit: BigintUtils.tryParse(json["origin_energy_limit"]), - trxHash: BytesUtils.tryFromHexString(json["trx_hash"]), - codeHash: BytesUtils.tryFromHexString(json["code_hash"]), - version: IntUtils.tryParse(json["version"]), - contractAddress: json["contract_address"] == null + originAddress: OnChainUtils.parseTronAddress( + value: json["origin_address"], name: "origin_address"), + bytecode: + OnChainUtils.parseHex(value: json["bytecode"], name: "bytecode"), + callValue: OnChainUtils.parseBigInt( + value: json["call_value"], name: "call_value"), + abi: OnChainUtils.parseMap( + value: json["abi"], name: "abi", throwOnNull: false) == + null ? null - : TronAddress(json["contract_address"])); + : SmartContractABI.fromJson(json["abi"]), + consumeUserResourcePercent: OnChainUtils.parseBigInt( + value: json["consume_user_resource_percent"], + name: "consume_user_resource_percent"), + name: OnChainUtils.parseString(value: json["name"], name: "name"), + originEnergyLimit: OnChainUtils.parseBigInt( + value: json["origin_energy_limit"], name: "origin_energy_limit"), + trxHash: + OnChainUtils.parseHex(value: json["trx_hash"], name: "trx_hash"), + codeHash: + OnChainUtils.parseHex(value: json["code_hash"], name: "code_hash"), + version: OnChainUtils.parseInt(value: json["version"], name: "version"), + contractAddress: OnChainUtils.parseTronAddress( + value: json["contract_address"], name: "contract_address")); } factory SmartContract.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); @@ -80,7 +91,9 @@ class SmartContract extends TronProtocolBufferImpl { abi, bytecode, callValue, - consumeUserResourcePercent, + consumeUserResourcePercent == BigInt.zero + ? null + : consumeUserResourcePercent, name, originEnergyLimit, codeHash, diff --git a/lib/tron/src/models/contract/smart_contract/smart_contract_abi.dart b/lib/tron/src/models/contract/smart_contract/smart_contract_abi.dart index 0df1cce3..c4e2c6df 100644 --- a/lib/tron/src/models/contract/smart_contract/smart_contract_abi.dart +++ b/lib/tron/src/models/contract/smart_contract/smart_contract_abi.dart @@ -1,5 +1,6 @@ import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; import 'smart_contract_abi_entry.dart'; @@ -11,7 +12,7 @@ class SmartContractABI extends TronProtocolBufferImpl { /// Create a new [SmartContractABI] instance by parsing a JSON map. factory SmartContractABI.fromJson(Map json) { return SmartContractABI( - entrys: (json["entrys"] as List?) + entrys: OnChainUtils.parseList(value: json["entrys"], name: "entrys") ?.map((e) => SmartContractABIEntry.fromJson(e)) .toList() ?? []); diff --git a/lib/tron/src/models/contract/smart_contract/smart_contract_abi_entry.dart b/lib/tron/src/models/contract/smart_contract/smart_contract_abi_entry.dart index 393de527..1416633d 100644 --- a/lib/tron/src/models/contract/smart_contract/smart_contract_abi_entry.dart +++ b/lib/tron/src/models/contract/smart_contract/smart_contract_abi_entry.dart @@ -2,24 +2,33 @@ import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/smart_contract/abi_types.dart'; import 'package:on_chain/tron/src/models/contract/smart_contract/smart_contract_abi_entry_param.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class SmartContractABIEntry extends TronProtocolBufferImpl { /// Create a new [SmartContractABIEntry] instance by parsing a JSON map. factory SmartContractABIEntry.fromJson(Map json) { return SmartContractABIEntry( - type: SmartContractAbiEntryType.fromName(json["type"]), - stateMutability: - SmartContractAbiStateMutabilityType.fromName(json["stateMutability"]), - anonymous: json["anonymous"], - inputs: (json["inputs"] as List?) + anonymous: OnChainUtils.parseBoolean( + value: json["anonymous"], name: "anonymous"), + type: SmartContractAbiEntryType.fromName( + OnChainUtils.parseString(value: json["type"], name: "type")), + stateMutability: OnChainUtils.parseString( + value: json["stateMutability"], name: "stateMutability") == + null + ? null + : SmartContractAbiStateMutabilityType.fromName( + json["stateMutability"]), + inputs: OnChainUtils.parseList(value: json["inputs"], name: "inputs") ?.map((e) => SmartContractBABIEntryParam.fromJson(e)) .toList(), - outputs: (json["outputs"] as List?) + outputs: OnChainUtils.parseList(value: json["outputs"], name: "outputs") ?.map((e) => SmartContractBABIEntryParam.fromJson(e)) .toList(), - constant: json["constant"], - name: json["name"], - payable: json["payable"], + constant: + OnChainUtils.parseBoolean(value: json["constant"], name: "constant"), + name: OnChainUtils.parseString(value: json["name"], name: "name"), + payable: + OnChainUtils.parseBoolean(value: json["payable"], name: "payable"), ); } @@ -55,8 +64,10 @@ class SmartContractABIEntry extends TronProtocolBufferImpl { .toList(), type: SmartContractAbiEntryType.fromValue(decode.getField(6)), payable: decode.getField(7), - stateMutability: - SmartContractAbiStateMutabilityType.fromValue(decode.getField(8))); + stateMutability: decode.getField(8) == null + ? null + : SmartContractAbiStateMutabilityType.fromValue( + decode.getField(8))); } final bool? anonymous; final bool? constant; @@ -70,7 +81,7 @@ class SmartContractABIEntry extends TronProtocolBufferImpl { List get fieldIds => [1, 2, 3, 4, 5, 6, 7, 8]; @override List get values => [ - anonymous, + anonymous == false ? null : anonymous, constant, name, inputs, diff --git a/lib/tron/src/models/contract/smart_contract/smart_contract_abi_entry_param.dart b/lib/tron/src/models/contract/smart_contract/smart_contract_abi_entry_param.dart index a8e7ee57..412592b8 100644 --- a/lib/tron/src/models/contract/smart_contract/smart_contract_abi_entry_param.dart +++ b/lib/tron/src/models/contract/smart_contract/smart_contract_abi_entry_param.dart @@ -1,5 +1,6 @@ import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; class SmartContractBABIEntryParam extends TronProtocolBufferImpl { /// Create a new [SmartContractBABIEntryParam] instance with specified parameters. @@ -8,7 +9,10 @@ class SmartContractBABIEntryParam extends TronProtocolBufferImpl { /// Create a new [SmartContractBABIEntryParam] instance by parsing a JSON map. factory SmartContractBABIEntryParam.fromJson(Map json) { return SmartContractBABIEntryParam( - type: json["type"], name: json["name"], indexed: json["indexed"]); + type: OnChainUtils.parseString(value: json["type"], name: "type"), + name: OnChainUtils.parseString(value: json["name"], name: "name"), + indexed: + OnChainUtils.parseBoolean(value: json["indexed"], name: "indexed")); } factory SmartContractBABIEntryParam.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); @@ -25,7 +29,11 @@ class SmartContractBABIEntryParam extends TronProtocolBufferImpl { List get fieldIds => [1, 2, 3]; @override - List get values => [indexed, name, type]; + List get values => [ + indexed == false ? null : indexed, + (name?.isEmpty ?? true) ? null : name, + type + ]; /// Convert the [SmartContractBABIEntryParam] object to a JSON representation. @override diff --git a/lib/tron/src/models/contract/smart_contract/trigger_smart_contract.dart b/lib/tron/src/models/contract/smart_contract/trigger_smart_contract.dart index ce899f07..09a918fc 100644 --- a/lib/tron/src/models/contract/smart_contract/trigger_smart_contract.dart +++ b/lib/tron/src/models/contract/smart_contract/trigger_smart_contract.dart @@ -2,17 +2,23 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; class TriggerSmartContract extends TronBaseContract { /// Create a new [TriggerSmartContract] instance by parsing a JSON map. factory TriggerSmartContract.fromJson(Map json) { return TriggerSmartContract( - ownerAddress: TronAddress(json["owner_address"]), - contractAddress: TronAddress(json["contract_address"]), - data: BytesUtils.tryFromHexString(json["data"]), - callTokenValue: BigintUtils.tryParse(json["call_token_value"]), - callValue: BigintUtils.tryParse(json["call_value"]), - tokenId: BigintUtils.tryParse(json["token_id"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + contractAddress: OnChainUtils.parseTronAddress( + value: json["contract_address"], name: "contract_address"), + data: OnChainUtils.parseHex(value: json["data"], name: "data"), + callTokenValue: OnChainUtils.parseBigInt( + value: json["call_token_value"], name: "call_token_value"), + callValue: OnChainUtils.parseBigInt( + value: json["call_value"], name: "call_value"), + tokenId: + OnChainUtils.parseBigInt(value: json["token_id"], name: "token_id"), ); } @@ -37,6 +43,7 @@ class TriggerSmartContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Contract address @@ -67,7 +74,7 @@ class TriggerSmartContract extends TronBaseContract { return { "owner_address": ownerAddress.toString(), "contract_address": contractAddress.toString(), - "data": BytesUtils.tryToHexString(data!), + "data": BytesUtils.tryToHexString(data), "call_value": callValue?.toString(), "call_token_value": callTokenValue?.toString(), "token_id": tokenId?.toString() @@ -83,4 +90,7 @@ class TriggerSmartContract extends TronBaseContract { @override TransactionContractType get contractType => TransactionContractType.triggerSmartContract; + + @override + BigInt get trxAmount => callValue ?? BigInt.zero; } diff --git a/lib/tron/src/models/contract/smart_contract/update_energy_limit_contract.dart b/lib/tron/src/models/contract/smart_contract/update_energy_limit_contract.dart index cf72dee0..5f5e7a53 100644 --- a/lib/tron/src/models/contract/smart_contract/update_energy_limit_contract.dart +++ b/lib/tron/src/models/contract/smart_contract/update_energy_limit_contract.dart @@ -1,16 +1,19 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Update the origin_energy_limit parameter of a smart contract class UpdateEnergyLimitContract extends TronBaseContract { /// Create a new [UpdateEnergyLimitContract] instance by parsing a JSON map. factory UpdateEnergyLimitContract.fromJson(Map json) { return UpdateEnergyLimitContract( - ownerAddress: TronAddress(json["owner_address"]), - contractAddress: TronAddress(json["contract_address"]), - originEnergyLimit: BigintUtils.tryParse(json["origin_energy_limit"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + contractAddress: OnChainUtils.parseTronAddress( + value: json["contract_address"], name: "contract_address"), + originEnergyLimit: OnChainUtils.parseBigInt( + value: json["origin_energy_limit"], name: "origin_energy_limit"), ); } @@ -29,6 +32,7 @@ class UpdateEnergyLimitContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Contract address diff --git a/lib/tron/src/models/contract/smart_contract/update_setting_contract.dart b/lib/tron/src/models/contract/smart_contract/update_setting_contract.dart index 540715f9..f7076570 100644 --- a/lib/tron/src/models/contract/smart_contract/update_setting_contract.dart +++ b/lib/tron/src/models/contract/smart_contract/update_setting_contract.dart @@ -1,17 +1,20 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; /// Update the consume_user_resource_percent parameter of a smart contract class UpdateSettingContract extends TronBaseContract { /// Create a new [UpdateSettingContract] instance by parsing a JSON map. factory UpdateSettingContract.fromJson(Map json) { return UpdateSettingContract( - ownerAddress: TronAddress(json["owner_address"]), - contractAddress: TronAddress(json["contract_address"]), - consumeUserResourcePercent: - BigintUtils.tryParse(json["consume_user_resource_percent"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + contractAddress: OnChainUtils.parseTronAddress( + value: json["contract_address"], name: "contract_address"), + consumeUserResourcePercent: OnChainUtils.parseBigInt( + value: json["consume_user_resource_percent"], + name: "consume_user_resource_percent"), ); } @@ -29,6 +32,7 @@ class UpdateSettingContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Contract address diff --git a/lib/tron/src/models/contract/storage_contract/update_brokerage_contract.dart b/lib/tron/src/models/contract/storage_contract/update_brokerage_contract.dart index 28372d04..049be209 100644 --- a/lib/tron/src/models/contract/storage_contract/update_brokerage_contract.dart +++ b/lib/tron/src/models/contract/storage_contract/update_brokerage_contract.dart @@ -1,7 +1,7 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class UpdateBrokerageContract extends TronBaseContract { /// Create a new [UpdateBrokerageContract] instance with specified parameters. @@ -10,8 +10,10 @@ class UpdateBrokerageContract extends TronBaseContract { /// Create a new [UpdateBrokerageContract] instance by parsing a JSON map. factory UpdateBrokerageContract.fromJson(Map json) { return UpdateBrokerageContract( - ownerAddress: TronAddress(json["owner_address"]), - brokerage: IntUtils.tryParse(json["brokerage"]), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + brokerage: + OnChainUtils.parseInt(value: json["brokerage"], name: "brokerage"), ); } factory UpdateBrokerageContract.deserialize(List bytes) { @@ -22,6 +24,7 @@ class UpdateBrokerageContract extends TronBaseContract { } /// Account address + @override final TronAddress ownerAddress; /// Dividend ratio, from 0 to 100, 1 represents 1% diff --git a/lib/tron/src/models/contract/transaction/any.dart b/lib/tron/src/models/contract/transaction/any.dart index c8935436..3210a943 100644 --- a/lib/tron/src/models/contract/transaction/any.dart +++ b/lib/tron/src/models/contract/transaction/any.dart @@ -1,5 +1,5 @@ -import 'package:blockchain_utils/blockchain_utils.dart'; -import 'package:on_chain/tron/src/models/contract/account/accout.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; +import 'package:on_chain/tron/src/models/contract/account/account.dart'; import 'package:on_chain/tron/src/models/contract/assets_issue_contract/asset.dart'; import 'package:on_chain/tron/src/models/contract/balance/balance.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; @@ -13,15 +13,20 @@ import 'package:on_chain/tron/src/models/contract/storage_contract/update_broker import 'package:on_chain/tron/src/models/contract/vote/vote.dart'; import 'package:on_chain/tron/src/models/contract/witness/witness.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class Any extends TronProtocolBufferImpl { /// Create a new [Any] instance with specified parameters. Any({required this.typeUrl, required this.value}); + factory Any.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); final String typeUrl = decode.getField(1); - final contractType = TransactionContractType.findByName( - typeUrl.split("type.googleapis.com/protocol.").last); + final parts = typeUrl.split("type.googleapis.com/protocol."); + if (parts.length != 2) { + throw const TronPluginException("Invalid contract typeUrl."); + } + final contractType = TransactionContractType.findByName(parts.last); final List contractBytes = decode.getField(2); TronBaseContract contract; switch (contractType) { @@ -143,7 +148,7 @@ class Any extends TronProtocolBufferImpl { contract = WitnessCreateContract.deserialize(contractBytes); break; default: - throw MessageException("Unsupported contract", + throw TronPluginException("Unsupported contract", details: {"contract": contractType.name}); } return Any(typeUrl: typeUrl, value: contract); @@ -151,10 +156,15 @@ class Any extends TronProtocolBufferImpl { /// Create a new [Any] instance by parsing a JSON map. factory Any.fromJson(Map json) { - final String typeUrl = json["type_url"]; - final contractType = TransactionContractType.findByName( - typeUrl.split("type.googleapis.com/protocol.").last); - final Map contractDetails = json["value"]; + final String typeUrl = + OnChainUtils.parseString(value: json["type_url"], name: "type_url"); + final parts = typeUrl.split("type.googleapis.com/protocol."); + if (parts.length != 2) { + throw const TronPluginException("Invalid contract typeUrl"); + } + final contractType = TransactionContractType.findByName(parts.last); + final Map contractDetails = OnChainUtils.parseMap( + value: json["value"], name: "value", throwOnNull: true)!; TronBaseContract contract; switch (contractType) { case TransactionContractType.transferContract: @@ -275,7 +285,7 @@ class Any extends TronProtocolBufferImpl { contract = WitnessCreateContract.fromJson(contractDetails); break; default: - throw MessageException("Unsupported contract", + throw TronPluginException("Unsupported contract", details: {"contract": contractType.name}); } return Any(typeUrl: typeUrl, value: contract); diff --git a/lib/tron/src/models/contract/transaction/transaction.dart b/lib/tron/src/models/contract/transaction/transaction.dart index 59f2742b..2d34c401 100644 --- a/lib/tron/src/models/contract/transaction/transaction.dart +++ b/lib/tron/src/models/contract/transaction/transaction.dart @@ -7,9 +7,10 @@ class Transaction extends TronProtocolBufferImpl { /// Create a new [Transaction] instance by parsing a JSON map. factory Transaction.fromJson(Map json) { final rawData = TransactionRaw.fromJson(json['raw_data']); - final signature = (json['signature'] as List) - .map((s) => BytesUtils.fromHexString(s)) - .toList(); + final signature = (json['signature'] as List?) + ?.map((s) => BytesUtils.fromHexString(s)) + .toList() ?? + []; return Transaction(rawData: rawData, signature: signature); } @@ -24,7 +25,7 @@ class Transaction extends TronProtocolBufferImpl { final decode = TronProtocolBufferImpl.decode(bytes); return Transaction( rawData: TransactionRaw.deserialize(decode.getField(1)), - signature: decode.getField(2)); + signature: decode.getField>?>(2) ?? const []); } /// The raw data of the transaction. @@ -46,7 +47,7 @@ class Transaction extends TronProtocolBufferImpl { Map toJson() { return { "raw_data": rawData.toJson(), - "signature": signature.map((s) => BytesUtils.toHexString(s)).toList(), + "signature": signature.map((s) => BytesUtils.toHexString(s)).toList() }; } diff --git a/lib/tron/src/models/contract/transaction/transaction_contract.dart b/lib/tron/src/models/contract/transaction/transaction_contract.dart index 2d7e5488..3d5e5706 100644 --- a/lib/tron/src/models/contract/transaction/transaction_contract.dart +++ b/lib/tron/src/models/contract/transaction/transaction_contract.dart @@ -3,20 +3,27 @@ import 'package:on_chain/tron/src/models/contract/transaction/any.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class TransactionContract extends TronProtocolBufferImpl { /// Create a new [TransactionContract] instance by parsing a JSON map. factory TransactionContract.fromJson(Map json) { - final type = TransactionContractType.findByName(json["type"]); - final any = Any.fromJson(json["parameter"]); - final int? permissionId = - IntUtils.tryParse(json["permission_id"] ?? json["Permission_id"]); + final type = TransactionContractType.findByName( + OnChainUtils.parseString(value: json["type"], name: "type")); + final any = Any.fromJson(OnChainUtils.parseMap( + value: json["parameter"], name: "parameter", throwOnNull: true)!); + final int? permissionId = OnChainUtils.parseInt( + value: json["permission_id"] ?? json["Permission_id"], + name: "permission_id"); + return TransactionContract( type: type, parameter: any, permissionId: permissionId, - provider: StringUtils.tryEncode(json["provider"]), - contractName: StringUtils.tryEncode(json["contract_name"]), + provider: + OnChainUtils.parseBytes(value: json["provider"], name: "provider"), + contractName: OnChainUtils.parseBytes( + value: json["contract_name"], name: "contract_name"), ); } diff --git a/lib/tron/src/models/contract/transaction/transaction_raw.dart b/lib/tron/src/models/contract/transaction/transaction_raw.dart index d77f441a..10f2e5e8 100644 --- a/lib/tron/src/models/contract/transaction/transaction_raw.dart +++ b/lib/tron/src/models/contract/transaction/transaction_raw.dart @@ -1,32 +1,57 @@ +import 'package:on_chain/tron/src/address/tron_address.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/account/authority.dart'; import 'package:on_chain/tron/src/models/contract/transaction/transaction_contract.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class TransactionRaw extends TronProtocolBufferImpl { /// Create a new [TransactionRaw] instance by parsing a JSON map. factory TransactionRaw.fromJson(Map json) { - final contractList = (json['contract'] as List) - .map((contract) => TransactionContract.fromJson(contract)) + final contractList = OnChainUtils.parseList( + value: json["contract"], name: "contract", throwOnNull: true)! + .map((e) => TransactionContract.fromJson(OnChainUtils.parseMap( + value: e, name: "contract", throwOnNull: true)!)) .toList(); + if (contractList.length != 1) { + throw const TronPluginException( + "Transaction must contain exactly one contract."); + } return TransactionRaw( contract: contractList, - refBlockBytes: BytesUtils.fromHexString(json['ref_block_bytes']), - refBlockHash: BytesUtils.fromHexString(json['ref_block_hash']), - expiration: BigintUtils.parse(json['expiration']), - timestamp: BigintUtils.parse(json['timestamp']), - data: StringUtils.tryEncode(json["data"]), - feeLimit: BigintUtils.tryParse(json["fee_limit"]), - refBlockNum: BigintUtils.tryParse(json["ref_block_num"]), - scripts: BytesUtils.tryFromHexString(json['scripts']), - auths: - (json["auths"] as List?)?.map((e) => Authority.fromJson(e)).toList(), + refBlockBytes: OnChainUtils.parseHex( + value: json['ref_block_bytes'], name: "ref_block_bytes"), + refBlockHash: OnChainUtils.parseHex( + value: json['ref_block_hash'], name: "ref_block_hash"), + expiration: OnChainUtils.parseBigInt( + value: json['expiration'], name: "expiration"), + timestamp: + OnChainUtils.parseBigInt(value: json['timestamp'], name: "timestamp"), + data: OnChainUtils.parseBytes(value: json["data"], name: "data"), + feeLimit: + OnChainUtils.parseBigInt(value: json["fee_limit"], name: "fee_limit"), + refBlockNum: OnChainUtils.parseBigInt( + value: json["ref_block_num"], name: "ref_block_num"), + scripts: OnChainUtils.parseHex(value: json["scripts"], name: "scripts"), + auths: OnChainUtils.parseList(value: json["auths"], name: "auths") + ?.map((e) => Authority.fromJson(OnChainUtils.parseMap( + value: e, name: "auths", throwOnNull: true)!)) + .toList(), ); } factory TransactionRaw.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); + final contracts = decode + .getFields>(11) + .map((e) => TransactionContract.deserialize(e)) + .toList(); + if (contracts.length != 1) { + throw const TronPluginException( + "Transaction must contain exactly one contract."); + } return TransactionRaw( refBlockBytes: decode.getField(1), refBlockNum: decode.getField(3), @@ -37,10 +62,7 @@ class TransactionRaw extends TronProtocolBufferImpl { .map((e) => Authority.deserialize(e)) .toList(), data: decode.getField(10), - contract: decode - .getFields>(11) - .map((e) => TransactionContract.deserialize(e)) - .toList(), + contract: contracts, scripts: decode.getField(12), timestamp: decode.getField(14), feeLimit: decode.getField(18)); @@ -62,7 +84,7 @@ class TransactionRaw extends TronProtocolBufferImpl { refBlockHash = BytesUtils.toBytes(refBlockHash, unmodifiable: true), data = BytesUtils.tryToBytes(data, unmodifiable: true), scripts = BytesUtils.tryToBytes(scripts, unmodifiable: true), - auths = auths == null ? null : List.unmodifiable(auths), + auths = auths == null ? null : List.unmodifiable(auths), contract = List.unmodifiable(contract); /// The reference block bytes of the transaction. @@ -99,9 +121,9 @@ class TransactionRaw extends TronProtocolBufferImpl { @override Map toJson() { return { - "ref_block_bytes": BytesUtils.tryToHexString(refBlockBytes), + "ref_block_bytes": BytesUtils.toHexString(refBlockBytes), "ref_block_num": refBlockNum?.toString(), - "ref_block_hash": BytesUtils.tryToHexString(refBlockHash), + "ref_block_hash": BytesUtils.toHexString(refBlockHash), "expiration": expiration.toString(), "auths": auths?.map((auth) => auth.toJson()).toList(), "data": StringUtils.tryDecode(data), @@ -162,6 +184,34 @@ class TransactionRaw extends TronProtocolBufferImpl { /// bytes length of encoded transaction late final int length = toBuffer().length; + TronAddress get ownerAddress { + if (contract.isEmpty) { + throw const TronPluginException("Transaction contains no contract."); + } + return contract[0].parameter.value.ownerAddress; + } + + T getContract() { + if (contract.isEmpty) { + throw const TronPluginException("Transaction contains no contract."); + } + return contract[0].parameter.value.cast(); + } + + int? permissionId() { + if (contract.isEmpty) { + throw const TronPluginException("Transaction contains no contract."); + } + return contract[0].permissionId; + } + + TransactionContractType get type { + if (contract.isEmpty) { + throw const TronPluginException("Transaction contains no contract."); + } + return contract[0].type; + } + /// Convert the [TransactionRaw] object to its string representation. @override String toString() { diff --git a/lib/tron/src/models/contract/vote/vote_asset_contract.dart b/lib/tron/src/models/contract/vote/vote_asset_contract.dart index 0c269548..9584ee46 100644 --- a/lib/tron/src/models/contract/vote/vote_asset_contract.dart +++ b/lib/tron/src/models/contract/vote/vote_asset_contract.dart @@ -1,21 +1,23 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class VoteAssetContract extends TronBaseContract { /// Create a new [VoteAssetContract] instance by parsing a JSON map. factory VoteAssetContract.fromJson(Map json) { - final ownerAddress = TronAddress(json['owner_address']); - final voteAddress = (json['vote_address'] as List) - .map((address) => TronAddress(address)) - .toList(); - return VoteAssetContract( - ownerAddress: ownerAddress, - voteAddress: voteAddress, - support: json['support'], - count: IntUtils.tryParse(json['count']), + ownerAddress: OnChainUtils.parseTronAddress( + value: json["owner_address"], name: "owner_address"), + voteAddress: OnChainUtils.parseList( + value: json["vote_address"], + name: "vote_address", + throwOnNull: true)! + .map((address) => TronAddress(address)) + .toList(), + support: + OnChainUtils.parseBoolean(value: json['support'], name: "support"), + count: OnChainUtils.parseInt(value: json['count'], name: "count"), ); } @@ -37,6 +39,7 @@ class VoteAssetContract extends TronBaseContract { count: decode.getField(5)); } + @override final TronAddress ownerAddress; final List voteAddress; final bool? support; diff --git a/lib/tron/src/models/contract/vote/vote_witness_contract.dart b/lib/tron/src/models/contract/vote/vote_witness_contract.dart index 48e71202..3524ff5e 100644 --- a/lib/tron/src/models/contract/vote/vote_witness_contract.dart +++ b/lib/tron/src/models/contract/vote/vote_witness_contract.dart @@ -3,20 +3,22 @@ import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:on_chain/tron/src/models/contract/vote/vote_witness_contract_vote.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class VoteWitnessContract extends TronBaseContract { /// Create a new [VoteWitnessContract] instance by parsing a JSON map. factory VoteWitnessContract.fromJson(Map json) { - final ownerAddress = TronAddress(json['owner_address']); - final votes = (json['votes'] as List?) - ?.map((vote) => VoteWitnessContractVote.fromJson(vote)) - .toList(); - final support = json['support']; - return VoteWitnessContract( - ownerAddress: ownerAddress, - votes: votes, - support: support, + ownerAddress: OnChainUtils.parseTronAddress( + value: json['owner_address'], name: "owner_address"), + votes: + OnChainUtils.parseList(value: json["votes"], name: "votes") + ?.map((vote) => VoteWitnessContractVote.fromJson( + OnChainUtils.parseMap( + value: vote, name: "vote", throwOnNull: true)!)) + .toList(), + support: + OnChainUtils.parseBoolean(value: json["support"], name: "support"), ); } @@ -38,6 +40,7 @@ class VoteWitnessContract extends TronBaseContract { .toList(), support: decode.getField(3)); } + @override final TronAddress ownerAddress; final List? votes; final bool? support; @@ -55,7 +58,7 @@ class VoteWitnessContract extends TronBaseContract { "owner_address": ownerAddress.toString(), "votes": votes?.map((vote) => vote.toJson()).toList(), "support": support, - }; + }..removeWhere((key, value) => value == null); } /// Convert the [VoteWitnessContract] object to its string representation. diff --git a/lib/tron/src/models/contract/vote/vote_witness_contract_vote.dart b/lib/tron/src/models/contract/vote/vote_witness_contract_vote.dart index 7e9c431f..04556b2d 100644 --- a/lib/tron/src/models/contract/vote/vote_witness_contract_vote.dart +++ b/lib/tron/src/models/contract/vote/vote_witness_contract_vote.dart @@ -1,17 +1,16 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class VoteWitnessContractVote extends TronProtocolBufferImpl { /// Create a new [VoteWitnessContractVote] instance by parsing a JSON map. factory VoteWitnessContractVote.fromJson(Map json) { - final voteAddress = TronAddress(json['vote_address']); - final voteCount = BigintUtils.parse(json['vote_count']); - return VoteWitnessContractVote( - voteAddress: voteAddress, - voteCount: voteCount, + voteAddress: OnChainUtils.parseTronAddress( + value: json["vote_address"], name: "vote_address"), + voteCount: OnChainUtils.parseBigInt( + value: json["vote_count"], name: "vote_count"), ); } factory VoteWitnessContractVote.deserialize(List bytes) { diff --git a/lib/tron/src/models/contract/witness/update_witness_contract.dart b/lib/tron/src/models/contract/witness/update_witness_contract.dart index 7c0c9505..5c6dd997 100644 --- a/lib/tron/src/models/contract/witness/update_witness_contract.dart +++ b/lib/tron/src/models/contract/witness/update_witness_contract.dart @@ -2,16 +2,16 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils.dart'; class WitnessUpdateContract extends TronBaseContract { /// Create a new [WitnessUpdateContract] instance by parsing a JSON map. factory WitnessUpdateContract.fromJson(Map json) { - final ownerAddress = TronAddress(json['owner_address']); - final updateUrl = StringUtils.tryEncode(json['update_url']); - return WitnessUpdateContract( - ownerAddress: ownerAddress, - updateUrl: updateUrl, + ownerAddress: OnChainUtils.parseTronAddress( + value: json['owner_address'], name: "owner_address"), + updateUrl: OnChainUtils.parseBytes( + value: json['update_url'], name: "update_url"), ); } factory WitnessUpdateContract.deserialize(List bytes) { @@ -24,6 +24,7 @@ class WitnessUpdateContract extends TronBaseContract { /// Create a new [WitnessUpdateContract] instance with specified parameters. WitnessUpdateContract({required this.ownerAddress, List? updateUrl}) : updateUrl = BytesUtils.tryToBytes(updateUrl, unmodifiable: true); + @override final TronAddress ownerAddress; final List? updateUrl; @@ -39,7 +40,7 @@ class WitnessUpdateContract extends TronBaseContract { return { "owner_address": ownerAddress.toString(), "update_url": StringUtils.tryDecode(updateUrl), - }; + }..removeWhere((k, v) => v == null); } /// Convert the [WitnessUpdateContract] object to its string representation. diff --git a/lib/tron/src/models/contract/witness/wintess_create_contract.dart b/lib/tron/src/models/contract/witness/wintess_create_contract.dart index 7e773fa0..21c04045 100644 --- a/lib/tron/src/models/contract/witness/wintess_create_contract.dart +++ b/lib/tron/src/models/contract/witness/wintess_create_contract.dart @@ -2,14 +2,16 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/protbuf/decoder.dart'; +import 'package:on_chain/utils/utils/utils.dart'; class WitnessCreateContract extends TronBaseContract { /// Create a new [WitnessCreateContract] instance by parsing a JSON map. factory WitnessCreateContract.fromJson(Map json) { - final ownerAddress = TronAddress(json['owner_address']); - final url = StringUtils.tryEncode(json['url']); - - return WitnessCreateContract(ownerAddress: ownerAddress, url: url); + return WitnessCreateContract( + ownerAddress: OnChainUtils.parseTronAddress( + value: json['owner_address'], name: "owner_address"), + url: OnChainUtils.parseBytes(value: json['url'], name: "url"), + ); } factory WitnessCreateContract.deserialize(List bytes) { final decode = TronProtocolBufferImpl.decode(bytes); @@ -21,6 +23,7 @@ class WitnessCreateContract extends TronBaseContract { /// Create a new [WitnessCreateContract] instance with specified parameters. WitnessCreateContract({required this.ownerAddress, List? url}) : url = BytesUtils.tryToBytes(url, unmodifiable: true); + @override final TronAddress ownerAddress; final List? url; @@ -36,7 +39,7 @@ class WitnessCreateContract extends TronBaseContract { return { "owner_address": ownerAddress.toString(), "url": StringUtils.tryDecode(url), - }; + }..removeWhere((k, v) => v == null); } /// Convert the [WitnessCreateContract] object to its string representation. diff --git a/lib/tron/src/models/parsed_request/parsed_contract_request.dart b/lib/tron/src/models/parsed_request/parsed_contract_request.dart index 0fa86177..de84ba89 100644 --- a/lib/tron/src/models/parsed_request/parsed_contract_request.dart +++ b/lib/tron/src/models/parsed_request/parsed_contract_request.dart @@ -55,8 +55,12 @@ class ParsedSmartContractRequest { if (outputs.isEmpty) { decodeResult = []; } else { - decodeResult = - fragment.decodeOutput(BytesUtils.fromHexString(outputs.first)); + try { + decodeResult = + fragment.decodeOutput(BytesUtils.fromHexString(outputs.first)); + } catch (_) { + decodeResult = null; + } } } diff --git a/lib/tron/src/protbuf/decoder.dart b/lib/tron/src/protbuf/decoder.dart index aed0827f..0fdd7292 100644 --- a/lib/tron/src/protbuf/decoder.dart +++ b/lib/tron/src/protbuf/decoder.dart @@ -1,14 +1,16 @@ -import 'package:blockchain_utils/exception/exception.dart'; import 'package:blockchain_utils/utils/utils.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; class ProtocolBufferDecoder { static List decode(List bytes) { final List results = []; int index = 0; while (index < bytes.length) { - int tag = bytes[index++]; - int fieldId = tag >> 3; - int wireType = tag & 0x07; + final decodeTag = _decodeVarint(bytes.sublist(index)); + index += decodeTag.consumed; + final int tag = decodeTag.value; + final int fieldId = tag >> 3; + final int wireType = tag & 0x07; switch (wireType) { case 2: final decodeLength = _decodeVarint(bytes.sublist(index)); @@ -17,7 +19,7 @@ class ProtocolBufferDecoder { tagNumber: fieldId, value: bytes.sublist(index, index + decodeLength.value))); index += decodeLength.value; - continue; + break; case 0: final decodeInt = _decodeInt(bytes.sublist(index)); @@ -25,11 +27,13 @@ class ProtocolBufferDecoder { final result = ProtocolBufferDecoderResult( tagNumber: fieldId, value: decodeInt.value); results.add(result); - continue; + break; default: - throw UnimplementedError("protobuf wiretype not supported."); + throw TronPluginException( + "protobuf wiretype not supported. filedId :$fieldId $wireType $tag"); } } + return results; } @@ -109,7 +113,7 @@ extension QuickProtocolBufferResults on List { return result.get(); } on StateError { if (null is T) return null as T; - throw MessageException("field id does not exist.", + throw TronPluginException("field id does not exist.", details: {"fieldIds": map((e) => e.tagNumber).join(", "), "id": tag}); } } @@ -120,7 +124,7 @@ extension QuickProtocolBufferResults on List { return result as T; } on StateError { if (null is T) return null as T; - throw MessageException("field id does not exist.", + throw TronPluginException("field id does not exist.", details: {"fieldIds": map((e) => e.tagNumber).join(", "), "id": id}); } } @@ -128,7 +132,7 @@ extension QuickProtocolBufferResults on List { List getFields(int tag, {bool allowNull = true}) { final result = where((element) => element.tagNumber == tag); if (result.isEmpty && !allowNull) { - throw MessageException("field id does not exist.", + throw TronPluginException("field id does not exist.", details: {"fieldIds": map((e) => e.tagNumber).join(", "), "id": tag}); } return result.map((e) => e.get()).toList(); @@ -137,7 +141,7 @@ extension QuickProtocolBufferResults on List { Map getMap(int tagId, {bool allowNull = true}) { final result = where((element) => element.tagNumber == tagId); if (result.isEmpty && !allowNull) { - throw MessageException("field id does not exist.", details: { + throw TronPluginException("field id does not exist.", details: { "fieldIds": map((e) => e.tagNumber).join(", "), "id": tagId }); @@ -166,13 +170,13 @@ extension QuickProtocolBufferResult on ProtocolBufferDecoderResult { return BigInt.from(value) as T; } else if (false is T) { if (value != 0 && value != 1) { - throw MessageException("Invalid boolean value.", + throw TronPluginException("Invalid boolean value.", details: {"value": value}); } return (value == 1 ? true : false) as T; } } - throw MessageException("Invalid type.", + throw TronPluginException("Invalid type.", details: {"type": "$T", "Excepted": value.runtimeType.toString()}); } @@ -183,7 +187,7 @@ extension QuickProtocolBufferResult on ProtocolBufferDecoderResult { return BigInt.from(value) as T; } else if (T == bool) { if (value != 0 && value != 1) { - throw MessageException("Invalid boolean value.", + throw TronPluginException("Invalid boolean value.", details: {"value": value}); } return (value == 1 ? true : false) as T; @@ -196,7 +200,7 @@ extension QuickProtocolBufferResult on ProtocolBufferDecoderResult { if (value is List && T == String) { return StringUtils.decode(value) as T; } - throw MessageException("cannot cast value.", details: { + throw TronPluginException("cannot cast value.", details: { "Type": "$T", "Excepted": value.runtimeType.toString(), "value": value diff --git a/lib/tron/src/protbuf/encoder.dart b/lib/tron/src/protbuf/encoder.dart index a6b6bef3..7da3a296 100644 --- a/lib/tron/src/protbuf/encoder.dart +++ b/lib/tron/src/protbuf/encoder.dart @@ -1,5 +1,6 @@ import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/address/tron_address.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/base_contract.dart'; import 'package:on_chain/tron/src/models/contract/base_contract/common.dart'; @@ -16,7 +17,7 @@ class ProtocolBufferEncoder { if (value.bitLength <= _int64BitLength) { return; } - throw MessageException("Value overflows 64-bit signed integer range", + throw TronPluginException("Value overflows 64-bit signed integer range", details: {"input": value}); } @@ -25,7 +26,7 @@ class ProtocolBufferEncoder { if (value.bitLength <= int32BitLength) { return; } - throw MessageException("Value overflows 32-bit signed integer range", + throw TronPluginException("Value overflows 32-bit signed integer range", details: {"input": value}); } @@ -52,7 +53,7 @@ class ProtocolBufferEncoder { } else if (value is Map) { return _encodeMap(fieldNumber, value); } - throw MessageException("unsupported type", + throw TronPluginException("unsupported type", details: {"runtime": value.runtimeType, "value": value}); } diff --git a/lib/tron/src/provider/methods/create_account.dart b/lib/tron/src/provider/methods/create_account.dart index d933aa8d..9500f3a7 100644 --- a/lib/tron/src/provider/methods/create_account.dart +++ b/lib/tron/src/provider/methods/create_account.dart @@ -1,5 +1,5 @@ import 'package:on_chain/tron/src/address/tron_address.dart'; -import 'package:on_chain/tron/src/models/contract/account/accout.dart'; +import 'package:on_chain/tron/src/models/contract/account/account.dart'; import 'package:on_chain/tron/src/models/parsed_request/parsed_contract_request.dart'; import 'package:on_chain/tron/src/provider/core/request.dart'; import 'package:on_chain/tron/src/provider/methods/request_methods.dart'; diff --git a/lib/tron/src/provider/methods/update_account.dart b/lib/tron/src/provider/methods/update_account.dart index b5a8412e..459d95fd 100644 --- a/lib/tron/src/provider/methods/update_account.dart +++ b/lib/tron/src/provider/methods/update_account.dart @@ -1,6 +1,6 @@ import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:on_chain/tron/src/address/tron_address.dart'; -import 'package:on_chain/tron/src/models/contract/account/accout.dart'; +import 'package:on_chain/tron/src/models/contract/account/account.dart'; import 'package:on_chain/tron/src/models/parsed_request/parsed_contract_request.dart'; import 'package:on_chain/tron/src/provider/core/request.dart'; import 'package:on_chain/tron/src/provider/methods/request_methods.dart'; diff --git a/lib/tron/tron.dart b/lib/tron/tron.dart index 91526246..620cc675 100644 --- a/lib/tron/tron.dart +++ b/lib/tron/tron.dart @@ -4,3 +4,4 @@ export 'src/models/models.dart'; export 'src/protbuf/encoder.dart'; export 'src/provider/provider.dart'; export 'src/utils/tron_helper.dart'; +export 'src/exception/exception.dart'; diff --git a/lib/utils/safe_cast.dart b/lib/utils/safe_cast.dart deleted file mode 100644 index 09587071..00000000 --- a/lib/utils/safe_cast.dart +++ /dev/null @@ -1,9 +0,0 @@ -extension SafeCastExtension on Object { - // T safeCast() { - // if (this is T) { - // return this as T; - // } else { - // throw TypeError(); - // } - // } -} diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart new file mode 100644 index 00000000..1d1879e4 --- /dev/null +++ b/lib/utils/utils.dart @@ -0,0 +1,2 @@ +export 'utils/number_utils.dart'; +export 'utils/utils.dart'; diff --git a/lib/utils/number_utils.dart b/lib/utils/utils/number_utils.dart similarity index 100% rename from lib/utils/number_utils.dart rename to lib/utils/utils/number_utils.dart diff --git a/lib/utils/utils/utils.dart b/lib/utils/utils/utils.dart new file mode 100644 index 00000000..278db483 --- /dev/null +++ b/lib/utils/utils/utils.dart @@ -0,0 +1,147 @@ +import 'package:blockchain_utils/utils/binary/utils.dart'; +import 'package:blockchain_utils/utils/numbers/utils/bigint_utils.dart'; +import 'package:blockchain_utils/utils/numbers/utils/int_utils.dart'; +import 'package:blockchain_utils/utils/string/string.dart'; +import 'package:on_chain/tron/src/address/tron_address.dart'; +import 'package:on_chain/tron/src/exception/exception.dart'; + +class OnChainUtils { + static T parseInt({required Object? value, required String name}) { + if (0 is! T) { + throw const TronPluginException( + "Invalid type casting for numeric parser."); + } + if (value == null && null is T) return null as T; + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + + final parse = IntUtils.tryParse(value); + if (parse != null) { + return parse as T; + } + throw TronPluginException("Invalid numeric value for parameter: $name."); + } + + static T parseBigInt({required Object? value, required String name}) { + if (BigInt.one is! T) { + throw const TronPluginException( + "Invalid type casting for BigInt parser."); + } + if (value == null && null is T) return null as T; + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + + final parse = BigintUtils.tryParse(value); + if (parse != null) { + return parse as T; + } + throw TronPluginException("Invalid BigInt value for parameter: $name."); + } + + static T parseHex({required Object? value, required String name}) { + if ([] is! T) { + throw const TronPluginException( + "Invalid type casting for String parser."); + } + if (value == null && null is T) return null as T; + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + if (value is String) { + final parse = BytesUtils.tryFromHexString(value); + if (parse != null) { + return parse as T; + } + } + throw TronPluginException("Invalid Hex bytes value for parameter: $name."); + } + + static T parseString({required Object? value, required String name}) { + if ("" is! T) { + throw const TronPluginException( + "Invalid type casting for String parser."); + } + if (value == null && null is T) return null as T; + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + if (value is String) { + return value as T; + } + throw TronPluginException("Invalid String value for parameter: $name."); + } + + static T parseTronAddress({required Object? value, required String name}) { + if (value == null && null is T) return null as T; + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + final String result = parseString(value: value, name: name); + try { + return TronAddress(result) as T; + } catch (e) { + throw TronPluginException("Invalid String value for parameter: $name."); + } + } + + static T parseBytes({required Object? value, required String name}) { + if ([] is! T) { + throw const TronPluginException("Invalid type casting for bytes parser."); + } + if (value == null && null is T) return null as T; + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + if (value is String) { + return StringUtils.toBytes(value) as T; + } + throw TronPluginException("Invalid value for parameter: $name."); + } + + static Map? parseMap( + {required Object? value, required String name, throwOnNull = false}) { + try { + return Map.from(value as Map); + } catch (e) { + if (!throwOnNull) return null; + } + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + throw TronPluginException("Invalid value for parameter: $name."); + } + + static List? parseList( + {required Object? value, + required String name, + bool throwOnNull = false}) { + if (value == null && !throwOnNull) return null; + try { + return List.from(value as List); + } catch (e) { + if (!throwOnNull) return null; + } + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + throw TronPluginException("Invalid List value for parameter: $name."); + } + + static T parseBoolean({required Object? value, required String name}) { + if (true is! T) { + throw const TronPluginException( + "Invalid type casting for BigInt parser."); + } + if (value == null && null is T) return null as T; + if (value == null) { + throw TronPluginException("Missing parameter: $name."); + } + + if (value is bool) { + return value as T; + } + throw TronPluginException("Invalid boolean value for parameter: $name."); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 2b805d93..f0e27705 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: on_chain description: Streamline Ethereum, Tron, Solana and Cardano operations. Effortlessly create transactions, interact with smart contracts, sign, and send transactions. -version: 3.9.0 +version: 4.0.0 homepage: "https://github.com/mrtnetwork/on_chain" repository: "https://github.com/mrtnetwork/on_chain" Author: mrhaydari.t@gmail.com diff --git a/test/abi/encode_decode/contract_test.dart b/test/abi/encode_decode/contract_test.dart index 53e9e6e9..8074aee3 100644 --- a/test/abi/encode_decode/contract_test.dart +++ b/test/abi/encode_decode/contract_test.dart @@ -61,7 +61,7 @@ void main() { ], "stateMutability": "payable", "type": "function" - }, false); + }); final params = [ [ [ @@ -94,7 +94,7 @@ void main() { ], "stateMutability": "nonpayable", "type": "function" - }, false); + }); final params = []; final encodeHex = fragment.encodeHex(params); expect(encodeHex, encoded); @@ -163,7 +163,7 @@ void main() { ], "stateMutability": "payable", "type": "function" - }, false); + }); final params = [ [ ETHAddress("0x305AEdB55Cd62106e075f0fE6cbDF0DA52FeDbDB"), @@ -202,7 +202,7 @@ void main() { "payable": false, "stateMutability": "view", "type": "function" - }, false); + }); final params = [ "METNETWORKMETNETWORKMETNETWORKMETNETWORKMETNETWORKMETNETWORKMETNETWORKMETNETWORKMETNETWORKMETNETWORK" ]; @@ -275,7 +275,7 @@ void main() { ], "stateMutability": "payable", "type": "function" - }, true); + }); final params = [ [ TronAddress.fromEthAddress(BytesUtils.fromHexString( diff --git a/test/tron/json_buff_serialization_test.dart b/test/tron/json_buff_serialization_test.dart new file mode 100644 index 00000000..1e9732a7 --- /dev/null +++ b/test/tron/json_buff_serialization_test.dart @@ -0,0 +1,1072 @@ +import 'package:on_chain/tron/tron.dart'; +import 'package:test/test.dart'; + +void main() { + transfer(); + issueTrc10(); + contract(); + contarct2(); +} + +void transfer() { + test("Transafer", () { + const Map tx = { + "visible": false, + "txID": + "4569d0bc9c0d36785233de45808da24c326b92d22919cc7e81335b57778105f5", + "raw_data_hex": + "0a026df02208670960a4a79f751c4080c2f29098325a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541fad447e0017b3b7e707a95f8ce1d2119092ea73e1215418840e6c55b9ada326d211d818c34a994aeced808180170a0edee909832", + "raw_data": { + "contract": [ + { + "parameter": { + "value": { + "to_address": "418840e6c55b9ada326d211d818c34a994aeced808", + "owner_address": "41fad447e0017b3b7e707a95f8ce1d2119092ea73e", + "amount": 1 + }, + "type_url": "type.googleapis.com/protocol.TransferContract" + }, + "type": "TransferContract" + } + ], + "ref_block_bytes": "6df0", + "ref_block_hash": "670960a4a79f751c", + "expiration": 1724464800000, + "timestamp": 1724464740000 + } + }; + final transaction = Transaction.fromJson(tx); + expect(transaction.rawData.txID, tx["txID"]); + final deserialize = Transaction.deserialize(transaction.toBuffer()); + expect(deserialize.rawData.txID, transaction.rawData.txID); + }); +} + +void issueTrc10() { + test("issueTrc10", () { + const issueJson = { + "visible": false, + "txID": + "f8c7adadffe7b5baed4169287eaa9088739a66bec193855265e84d3f4ce29d4c", + "raw_data_hex": + "0a02f5b722086b94058b90a9d3894098958fc398325aab01080612a6010a2f747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e41737365744973737565436f6e747261637412730a1541084937b3f86ea7bbca86f2809809a65ed8a7ada9120a4d52544e4554574f524b1a034d525420e087b7a12530013806400148e0bc8bc3983250e0f4a4ec9832a2010e4d5254205445535420544f4b454eaa011d68747470733a2f2f6769746875622e636f6d2f6d72746e6574776f726b70b8c08bc39832", + "raw_data": { + "contract": [ + { + "parameter": { + "value": { + "owner_address": "41084937b3f86ea7bbca86f2809809a65ed8a7ada9", + "name": "4d52544e4554574f524b", + "abbr": "4d5254", + "description": "4d5254205445535420544f4b454e", + "url": + "68747470733a2f2f6769746875622e636f6d2f6d72746e6574776f726b", + "total_supply": 10002220000, + "trx_num": 1, + "num": 1, + "start_time": 1724570066528, + "end_time": 1724656466528, + "precision": 6 + }, + "type_url": "type.googleapis.com/protocol.AssetIssueContract" + }, + "type": "AssetIssueContract" + } + ], + "ref_block_bytes": "f5b7", + "ref_block_hash": "6b94058b90a9d389", + "expiration": 1724570127000, + "timestamp": 1724570067000 + } + }; + final transaction = Transaction.fromJson(issueJson); + expect(transaction.rawData.txID, + "f8c7adadffe7b5baed4169287eaa9088739a66bec193855265e84d3f4ce29d4c"); + final decBuffer = Transaction.deserialize(transaction.toBuffer()); + expect(transaction.rawData.txID, decBuffer.rawData.txID); + final decodeJson = Transaction.fromJson(decBuffer.toJson()); + expect(transaction.rawData.txID, decodeJson.rawData.txID); + }); +} + +void contract() { + const issueJson = { + "visible": false, + "txID": "6d3b55e3808e13dd1b28b96eabade1b414d6653c4a1882c035cef391b3349571", + "raw_data_hex": + "0a0212a7220863c3b048579e00b340b8c3e9cd98325abb03081e12b6030a30747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e437265617465536d617274436f6e74726163741281030a1541084937b3f86ea7bbca86f2809809a65ed8a7ada912e7020a1541084937b3f86ea7bbca86f2809809a65ed8a7ada91a1e0a04300140030a161a066d794e616d652a081a06737472696e673002400322a102608060405234801561000f575f80fd5b50d3801561001b575f80fd5b50d28015610027575f80fd5b5060ed806100345f395ff3fe6080604052348015600e575f80fd5b50d380156019575f80fd5b50d280156024575f80fd5b5060043610603c575f3560e01c8063fae2dd4b146040575b5f80fd5b60408051808201825260058152643530b330b960d91b6020820152905160659190606e565b60405180910390f35b5f6020808352835180828501525f5b81811015609757858101830151858201604001528201607d565b505f604082860101526040601f19601f830116850101925050509291505056fea26474726f6e582212203d6b35ebf51892fa65e848b06fc5d1ce070feefd31ea251c5e9c633d9b2ebb9a64736f6c634300081400333a054a414641524080ade20470d8eee5cd9832900180a8d6b907", + "raw_data": { + "contract": [ + { + "parameter": { + "value": { + "owner_address": "41084937b3f86ea7bbca86f2809809a65ed8a7ada9", + "new_contract": { + "abi": { + "entrys": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "myName", + "outputs": [ + {"internalType": "string", "name": "", "type": "string"} + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "consume_user_resource_percent": 0, + "origin_energy_limit": 10000000, + "origin_address": "41084937b3f86ea7bbca86f2809809a65ed8a7ada9", + "bytecode": + "608060405234801561000f575f80fd5b50d3801561001b575f80fd5b50d28015610027575f80fd5b5060ed806100345f395ff3fe6080604052348015600e575f80fd5b50d380156019575f80fd5b50d280156024575f80fd5b5060043610603c575f3560e01c8063fae2dd4b146040575b5f80fd5b60408051808201825260058152643530b330b960d91b6020820152905160659190606e565b60405180910390f35b5f6020808352835180828501525f5b81811015609757858101830151858201604001528201607d565b505f604082860101526040601f19601f830116850101925050509291505056fea26474726f6e582212203d6b35ebf51892fa65e848b06fc5d1ce070feefd31ea251c5e9c633d9b2ebb9a64736f6c63430008140033", + "name": "JAFAR" + } + }, + "type_url": "type.googleapis.com/protocol.CreateSmartContract" + }, + "type": "CreateSmartContract" + } + ], + "ref_block_bytes": "12a7", + "ref_block_hash": "63c3b048579e00b3", + "expiration": 1724592579000, + "timestamp": 1724592519000, + "fee_limit": 2000000000 + }, + "contract_address": "412a8b3ca0472e8a86610ceea810fb1cc31b69ee26" + }; + test("create smart contract", () { + final transaction = Transaction.fromJson(issueJson); + expect(transaction.rawData.txID, + "6d3b55e3808e13dd1b28b96eabade1b414d6653c4a1882c035cef391b3349571"); + final decBuffer = Transaction.deserialize(transaction.toBuffer()); + expect(transaction.rawData.txID, decBuffer.rawData.txID); + final decodeJson = Transaction.fromJson(decBuffer.toJson()); + expect(transaction.rawData.txID, decodeJson.rawData.txID); + }); +} + +void contarct2() { + const issueJson = { + "visible": false, + "txID": "03bf549df3dfceaf04716df728e77434c04046f4d7a564753d92ad160c8a8d93", + "raw_data_hex": + "0a021baf2208126503230ae79de240c8f294d198325ab574081e12b0740a30747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e437265617465536d617274436f6e747261637412fb730a1541084937b3f86ea7bbca86f2809809a65ed8a7ada912e1730a1541084937b3f86ea7bbca86f2809809a65ed8a7ada91aba150a04300140030a7c1a094f726465725061696422101205746f74616c1a0775696e743235362215080112086f726465725f69641a0775696e7432353622120801120562757965721a076164647265737322130801120673656c6c65721a0761646472657373221b1210636f6e74726163745f616464726573731a076164647265737330030a4b1a144f776e6572736869705472616e73666572726564221a0801120d70726576696f75734f776e65721a07616464726573732215080112086e65774f776e65721a076164647265737330030a311a0b546f6b656e55706461746522101205746f6b656e1a0761646472657373220e12066163746976651a04626f6f6c30030a711a0954726331305061696422101205746f74616c1a0775696e743235362215080112086f726465725f69641a0775696e7432353622120801120562757965721a076164647265737322130801120673656c6c65721a076164647265737322101205746f6b656e1a0775696e7432353630030a311a0b547263313055706461746522101205746f6b656e1a0775696e74323536220e12066163746976651a04626f6f6c30030a3a1a0d5573657252656769737472656422121208757365726e616d651a06737472696e6722130801120673656c6c65721a076164647265737330030a481a065742757965722215080112086f726465725f69641a0775696e7432353622120801120562757965721a07616464726573732211120673656c6c65721a076164647265737330030a491a075753656c6c65722215080112086f726465725f69641a0775696e7432353622130801120673656c6c65721a07616464726573732210120562757965721a076164647265737330030a211a12434f4e545241435450455243454e544147452a071a0575696e7438300240020a85011a0d50617957697468546f6b656e73221312086f726465725f69641a0775696e743235362216120b6f726465725f746f74616c1a0775696e74323536221a120f636f6e7472616374416464726573731a07616464726573732211120673656c6c65721a07616464726573732a091a0775696e743235362a091a0775696e74323536300240030a501a0c506179576974685472633130221312086f726465725f69641a0775696e743235362211120673656c6c65721a07616464726573732a091a0775696e743235362a091a0775696e74323536300240040a1f1a0f544f4b454e494e435245414d454e542a081a0675696e743136300240020a2b1a105f636f6e747261637442616c616e636522081a0675696e7431362a091a0775696e74323536300240020a311a155f636f6e7472616374547263313042616c616e636522091a0775696e743235362a091a0775696e74323536300240020a211a085f7369676e65727322091a07616464726573732a061a04626f6f6c300240020a391a075f746f6b656e7322091a07616464726573732a0e12066163746976651a04626f6f6c2a0f1205746f6b656e1a0675696e743136300240020a1f1a065f747263313022091a0775696e743235362a061a04626f6f6c300240020a271a065f757365727322091a07616464726573732a0e12066163746976651a04626f6f6c300240020a3f1a15636f6e7472616374547263313057697468647261772210120576616c75651a0775696e7432353622101205746f6b656e1a0775696e74323536300240030a451a10636f6e747261637457697468647261772210120576616c75651a0775696e74323536221b12105f636f6e7472616374416464726573731a0761646472657373300240030a161a056f776e65722a091a0761646472657373300240020a421a0d706179546f436f6e747261637422101205746f6b656e1a07616464726573732210120576616c75651a0775696e743235362a091a0775696e74323536300240040a2e1a127061795472633130546f436f6e74726163742a091a0775696e743235362a091a0775696e74323536300240040a561a12706179576974684e6174697665546f6b656e221312086f726465725f69641a0775696e743235362211120673656c6c65721a07616464726573732a091a0775696e743235362a091a0775696e74323536300240040a2e1a0c72656769737465725573657222121208757365726e616d651a06737472696e672a061a04626f6f6c300240030a171a1172656e6f756e63654f776e657273686970300240030a691a0b73656c6563744f72646572221312086f726465725f69641a0775696e743235362211120673656c6c65721a07616464726573732210120562757965721a07616464726573732a091a0775696e743235362a081a0675696e7431362a071a0575696e7438300240020a6a1a0b73656c6563745472633130221312086f726465725f69641a0775696e743235362211120673656c6c65721a07616464726573732210120562757965721a07616464726573732a091a0775696e743235362a091a0775696e743235362a071a0575696e7438300240020a381a0c746f67676c655369676e6572221112067369676e65721a07616464726573732a091a07616464726573732a061a04626f6f6c300240030a3d1a0b746f67676c65546f6b656e2217120c746f6b656e416464726573731a07616464726573732a091a07616464726573732a061a04626f6f6c300240030a361a0b746f67676c65547263313022101205746f6b656e1a0775696e743235362a091a0775696e743235362a061a04626f6f6c300240030a2c1a117472616e736665724f776e657273686970221312086e65774f776e65721a0761646472657373300240030a3f1a18757064617465436f6e747261637450657263656e746167652216120d6e657750657263656e746167651a0575696e74382a071a0575696e7438300240030a781a167665726966795061796d656e745369676e6174757265221312086f726465725f69641a0775696e74323536221112067369676e65721a07616464726573732213120872656365697665721a0761646472657373221212097369676e61747572651a0562797465732a091a0761646472657373300240020a80011a127769647468726177466f7253656c6c6572732212120562757965721a09616464726573735b5d221412097369676e61747572651a0762797465735b5d221512086f726465725f69641a0975696e743235365b5d221a120f636f6e7472616374416464726573731a07616464726573732a091a0775696e74323536300240030a7b1a1777696474687261775472633130466f7253656c6c6572732212120562757965721a09616464726573735b5d221412097369676e61747572651a0762797465735b5d221512086f726465725f69641a0975696e743235365b5d22101205746f6b656e1a0775696e743235362a091a0775696e74323536300240030a7a1a117769647468726f77466f724275796572732211120673656c6c65721a0761646472657373221212097369676e61747572651a056279746573221312086f726465725f69641a0775696e74323536221a120f636f6e7472616374416464726573731a07616464726573732a091a0775696e74323536300240030a751a167769647468726f775472633130466f724275796572732211120673656c6c65721a0761646472657373221212097369676e61747572651a056279746573221312086f726465725f69641a0775696e7432353622101205746f6b656e1a0775696e743235362a091a0775696e743235363002400322805e60806040526007805462ffff00191661010017905534801562000020575f80fd5b50d380156200002d575f80fd5b50d280156200003a575f80fd5b5062000046336200004c565b6200009b565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612e5780620000a95f395ff3fe6080604052600436106101c5575f3560e01c8063723e4c78116100f2578063b41529ce11610092578063ccbb605111610062578063ccbb6051146108bc578063d296ef9f14610902578063e8c8250a14610939578063f2fde38b14610941575f80fd5b8063b41529ce1461077d578063b7a608d814610819578063bab89e7b14610863578063c76ab5c8146108a9575f80fd5b80638da5cb5b116100cd5780638da5cb5b1461062c578063a7585bab14610660578063ad874cab14610697578063b2a51a5114610731575f80fd5b8063723e4c781461059357806377fc2856146105a65780638d7274aa146105dd575f80fd5b80632b4cd814116101685780636ceadadc116101385780636ceadadc146104da5780636d6ce44f146104ed578063704f1b9414610530578063715018a614610567575f80fd5b80632b4cd814146103c85780632e8609fc1461041457806331b7e10c1461044d5780633cacd7d614610484575f80fd5b80630c74e27e116101a35780630c74e27e146102c157806315c75f89146103045780632281eb691461035a578063283aa9c214610391575f80fd5b8063011b271b146101c957806306f41646146102135780630762c0851461027e575b5f80fd5b3480156101d4575f80fd5b50d380156101e0575f80fd5b50d280156101ec575f80fd5b506102006101fb3660046125de565b610978565b6040519081526020015b60405180910390f35b34801561021e575f80fd5b50d3801561022a575f80fd5b50d28015610236575f80fd5b50610264610245366004612642565b60026020525f908152604090205460ff811690610100900461ffff1682565b60408051921515835261ffff90911660208301520161020a565b348015610289575f80fd5b50d38015610295575f80fd5b50d280156102a1575f80fd5b506102006102b036600461265b565b60056020525f908152604090205481565b3480156102cc575f80fd5b50d380156102d8575f80fd5b50d280156102e4575f80fd5b506102006102f336600461267c565b60066020525f908152604090205481565b34801561030f575f80fd5b50d3801561031b575f80fd5b50d28015610327575f80fd5b5061033b610336366004612642565b610b27565b604080516001600160a01b03909316835290151560208301520161020a565b348015610365575f80fd5b50d38015610371575f80fd5b50d2801561037d575f80fd5b5061020061038c3660046127f9565b610c27565b34801561039c575f80fd5b50d380156103a8575f80fd5b50d280156103b4575f80fd5b506102006103c3366004612881565b610f6d565b3480156103d3575f80fd5b50d380156103df575f80fd5b50d280156103eb575f80fd5b506103ff6103fa36600461290b565b611278565b6040805192835260208301919091520161020a565b34801561041f575f80fd5b50d3801561042b575f80fd5b50d28015610437575f80fd5b5061044b610446366004612943565b61144d565b005b348015610458575f80fd5b50d38015610464575f80fd5b50d28015610470575f80fd5b5061044b61047f36600461296d565b611514565b34801561048f575f80fd5b50d3801561049b575f80fd5b50d280156104a7575f80fd5b506104ca6104b6366004612642565b60016020525f908152604090205460ff1681565b604051901515815260200161020a565b6103ff6104e8366004612943565b6115b4565b3480156104f8575f80fd5b50d38015610504575f80fd5b50d28015610510575f80fd5b5060075461051e9060ff1681565b60405160ff909116815260200161020a565b34801561053b575f80fd5b50d38015610547575f80fd5b50d28015610553575f80fd5b506104ca61056236600461298d565b61172a565b348015610572575f80fd5b50d3801561057e575f80fd5b50d2801561058a575f80fd5b5061044b6117dd565b6102006105a13660046129d2565b6117f0565b3480156105b1575f80fd5b50d380156105bd575f80fd5b50d280156105c9575f80fd5b5061033b6105d8366004612642565b6118d1565b3480156105e8575f80fd5b50d380156105f4575f80fd5b50d28015610600575f80fd5b5061061461060f3660046129fa565b611920565b6040516001600160a01b03909116815260200161020a565b348015610637575f80fd5b50d38015610643575f80fd5b50d2801561064f575f80fd5b505f546001600160a01b0316610614565b34801561066b575f80fd5b50d38015610677575f80fd5b50d28015610683575f80fd5b50610200610692366004612a5e565b611a45565b3480156106a2575f80fd5b50d380156106ae575f80fd5b50d280156106ba575f80fd5b506107136106c9366004612ab8565b6001600160a01b038083165f908152600160208181526040808420948616845260029485018252808420888552909152909120908101548154919092015460ff1693509350939050565b60408051938452602084019290925260ff169082015260600161020a565b34801561073c575f80fd5b50d38015610748575f80fd5b50d28015610754575f80fd5b5061076861076336600461267c565b611bd3565b6040805192835290151560208301520161020a565b348015610788575f80fd5b50d38015610794575f80fd5b50d280156107a0575f80fd5b506107f86107af366004612ab8565b6001600160a01b039182165f908152600160208181526040808420949095168352928101835283822094825293909152209081015490549091610100820461ffff169160ff1690565b6040805193845261ffff909216602084015260ff169082015260600161020a565b348015610824575f80fd5b50d38015610830575f80fd5b50d2801561083c575f80fd5b5060075461085090610100900461ffff1681565b60405161ffff909116815260200161020a565b34801561086e575f80fd5b50d3801561087a575f80fd5b50d28015610886575f80fd5b506104ca610895366004612642565b60046020525f908152604090205460ff1681565b6103ff6108b7366004612943565b611c56565b3480156108c7575f80fd5b50d380156108d3575f80fd5b50d280156108df575f80fd5b506104ca6108ee36600461267c565b60036020525f908152604090205460ff1681565b34801561090d575f80fd5b50d38015610919575f80fd5b50d28015610925575f80fd5b5061051e610934366004612af1565b611d81565b6103ff611db0565b34801561094c575f80fd5b50d38015610958575f80fd5b50d28015610964575f80fd5b5061044b610973366004612642565b611e03565b6001600160a01b0381165f90815260026020526040812054610100900461ffff168082036109a4575060015b6001600160a01b0386165f908152600160208181526040808420338552909201815281832087845290529020805461ffff8381166101009092041614610a055760405162461bcd60e51b81526004016109fc90612b11565b60405180910390fd5b805460ff16600203610a295760405162461bcd60e51b81526004016109fc90612b36565b805460ff16600303610a4d5760405162461bcd60e51b81526004016109fc90612b63565b610a5985883389611920565b50805460ff16600114610a7e5760405162461bcd60e51b81526004016109fc90612b8f565b805460ff19166003178155600161ffff83161115610aaa57610aa584338360010154611e7c565b610ad9565b6001810154604051339180156108fc02915f818181858888f19350505050158015610ad7573d5f803e3d5ffd5b505b6040516001600160a01b0388168152339086907f22c534eb26e5136ec7972747d88dc58ea5e5cb26dda483be89a3903ff4db56339060200160405180910390a3600101549695505050505050565b5f80610b31611faf565b823b610b3b575f80fd5b6001600160a01b0383165f9081526002602052604081208054909161010090910461ffff169003610bbf5760078054610100900461ffff16906001610b7f83612bc9565b825461010092830a61ffff818102199092169282160291909117909255600754845462ffffff1916908290049092160260ff191617600117825550610bd0565b805460ff19811660ff909116151781555b8054604080516001600160a01b038716815260ff909216151560208301527f1737c70f0c34bfb9be118ab02eff6bd1672fdf69eba5cb1dd13a46a30bfbc36f910160405180910390a15483925060ff169050915091565b5f80835111610c485760405162461bcd60e51b81526004016109fc90612b8f565b6001600160a01b0382165f90815260026020526040812054610100900461ffff16808203610c74575060015b5f5b85518160ff161015610eb557335f90815260016020819052604082208a5191019082908b9060ff8616908110610cae57610cae612be9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f888460ff1681518110610ceb57610ceb612be9565b602002602001015181526020019081526020015f2090508261ffff16815f0160019054906101000a900461ffff1661ffff1614610d3a5760405162461bcd60e51b81526004016109fc90612b11565b805460ff16600203610d5e5760405162461bcd60e51b81526004016109fc90612b36565b805460ff16600303610d825760405162461bcd60e51b81526004016109fc90612b63565b610de2878360ff1681518110610d9a57610d9a612be9565b60200260200101518a8460ff1681518110610db757610db7612be9565b6020026020010151338b8660ff1681518110610dd557610dd5612be9565b6020026020010151611920565b50805460ff16600114610e075760405162461bcd60e51b81526004016109fc90612b8f565b805460ff191660021781556001810154610e219085612bfd565b9350336001600160a01b0316878360ff1681518110610e4257610e42612be9565b60200260200101517f8b095c27ef5f0125ae7b1d417006b951316cf90f224a00c86e48004659f23b638b8560ff1681518110610e8057610e80612be9565b6020026020010151604051610ea491906001600160a01b0391909116815260200190565b60405180910390a350600101610c76565b5060075460ff1615610f1a576007545f90606490610ed69060ff1685612c10565b610ee09190612c3b565b9050610eec8184612c4e565b61ffff83165f90815260056020526040812080549295508392909190610f13908490612bfd565b9091555050505b60018161ffff161115610f3757610f32843384611e7c565b610f63565b604051339083156108fc029084905f818181858888f19350505050158015610f61573d5f803e3d5ffd5b505b5095945050505050565b5f80835111610f8e5760405162461bcd60e51b81526004016109fc90612b8f565b5f805b84518160ff1610156111bc57335f908152600160205260408120885160029091019082908a9060ff8616908110610fca57610fca612be9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f878460ff168151811061100757611007612be9565b602002602001015181526020019081526020015f20905084815f0154146110405760405162461bcd60e51b81526004016109fc90612b11565b60028082015460ff1690036110675760405162461bcd60e51b81526004016109fc90612b36565b600281015460ff1660030361108e5760405162461bcd60e51b81526004016109fc90612b63565b6110e1868360ff16815181106110a6576110a6612be9565b6020026020010151898460ff16815181106110c3576110c3612be9565b6020026020010151338a8660ff1681518110610dd557610dd5612be9565b50600281015460ff166001146111095760405162461bcd60e51b81526004016109fc90612b8f565b6002818101805460ff1916909117905560018101546111289084612bfd565b9250336001600160a01b0316868360ff168151811061114957611149612be9565b60200260200101517f8b095c27ef5f0125ae7b1d417006b951316cf90f224a00c86e48004659f23b638a8560ff168151811061118757611187612be9565b60200260200101516040516111ab91906001600160a01b0391909116815260200190565b60405180910390a350600101610f91565b5060075460ff161561121c576007545f906064906111dd9060ff1684612c10565b6111e79190612c3b565b90506111f38183612c4e565b91508060065f8681526020019081526020015f205f8282546112159190612bfd565b9091555050505b3381156108fc02828580158015611231575f80fd5b50806001603f1b11158015611244575f80fd5b5080620f424010158015611256575f80fd5b506040515f81818185878a8ad0945050505050158015610f63573d5f803e3d5ffd5b5f8033611283575f80fd5b5f85116112a25760405162461bcd60e51b81526004016109fc90612c61565b6001600160a01b0383165f9081526001602052604090205460ff166112d95760405162461bcd60e51b81526004016109fc90612c83565b6001600160a01b0384165f9081526002602052604090205460ff166113105760405162461bcd60e51b81526004016109fc90612b11565b6001600160a01b0383165f908152600160208181526040808420338552909201815281832089845290529020805460ff161561135e5760405162461bcd60e51b81526004016109fc90612cac565b6001600160a01b0385165f908152600260205260409020548154600183810189905560ff1961ffff61010094859004169093029290921662ffffff19909116171781556113ad85333089612008565b604080518781526001600160a01b03878116602083015286169133918a917fab3af43bba8f337a1a25176e89381aee76ab50668b2bda147da9371677e5ed6e910160405180910390a4604080518781526001600160a01b03878116602083015286169133918a917fab3af43bba8f337a1a25176e89381aee76ab50668b2bda147da9371677e5ed6e910160405180910390a4600101549596945050505050565b611455611faf565b6001600160a01b0381165f90815260026020526040812054610100900461ffff1690819003611482575060015b61ffff81165f908152600560205260409020548311156114a0575f80fd5b61ffff81165f90815260056020526040812080548592906114c2908490612c4e565b9091555050600161ffff821611156114e4576114df823385611e7c565b505050565b604051339084156108fc029085905f818181858888f1935050505015801561150e573d5f803e3d5ffd5b50505050565b61151c611faf565b5f81815260066020526040902054821115611535575f80fd5b5f8181526006602052604081208054849290611552908490612c4e565b9091555033905082156108fc0283838015801561156d575f80fd5b50806001603f1b11158015611580575f80fd5b5080620f424010158015611592575f80fd5b506040515f81818185878a8ad09450505050501580156114df573d5f803e3d5ffd5b5f80336115bf575f80fd5b6001600160a01b0383165f9081526001602052604090205460ff166115f65760405162461bcd60e51b81526004016109fc90612c83565bd35f9081526003602052604090205460ff166116245760405162461bcd60e51b81526004016109fc90612b11565b6001600160a01b0383165f90815260016020908152604080832033845260029081018352818420888552909252909120015460ff16156116765760405162461bcd60e51b81526004016109fc90612cac565b5fd2116116955760405162461bcd60e51b81526004016109fc90612c61565b6001600160a01b0383165f81815260016020818152604080842033808652600291820184528286208b8752845294829020d3808255d2828701819055928201805460ff19169096179095558251918252928101939093529093929188917f5e4e1d7e1a1b50d3acb16c2ee41c49f7d5b85f7b9283731fd00e4f016305894b91015b60405180910390a460010154939492505050565b5f33611734575f80fd5b335f9081526001602052604090205460ff16156117825760405162461bcd60e51b815260206004820152600c60248201526b1c9957dd5cd95c995e1a5cdd60a21b60448201526064016109fc565b335f81815260016020819052604091829020805460ff19169091179055517f4158c7d5f16e4b46a33f33fdc3f7bbe2253ea2fbba5dfffbe6a366b1d2cce09a906117cd908590612cf4565b60405180910390a2506001919050565b6117e5611faf565b6117ee5f612140565b565b6001600160a01b0382165f90815260026020526040812054610100900461ffff1680820361181c575060015b8061ffff16600114801561182f57505f34115b80611848575060018161ffff1611801561184857505f83115b611850575f80fd5b60018161ffff16111561189a5761186984333086612008565b61ffff81165f908152600560205260408120805485929061188b908490612bfd565b909155508392506118cb915050565b61ffff81165f90815260056020526040812080543492906118bc908490612bfd565b909155503492506118cb915050565b92915050565b5f806118db611faf565b6001600160a01b0383166118ed575f80fd5b50506001600160a01b0381165f908152600460205260409020805460ff8082161560ff1990921682179092559192911690565b5f80611936846001600160a01b0316601461218f565b61193f8761232c565b604051602001611950929190612d26565b60405160208183030381529060405290505f81805190602001206040516020016119a691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b6040516020818303038152906040528051906020012090505f6119c98286612431565b9050866001600160a01b0316816001600160a01b03161480611a0257506001600160a01b0381165f9081526004602052604090205460ff165b611a3a5760405162461bcd60e51b815260206004820152600960248201526872655f76657269667960b81b60448201526064016109fc565b979650505050505050565b6001600160a01b0384165f9081526001602090815260408083203384526002018252808320858452909152812080548314611a925760405162461bcd60e51b81526004016109fc90612b11565b60028082015460ff169003611ab95760405162461bcd60e51b81526004016109fc90612b36565b600281015460ff16600303611ae05760405162461bcd60e51b81526004016109fc90612b63565b611aec84873388611920565b50600281015460ff16600114611b145760405162461bcd60e51b81526004016109fc90612b8f565b60028101805460ff191660031790556001810154339080156108fc02908580158015611b3e575f80fd5b50806001603f1b11158015611b51575f80fd5b5080620f424010158015611b63575f80fd5b506040515f81818185878a8ad0945050505050158015611b85573d5f803e3d5ffd5b506040516001600160a01b0387168152339085907f22c534eb26e5136ec7972747d88dc58ea5e5cb26dda483be89a3903ff4db56339060200160405180910390a36001015495945050505050565b5f80611bdd611faf565b5f83815260036020908152604091829020805460ff8082161560ff199092168217909255835187815291161515918101919091527faf5cd8c9cd9b00ec027f4923710f6fd427975c48a24096a4cf83be7695ac991f910160405180910390a150505f81815260036020526040902054819060ff16915091565b5f8033611c61575f80fd5b6001600160a01b0383165f9081526001602052604090205460ff16611c985760405162461bcd60e51b81526004016109fc90612c83565b5f3411611cb75760405162461bcd60e51b81526004016109fc90612c61565b6001600160a01b0383165f9081526001602081815260408084203385529092018152818320878452905290205460ff1615611d045760405162461bcd60e51b81526004016109fc90612cac565b6001600160a01b0383165f8181526001602081815260408084203380865290840183528185208a8652835281852034948101859055805462ffffff19166101011781558251948552928401949094529093929188917fab3af43bba8f337a1a25176e89381aee76ab50668b2bda147da9371677e5ed6e9101611716565b5f611d8a611faf565b60038260ff1610611d99575f80fd5b506007805460ff191660ff92909216918217905590565b5f805fd211611dbd575f80fd5bd35f9081526003602052604090205460ff16611dd7575f80fd5bd35f9081526006602052604081208054d29290611df5908490612bfd565b90915550d393d29350915050565b611e0b611faf565b6001600160a01b038116611e705760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109fc565b611e7981612140565b50565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180516001600160e01b031663a9059cbb60e01b17905291515f928392871691611f079190612d69565b5f604051808303815f865af19150503d805f8114611f40576040519150601f19603f3d011682016040523d82523d5f602084013e611f45565b606091505b5091509150818015611f6f575080511580611f6f575080806020019051810190611f6f9190612d84565b611fa85760405162461bcd60e51b815260206004820152600a6024820152691c9957da185c9d995cdd60b21b60448201526064016109fc565b5050505050565b5f546001600160a01b031633146117ee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109fc565b5f80856001600160a01b0316604051806060016040528060258152602001612dfd6025913980516020909101206040516001600160a01b038089166024830152871660448201526064810186905260840160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516120979190612d69565b5f604051808303815f865af19150503d805f81146120d0576040519150601f19603f3d011682016040523d82523d5f602084013e6120d5565b606091505b50915091508180156120ff5750805115806120ff5750808060200190518101906120ff9190612d84565b6121385760405162461bcd60e51b815260206004820152600a6024820152691c9957da185c9d995cdd60b21b60448201526064016109fc565b505050505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60605f61219d836002612c10565b6121a8906002612bfd565b67ffffffffffffffff8111156121c0576121c0612526565b6040519080825280601f01601f1916602001820160405280156121ea576020820181803683370190505b509050600360fc1b815f8151811061220457612204612be9565b60200101906001600160f81b03191690815f1a905350600f60fb1b8160018151811061223257612232612be9565b60200101906001600160f81b03191690815f1a9053505f612254846002612c10565b61225f906001612bfd565b90505b60018111156122d6576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061229357612293612be9565b1a60f81b8282815181106122a9576122a9612be9565b60200101906001600160f81b03191690815f1a90535060049490941c936122cf81612da3565b9050612262565b5083156123255760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109fc565b9392505050565b6060815f036123525750506040805180820190915260018152600360fc1b602082015290565b815f5b811561237b578061236581612db8565b91506123749050600a83612c3b565b9150612355565b5f8167ffffffffffffffff81111561239557612395612526565b6040519080825280601f01601f1916602001820160405280156123bf576020820181803683370190505b5090505b8415612429576123d4600183612c4e565b91506123e1600a86612dd0565b6123ec906030612bfd565b60f81b81838151811061240157612401612be9565b60200101906001600160f81b03191690815f1a905350612422600a86612c3b565b94506123c3565b949350505050565b5f805f808451604114612449575f93505050506118cb565b5050506020820151604083015160608401515f1a601b81101561247457612471601b82612de3565b90505b8060ff16601b1415801561248c57508060ff16601c14155b1561249c575f93505050506118cb565b604080515f81526020810180835288905260ff831691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa1580156124ec573d5f803e3d5ffd5b5050506020604051035193505050506118cb565b5f81356001600160a81b0381168114612517575f80fd5b6001600160a01b031692915050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561256357612563612526565b604052919050565b5f67ffffffffffffffff83111561258457612584612526565b612597601f8401601f191660200161253a565b90508281528383830111156125aa575f80fd5b828260208301375f602084830101529392505050565b5f82601f8301126125cf575f80fd5b6123258383356020850161256b565b5f805f80608085870312156125f1575f80fd5b6125fa85612500565b9350602085013567ffffffffffffffff811115612615575f80fd5b612621878288016125c0565b9350506040850135915061263760608601612500565b905092959194509250565b5f60208284031215612652575f80fd5b61232582612500565b5f6020828403121561266b575f80fd5b813561ffff81168114612325575f80fd5b5f6020828403121561268c575f80fd5b5035919050565b5f67ffffffffffffffff8211156126ac576126ac612526565b5060051b60200190565b5f82601f8301126126c5575f80fd5b813560206126da6126d583612693565b61253a565b82815260059290921b840181019181810190868411156126f8575f80fd5b8286015b8481101561271a5761270d81612500565b83529183019183016126fc565b509695505050505050565b5f82601f830112612734575f80fd5b813560206127446126d583612693565b82815260059290921b84018101918181019086841115612762575f80fd5b8286015b8481101561271a57803567ffffffffffffffff811115612785575f8081fd5b6127938986838b01016125c0565b845250918301918301612766565b5f82601f8301126127b0575f80fd5b813560206127c06126d583612693565b82815260059290921b840181019181810190868411156127de575f80fd5b8286015b8481101561271a57803583529183019183016127e2565b5f805f806080858703121561280c575f80fd5b843567ffffffffffffffff80821115612823575f80fd5b61282f888389016126b6565b95506020870135915080821115612844575f80fd5b61285088838901612725565b94506040870135915080821115612865575f80fd5b50612872878288016127a1565b92505061263760608601612500565b5f805f8060808587031215612894575f80fd5b843567ffffffffffffffff808211156128ab575f80fd5b6128b7888389016126b6565b955060208701359150808211156128cc575f80fd5b6128d888838901612725565b945060408701359150808211156128ed575f80fd5b506128fa878288016127a1565b949793965093946060013593505050565b5f805f806080858703121561291e575f80fd5b843593506020850135925061293560408601612500565b915061263760608601612500565b5f8060408385031215612954575f80fd5b8235915061296460208401612500565b90509250929050565b5f806040838503121561297e575f80fd5b50508035926020909101359150565b5f6020828403121561299d575f80fd5b813567ffffffffffffffff8111156129b3575f80fd5b8201601f810184136129c3575f80fd5b6124298482356020840161256b565b5f80604083850312156129e3575f80fd5b6129ec83612500565b946020939093013593505050565b5f805f8060808587031215612a0d575f80fd5b84359350612a1d60208601612500565b9250612a2b60408601612500565b9150606085013567ffffffffffffffff811115612a46575f80fd5b612a52878288016125c0565b91505092959194509250565b5f805f8060808587031215612a71575f80fd5b612a7a85612500565b9350602085013567ffffffffffffffff811115612a95575f80fd5b612aa1878288016125c0565b949794965050505060408301359260600135919050565b5f805f60608486031215612aca575f80fd5b83359250612ada60208501612500565b9150612ae860408501612500565b90509250925092565b5f60208284031215612b01575f80fd5b813560ff81168114612325575f80fd5b6020808252600b908201526a1c9957d8dbdb9d1c9858dd60aa1b604082015260600190565b6020808252601390820152723932afbbb4ba34323930bbb13cb9b2b63632b960691b604082015260600190565b6020808252601290820152713932afbbb4ba34323930bbb13ca13abcb2b960711b604082015260600190565b6020808252600c908201526b72655f77726f6e676461746160a01b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b5f61ffff808316818103612bdf57612bdf612bb5565b6001019392505050565b634e487b7160e01b5f52603260045260245ffd5b808201808211156118cb576118cb612bb5565b80820281158282048414176118cb576118cb612bb5565b634e487b7160e01b5f52601260045260245ffd5b5f82612c4957612c49612c27565b500490565b818103818111156118cb576118cb612bb5565b60208082526008908201526772655f76616c756560c01b604082015260600190565b6020808252600f908201526e1c9957dd5cd95c9b9bdd195e1a5cdd608a1b604082015260600190565b6020808252600c908201526b1c9957dbdc99195c9c185a5960a21b604082015260600190565b5f5b83811015612cec578181015183820152602001612cd4565b50505f910152565b602081525f8251806020840152612d12816040850160208701612cd2565b601f01601f19169190910160400192915050565b653737b731b29d60d11b81525f8351612d46816006850160208801612cd2565b835190830190612d5d816006840160208801612cd2565b01600601949350505050565b5f8251612d7a818460208701612cd2565b9190910192915050565b5f60208284031215612d94575f80fd5b81518015158114612325575f80fd5b5f81612db157612db1612bb5565b505f190190565b5f60018201612dc957612dc9612bb5565b5060010190565b5f82612dde57612dde612c27565b500690565b60ff81811683821601908111156118cb576118cb612bb556fe7472616e7366657246726f6d28616464726573732c616464726573732c75696e7432353629a26474726f6e582212200dba772bcb99bd5a588e72dd7a814b0b4084f000bd8984c6cae60e39b6c29d4b64736f6c634300081400333a034d52544080ade20470e89d91d19832900180a8d6b907", + "raw_data": { + "contract": [ + { + "parameter": { + "value": { + "owner_address": "41084937b3f86ea7bbca86f2809809a65ed8a7ada9", + "new_contract": { + "abi": { + "entrys": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "total", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "contract_address", + "type": "address" + } + ], + "name": "OrderPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "active", + "type": "bool" + } + ], + "name": "TokenUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "total", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "token", + "type": "uint256" + } + ], + "name": "Trc10Paid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "token", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "active", + "type": "bool" + } + ], + "name": "Trc10Update", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "username", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "seller", + "type": "address" + } + ], + "name": "UserRegistred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "seller", + "type": "address" + } + ], + "name": "WBuyer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "buyer", + "type": "address" + } + ], + "name": "WSeller", + "type": "event" + }, + { + "inputs": [], + "name": "CONTRACTPERCENTAGE", + "outputs": [ + {"internalType": "uint8", "name": "", "type": "uint8"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "order_total", + "type": "uint256" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "seller", + "type": "address" + } + ], + "name": "PayWithTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "seller", + "type": "address" + } + ], + "name": "PayWithTrc10", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "TOKENINCREAMENT", + "outputs": [ + {"internalType": "uint16", "name": "", "type": "uint16"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "uint16", "name": "", "type": "uint16"} + ], + "name": "_contractBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_contractTrc10Balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "_signers", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "_tokens", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "token", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_trc10", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "_users", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "token", + "type": "uint256" + } + ], + "name": "contractTrc10Withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_contractAddress", + "type": "address" + } + ], + "name": "contractWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "payToContract", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "payTrc10ToContract", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "seller", + "type": "address" + } + ], + "name": "payWithNativeToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "username", + "type": "string" + } + ], + "name": "registerUser", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "internalType": "address", + "name": "buyer", + "type": "address" + } + ], + "name": "selectOrder", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + {"internalType": "uint8", "name": "", "type": "uint8"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "internalType": "address", + "name": "buyer", + "type": "address" + } + ], + "name": "selectTrc10", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + {"internalType": "uint8", "name": "", "type": "uint8"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "toggleSigner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "toggleToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "token", + "type": "uint256" + } + ], + "name": "toggleTrc10", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "newPercentage", + "type": "uint8" + } + ], + "name": "updateContractPercentage", + "outputs": [ + {"internalType": "uint8", "name": "", "type": "uint8"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "verifyPaymentSignature", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "buyer", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "signature", + "type": "bytes[]" + }, + { + "internalType": "uint256[]", + "name": "order_id", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "widthrawForSellers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "buyer", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "signature", + "type": "bytes[]" + }, + { + "internalType": "uint256[]", + "name": "order_id", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "token", + "type": "uint256" + } + ], + "name": "widthrawTrc10ForSellers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "widthrowForBuyers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "order_id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "token", + "type": "uint256" + } + ], + "name": "widthrowTrc10ForBuyers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "consume_user_resource_percent": 0, + "origin_energy_limit": 10000000, + "origin_address": "41084937b3f86ea7bbca86f2809809a65ed8a7ada9", + "bytecode": + "60806040526007805462ffff00191661010017905534801562000020575f80fd5b50d380156200002d575f80fd5b50d280156200003a575f80fd5b5062000046336200004c565b6200009b565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612e5780620000a95f395ff3fe6080604052600436106101c5575f3560e01c8063723e4c78116100f2578063b41529ce11610092578063ccbb605111610062578063ccbb6051146108bc578063d296ef9f14610902578063e8c8250a14610939578063f2fde38b14610941575f80fd5b8063b41529ce1461077d578063b7a608d814610819578063bab89e7b14610863578063c76ab5c8146108a9575f80fd5b80638da5cb5b116100cd5780638da5cb5b1461062c578063a7585bab14610660578063ad874cab14610697578063b2a51a5114610731575f80fd5b8063723e4c781461059357806377fc2856146105a65780638d7274aa146105dd575f80fd5b80632b4cd814116101685780636ceadadc116101385780636ceadadc146104da5780636d6ce44f146104ed578063704f1b9414610530578063715018a614610567575f80fd5b80632b4cd814146103c85780632e8609fc1461041457806331b7e10c1461044d5780633cacd7d614610484575f80fd5b80630c74e27e116101a35780630c74e27e146102c157806315c75f89146103045780632281eb691461035a578063283aa9c214610391575f80fd5b8063011b271b146101c957806306f41646146102135780630762c0851461027e575b5f80fd5b3480156101d4575f80fd5b50d380156101e0575f80fd5b50d280156101ec575f80fd5b506102006101fb3660046125de565b610978565b6040519081526020015b60405180910390f35b34801561021e575f80fd5b50d3801561022a575f80fd5b50d28015610236575f80fd5b50610264610245366004612642565b60026020525f908152604090205460ff811690610100900461ffff1682565b60408051921515835261ffff90911660208301520161020a565b348015610289575f80fd5b50d38015610295575f80fd5b50d280156102a1575f80fd5b506102006102b036600461265b565b60056020525f908152604090205481565b3480156102cc575f80fd5b50d380156102d8575f80fd5b50d280156102e4575f80fd5b506102006102f336600461267c565b60066020525f908152604090205481565b34801561030f575f80fd5b50d3801561031b575f80fd5b50d28015610327575f80fd5b5061033b610336366004612642565b610b27565b604080516001600160a01b03909316835290151560208301520161020a565b348015610365575f80fd5b50d38015610371575f80fd5b50d2801561037d575f80fd5b5061020061038c3660046127f9565b610c27565b34801561039c575f80fd5b50d380156103a8575f80fd5b50d280156103b4575f80fd5b506102006103c3366004612881565b610f6d565b3480156103d3575f80fd5b50d380156103df575f80fd5b50d280156103eb575f80fd5b506103ff6103fa36600461290b565b611278565b6040805192835260208301919091520161020a565b34801561041f575f80fd5b50d3801561042b575f80fd5b50d28015610437575f80fd5b5061044b610446366004612943565b61144d565b005b348015610458575f80fd5b50d38015610464575f80fd5b50d28015610470575f80fd5b5061044b61047f36600461296d565b611514565b34801561048f575f80fd5b50d3801561049b575f80fd5b50d280156104a7575f80fd5b506104ca6104b6366004612642565b60016020525f908152604090205460ff1681565b604051901515815260200161020a565b6103ff6104e8366004612943565b6115b4565b3480156104f8575f80fd5b50d38015610504575f80fd5b50d28015610510575f80fd5b5060075461051e9060ff1681565b60405160ff909116815260200161020a565b34801561053b575f80fd5b50d38015610547575f80fd5b50d28015610553575f80fd5b506104ca61056236600461298d565b61172a565b348015610572575f80fd5b50d3801561057e575f80fd5b50d2801561058a575f80fd5b5061044b6117dd565b6102006105a13660046129d2565b6117f0565b3480156105b1575f80fd5b50d380156105bd575f80fd5b50d280156105c9575f80fd5b5061033b6105d8366004612642565b6118d1565b3480156105e8575f80fd5b50d380156105f4575f80fd5b50d28015610600575f80fd5b5061061461060f3660046129fa565b611920565b6040516001600160a01b03909116815260200161020a565b348015610637575f80fd5b50d38015610643575f80fd5b50d2801561064f575f80fd5b505f546001600160a01b0316610614565b34801561066b575f80fd5b50d38015610677575f80fd5b50d28015610683575f80fd5b50610200610692366004612a5e565b611a45565b3480156106a2575f80fd5b50d380156106ae575f80fd5b50d280156106ba575f80fd5b506107136106c9366004612ab8565b6001600160a01b038083165f908152600160208181526040808420948616845260029485018252808420888552909152909120908101548154919092015460ff1693509350939050565b60408051938452602084019290925260ff169082015260600161020a565b34801561073c575f80fd5b50d38015610748575f80fd5b50d28015610754575f80fd5b5061076861076336600461267c565b611bd3565b6040805192835290151560208301520161020a565b348015610788575f80fd5b50d38015610794575f80fd5b50d280156107a0575f80fd5b506107f86107af366004612ab8565b6001600160a01b039182165f908152600160208181526040808420949095168352928101835283822094825293909152209081015490549091610100820461ffff169160ff1690565b6040805193845261ffff909216602084015260ff169082015260600161020a565b348015610824575f80fd5b50d38015610830575f80fd5b50d2801561083c575f80fd5b5060075461085090610100900461ffff1681565b60405161ffff909116815260200161020a565b34801561086e575f80fd5b50d3801561087a575f80fd5b50d28015610886575f80fd5b506104ca610895366004612642565b60046020525f908152604090205460ff1681565b6103ff6108b7366004612943565b611c56565b3480156108c7575f80fd5b50d380156108d3575f80fd5b50d280156108df575f80fd5b506104ca6108ee36600461267c565b60036020525f908152604090205460ff1681565b34801561090d575f80fd5b50d38015610919575f80fd5b50d28015610925575f80fd5b5061051e610934366004612af1565b611d81565b6103ff611db0565b34801561094c575f80fd5b50d38015610958575f80fd5b50d28015610964575f80fd5b5061044b610973366004612642565b611e03565b6001600160a01b0381165f90815260026020526040812054610100900461ffff168082036109a4575060015b6001600160a01b0386165f908152600160208181526040808420338552909201815281832087845290529020805461ffff8381166101009092041614610a055760405162461bcd60e51b81526004016109fc90612b11565b60405180910390fd5b805460ff16600203610a295760405162461bcd60e51b81526004016109fc90612b36565b805460ff16600303610a4d5760405162461bcd60e51b81526004016109fc90612b63565b610a5985883389611920565b50805460ff16600114610a7e5760405162461bcd60e51b81526004016109fc90612b8f565b805460ff19166003178155600161ffff83161115610aaa57610aa584338360010154611e7c565b610ad9565b6001810154604051339180156108fc02915f818181858888f19350505050158015610ad7573d5f803e3d5ffd5b505b6040516001600160a01b0388168152339086907f22c534eb26e5136ec7972747d88dc58ea5e5cb26dda483be89a3903ff4db56339060200160405180910390a3600101549695505050505050565b5f80610b31611faf565b823b610b3b575f80fd5b6001600160a01b0383165f9081526002602052604081208054909161010090910461ffff169003610bbf5760078054610100900461ffff16906001610b7f83612bc9565b825461010092830a61ffff818102199092169282160291909117909255600754845462ffffff1916908290049092160260ff191617600117825550610bd0565b805460ff19811660ff909116151781555b8054604080516001600160a01b038716815260ff909216151560208301527f1737c70f0c34bfb9be118ab02eff6bd1672fdf69eba5cb1dd13a46a30bfbc36f910160405180910390a15483925060ff169050915091565b5f80835111610c485760405162461bcd60e51b81526004016109fc90612b8f565b6001600160a01b0382165f90815260026020526040812054610100900461ffff16808203610c74575060015b5f5b85518160ff161015610eb557335f90815260016020819052604082208a5191019082908b9060ff8616908110610cae57610cae612be9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f888460ff1681518110610ceb57610ceb612be9565b602002602001015181526020019081526020015f2090508261ffff16815f0160019054906101000a900461ffff1661ffff1614610d3a5760405162461bcd60e51b81526004016109fc90612b11565b805460ff16600203610d5e5760405162461bcd60e51b81526004016109fc90612b36565b805460ff16600303610d825760405162461bcd60e51b81526004016109fc90612b63565b610de2878360ff1681518110610d9a57610d9a612be9565b60200260200101518a8460ff1681518110610db757610db7612be9565b6020026020010151338b8660ff1681518110610dd557610dd5612be9565b6020026020010151611920565b50805460ff16600114610e075760405162461bcd60e51b81526004016109fc90612b8f565b805460ff191660021781556001810154610e219085612bfd565b9350336001600160a01b0316878360ff1681518110610e4257610e42612be9565b60200260200101517f8b095c27ef5f0125ae7b1d417006b951316cf90f224a00c86e48004659f23b638b8560ff1681518110610e8057610e80612be9565b6020026020010151604051610ea491906001600160a01b0391909116815260200190565b60405180910390a350600101610c76565b5060075460ff1615610f1a576007545f90606490610ed69060ff1685612c10565b610ee09190612c3b565b9050610eec8184612c4e565b61ffff83165f90815260056020526040812080549295508392909190610f13908490612bfd565b9091555050505b60018161ffff161115610f3757610f32843384611e7c565b610f63565b604051339083156108fc029084905f818181858888f19350505050158015610f61573d5f803e3d5ffd5b505b5095945050505050565b5f80835111610f8e5760405162461bcd60e51b81526004016109fc90612b8f565b5f805b84518160ff1610156111bc57335f908152600160205260408120885160029091019082908a9060ff8616908110610fca57610fca612be9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f878460ff168151811061100757611007612be9565b602002602001015181526020019081526020015f20905084815f0154146110405760405162461bcd60e51b81526004016109fc90612b11565b60028082015460ff1690036110675760405162461bcd60e51b81526004016109fc90612b36565b600281015460ff1660030361108e5760405162461bcd60e51b81526004016109fc90612b63565b6110e1868360ff16815181106110a6576110a6612be9565b6020026020010151898460ff16815181106110c3576110c3612be9565b6020026020010151338a8660ff1681518110610dd557610dd5612be9565b50600281015460ff166001146111095760405162461bcd60e51b81526004016109fc90612b8f565b6002818101805460ff1916909117905560018101546111289084612bfd565b9250336001600160a01b0316868360ff168151811061114957611149612be9565b60200260200101517f8b095c27ef5f0125ae7b1d417006b951316cf90f224a00c86e48004659f23b638a8560ff168151811061118757611187612be9565b60200260200101516040516111ab91906001600160a01b0391909116815260200190565b60405180910390a350600101610f91565b5060075460ff161561121c576007545f906064906111dd9060ff1684612c10565b6111e79190612c3b565b90506111f38183612c4e565b91508060065f8681526020019081526020015f205f8282546112159190612bfd565b9091555050505b3381156108fc02828580158015611231575f80fd5b50806001603f1b11158015611244575f80fd5b5080620f424010158015611256575f80fd5b506040515f81818185878a8ad0945050505050158015610f63573d5f803e3d5ffd5b5f8033611283575f80fd5b5f85116112a25760405162461bcd60e51b81526004016109fc90612c61565b6001600160a01b0383165f9081526001602052604090205460ff166112d95760405162461bcd60e51b81526004016109fc90612c83565b6001600160a01b0384165f9081526002602052604090205460ff166113105760405162461bcd60e51b81526004016109fc90612b11565b6001600160a01b0383165f908152600160208181526040808420338552909201815281832089845290529020805460ff161561135e5760405162461bcd60e51b81526004016109fc90612cac565b6001600160a01b0385165f908152600260205260409020548154600183810189905560ff1961ffff61010094859004169093029290921662ffffff19909116171781556113ad85333089612008565b604080518781526001600160a01b03878116602083015286169133918a917fab3af43bba8f337a1a25176e89381aee76ab50668b2bda147da9371677e5ed6e910160405180910390a4604080518781526001600160a01b03878116602083015286169133918a917fab3af43bba8f337a1a25176e89381aee76ab50668b2bda147da9371677e5ed6e910160405180910390a4600101549596945050505050565b611455611faf565b6001600160a01b0381165f90815260026020526040812054610100900461ffff1690819003611482575060015b61ffff81165f908152600560205260409020548311156114a0575f80fd5b61ffff81165f90815260056020526040812080548592906114c2908490612c4e565b9091555050600161ffff821611156114e4576114df823385611e7c565b505050565b604051339084156108fc029085905f818181858888f1935050505015801561150e573d5f803e3d5ffd5b50505050565b61151c611faf565b5f81815260066020526040902054821115611535575f80fd5b5f8181526006602052604081208054849290611552908490612c4e565b9091555033905082156108fc0283838015801561156d575f80fd5b50806001603f1b11158015611580575f80fd5b5080620f424010158015611592575f80fd5b506040515f81818185878a8ad09450505050501580156114df573d5f803e3d5ffd5b5f80336115bf575f80fd5b6001600160a01b0383165f9081526001602052604090205460ff166115f65760405162461bcd60e51b81526004016109fc90612c83565bd35f9081526003602052604090205460ff166116245760405162461bcd60e51b81526004016109fc90612b11565b6001600160a01b0383165f90815260016020908152604080832033845260029081018352818420888552909252909120015460ff16156116765760405162461bcd60e51b81526004016109fc90612cac565b5fd2116116955760405162461bcd60e51b81526004016109fc90612c61565b6001600160a01b0383165f81815260016020818152604080842033808652600291820184528286208b8752845294829020d3808255d2828701819055928201805460ff19169096179095558251918252928101939093529093929188917f5e4e1d7e1a1b50d3acb16c2ee41c49f7d5b85f7b9283731fd00e4f016305894b91015b60405180910390a460010154939492505050565b5f33611734575f80fd5b335f9081526001602052604090205460ff16156117825760405162461bcd60e51b815260206004820152600c60248201526b1c9957dd5cd95c995e1a5cdd60a21b60448201526064016109fc565b335f81815260016020819052604091829020805460ff19169091179055517f4158c7d5f16e4b46a33f33fdc3f7bbe2253ea2fbba5dfffbe6a366b1d2cce09a906117cd908590612cf4565b60405180910390a2506001919050565b6117e5611faf565b6117ee5f612140565b565b6001600160a01b0382165f90815260026020526040812054610100900461ffff1680820361181c575060015b8061ffff16600114801561182f57505f34115b80611848575060018161ffff1611801561184857505f83115b611850575f80fd5b60018161ffff16111561189a5761186984333086612008565b61ffff81165f908152600560205260408120805485929061188b908490612bfd565b909155508392506118cb915050565b61ffff81165f90815260056020526040812080543492906118bc908490612bfd565b909155503492506118cb915050565b92915050565b5f806118db611faf565b6001600160a01b0383166118ed575f80fd5b50506001600160a01b0381165f908152600460205260409020805460ff8082161560ff1990921682179092559192911690565b5f80611936846001600160a01b0316601461218f565b61193f8761232c565b604051602001611950929190612d26565b60405160208183030381529060405290505f81805190602001206040516020016119a691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b6040516020818303038152906040528051906020012090505f6119c98286612431565b9050866001600160a01b0316816001600160a01b03161480611a0257506001600160a01b0381165f9081526004602052604090205460ff165b611a3a5760405162461bcd60e51b815260206004820152600960248201526872655f76657269667960b81b60448201526064016109fc565b979650505050505050565b6001600160a01b0384165f9081526001602090815260408083203384526002018252808320858452909152812080548314611a925760405162461bcd60e51b81526004016109fc90612b11565b60028082015460ff169003611ab95760405162461bcd60e51b81526004016109fc90612b36565b600281015460ff16600303611ae05760405162461bcd60e51b81526004016109fc90612b63565b611aec84873388611920565b50600281015460ff16600114611b145760405162461bcd60e51b81526004016109fc90612b8f565b60028101805460ff191660031790556001810154339080156108fc02908580158015611b3e575f80fd5b50806001603f1b11158015611b51575f80fd5b5080620f424010158015611b63575f80fd5b506040515f81818185878a8ad0945050505050158015611b85573d5f803e3d5ffd5b506040516001600160a01b0387168152339085907f22c534eb26e5136ec7972747d88dc58ea5e5cb26dda483be89a3903ff4db56339060200160405180910390a36001015495945050505050565b5f80611bdd611faf565b5f83815260036020908152604091829020805460ff8082161560ff199092168217909255835187815291161515918101919091527faf5cd8c9cd9b00ec027f4923710f6fd427975c48a24096a4cf83be7695ac991f910160405180910390a150505f81815260036020526040902054819060ff16915091565b5f8033611c61575f80fd5b6001600160a01b0383165f9081526001602052604090205460ff16611c985760405162461bcd60e51b81526004016109fc90612c83565b5f3411611cb75760405162461bcd60e51b81526004016109fc90612c61565b6001600160a01b0383165f9081526001602081815260408084203385529092018152818320878452905290205460ff1615611d045760405162461bcd60e51b81526004016109fc90612cac565b6001600160a01b0383165f8181526001602081815260408084203380865290840183528185208a8652835281852034948101859055805462ffffff19166101011781558251948552928401949094529093929188917fab3af43bba8f337a1a25176e89381aee76ab50668b2bda147da9371677e5ed6e9101611716565b5f611d8a611faf565b60038260ff1610611d99575f80fd5b506007805460ff191660ff92909216918217905590565b5f805fd211611dbd575f80fd5bd35f9081526003602052604090205460ff16611dd7575f80fd5bd35f9081526006602052604081208054d29290611df5908490612bfd565b90915550d393d29350915050565b611e0b611faf565b6001600160a01b038116611e705760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109fc565b611e7981612140565b50565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180516001600160e01b031663a9059cbb60e01b17905291515f928392871691611f079190612d69565b5f604051808303815f865af19150503d805f8114611f40576040519150601f19603f3d011682016040523d82523d5f602084013e611f45565b606091505b5091509150818015611f6f575080511580611f6f575080806020019051810190611f6f9190612d84565b611fa85760405162461bcd60e51b815260206004820152600a6024820152691c9957da185c9d995cdd60b21b60448201526064016109fc565b5050505050565b5f546001600160a01b031633146117ee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109fc565b5f80856001600160a01b0316604051806060016040528060258152602001612dfd6025913980516020909101206040516001600160a01b038089166024830152871660448201526064810186905260840160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516120979190612d69565b5f604051808303815f865af19150503d805f81146120d0576040519150601f19603f3d011682016040523d82523d5f602084013e6120d5565b606091505b50915091508180156120ff5750805115806120ff5750808060200190518101906120ff9190612d84565b6121385760405162461bcd60e51b815260206004820152600a6024820152691c9957da185c9d995cdd60b21b60448201526064016109fc565b505050505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60605f61219d836002612c10565b6121a8906002612bfd565b67ffffffffffffffff8111156121c0576121c0612526565b6040519080825280601f01601f1916602001820160405280156121ea576020820181803683370190505b509050600360fc1b815f8151811061220457612204612be9565b60200101906001600160f81b03191690815f1a905350600f60fb1b8160018151811061223257612232612be9565b60200101906001600160f81b03191690815f1a9053505f612254846002612c10565b61225f906001612bfd565b90505b60018111156122d6576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061229357612293612be9565b1a60f81b8282815181106122a9576122a9612be9565b60200101906001600160f81b03191690815f1a90535060049490941c936122cf81612da3565b9050612262565b5083156123255760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109fc565b9392505050565b6060815f036123525750506040805180820190915260018152600360fc1b602082015290565b815f5b811561237b578061236581612db8565b91506123749050600a83612c3b565b9150612355565b5f8167ffffffffffffffff81111561239557612395612526565b6040519080825280601f01601f1916602001820160405280156123bf576020820181803683370190505b5090505b8415612429576123d4600183612c4e565b91506123e1600a86612dd0565b6123ec906030612bfd565b60f81b81838151811061240157612401612be9565b60200101906001600160f81b03191690815f1a905350612422600a86612c3b565b94506123c3565b949350505050565b5f805f808451604114612449575f93505050506118cb565b5050506020820151604083015160608401515f1a601b81101561247457612471601b82612de3565b90505b8060ff16601b1415801561248c57508060ff16601c14155b1561249c575f93505050506118cb565b604080515f81526020810180835288905260ff831691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa1580156124ec573d5f803e3d5ffd5b5050506020604051035193505050506118cb565b5f81356001600160a81b0381168114612517575f80fd5b6001600160a01b031692915050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561256357612563612526565b604052919050565b5f67ffffffffffffffff83111561258457612584612526565b612597601f8401601f191660200161253a565b90508281528383830111156125aa575f80fd5b828260208301375f602084830101529392505050565b5f82601f8301126125cf575f80fd5b6123258383356020850161256b565b5f805f80608085870312156125f1575f80fd5b6125fa85612500565b9350602085013567ffffffffffffffff811115612615575f80fd5b612621878288016125c0565b9350506040850135915061263760608601612500565b905092959194509250565b5f60208284031215612652575f80fd5b61232582612500565b5f6020828403121561266b575f80fd5b813561ffff81168114612325575f80fd5b5f6020828403121561268c575f80fd5b5035919050565b5f67ffffffffffffffff8211156126ac576126ac612526565b5060051b60200190565b5f82601f8301126126c5575f80fd5b813560206126da6126d583612693565b61253a565b82815260059290921b840181019181810190868411156126f8575f80fd5b8286015b8481101561271a5761270d81612500565b83529183019183016126fc565b509695505050505050565b5f82601f830112612734575f80fd5b813560206127446126d583612693565b82815260059290921b84018101918181019086841115612762575f80fd5b8286015b8481101561271a57803567ffffffffffffffff811115612785575f8081fd5b6127938986838b01016125c0565b845250918301918301612766565b5f82601f8301126127b0575f80fd5b813560206127c06126d583612693565b82815260059290921b840181019181810190868411156127de575f80fd5b8286015b8481101561271a57803583529183019183016127e2565b5f805f806080858703121561280c575f80fd5b843567ffffffffffffffff80821115612823575f80fd5b61282f888389016126b6565b95506020870135915080821115612844575f80fd5b61285088838901612725565b94506040870135915080821115612865575f80fd5b50612872878288016127a1565b92505061263760608601612500565b5f805f8060808587031215612894575f80fd5b843567ffffffffffffffff808211156128ab575f80fd5b6128b7888389016126b6565b955060208701359150808211156128cc575f80fd5b6128d888838901612725565b945060408701359150808211156128ed575f80fd5b506128fa878288016127a1565b949793965093946060013593505050565b5f805f806080858703121561291e575f80fd5b843593506020850135925061293560408601612500565b915061263760608601612500565b5f8060408385031215612954575f80fd5b8235915061296460208401612500565b90509250929050565b5f806040838503121561297e575f80fd5b50508035926020909101359150565b5f6020828403121561299d575f80fd5b813567ffffffffffffffff8111156129b3575f80fd5b8201601f810184136129c3575f80fd5b6124298482356020840161256b565b5f80604083850312156129e3575f80fd5b6129ec83612500565b946020939093013593505050565b5f805f8060808587031215612a0d575f80fd5b84359350612a1d60208601612500565b9250612a2b60408601612500565b9150606085013567ffffffffffffffff811115612a46575f80fd5b612a52878288016125c0565b91505092959194509250565b5f805f8060808587031215612a71575f80fd5b612a7a85612500565b9350602085013567ffffffffffffffff811115612a95575f80fd5b612aa1878288016125c0565b949794965050505060408301359260600135919050565b5f805f60608486031215612aca575f80fd5b83359250612ada60208501612500565b9150612ae860408501612500565b90509250925092565b5f60208284031215612b01575f80fd5b813560ff81168114612325575f80fd5b6020808252600b908201526a1c9957d8dbdb9d1c9858dd60aa1b604082015260600190565b6020808252601390820152723932afbbb4ba34323930bbb13cb9b2b63632b960691b604082015260600190565b6020808252601290820152713932afbbb4ba34323930bbb13ca13abcb2b960711b604082015260600190565b6020808252600c908201526b72655f77726f6e676461746160a01b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b5f61ffff808316818103612bdf57612bdf612bb5565b6001019392505050565b634e487b7160e01b5f52603260045260245ffd5b808201808211156118cb576118cb612bb5565b80820281158282048414176118cb576118cb612bb5565b634e487b7160e01b5f52601260045260245ffd5b5f82612c4957612c49612c27565b500490565b818103818111156118cb576118cb612bb5565b60208082526008908201526772655f76616c756560c01b604082015260600190565b6020808252600f908201526e1c9957dd5cd95c9b9bdd195e1a5cdd608a1b604082015260600190565b6020808252600c908201526b1c9957dbdc99195c9c185a5960a21b604082015260600190565b5f5b83811015612cec578181015183820152602001612cd4565b50505f910152565b602081525f8251806020840152612d12816040850160208701612cd2565b601f01601f19169190910160400192915050565b653737b731b29d60d11b81525f8351612d46816006850160208801612cd2565b835190830190612d5d816006840160208801612cd2565b01600601949350505050565b5f8251612d7a818460208701612cd2565b9190910192915050565b5f60208284031215612d94575f80fd5b81518015158114612325575f80fd5b5f81612db157612db1612bb5565b505f190190565b5f60018201612dc957612dc9612bb5565b5060010190565b5f82612dde57612dde612c27565b500690565b60ff81811683821601908111156118cb576118cb612bb556fe7472616e7366657246726f6d28616464726573732c616464726573732c75696e7432353629a26474726f6e582212200dba772bcb99bd5a588e72dd7a814b0b4084f000bd8984c6cae60e39b6c29d4b64736f6c63430008140033", + "name": "MRT" + } + }, + "type_url": "type.googleapis.com/protocol.CreateSmartContract" + }, + "type": "CreateSmartContract" + } + ], + "ref_block_bytes": "1baf", + "ref_block_hash": "126503230ae79de2", + "expiration": 1724599581000, + "timestamp": 1724599521000, + "fee_limit": 2000000000 + }, + "contract_address": "414878757a31a4fb369be7c0b85ad5528ba479159b" + }; + + test("create smart contract", () { + final transaction = Transaction.fromJson(issueJson); + expect(transaction.rawData.txID, + "03bf549df3dfceaf04716df728e77434c04046f4d7a564753d92ad160c8a8d93"); + final decBuffer = Transaction.deserialize(transaction.toBuffer()); + expect(transaction.rawData.txID, decBuffer.rawData.txID); + final decodeJson = Transaction.fromJson(decBuffer.toJson()); + expect(transaction.rawData.txID, decodeJson.rawData.txID); + }); +}