From 78719a85acc6c36ac83db83f0b8cb14007877863 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Thu, 2 Jan 2025 15:45:07 +0330 Subject: [PATCH] V5.0.0 * Update dependencies * Minimum required Dart SDK version updated to 3.3. --- CHANGELOG.md | 7 +- README.md | 18 +- analysis_options.yaml | 55 +- .../lib/bitcoin_cash/burn_token_example.dart | 9 +- .../create_cash_token_example.dart | 9 +- .../lib/bitcoin_cash/create_nft_example.dart | 9 +- .../lib/bitcoin_cash/make_vout0_example.dart | 9 +- .../lib/bitcoin_cash/minting_nft_example.dart | 9 +- .../bitcoin_cash/p2sh32_spend_example.dart | 10 +- .../bitcoin_cash/send_ft_token_example.dart | 9 +- .../bitcoin_cash/transfer_bch_example.dart | 9 +- example/lib/global/bch_example.dart | 9 +- ...amples_multisig_taproot_legacy_uncomp.dart | 47 +- ...er_from_7_account_to_6_accout_example.dart | 11 +- .../global/transfer_to_8_account_example.dart | 12 +- .../electrum/electrum_ssl_service.dart | 15 +- .../electrum/electrum_tcp_service.dart | 17 +- .../electrum/electrum_websocket_service.dart | 15 +- example/pubspec.lock | 36 +- example/pubspec.yaml | 4 +- example/test/test_test.dart | 1 + lib/bitcoin_base.dart | 20 +- lib/src/bitcoin/address/address.dart | 2 +- lib/src/bitcoin/address/core.dart | 56 +- lib/src/bitcoin/address/legacy_address.dart | 26 +- lib/src/bitcoin/address/network_address.dart | 2 +- lib/src/bitcoin/address/segwit_address.dart | 58 +- .../bitcoin/address/utils/address_utils.dart | 36 +- lib/src/bitcoin/script/control_block.dart | 6 +- lib/src/bitcoin/script/input.dart | 19 +- lib/src/bitcoin/script/op_code/constant.dart | 10 +- .../bitcoin/script/op_code/constant_lib.dart | 2 +- lib/src/bitcoin/script/op_code/tools.dart | 10 +- lib/src/bitcoin/script/output.dart | 13 +- lib/src/bitcoin/script/script.dart | 20 +- lib/src/bitcoin/script/sequence.dart | 10 +- lib/src/bitcoin/script/transaction.dart | 117 +- lib/src/bitcoin/script/witness.dart | 7 +- lib/src/bitcoin_cash/bcmr.dart | 8 +- lib/src/bitcoin_cash/bcmr_registery.dart | 47 +- lib/src/cash_token/cash_token.dart | 74 +- lib/src/crypto/crypto.dart | 4 +- lib/src/crypto/keypair/ec_private.dart | 24 +- lib/src/crypto/keypair/ec_public.dart | 42 +- lib/src/exception/exception.dart | 4 +- lib/src/models/network.dart | 43 +- lib/src/provider/api_provider.dart | 9 +- .../api_provider/electrum_api_provider.dart | 37 - lib/src/provider/api_provider/providers.dart | 2 - lib/src/provider/constant/constant.dart | 18 +- .../{service/electrum => core}/methods.dart | 58 +- lib/src/provider/core/params.dart | 66 + .../electrum_methods/methods/add_peer.dart | 7 +- .../methods/block_headers.dart | 7 +- .../electrum_methods/methods/broad_cast.dart | 9 +- .../methods/donate_address.dart | 5 +- .../methods/electrum_version.dart | 9 +- .../methods/estimate_fee.dart | 7 +- .../electrum_methods/methods/get_balance.dart | 8 +- .../methods/get_fee_histogram.dart | 14 +- .../electrum_methods/methods/get_history.dart | 8 +- .../electrum_methods/methods/get_mempool.dart | 8 +- .../electrum_methods/methods/get_merkle.dart | 9 +- .../methods/get_transaction.dart | 9 +- .../electrum_methods/methods/get_unspet.dart | 13 +- .../methods/get_value_proof.dart | 8 +- .../electrum_methods/methods/header.dart | 8 +- .../methods/headers_subscribe.dart | 5 +- .../electrum_methods/methods/id_from_pos.dart | 8 +- .../masternode_announce_broadcast.dart | 8 +- .../methods/masternode_list.dart | 7 +- .../methods/masternode_subscribe.dart | 8 +- .../electrum_methods/methods/ping.dart | 5 +- .../electrum_methods/methods/protx_diff.dart | 8 +- .../electrum_methods/methods/protx_info.dart | 8 +- .../electrum_methods/methods/relay_fee.dart | 5 +- .../methods/scripthash_unsubscribe.dart | 7 +- .../methods/server_banner.dart | 5 +- .../methods/server_features.dart | 5 +- .../methods/server_peer_subscribe.dart | 5 +- .../electrum_methods/methods/status.dart | 7 +- .../block_cypher/block_cypher_models.dart | 2 +- lib/src/provider/models/config.dart | 42 +- .../models/electrum/electrum_utxo.dart | 12 +- .../provider/models/fee_rate/fee_rate.dart | 4 +- .../models/mempool/mempol_models.dart | 2 +- lib/src/provider/models/multisig_script.dart | 12 +- lib/src/provider/models/utxo_details.dart | 44 +- lib/src/provider/providers/electrum.dart | 57 + .../explorer.dart} | 36 +- .../provider/service/electrum/electrum.dart | 3 - lib/src/provider/service/electrum/params.dart | 54 - .../provider/service/electrum/service.dart | 13 - lib/src/provider/service/services.dart | 2 - lib/src/provider/services/electrum.dart | 10 + .../explorer.dart} | 2 +- .../transaction_builder/builder.dart | 0 .../transaction_builder/core.dart | 0 .../forked_transaction_builder.dart | 111 +- .../transaction_builder.dart | 146 +-- lib/src/utils/btc_utils.dart | 10 +- lib/src/utils/enumerate.dart | 2 +- pubspec.yaml | 8 +- test/bcmr/art_collection.dart | 136 +- test/bcmr/bcmr_test.dart | 2 +- test/bcmr/decentralized_application.dart | 116 +- test/bcmr/fungible_token.dart | 52 +- test/bcmr/payouts_or_dividends.dart | 136 +- test/bitcoin_cash_address_test.dart | 336 ++--- test/bitcoin_cash_token_encoding_test.dart | 1119 ++++++++--------- test/deserialize_test.dart | 8 +- test/encode_decode_transaction_test.dart | 56 +- test/keys_test.dart | 122 +- test/p2kh_tr_test.dart | 38 +- test/p2sh_test.dart | 10 +- test/p2tr_test.dart | 55 +- test/p2wpkh_test.dart | 84 +- test/p2wsh_test.dart | 32 +- test/xep_address_test.dart | 23 - 119 files changed, 2159 insertions(+), 2128 deletions(-) create mode 100644 example/test/test_test.dart delete mode 100644 lib/src/provider/api_provider/electrum_api_provider.dart delete mode 100644 lib/src/provider/api_provider/providers.dart rename lib/src/provider/{service/electrum => core}/methods.dart (70%) create mode 100644 lib/src/provider/core/params.dart create mode 100644 lib/src/provider/providers/electrum.dart rename lib/src/provider/{api_provider/api_provider.dart => providers/explorer.dart} (82%) delete mode 100644 lib/src/provider/service/electrum/electrum.dart delete mode 100644 lib/src/provider/service/electrum/params.dart delete mode 100644 lib/src/provider/service/electrum/service.dart delete mode 100644 lib/src/provider/service/services.dart create mode 100644 lib/src/provider/services/electrum.dart rename lib/src/provider/{service/http/http_service.dart => services/explorer.dart} (88%) rename lib/src/{provider => }/transaction_builder/builder.dart (100%) rename lib/src/{provider => }/transaction_builder/core.dart (100%) rename lib/src/{provider => }/transaction_builder/forked_transaction_builder.dart (89%) rename lib/src/{provider => }/transaction_builder/transaction_builder.dart (87%) delete mode 100644 test/xep_address_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index abffeb3..8c20001 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ +## 5.0.0 +* Update dependencies +* Minimum required Dart SDK version updated to 3.3. + ## 4.9.4 + * Improved serialization process for large transaction scripts. * Added support for the Electra network. * Create and spent from uncomprossed public key format. * Important Notice: This is the final version supporting Dart v2. The next release will require Dart v3.3 or higher. - ## 4.9.2 + * Update dependencies * Resolved issue with transaction deserialization (unsigned tx) diff --git a/README.md b/README.md index a02d9b5..abc55cb 100644 --- a/README.md +++ b/README.md @@ -280,7 +280,7 @@ In the [example](https://github.com/mrtnetwork/bitcoin_base/tree/main/example/li await ElectrumWebSocketService.connect("184...."); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// spender details final privateKey = ECPrivate.fromHex( @@ -310,7 +310,7 @@ In the [example](https://github.com/mrtnetwork/bitcoin_base/tree/main/example/li for (final i in spenders) { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account final elctrumUtxos = await provider - .request(ElectrumScriptHashListUnspent(scriptHash: i.pubKeyHash())); + .request(ElectrumRequestScriptHashListUnspent(scriptHash: i.pubKeyHash())); /// Converts all UTXOs to a list of UtxoWithAddress, containing UTXO information along with address details. /// read spender utxos @@ -427,7 +427,7 @@ In the [example](https://github.com/mrtnetwork/bitcoin_base/tree/main/example/li final raw = transaction.serialize(); /// send to network - await provider.request(ElectrumBroadCastTransaction(transactionRaw: raw)); + await provider.request(ElectrumRequestBroadCastTransaction(transactionRaw: raw)); /// Once completed, we verify the status by checking the mempool or using another explorer to review the transaction details. /// https://mempool.space/testnet/tx/70cf664bba4b5ac9edc6133e9c6891ffaf8a55eaea9d2ac99aceead1c3db8899 @@ -446,7 +446,7 @@ In the [example](https://github.com/mrtnetwork/bitcoin_base/tree/main/example/li "wss://chipnet.imaginary.cash:50004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -470,7 +470,7 @@ In the [example](https://github.com/mrtnetwork/bitcoin_base/tree/main/example/li /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.baseAddress.pubKeyHash(), includeTokens: true, )); @@ -566,7 +566,7 @@ In the [example](https://github.com/mrtnetwork/bitcoin_base/tree/main/example/li /// send transaction to network await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + .request(ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/97030c1236a024de7cad7ceadf8571833029c508e016bcc8173146317e367ae6 @@ -704,7 +704,7 @@ I haven't implemented any specific HTTP service or socket service within this pl await ElectrumSSLService.connect("testnet.aranguren.org:51002"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); final address = P2trAddress.fromAddress(address: ".....", network: network); @@ -714,7 +714,7 @@ I haven't implemented any specific HTTP service or socket service within this pl /// Return an ordered list of UTXOs sent to a script hash. final accountUnspend = await provider - .request(ElectrumScriptHashListUnspent(scriptHash: address.pubKeyHash())); + .request(ElectrumRequestScriptHashListUnspent(scriptHash: address.pubKeyHash())); /// Return the confirmed and unconfirmed history of a script hash. final accountHistory = await provider @@ -722,7 +722,7 @@ I haven't implemented any specific HTTP service or socket service within this pl /// Broadcast a transaction to the network. final broadcastTransaction = await provider - .request(ElectrumBroadCastTransaction(transactionRaw: "txDigest")); + .request(ElectrumRequestBroadCastTransaction(transactionRaw: "txDigest")); /// .... ``` diff --git a/analysis_options.yaml b/analysis_options.yaml index 231b316..32dccdb 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,9 +1,56 @@ # include: package:lints/recommended.yaml include: package:flutter_lints/flutter.yaml +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options # Uncomment the following section to specify additional rules. linter: rules: - prefer_final_locals: true # Warns when a local variable could be final - prefer_final_in_for_each: true # Warns when a forEach variable could be final - prefer_const_constructors: true # Warns when a constructor could be const - prefer_const_declarations: true # Warns when a declaration could be const + - always_declare_return_types + - annotate_overrides + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_relative_lib_imports + - avoid_return_types_on_setters + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements + - avoid_types_as_parameter_names + - await_only_futures + - camel_case_extensions + - curly_braces_in_flow_control_structures + - empty_catches + - empty_constructor_bodies + - library_names + - library_prefixes + - no_duplicate_case_values + - null_closures + - omit_local_variable_types + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_contains + - prefer_equal_for_default_values + - prefer_final_fields + - prefer_for_elements_to_map_fromIterable + - prefer_generic_function_type_aliases + - prefer_if_null_operators + - prefer_inlined_adds + - prefer_is_empty + - prefer_is_not_empty + - prefer_iterable_whereType + - prefer_single_quotes + - prefer_spread_collections + - recursive_getters + - slash_for_doc_comments + - sort_child_properties_last + - type_init_formals + - unawaited_futures + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_getters_setters + - unnecessary_new + - unnecessary_null_in_if_null_operators + - unnecessary_this + - unrelated_type_equality_checks + - use_function_type_syntax_for_parameters + - use_rethrow_when_possible + - valid_regexps \ No newline at end of file diff --git a/example/lib/bitcoin_cash/burn_token_example.dart b/example/lib/bitcoin_cash/burn_token_example.dart index 9b25036..b0e8a36 100644 --- a/example/lib/bitcoin_cash/burn_token_example.dart +++ b/example/lib/bitcoin_cash/burn_token_example.dart @@ -10,7 +10,7 @@ void main() async { "wss://chipnet.imaginary.cash:50004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -34,7 +34,8 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.baseAddress.pubKeyHash(), includeTokens: true, )); @@ -141,8 +142,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/d85da44ba0c12ab8b0f4c636ca5451ae2c3a90b0f6d9e47fe381d0f5c6966ff3 diff --git a/example/lib/bitcoin_cash/create_cash_token_example.dart b/example/lib/bitcoin_cash/create_cash_token_example.dart index bb93937..19af892 100644 --- a/example/lib/bitcoin_cash/create_cash_token_example.dart +++ b/example/lib/bitcoin_cash/create_cash_token_example.dart @@ -11,7 +11,7 @@ void main() async { "wss://chipnet.imaginary.cash:50004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -29,7 +29,8 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.pubKeyHash(), includeTokens: false, )); @@ -135,8 +136,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/fe0f9f84bd8782b8037160c09a515d39a9cc5bbeda6dcca6fb8a89e952bc9dea diff --git a/example/lib/bitcoin_cash/create_nft_example.dart b/example/lib/bitcoin_cash/create_nft_example.dart index 28404cd..e9af101 100644 --- a/example/lib/bitcoin_cash/create_nft_example.dart +++ b/example/lib/bitcoin_cash/create_nft_example.dart @@ -11,7 +11,7 @@ void main() async { "wss://chipnet.imaginary.cash:50004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -30,7 +30,8 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.baseAddress.pubKeyHash(), includeTokens: false, )); @@ -121,8 +122,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/4e153029c75963f39920184233756f8f55d5a8f86e01cbdaf0340320c814e25e diff --git a/example/lib/bitcoin_cash/make_vout0_example.dart b/example/lib/bitcoin_cash/make_vout0_example.dart index aa71f8b..4f1730c 100644 --- a/example/lib/bitcoin_cash/make_vout0_example.dart +++ b/example/lib/bitcoin_cash/make_vout0_example.dart @@ -12,7 +12,7 @@ void main() async { await ElectrumSSLService.connect("chipnet.imaginary.cash:50002"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -30,7 +30,8 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.pubKeyHash(), includeTokens: false, )); @@ -77,8 +78,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/b20d4c13fe67adc2f73aee0161eb51c7e813643ddc8eb655c6bd9ae72b7562cb diff --git a/example/lib/bitcoin_cash/minting_nft_example.dart b/example/lib/bitcoin_cash/minting_nft_example.dart index 092fb24..621c241 100644 --- a/example/lib/bitcoin_cash/minting_nft_example.dart +++ b/example/lib/bitcoin_cash/minting_nft_example.dart @@ -11,7 +11,7 @@ void main() async { await ElectrumWebSocketService.connect("wss://tbch4.loping.net:62004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -30,7 +30,8 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.baseAddress.pubKeyHash(), includeTokens: true, )); @@ -177,8 +178,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://tbch4.loping.net/tx/caa91b0fea2843a99c3cd7375ac4d3102b6b74a25e52cd866ad7ecc486204f0d diff --git a/example/lib/bitcoin_cash/p2sh32_spend_example.dart b/example/lib/bitcoin_cash/p2sh32_spend_example.dart index d46b23d..0081118 100644 --- a/example/lib/bitcoin_cash/p2sh32_spend_example.dart +++ b/example/lib/bitcoin_cash/p2sh32_spend_example.dart @@ -12,7 +12,7 @@ void main() async { "wss://chipnet.imaginary.cash:50004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -45,12 +45,12 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. final example1ElectrumUtxos = - await provider.request(ElectrumScriptHashListUnspent( + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2sh32Example1.baseAddress.pubKeyHash(), includeTokens: false, )); final example2ElectrumUtxos = - await provider.request(ElectrumScriptHashListUnspent( + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2sh32Example2.baseAddress.pubKeyHash(), includeTokens: false, )); @@ -111,8 +111,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/b76b851ce0374504591db414d7469aadb68649079defb26e44c62e970afda729 diff --git a/example/lib/bitcoin_cash/send_ft_token_example.dart b/example/lib/bitcoin_cash/send_ft_token_example.dart index d875661..cfbfc2b 100644 --- a/example/lib/bitcoin_cash/send_ft_token_example.dart +++ b/example/lib/bitcoin_cash/send_ft_token_example.dart @@ -11,7 +11,7 @@ void main() async { "wss://chipnet.imaginary.cash:50004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -35,7 +35,8 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.baseAddress.pubKeyHash(), includeTokens: true, )); @@ -136,8 +137,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/97030c1236a024de7cad7ceadf8571833029c508e016bcc8173146317e367ae6 diff --git a/example/lib/bitcoin_cash/transfer_bch_example.dart b/example/lib/bitcoin_cash/transfer_bch_example.dart index f9631f9..a51ac29 100644 --- a/example/lib/bitcoin_cash/transfer_bch_example.dart +++ b/example/lib/bitcoin_cash/transfer_bch_example.dart @@ -12,7 +12,7 @@ void main() async { "wss://chipnet.imaginary.cash:50004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -39,7 +39,8 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.baseAddress.pubKeyHash(), includeTokens: false, )); @@ -96,8 +97,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/9e534f8a64f76b1af5ccf2522392697f2242fd215206a458cfe286bca4a3ec0a diff --git a/example/lib/global/bch_example.dart b/example/lib/global/bch_example.dart index 6b31303..73b5952 100644 --- a/example/lib/global/bch_example.dart +++ b/example/lib/global/bch_example.dart @@ -9,7 +9,7 @@ void main() async { "wss://chipnet.imaginary.cash:50004"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// initialize private key final privateKey = ECPrivate.fromBytes(BytesUtils.fromHexString( @@ -36,7 +36,8 @@ void main() async { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account. /// We does not need tokens utxo and we set to false. - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( + final elctrumUtxos = + await provider.request(ElectrumRequestScriptHashListUnspent( scriptHash: p2pkhAddress.baseAddress.pubKeyHash(), includeTokens: false, )); @@ -93,8 +94,8 @@ void main() async { final transactionRaw = transaaction.toHex(); /// send transaction to network - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); /// done! check the transaction in block explorer /// https://chipnet.imaginary.cash/tx/9e534f8a64f76b1af5ccf2522392697f2242fd215206a458cfe286bca4a3ec0a diff --git a/example/lib/global/btc_examples_multisig_taproot_legacy_uncomp.dart b/example/lib/global/btc_examples_multisig_taproot_legacy_uncomp.dart index 1bd9fc1..617fa11 100644 --- a/example/lib/global/btc_examples_multisig_taproot_legacy_uncomp.dart +++ b/example/lib/global/btc_examples_multisig_taproot_legacy_uncomp.dart @@ -16,15 +16,18 @@ void main() async { }; final account = MultiSignatureAddress(threshold: 8, signers: [ MultiSignatureSigner( - publicKey: one.getPublic().toHex(compressed: false), weight: 1), + publicKey: one.getPublic().toHex(mode: PublicKeyType.uncompressed), + weight: 1), MultiSignatureSigner(publicKey: two.getPublic().toHex(), weight: 1), MultiSignatureSigner(publicKey: three.getPublic().toHex(), weight: 1), MultiSignatureSigner( - publicKey: four.getPublic().toHex(compressed: false), weight: 1), + publicKey: four.getPublic().toHex(mode: PublicKeyType.uncompressed), + weight: 1), MultiSignatureSigner(publicKey: five.getPublic().toHex(), weight: 1), MultiSignatureSigner(publicKey: six.getPublic().toHex(), weight: 1), MultiSignatureSigner( - publicKey: seven.getPublic().toHex(compressed: false), weight: 1), + publicKey: seven.getPublic().toHex(mode: PublicKeyType.uncompressed), + weight: 1), MultiSignatureSigner(publicKey: eight.getPublic().toHex(), weight: 1), ]); @@ -34,24 +37,27 @@ void main() async { "testnet4-electrumx.wakiyamap.dev:51002"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); - final addrOne = one.getPublic().toP2pkAddress(compressed: false); + final addrOne = + one.getPublic().toP2pkAddress(mode: PublicKeyType.uncompressed); - final addrTwo = two.getPublic().toAddress(compressed: false); + final addrTwo = two.getPublic().toAddress(mode: PublicKeyType.uncompressed); - final addrThree = three.getPublic().toP2pkInP2sh(compressed: false); - final addrFour = four.getPublic().toP2pkhInP2sh(compressed: false); + final addrThree = + three.getPublic().toP2pkInP2sh(mode: PublicKeyType.uncompressed); + final addrFour = + four.getPublic().toP2pkhInP2sh(mode: PublicKeyType.uncompressed); final addrFive = four.getPublic().toSegwitAddress(); final addrSix = account.toP2shAddress(); final addr7 = eight.getPublic().toTaprootAddress(); final addr8 = eight.getPublic().toP2wshAddress(); final addr9 = eight.getPublic().toP2wshInP2sh(); final List pubkys = [ - one.getPublic().toHex(compressed: false), - two.getPublic().toHex(compressed: false), - three.getPublic().toHex(compressed: false), - four.getPublic().toHex(compressed: false), + one.getPublic().toHex(mode: PublicKeyType.uncompressed), + two.getPublic().toHex(mode: PublicKeyType.uncompressed), + three.getPublic().toHex(mode: PublicKeyType.uncompressed), + four.getPublic().toHex(mode: PublicKeyType.uncompressed), four.getPublic().toHex(), four.getPublic().toHex(), eight.getPublic().toHex(), @@ -60,10 +66,10 @@ void main() async { eight.getPublic().toHex(), ]; final addresses = [ - one.getPublic().toP2pkAddress(compressed: false), - two.getPublic().toAddress(compressed: false), - three.getPublic().toP2pkInP2sh(compressed: false), - four.getPublic().toP2pkhInP2sh(compressed: false), + one.getPublic().toP2pkAddress(mode: PublicKeyType.uncompressed), + two.getPublic().toAddress(mode: PublicKeyType.uncompressed), + three.getPublic().toP2pkInP2sh(mode: PublicKeyType.uncompressed), + four.getPublic().toP2pkhInP2sh(mode: PublicKeyType.uncompressed), four.getPublic().toSegwitAddress(), four.getPublic().toP2wshInP2sh(), addrSix, @@ -74,8 +80,9 @@ void main() async { List utxos = []; for (int i = 0; i < addresses.length; i++) { final address = addresses[i]; - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( - scriptHash: address.pubKeyHash(), includeTokens: false)); + final elctrumUtxos = await provider.request( + ElectrumRequestScriptHashListUnspent( + scriptHash: address.pubKeyHash(), includeTokens: false)); if (elctrumUtxos.isEmpty) continue; if (i == 6) { utxos.addAll(elctrumUtxos.map((e) => UtxoWithAddress( @@ -124,8 +131,8 @@ void main() async { }); final transactionRaw = transaaction.toHex(); - await provider - .request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw)); + await provider.request( + ElectrumRequestBroadCastTransaction(transactionRaw: transactionRaw)); } /// https://mempool.space/testnet4/tx/a7f08f07739de45a6a4f8871f8e6ad79e0aefbc940086df76571354ba22263fa diff --git a/example/lib/global/transfer_from_7_account_to_6_accout_example.dart b/example/lib/global/transfer_from_7_account_to_6_accout_example.dart index 61d02cc..bdfcaee 100644 --- a/example/lib/global/transfer_from_7_account_to_6_accout_example.dart +++ b/example/lib/global/transfer_from_7_account_to_6_accout_example.dart @@ -19,7 +19,7 @@ void main() async { await ElectrumSSLService.connect("testnet.aranguren.org:51002"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// spender details final privateKey = ECPrivate.fromHex( @@ -48,8 +48,8 @@ void main() async { /// loop each spenders address and get utxos and add to accountsUtxos for (final i in spenders) { /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account - final elctrumUtxos = await provider - .request(ElectrumScriptHashListUnspent(scriptHash: i.pubKeyHash())); + final elctrumUtxos = await provider.request( + ElectrumRequestScriptHashListUnspent(scriptHash: i.pubKeyHash())); /// Converts all UTXOs to a list of UtxoWithAddress, containing UTXO information along with address details. /// read spender utxos @@ -121,7 +121,7 @@ void main() async { enableRBF: true); /// get network fee esmtimate (fee per kilobyte) - final networkEstimate = await provider.request(ElectrumEstimateFee()); + final networkEstimate = await provider.request(ElectrumRequestEstimateFee()); /// the daemon does not have enough information to make an estimate if (networkEstimate == null) { @@ -171,7 +171,8 @@ void main() async { final raw = transaction.serialize(); /// send to network - await provider.request(ElectrumBroadCastTransaction(transactionRaw: raw)); + await provider + .request(ElectrumRequestBroadCastTransaction(transactionRaw: raw)); /// Once completed, we verify the status by checking the mempool or using another explorer to review the transaction details. /// https://mempool.space/testnet/tx/70cf664bba4b5ac9edc6133e9c6891ffaf8a55eaea9d2ac99aceead1c3db8899 diff --git a/example/lib/global/transfer_to_8_account_example.dart b/example/lib/global/transfer_to_8_account_example.dart index 235c673..3469d37 100644 --- a/example/lib/global/transfer_to_8_account_example.dart +++ b/example/lib/global/transfer_to_8_account_example.dart @@ -9,7 +9,7 @@ void main() async { await ElectrumSSLService.connect("testnet.aranguren.org:51002"); /// create provider with service - final provider = ElectrumApiProvider(service); + final provider = ElectrumProvider(service); /// spender details /// Define another private key from wif @@ -26,8 +26,9 @@ void main() async { const network = BitcoinNetwork.testnet; /// Reads all UTXOs (Unspent Transaction Outputs) associated with the account - final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent( - scriptHash: examplePublicKey2.toAddress().pubKeyHash())); + final elctrumUtxos = await provider.request( + ElectrumRequestScriptHashListUnspent( + scriptHash: examplePublicKey2.toAddress().pubKeyHash())); /// Converts all UTXOs to a list of UtxoWithAddress, containing UTXO information along with address details. /// read spender utxos @@ -100,7 +101,7 @@ void main() async { enableRBF: true); /// get network fee esmtimate (kb/s) - final networkEstimate = await provider.request(ElectrumEstimateFee()); + final networkEstimate = await provider.request(ElectrumRequestEstimateFee()); /// the daemon does not have enough information to make an estimate if (networkEstimate == null) { @@ -149,7 +150,8 @@ void main() async { final raw = transaction.serialize(); /// send to network - await provider.request(ElectrumBroadCastTransaction(transactionRaw: raw)); + await provider + .request(ElectrumRequestBroadCastTransaction(transactionRaw: raw)); /// Once completed, we verify the status by checking the mempool or using another explorer to review the transaction details. /// https://mempool.space/testnet/tx/abab018f3d2b92bf30c63b4aca419cf6d6571692b3620f06311c7e5a21a88b56 diff --git a/example/lib/services_examples/electrum/electrum_ssl_service.dart b/example/lib/services_examples/electrum/electrum_ssl_service.dart index 362c306..048d825 100644 --- a/example/lib/services_examples/electrum/electrum_ssl_service.dart +++ b/example/lib/services_examples/electrum/electrum_ssl_service.dart @@ -4,9 +4,10 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:blockchain_utils/service/models/params.dart'; import 'package:example/services_examples/electrum/request_completer.dart'; -class ElectrumSSLService with BitcoinBaseElectrumRPCService { +class ElectrumSSLService with ElectrumServiceProvider { ElectrumSSLService._( this.url, SecureSocket channel, { @@ -24,7 +25,6 @@ class ElectrumSSLService with BitcoinBaseElectrumRPCService { bool get isConnected => _isDiscounnect; - @override final String url; void add(List params) { @@ -77,19 +77,18 @@ class ElectrumSSLService with BitcoinBaseElectrumRPCService { } @override - Future> call(ElectrumRequestDetails params, - [Duration? timeout]) async { + Future> doRequest(ElectrumRequestDetails params, + {Duration? timeout}) async { final AsyncRequestCompleter compeleter = AsyncRequestCompleter(params.params); - try { - requests[params.id] = compeleter; + requests[params.requestID] = compeleter; add(params.toTCPParams()); final result = await compeleter.completer.future .timeout(timeout ?? defaultRequestTimeOut); - return result; + return params.toResponse(result); } finally { - requests.remove(params.id); + requests.remove(params.requestID); } } } diff --git a/example/lib/services_examples/electrum/electrum_tcp_service.dart b/example/lib/services_examples/electrum/electrum_tcp_service.dart index 750aad0..570665a 100644 --- a/example/lib/services_examples/electrum/electrum_tcp_service.dart +++ b/example/lib/services_examples/electrum/electrum_tcp_service.dart @@ -4,9 +4,10 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:blockchain_utils/service/models/params.dart'; import 'package:example/services_examples/electrum/request_completer.dart'; -class ElectrumTCPService with BitcoinBaseElectrumRPCService { +class ElectrumTCPService with ElectrumServiceProvider { ElectrumTCPService._( this.url, Socket channel, { @@ -24,7 +25,6 @@ class ElectrumTCPService with BitcoinBaseElectrumRPCService { bool get isConnected => _isDiscounnect; - @override final String url; void add(List params) { @@ -74,19 +74,18 @@ class ElectrumTCPService with BitcoinBaseElectrumRPCService { } @override - Future> call(ElectrumRequestDetails params, - [Duration? timeout]) async { + Future> doRequest(ElectrumRequestDetails params, + {Duration? timeout}) async { final AsyncRequestCompleter compeleter = AsyncRequestCompleter(params.params); - try { - requests[params.id] = compeleter; - add(params.toWebSocketParams()); + requests[params.requestID] = compeleter; + add(params.toTCPParams()); final result = await compeleter.completer.future .timeout(timeout ?? defaultRequestTimeOut); - return result; + return params.toResponse(result); } finally { - requests.remove(params.id); + requests.remove(params.requestID); } } } diff --git a/example/lib/services_examples/electrum/electrum_websocket_service.dart b/example/lib/services_examples/electrum/electrum_websocket_service.dart index 6ca10a2..341f1a6 100644 --- a/example/lib/services_examples/electrum/electrum_websocket_service.dart +++ b/example/lib/services_examples/electrum/electrum_websocket_service.dart @@ -2,10 +2,11 @@ import 'dart:async'; import 'dart:convert'; import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:blockchain_utils/service/models/params.dart'; import 'package:example/services_examples/cross_platform_websocket/core.dart'; import 'package:example/services_examples/electrum/request_completer.dart'; -class ElectrumWebSocketService with BitcoinBaseElectrumRPCService { +class ElectrumWebSocketService with ElectrumServiceProvider { ElectrumWebSocketService._( this.url, WebSocketCore channel, { @@ -24,7 +25,6 @@ class ElectrumWebSocketService with BitcoinBaseElectrumRPCService { bool get isConnected => _isDiscounnect; - @override final String url; void add(List params) { @@ -73,19 +73,18 @@ class ElectrumWebSocketService with BitcoinBaseElectrumRPCService { } @override - Future> call(ElectrumRequestDetails params, - [Duration? timeout]) async { + Future> doRequest(ElectrumRequestDetails params, + {Duration? timeout}) async { final AsyncRequestCompleter compeleter = AsyncRequestCompleter(params.params); - try { - requests[params.id] = compeleter; + requests[params.requestID] = compeleter; add(params.toWebSocketParams()); final result = await compeleter.completer.future .timeout(timeout ?? defaultRequestTimeOut); - return result; + return params.toResponse(result); } finally { - requests.remove(params.id); + requests.remove(params.requestID); } } } diff --git a/example/pubspec.lock b/example/pubspec.lock index 1ebf47f..e317342 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -15,15 +15,15 @@ packages: path: ".." relative: true source: path - version: "4.9.4" + version: "5.0.0" blockchain_utils: dependency: "direct main" description: name: blockchain_utils - sha256: "1e4f30b98d92f7ccf2eda009a23b53871a1c9b8b6dfa00bb1eb17ec00ae5eeeb" + sha256: d25cf2ebfa340c5261e77bc0b960f97529c283160d1b9b4f63f3015816369d9f url: "https://pub.dev" source: hosted - version: "3.6.0" + version: "4.0.0" boolean_selector: dependency: transitive description: @@ -52,10 +52,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" cupertino_icons: dependency: "direct main" description: @@ -110,18 +110,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.7" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.8" leak_tracker_testing: dependency: transitive description: @@ -174,7 +174,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -187,10 +187,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -203,10 +203,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" term_glyph: dependency: transitive description: @@ -219,10 +219,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.3" typed_data: dependency: transitive description: @@ -243,10 +243,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "14.3.0" web: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 0997c19..c07a9b7 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -38,8 +38,8 @@ dependencies: bitcoin_base: path: ../ # blockchain_utils: - # path: ../../blockchain_utils - blockchain_utils: ^3.6.0 + # path: ../../../blockchain_utils + blockchain_utils: ^4.0.0 http: ^1.2.0 dev_dependencies: diff --git a/example/test/test_test.dart b/example/test/test_test.dart new file mode 100644 index 0000000..ab73b3a --- /dev/null +++ b/example/test/test_test.dart @@ -0,0 +1 @@ +void main() {} diff --git a/lib/bitcoin_base.dart b/lib/bitcoin_base.dart index ef45ef4..e908780 100644 --- a/lib/bitcoin_base.dart +++ b/lib/bitcoin_base.dart @@ -4,20 +4,22 @@ /// including spending transactions, Bitcoin address management, /// Bitcoin Schnorr signatures, BIP-39 mnemonic phrase generation, /// hierarchical deterministic (HD) wallet derivation, and Web3 Secret Storage Definition. -library bitcoin_base; +library; -export 'package:bitcoin_base/src/bitcoin/address/address.dart'; +export 'src/bitcoin/address/address.dart'; -export 'package:bitcoin_base/src/bitcoin/script/scripts.dart'; +export 'src/bitcoin/script/scripts.dart'; -export 'package:bitcoin_base/src/crypto/crypto.dart'; +export 'src/crypto/crypto.dart'; -export 'package:bitcoin_base/src/models/network.dart'; +export 'src/models/network.dart'; -export 'package:bitcoin_base/src/provider/api_provider.dart'; +export 'src/provider/api_provider.dart'; -export 'package:bitcoin_base/src/utils/btc_utils.dart'; +export 'src/utils/btc_utils.dart'; -export 'package:bitcoin_base/src/cash_token/cash_token.dart'; +export 'src/cash_token/cash_token.dart'; -export 'package:bitcoin_base/src/bitcoin_cash/bitcoin_cash.dart'; +export 'src/bitcoin_cash/bitcoin_cash.dart'; + +export 'src/transaction_builder/builder.dart'; diff --git a/lib/src/bitcoin/address/address.dart b/lib/src/bitcoin/address/address.dart index 45ee9fe..f878515 100644 --- a/lib/src/bitcoin/address/address.dart +++ b/lib/src/bitcoin/address/address.dart @@ -6,7 +6,7 @@ // - Utility functions for address manipulation. // - encode/decode Segregated Witness (SegWit) address implementation. // - Enhanced functionality for improved handling of addresses across diverse networks. -library address; +library; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_base/src/exception/exception.dart'; diff --git a/lib/src/bitcoin/address/core.dart b/lib/src/bitcoin/address/core.dart index 1ec79cc..00517f4 100644 --- a/lib/src/bitcoin/address/core.dart +++ b/lib/src/bitcoin/address/core.dart @@ -38,15 +38,15 @@ abstract class BitcoinAddressType implements Enumerate { ]; T cast() { if (this is! T) { - throw DartBitcoinPluginException("BitcoinAddressType casting failed.", - details: {"excepted": "$T", "type": value}); + throw DartBitcoinPluginException('BitcoinAddressType casting failed.', + details: {'excepted': '$T', 'type': value}); } return this as T; } @override String toString() { - return "BitcoinAddressType.$value"; + return 'BitcoinAddressType.$value'; } } @@ -59,8 +59,8 @@ abstract class BitcoinBaseAddress { } class PubKeyAddressType extends BitcoinAddressType { - const PubKeyAddressType._(String value) : super._(value); - static const PubKeyAddressType p2pk = PubKeyAddressType._("P2PK"); + const PubKeyAddressType._(super.value) : super._(); + static const PubKeyAddressType p2pk = PubKeyAddressType._('P2PK'); @override bool get isP2sh => false; @override @@ -70,14 +70,14 @@ class PubKeyAddressType extends BitcoinAddressType { int get hashLength => 20; @override String toString() { - return "PubKeyAddressType.$value"; + return 'PubKeyAddressType.$value'; } } class P2pkhAddressType extends BitcoinAddressType { - const P2pkhAddressType._(String value) : super._(value); - static const P2pkhAddressType p2pkh = P2pkhAddressType._("P2PKH"); - static const P2pkhAddressType p2pkhwt = P2pkhAddressType._("P2PKHWT"); + const P2pkhAddressType._(super.value) : super._(); + static const P2pkhAddressType p2pkh = P2pkhAddressType._('P2PKH'); + static const P2pkhAddressType p2pkhwt = P2pkhAddressType._('P2PKHWT'); @override bool get isP2sh => false; @@ -88,21 +88,21 @@ class P2pkhAddressType extends BitcoinAddressType { int get hashLength => 20; @override String toString() { - return "P2pkhAddressType.$value"; + return 'P2pkhAddressType.$value'; } } class P2shAddressType extends BitcoinAddressType { - const P2shAddressType._(String value, this.hashLength, this.withToken) - : super._(value); + const P2shAddressType._(super.value, this.hashLength, this.withToken) + : super._(); static const P2shAddressType p2wshInP2sh = P2shAddressType._( - "P2SH/P2WSH", _BitcoinAddressUtils.hash160DigestLength, false); + 'P2SH/P2WSH', _BitcoinAddressUtils.hash160DigestLength, false); static const P2shAddressType p2wpkhInP2sh = P2shAddressType._( - "P2SH/P2WPKH", _BitcoinAddressUtils.hash160DigestLength, false); + 'P2SH/P2WPKH', _BitcoinAddressUtils.hash160DigestLength, false); static const P2shAddressType p2pkhInP2sh = P2shAddressType._( - "P2SH/P2PKH", _BitcoinAddressUtils.hash160DigestLength, false); + 'P2SH/P2PKH', _BitcoinAddressUtils.hash160DigestLength, false); static const P2shAddressType p2pkInP2sh = P2shAddressType._( - "P2SH/P2PK", _BitcoinAddressUtils.hash160DigestLength, false); + 'P2SH/P2PK', _BitcoinAddressUtils.hash160DigestLength, false); @override bool get isP2sh => true; @override @@ -115,38 +115,38 @@ class P2shAddressType extends BitcoinAddressType { /// specify BCH NETWORK for now! /// Pay-to-Script-Hash-32 static const P2shAddressType p2pkhInP2sh32 = P2shAddressType._( - "P2SH32/P2PKH", _BitcoinAddressUtils.scriptHashLenght, false); + 'P2SH32/P2PKH', _BitcoinAddressUtils.scriptHashLenght, false); //// Pay-to-Script-Hash-32 static const P2shAddressType p2pkInP2sh32 = P2shAddressType._( - "P2SH32/P2PK", _BitcoinAddressUtils.scriptHashLenght, false); + 'P2SH32/P2PK', _BitcoinAddressUtils.scriptHashLenght, false); /// Pay-to-Script-Hash-32-with-token static const P2shAddressType p2pkhInP2sh32wt = P2shAddressType._( - "P2SH32WT/P2PKH", _BitcoinAddressUtils.scriptHashLenght, true); + 'P2SH32WT/P2PKH', _BitcoinAddressUtils.scriptHashLenght, true); /// Pay-to-Script-Hash-32-with-token static const P2shAddressType p2pkInP2sh32wt = P2shAddressType._( - "P2SH32WT/P2PK", _BitcoinAddressUtils.scriptHashLenght, true); + 'P2SH32WT/P2PK', _BitcoinAddressUtils.scriptHashLenght, true); /// Pay-to-Script-Hash-with-token static const P2shAddressType p2pkhInP2shwt = P2shAddressType._( - "P2SHWT/P2PKH", _BitcoinAddressUtils.hash160DigestLength, true); + 'P2SHWT/P2PKH', _BitcoinAddressUtils.hash160DigestLength, true); /// Pay-to-Script-Hash-with-token static const P2shAddressType p2pkInP2shwt = P2shAddressType._( - "P2SHWT/P2PK", _BitcoinAddressUtils.hash160DigestLength, true); + 'P2SHWT/P2PK', _BitcoinAddressUtils.hash160DigestLength, true); @override String toString() { - return "P2shAddressType.$value"; + return 'P2shAddressType.$value'; } } class SegwitAddressType extends BitcoinAddressType { - const SegwitAddressType._(String value) : super._(value); - static const SegwitAddressType p2wpkh = SegwitAddressType._("P2WPKH"); - static const SegwitAddressType p2tr = SegwitAddressType._("P2TR"); - static const SegwitAddressType p2wsh = SegwitAddressType._("P2WSH"); + const SegwitAddressType._(super.value) : super._(); + static const SegwitAddressType p2wpkh = SegwitAddressType._('P2WPKH'); + static const SegwitAddressType p2tr = SegwitAddressType._('P2TR'); + static const SegwitAddressType p2wsh = SegwitAddressType._('P2WSH'); @override bool get isP2sh => false; @override @@ -164,6 +164,6 @@ class SegwitAddressType extends BitcoinAddressType { @override String toString() { - return "SegwitAddressType.$value"; + return 'SegwitAddressType.$value'; } } diff --git a/lib/src/bitcoin/address/legacy_address.dart b/lib/src/bitcoin/address/legacy_address.dart index 30b1445..0b0202e 100644 --- a/lib/src/bitcoin/address/legacy_address.dart +++ b/lib/src/bitcoin/address/legacy_address.dart @@ -15,7 +15,7 @@ abstract class LegacyAddress implements BitcoinBaseAddress { address: address, type: type, network: network); if (decode == null) { throw DartBitcoinPluginException( - "Invalid ${network.conf.coinName} address"); + 'Invalid ${network.conf.coinName} address'); } _addressProgram = decode; } @@ -45,14 +45,14 @@ abstract class LegacyAddress implements BitcoinBaseAddress { class P2shAddress extends LegacyAddress { P2shAddress.fromScript( - {required Script script, this.type = P2shAddressType.p2pkInP2sh}) - : super.fromScript(script: script); + {required super.script, this.type = P2shAddressType.p2pkInP2sh}) + : super.fromScript(); P2shAddress.fromAddress( - {required String address, - required BasedUtxoNetwork network, + {required super.address, + required super.network, this.type = P2shAddressType.p2pkInP2sh}) - : super.fromAddress(address: address, network: network); + : super.fromAddress(); P2shAddress.fromHash160( {required String addrHash, this.type = P2shAddressType.p2pkInP2sh}) : super.fromHash160(addrHash, type); @@ -64,7 +64,7 @@ class P2shAddress extends LegacyAddress { String toAddress(BasedUtxoNetwork network) { if (!network.supportedAddress.contains(type)) { throw DartBitcoinPluginException( - "network does not support ${type.value} address"); + 'network does not support ${type.value} address'); } return super.toAddress(network); } @@ -81,13 +81,13 @@ class P2shAddress extends LegacyAddress { class P2pkhAddress extends LegacyAddress { P2pkhAddress.fromScript( - {required Script script, this.type = P2pkhAddressType.p2pkh}) - : super.fromScript(script: script); + {required super.script, this.type = P2pkhAddressType.p2pkh}) + : super.fromScript(); P2pkhAddress.fromAddress( - {required String address, - required BasedUtxoNetwork network, + {required super.address, + required super.network, this.type = P2pkhAddressType.p2pkh}) - : super.fromAddress(address: address, network: network); + : super.fromAddress(); P2pkhAddress.fromHash160( {required String addrHash, this.type = P2pkhAddressType.p2pkh}) : super.fromHash160(addrHash, type); @@ -111,7 +111,7 @@ class P2pkAddress extends LegacyAddress { P2pkAddress({required String publicKey}) : super._() { final toBytes = BytesUtils.fromHexString(publicKey); if (!Secp256k1PublicKeyEcdsa.isValidBytes(toBytes)) { - throw const DartBitcoinPluginException("Invalid secp256k1 public key"); + throw const DartBitcoinPluginException('Invalid secp256k1 public key'); } publicHex = publicKey; } diff --git a/lib/src/bitcoin/address/network_address.dart b/lib/src/bitcoin/address/network_address.dart index 56132e2..62770b4 100644 --- a/lib/src/bitcoin/address/network_address.dart +++ b/lib/src/bitcoin/address/network_address.dart @@ -108,7 +108,7 @@ class BitcoinCashAddress extends BitcoinNetworkAddress { address, network, validateNetworkHRP: validateNetworkPrefix); if (decodeAddress == null) { - throw DartBitcoinPluginException("Invalid ${network.value} address."); + throw DartBitcoinPluginException('Invalid ${network.value} address.'); } return BitcoinCashAddress._(decodeAddress, address, network); } diff --git a/lib/src/bitcoin/address/segwit_address.dart b/lib/src/bitcoin/address/segwit_address.dart index 5ecaf2f..2e3e8c1 100644 --- a/lib/src/bitcoin/address/segwit_address.dart +++ b/lib/src/bitcoin/address/segwit_address.dart @@ -7,7 +7,7 @@ abstract class SegwitAddress implements BitcoinBaseAddress { required this.segwitVersion}) { if (!network.supportedAddress.contains(type)) { throw DartBitcoinPluginException( - "network does not support ${type.value} address"); + 'network does not support ${type.value} address'); } addressProgram = _BitcoinAddressUtils.toSegwitProgramWithVersionAndNetwork( address: address, version: segwitVersion, network: network); @@ -31,7 +31,7 @@ abstract class SegwitAddress implements BitcoinBaseAddress { String toAddress(BasedUtxoNetwork network) { if (!network.supportedAddress.contains(type)) { throw DartBitcoinPluginException( - "network does not support ${type.value} address"); + 'network does not support ${type.value} address'); } return _BitcoinAddressUtils.segwitToAddress( addressProgram: addressProgram, @@ -46,21 +46,15 @@ abstract class SegwitAddress implements BitcoinBaseAddress { } class P2wpkhAddress extends SegwitAddress { - P2wpkhAddress.fromAddress( - {required String address, required BasedUtxoNetwork network}) - : super.fromAddress( - segwitVersion: _BitcoinAddressUtils.segwitV0, - address: address, - network: network); + P2wpkhAddress.fromAddress({required super.address, required super.network}) + : super.fromAddress(segwitVersion: _BitcoinAddressUtils.segwitV0); - P2wpkhAddress.fromProgram({required String program}) + P2wpkhAddress.fromProgram({required super.program}) : super.fromProgram( segwitVersion: _BitcoinAddressUtils.segwitV0, - addresType: SegwitAddressType.p2wpkh, - program: program); - P2wpkhAddress.fromScript({required Script script}) - : super.fromScript( - segwitVersion: _BitcoinAddressUtils.segwitV0, script: script); + addresType: SegwitAddressType.p2wpkh); + P2wpkhAddress.fromScript({required super.script}) + : super.fromScript(segwitVersion: _BitcoinAddressUtils.segwitV0); /// returns the scriptPubKey of a P2WPKH witness script @override @@ -74,20 +68,14 @@ class P2wpkhAddress extends SegwitAddress { } class P2trAddress extends SegwitAddress { - P2trAddress.fromAddress( - {required String address, required BasedUtxoNetwork network}) - : super.fromAddress( - segwitVersion: _BitcoinAddressUtils.segwitV1, - address: address, - network: network); - P2trAddress.fromProgram({required String program}) + P2trAddress.fromAddress({required super.address, required super.network}) + : super.fromAddress(segwitVersion: _BitcoinAddressUtils.segwitV1); + P2trAddress.fromProgram({required super.program}) : super.fromProgram( segwitVersion: _BitcoinAddressUtils.segwitV1, - addresType: SegwitAddressType.p2tr, - program: program); - P2trAddress.fromScript({required Script script}) - : super.fromScript( - segwitVersion: _BitcoinAddressUtils.segwitV1, script: script); + addresType: SegwitAddressType.p2tr); + P2trAddress.fromScript({required super.script}) + : super.fromScript(segwitVersion: _BitcoinAddressUtils.segwitV1); /// returns the scriptPubKey of a P2TR witness script @override @@ -101,20 +89,14 @@ class P2trAddress extends SegwitAddress { } class P2wshAddress extends SegwitAddress { - P2wshAddress.fromAddress( - {required String address, required BasedUtxoNetwork network}) - : super.fromAddress( - segwitVersion: _BitcoinAddressUtils.segwitV0, - address: address, - network: network); - P2wshAddress.fromProgram({required String program}) + P2wshAddress.fromAddress({required super.address, required super.network}) + : super.fromAddress(segwitVersion: _BitcoinAddressUtils.segwitV0); + P2wshAddress.fromProgram({required super.program}) : super.fromProgram( segwitVersion: _BitcoinAddressUtils.segwitV0, - addresType: SegwitAddressType.p2wsh, - program: program); - P2wshAddress.fromScript({required Script script}) - : super.fromScript( - segwitVersion: _BitcoinAddressUtils.segwitV0, script: script); + addresType: SegwitAddressType.p2wsh); + P2wshAddress.fromScript({required super.script}) + : super.fromScript(segwitVersion: _BitcoinAddressUtils.segwitV0); /// Returns the scriptPubKey of a P2WPKH witness script @override diff --git a/lib/src/bitcoin/address/utils/address_utils.dart b/lib/src/bitcoin/address/utils/address_utils.dart index 9463f32..22538bf 100644 --- a/lib/src/bitcoin/address/utils/address_utils.dart +++ b/lib/src/bitcoin/address/utils/address_utils.dart @@ -25,7 +25,7 @@ class _BitcoinAddressUtils { final decode = List.unmodifiable(Base58Decoder.decode(address)); /// Extract script bytes excluding version and checksum. - final List scriptBytes = + final scriptBytes = decode.sublist(1, decode.length - Base58Const.checksumByteLen); /// Ensure the script bytes have the expected length. @@ -34,14 +34,14 @@ class _BitcoinAddressUtils { } /// Extract version, data, and checksum. - final List version = [decode[0]]; - final List data = + final version = [decode[0]]; + final data = decode.sublist(0, decode.length - Base58Const.checksumByteLen); - final List checksum = + final checksum = decode.sublist(decode.length - Base58Const.checksumByteLen); /// Verify the checksum. - final List hash = QuickCrypto.sha256DoubleHash(data) + final hash = QuickCrypto.sha256DoubleHash(data) .sublist(0, Base58Const.checksumByteLen); if (!BytesUtils.bytesEqual(checksum, hash)) { return null; @@ -89,7 +89,7 @@ class _BitcoinAddressUtils { final convert = SegwitBech32Decoder.decode(network.p2wpkhHrp, address); final witnessVersion = convert.item1; if (witnessVersion != version) { - throw const DartBitcoinPluginException("Invalid segwit version"); + throw const DartBitcoinPluginException('Invalid segwit version'); } return BytesUtils.toHexString(convert.item2); } @@ -138,7 +138,7 @@ class _BitcoinAddressUtils { return address; } throw DartBitcoinPluginException( - "${network.value} does not support ${address.type.value} address"); + '${network.value} does not support ${address.type.value} address'); } /// Decodes a Bitcoin address and returns a corresponding BitcoinBaseAddress instance @@ -158,7 +158,7 @@ class _BitcoinAddressUtils { } baseAddress ??= toLegacy(address, network); if (baseAddress == null) { - throw const DartBitcoinPluginException("Invalid Bitcoin address"); + throw const DartBitcoinPluginException('Invalid Bitcoin address'); } return validateAddress(baseAddress, network); } @@ -181,7 +181,7 @@ class _BitcoinAddressUtils { // ignore: empty_catches } catch (e) {} throw const DartBitcoinPluginException( - "Invalid Bitcoin address program length (program length should be 32 or 20 bytes)"); + 'Invalid Bitcoin address program length (program length should be 32 or 20 bytes)'); } /// Decodes a Bitcoin Cash (BCH) address and returns a corresponding LegacyAddress instance @@ -197,9 +197,9 @@ class _BitcoinAddressUtils { String address, BitcoinCashNetwork network, {bool validateNetworkHRP = false}) { try { - final String hrp = validateNetworkHRP + final hrp = validateNetworkHRP ? network.networkHRP - : address.substring(0, address.indexOf(":")); + : address.substring(0, address.indexOf(':')); final decode = BchBech32Decoder.decode(hrp, address); final scriptBytes = decode.item2; final version = decode.item1; @@ -277,7 +277,7 @@ class _BitcoinAddressUtils { required BasedUtxoNetwork network}) { if (!network.supportedAddress.contains(type)) { throw DartBitcoinPluginException( - "${network.value} does not support ${type.value} address type"); + '${network.value} does not support ${type.value} address type'); } if (network is BitcoinCashNetwork) { final decode = _BitcoinAddressUtils.decodeBchAddress(address, network); @@ -292,7 +292,7 @@ class _BitcoinAddressUtils { if (decode == null) return null; final version = decode.item2; final addrBytes = decode.item1; - final String scriptHex = BytesUtils.toHexString(addrBytes); + final scriptHex = BytesUtils.toHexString(addrBytes); switch (type) { case P2pkhAddressType.p2pkh: @@ -351,8 +351,8 @@ class _BitcoinAddressUtils { {required BitcoinCashNetwork network, required String addressProgram, required BitcoinAddressType type}) { - final List programBytes = BytesUtils.fromHexString(addressProgram); - final List netVersion = _getBchNetVersion( + final programBytes = BytesUtils.fromHexString(addressProgram); + final netVersion = _getBchNetVersion( network: network, type: type, secriptLength: programBytes.length); return BchBech32Encoder.encode( @@ -370,7 +370,7 @@ class _BitcoinAddressUtils { {required BitcoinCashNetwork network, required BitcoinAddressType type, int secriptLength = hash160DigestLength}) { - final bool isToken = type.value.contains("WT"); + final isToken = type.value.contains('WT'); if (!type.isP2sh) { if (!isToken) return network.p2pkhNetVer; return network.p2pkhWtNetVer; @@ -406,7 +406,7 @@ class _BitcoinAddressUtils { return legacyToBchAddress( addressProgram: addressProgram, network: network, type: type); } - List programBytes = BytesUtils.fromHexString(addressProgram); + var programBytes = BytesUtils.fromHexString(addressProgram); switch (type) { case P2shAddressType.p2wpkhInP2sh: case P2shAddressType.p2wshInP2sh: @@ -431,7 +431,7 @@ class _BitcoinAddressUtils { /// Returns the RIPEMD-160 hash of the public key as a hexadecimal string. static String pubkeyToHash160(String publicKey) { final bytes = BytesUtils.fromHexString(publicKey); - final List ripemd160Hash = QuickCrypto.hash160(bytes); + final ripemd160Hash = QuickCrypto.hash160(bytes); return BytesUtils.toHexString(ripemd160Hash); } diff --git a/lib/src/bitcoin/script/control_block.dart b/lib/src/bitcoin/script/control_block.dart index d6a07b2..209e4eb 100644 --- a/lib/src/bitcoin/script/control_block.dart +++ b/lib/src/bitcoin/script/control_block.dart @@ -12,10 +12,10 @@ class ControlBlock { final List? scripts; List toBytes() { - final List version = [BitcoinOpCodeConst.LEAF_VERSION_TAPSCRIPT]; + final version = [BitcoinOpCodeConst.LEAF_VERSION_TAPSCRIPT]; - final List pubKey = BytesUtils.fromHexString(public.toXOnlyHex()); - final List marklePath = scripts ?? []; + final pubKey = BytesUtils.fromHexString(public.toXOnlyHex()); + final marklePath = scripts ?? []; return [...version, ...pubKey, ...marklePath]; } diff --git a/lib/src/bitcoin/script/input.dart b/lib/src/bitcoin/script/input.dart index f1b56da..c5f841b 100644 --- a/lib/src/bitcoin/script/input.dart +++ b/lib/src/bitcoin/script/input.dart @@ -60,17 +60,16 @@ class TxInput { static Tuple deserialize( {required List bytes, int cursor = 0, bool hasSegwit = false}) { - final List inpHash = - bytes.sublist(cursor, cursor + 32).reversed.toList(); + final inpHash = bytes.sublist(cursor, cursor + 32).reversed.toList(); cursor += 32; - final int outputN = IntUtils.fromBytes(bytes.sublist(cursor, cursor + 4), + final outputN = IntUtils.fromBytes(bytes.sublist(cursor, cursor + 4), byteOrder: Endian.little); cursor += 4; final vi = IntUtils.decodeVarint(bytes.sublist(cursor)); cursor += vi.item2; - final List unlockingScript = bytes.sublist(cursor, cursor + vi.item1); + final unlockingScript = bytes.sublist(cursor, cursor + vi.item1); cursor += vi.item1; - final List sequenceNumberData = bytes.sublist(cursor, cursor + 4); + final sequenceNumberData = bytes.sublist(cursor, cursor + 4); cursor += 4; return Tuple( TxInput( @@ -84,15 +83,15 @@ class TxInput { Map toJson() { return { - "txid": txId, - "txIndex": txIndex, - "scriptSig": scriptSig.script, - "sequance": BytesUtils.toHexString(sequence), + 'txid': txId, + 'txIndex': txIndex, + 'scriptSig': scriptSig.script, + 'sequance': BytesUtils.toHexString(sequence), }; } @override String toString() { - return "TxInput{txId: $txId, txIndex: $txIndex, scriptSig: $scriptSig, sequence: ${BytesUtils.toHexString(sequence)}}"; + return 'TxInput{txId: $txId, txIndex: $txIndex, scriptSig: $scriptSig, sequence: ${BytesUtils.toHexString(sequence)}}'; } } diff --git a/lib/src/bitcoin/script/op_code/constant.dart b/lib/src/bitcoin/script/op_code/constant.dart index 4825e66..7091ec1 100644 --- a/lib/src/bitcoin/script/op_code/constant.dart +++ b/lib/src/bitcoin/script/op_code/constant.dart @@ -261,9 +261,9 @@ class BitcoinOpCodeConst { static const int NEGATIVE_SATOSHI = -1; /// Bitcoin address types - static const String P2PKH_ADDRESS = "p2pkh"; - static const String P2SH_ADDRESS = "p2sh"; - static const String P2WPKH_ADDRESS_V0 = "p2wpkhv0"; - static const String P2WSH_ADDRESS_V0 = "p2wshv0"; - static const String P2TR_ADDRESS_V1 = "p2trv1"; + static const String P2PKH_ADDRESS = 'p2pkh'; + static const String P2SH_ADDRESS = 'p2sh'; + static const String P2WPKH_ADDRESS_V0 = 'p2wpkhv0'; + static const String P2WSH_ADDRESS_V0 = 'p2wshv0'; + static const String P2TR_ADDRESS_V1 = 'p2trv1'; } diff --git a/lib/src/bitcoin/script/op_code/constant_lib.dart b/lib/src/bitcoin/script/op_code/constant_lib.dart index a304302..e6c4f56 100644 --- a/lib/src/bitcoin/script/op_code/constant_lib.dart +++ b/lib/src/bitcoin/script/op_code/constant_lib.dart @@ -1,4 +1,4 @@ -library op_code; +library; export 'constant.dart'; export 'tools.dart'; diff --git a/lib/src/bitcoin/script/op_code/tools.dart b/lib/src/bitcoin/script/op_code/tools.dart index a68492a..1dafe7b 100644 --- a/lib/src/bitcoin/script/op_code/tools.dart +++ b/lib/src/bitcoin/script/op_code/tools.dart @@ -5,7 +5,7 @@ import 'package:bitcoin_base/src/exception/exception.dart'; import 'package:blockchain_utils/utils/utils.dart'; List opPushData(String hexData) { - final List dataBytes = BytesUtils.fromHexString(hexData); + final dataBytes = BytesUtils.fromHexString(hexData); if (dataBytes.length < BitcoinOpCodeConst.opPushData1) { return [dataBytes.length, ...dataBytes]; } else if (dataBytes.length < mask8) { @@ -20,7 +20,7 @@ List opPushData(String hexData) { return [BitcoinOpCodeConst.opPushData4, ...lengthBytes, ...dataBytes]; } else { throw const DartBitcoinPluginException( - "Data too large. Cannot push into script"); + 'Data too large. Cannot push into script'); } } @@ -31,11 +31,11 @@ List pushInteger(int integer) { } /// Calculate the number of bytes required to represent the integer - final int numberOfBytes = (integer.bitLength + 7) ~/ 8; + final numberOfBytes = (integer.bitLength + 7) ~/ 8; /// Convert to little-endian bytes - List integerBytes = List.filled(numberOfBytes, 0); - for (int i = 0; i < numberOfBytes; i++) { + var integerBytes = List.filled(numberOfBytes, 0); + for (var i = 0; i < numberOfBytes; i++) { integerBytes[i] = (integer >> (i * 8)) & mask8; } diff --git a/lib/src/bitcoin/script/output.dart b/lib/src/bitcoin/script/output.dart index 61bca22..555d062 100644 --- a/lib/src/bitcoin/script/output.dart +++ b/lib/src/bitcoin/script/output.dart @@ -16,9 +16,9 @@ class TxOutput { Map toJson() { return { - "cashToken": cashToken?.toJson(), - "amount": amount.toString(), - "scriptPubKey": scriptPubKey.script + 'cashToken': cashToken?.toJson(), + 'amount': amount.toString(), + 'scriptPubKey': scriptPubKey.script }; } @@ -33,7 +33,7 @@ class TxOutput { List toBytes() { final amountBytes = BigintUtils.toBytes(amount, length: 8, order: Endian.little); - final List scriptBytes = [ + final scriptBytes = [ ...cashToken?.toBytes() ?? [], ...scriptPubKey.toBytes() ]; @@ -56,8 +56,7 @@ class TxOutput { cursor += vi.item2; final token = CashToken.fromRaw(bytes.sublist(cursor)); - final List lockScript = - bytes.sublist(cursor + token.item2, cursor + vi.item1); + final lockScript = bytes.sublist(cursor + token.item2, cursor + vi.item1); cursor += vi.item1; return Tuple( TxOutput( @@ -70,6 +69,6 @@ class TxOutput { @override String toString() { - return "TxOutput{cashToken: ${cashToken?.toString()}}, amount: $amount, script: ${scriptPubKey.toString()}}"; + return 'TxOutput{cashToken: ${cashToken?.toString()}}, amount: $amount, script: ${scriptPubKey.toString()}}'; } } diff --git a/lib/src/bitcoin/script/script.dart b/lib/src/bitcoin/script/script.dart index 96c57c7..04d08d5 100644 --- a/lib/src/bitcoin/script/script.dart +++ b/lib/src/bitcoin/script/script.dart @@ -12,17 +12,17 @@ class Script { } return true; }(), - "A valid script is a composition of opcodes, hexadecimal strings, and integers arranged in a structured list."), + 'A valid script is a composition of opcodes, hexadecimal strings, and integers arranged in a structured list.'), script = List.unmodifiable(script); final List script; static Script deserialize( {required List bytes, bool hasSegwit = false}) { - final List commands = []; - int index = 0; + final commands = []; + var index = 0; // final scriptBytes = BytesUtils.fromHexString(hexData); while (index < bytes.length) { - final int byte = bytes[index]; + final byte = bytes[index]; if (BitcoinOpCodeConst.CODE_OPS.containsKey(byte)) { if (!BitcoinOpCodeConst.isOpPushData(byte)) { commands.add(BitcoinOpCodeConst.CODE_OPS[byte]!); @@ -32,7 +32,7 @@ class Script { index = index + 1; if (byte == BitcoinOpCodeConst.opPushData1) { // get len - final int bytesToRead = bytes[index]; + final bytesToRead = bytes[index]; // skip len index = index + 1; commands.add(BytesUtils.toHexString( @@ -42,13 +42,13 @@ class Script { index = index + bytesToRead; } else if (byte == BitcoinOpCodeConst.opPushData2) { /// get len - final int bytesToRead = readUint16LE(bytes, index); + final bytesToRead = readUint16LE(bytes, index); index = index + 2; commands.add(BytesUtils.toHexString( bytes.sublist(index, index + bytesToRead))); index = index + bytesToRead; } else if (byte == BitcoinOpCodeConst.opPushData4) { - final int bytesToRead = readUint32LE(bytes, index); + final bytesToRead = readUint32LE(bytes, index); index = index + 4; commands.add(BytesUtils.toHexString( @@ -57,8 +57,8 @@ class Script { } } else { final viAndSize = IntUtils.decodeVarint(bytes.sublist(index)); - final int dataSize = viAndSize.item1; - final int size = viAndSize.item2; + final dataSize = viAndSize.item1; + final size = viAndSize.item2; final lastIndex = (index + size + dataSize) > bytes.length ? bytes.length : (index + size + dataSize); @@ -72,7 +72,7 @@ class Script { List toBytes() { if (script.isEmpty) return []; - final DynamicByteTracker scriptBytes = DynamicByteTracker(); + final scriptBytes = DynamicByteTracker(); for (final token in script) { if (BitcoinOpCodeConst.OP_CODES.containsKey(token)) { scriptBytes.add(BitcoinOpCodeConst.OP_CODES[token]!); diff --git a/lib/src/bitcoin/script/sequence.dart b/lib/src/bitcoin/script/sequence.dart index 920212f..e4cfd0f 100644 --- a/lib/src/bitcoin/script/sequence.dart +++ b/lib/src/bitcoin/script/sequence.dart @@ -31,7 +31,7 @@ class Sequence { return List.from(BitcoinOpCodeConst.REPLACE_BY_FEE_SEQUENCE); } if (seqType == BitcoinOpCodeConst.TYPE_RELATIVE_TIMELOCK) { - int seq = 0; + var seq = 0; if (!isTypeBlock) { seq |= 1 << 22; } @@ -39,16 +39,16 @@ class Sequence { return IntUtils.toBytes(seq, length: 4, byteOrder: Endian.little); } - throw const DartBitcoinPluginException("Invalid seqType"); + throw const DartBitcoinPluginException('Invalid seqType'); } /// Returns the appropriate integer for a script; e.g. for relative timelocks int forScript() { if (seqType == BitcoinOpCodeConst.TYPE_REPLACE_BY_FEE) { throw const DartBitcoinPluginException( - "RBF is not to be included in a script."); + 'RBF is not to be included in a script.'); } - int scriptIntiger = value; + var scriptIntiger = value; if (seqType == BitcoinOpCodeConst.TYPE_RELATIVE_TIMELOCK && !isTypeBlock) { scriptIntiger |= 1 << 22; } @@ -57,6 +57,6 @@ class Sequence { @override String toString() { - return "Sequence{seqType: $seqType, value: $value, isTypeBlock: $isTypeBlock}"; + return 'Sequence{seqType: $seqType, value: $value, isTypeBlock: $isTypeBlock}'; } } diff --git a/lib/src/bitcoin/script/transaction.dart b/lib/src/bitcoin/script/transaction.dart index a7f06a2..c0273a0 100644 --- a/lib/src/bitcoin/script/transaction.dart +++ b/lib/src/bitcoin/script/transaction.dart @@ -70,10 +70,10 @@ class BtcTransaction { /// Instantiates a Transaction from serialized raw hexadacimal data (classmethod) static BtcTransaction fromRaw(String raw) { final rawtx = BytesUtils.fromHexString(raw); - final List version = rawtx.sublist(0, 4); - int cursor = 4; + final version = rawtx.sublist(0, 4); + var cursor = 4; List? flag; - bool hasSegwit = false; + var hasSegwit = false; if (rawtx[4] == 0) { flag = List.from(rawtx.sublist(5, 6)); if (flag[0] == 1) { @@ -83,32 +83,32 @@ class BtcTransaction { } final vi = IntUtils.decodeVarint(rawtx.sublist(cursor)); cursor += vi.item2; - final List inputs = []; - for (int index = 0; index < vi.item1; index++) { + final inputs = []; + for (var index = 0; index < vi.item1; index++) { final inp = TxInput.deserialize( bytes: rawtx, hasSegwit: hasSegwit, cursor: cursor); inputs.add(inp.item1); cursor = inp.item2; } - final List outputs = []; + final outputs = []; final viOut = IntUtils.decodeVarint(rawtx.sublist(cursor)); cursor += viOut.item2; - for (int index = 0; index < viOut.item1; index++) { + for (var index = 0; index < viOut.item1; index++) { final inp = TxOutput.deserialize( bytes: rawtx, hasSegwit: hasSegwit, cursor: cursor); outputs.add(inp.item1); cursor = inp.item2; } - final List witnesses = []; + final witnesses = []; if (hasSegwit) { if (cursor + 4 < rawtx.length) { // in this case the tx contains wintness data. - for (int n = 0; n < inputs.length; n++) { + for (var n = 0; n < inputs.length; n++) { final wVi = IntUtils.decodeVarint(rawtx.sublist(cursor)); cursor += wVi.item2; - final List witnessesTmp = []; - for (int n = 0; n < wVi.item1; n++) { - List witness = []; + final witnessesTmp = []; + for (var n = 0; n < wVi.item1; n++) { + var witness = []; final wtVi = IntUtils.decodeVarint(rawtx.sublist(cursor)); if (wtVi.item1 != 0) { witness = rawtx.sublist( @@ -144,14 +144,14 @@ class BtcTransaction { {required int txInIndex, required Script script, int sighash = BitcoinOpCodeConst.SIGHASH_ALL}) { - BtcTransaction tx = copy(this); + var tx = copy(this); for (final i in tx.inputs) { i.scriptSig = Script(script: []); } tx.inputs[txInIndex].scriptSig = script; if ((sighash & 0x1f) == BitcoinOpCodeConst.SIGHASH_NONE) { tx = tx.copyWith(outputs: []); - for (int i = 0; i < tx.inputs.length; i++) { + for (var i = 0; i < tx.inputs.length; i++) { if (i != txInIndex) { tx.inputs[i].sequence = BitcoinOpCodeConst.EMPTY_TX_SEQUENCE; } @@ -159,17 +159,17 @@ class BtcTransaction { } else if ((sighash & 0x1f) == BitcoinOpCodeConst.SIGHASH_SINGLE) { if (txInIndex >= tx.outputs.length) { throw const DartBitcoinPluginException( - "Transaction index is greater than the available outputs"); + 'Transaction index is greater than the available outputs'); } - final List outputs = []; - for (int i = 0; i < txInIndex; i++) { + final outputs = []; + for (var i = 0; i < txInIndex; i++) { outputs.add(TxOutput( amount: BigInt.from(BitcoinOpCodeConst.NEGATIVE_SATOSHI), scriptPubKey: Script(script: []))); } tx = tx.copyWith(outputs: [...outputs, tx.outputs[txInIndex]]); - for (int i = 0; i < tx.inputs.length; i++) { + for (var i = 0; i < tx.inputs.length; i++) { if (i != txInIndex) { tx.inputs[i].sequence = BitcoinOpCodeConst.EMPTY_TX_SEQUENCE; } @@ -178,7 +178,7 @@ class BtcTransaction { if ((sighash & BitcoinOpCodeConst.SIGHASH_ANYONECANPAY) != 0) { tx = tx.copyWith(inputs: [tx.inputs[txInIndex]]); } - List txForSign = tx.toBytes(segwit: false); + var txForSign = tx.toBytes(segwit: false); txForSign = [ ...txForSign, @@ -189,7 +189,7 @@ class BtcTransaction { /// Serializes Transaction to bytes List toBytes({bool segwit = false}) { - final DynamicByteTracker data = DynamicByteTracker(); + final data = DynamicByteTracker(); data.add(version); if (segwit) { data.add([0x00, 0x01]); @@ -229,19 +229,18 @@ class BtcTransaction { required BigInt amount, CashToken? token}) { final tx = copy(this); - List hashPrevouts = List.filled(32, 0); - List hashSequence = List.filled(32, 0); - List hashOutputs = List.filled(32, 0); - final int basicSigHashType = sighash & 0x1F; - final bool anyoneCanPay = + var hashPrevouts = List.filled(32, 0); + var hashSequence = List.filled(32, 0); + var hashOutputs = List.filled(32, 0); + final basicSigHashType = sighash & 0x1F; + final anyoneCanPay = (sighash & 0xF0) == BitcoinOpCodeConst.SIGHASH_ANYONECANPAY; - final bool signAll = - (basicSigHashType != BitcoinOpCodeConst.SIGHASH_SINGLE) && - (basicSigHashType != BitcoinOpCodeConst.SIGHASH_NONE); + final signAll = (basicSigHashType != BitcoinOpCodeConst.SIGHASH_SINGLE) && + (basicSigHashType != BitcoinOpCodeConst.SIGHASH_NONE); if (!anyoneCanPay) { hashPrevouts = []; for (final txin in tx.inputs) { - final List txidBytes = List.from( + final txidBytes = List.from( BytesUtils.fromHexString(txin.txId).reversed.toList()); hashPrevouts = [ ...hashPrevouts, @@ -268,21 +267,20 @@ class BtcTransaction { } else if (basicSigHashType == BitcoinOpCodeConst.SIGHASH_SINGLE && txInIndex < tx.outputs.length) { final out = tx.outputs[txInIndex]; - final List packedAmount = + final packedAmount = BigintUtils.toBytes(out.amount, length: 8, order: Endian.little); final scriptBytes = IntUtils.prependVarint(out.scriptPubKey.toBytes()); hashOutputs = [...packedAmount, ...scriptBytes]; hashOutputs = QuickCrypto.sha256DoubleHash(hashOutputs); } - final DynamicByteTracker txForSigning = DynamicByteTracker(); + final txForSigning = DynamicByteTracker(); txForSigning.add(version); txForSigning.add(hashPrevouts); txForSigning.add(hashSequence); final txIn = inputs[txInIndex]; - final List txidBytes = - BytesUtils.fromHexString(txIn.txId).reversed.toList(); + final txidBytes = BytesUtils.fromHexString(txIn.txId).reversed.toList(); txForSigning.add([ ...txidBytes, ...IntUtils.toBytes(txIn.txIndex, length: 4, byteOrder: Endian.little) @@ -293,7 +291,7 @@ class BtcTransaction { final varintBytes = IntUtils.prependVarint(script.toBytes()); txForSigning.add(varintBytes); - final List packedAmount = + final packedAmount = BigintUtils.toBytes(amount, length: 8, order: Endian.little); txForSigning.add(packedAmount); txForSigning.add(txIn.sequence); @@ -322,26 +320,23 @@ class BtcTransaction { int leafVar = BitcoinOpCodeConst.LEAF_VERSION_TAPSCRIPT, int sighash = BitcoinOpCodeConst.TAPROOT_SIGHASH_ALL}) { final newTx = copy(this); - final bool sighashNone = - (sighash & 0x03) == BitcoinOpCodeConst.SIGHASH_NONE; - final bool sighashSingle = - (sighash & 0x03) == BitcoinOpCodeConst.SIGHASH_SINGLE; - final bool anyoneCanPay = + final sighashNone = (sighash & 0x03) == BitcoinOpCodeConst.SIGHASH_NONE; + final sighashSingle = (sighash & 0x03) == BitcoinOpCodeConst.SIGHASH_SINGLE; + final anyoneCanPay = (sighash & 0x80) == BitcoinOpCodeConst.SIGHASH_ANYONECANPAY; - final DynamicByteTracker txForSign = DynamicByteTracker(); + final txForSign = DynamicByteTracker(); txForSign.add([0]); txForSign.add([sighash]); txForSign.add(version); txForSign.add(locktime); - List hashPrevouts = []; - List hashAmounts = []; - List hashScriptPubkeys = []; - List hashSequences = []; - List hashOutputs = []; + var hashPrevouts = []; + var hashAmounts = []; + var hashScriptPubkeys = []; + var hashSequences = []; + var hashOutputs = []; if (!anyoneCanPay) { for (final txin in newTx.inputs) { - final List txidBytes = - BytesUtils.fromHexString(txin.txId).reversed.toList(); + final txidBytes = BytesUtils.fromHexString(txin.txId).reversed.toList(); hashPrevouts = [ ...hashPrevouts, ...txidBytes, @@ -373,7 +368,7 @@ class BtcTransaction { } if (!(sighashNone || sighashSingle)) { for (final txOut in newTx.outputs) { - final List packedAmount = + final packedAmount = BigintUtils.toBytes(txOut.amount, length: 8, order: Endian.little); final scriptBytes = IntUtils.prependVarint(txOut.scriptPubKey.toBytes()); @@ -383,7 +378,7 @@ class BtcTransaction { txForSign.add(hashOutputs); } - final int spendType = extFlags * 2 + 0; + final spendType = extFlags * 2 + 0; txForSign.add([spendType]); if (anyoneCanPay) { @@ -418,12 +413,12 @@ class BtcTransaction { leafVar, ...IntUtils.prependVarint(script?.toBytes() ?? []) ]; - txForSign.add(taggedHash(leafVarBytes, "TapLeaf")); + txForSign.add(taggedHash(leafVarBytes, 'TapLeaf')); txForSign.add([0]); txForSign.add(List.filled(4, mask8)); } final bytes = txForSign.toBytes(); - return taggedHash(bytes, "TapSighash"); + return taggedHash(bytes, 'TapSighash'); } /// converts result of to_bytes to hexadecimal string @@ -445,16 +440,16 @@ class BtcTransaction { /// Calculates the tx segwit size int getVSize() { if (!hasSegwit) return getSize(); - const int markerSize = 2; - int witSize = 0; - List data = []; + const markerSize = 2; + var witSize = 0; + var data = []; for (final w in witnesses) { final countBytes = List.from([w.stack.length]); data = List.from([...data, ...countBytes, ...w.toBytes()]); } witSize = data.length; - final int size = getSize() - (markerSize + witSize); - final double vSize = size + (markerSize + witSize) / 4; + final size = getSize() - (markerSize + witSize); + final vSize = size + (markerSize + witSize) / 4; return vSize.ceil(); } @@ -467,11 +462,11 @@ class BtcTransaction { Map toJson() { return { - "inputs": inputs.map((e) => e.toJson()).toList(), - "outputs": outputs.map((e) => e.toJson()).toList(), - "locktime": BytesUtils.toHexString(locktime), - "version": BytesUtils.toHexString(version), - "witnesses": witnesses.map((e) => e.toJson()).toList() + 'inputs': inputs.map((e) => e.toJson()).toList(), + 'outputs': outputs.map((e) => e.toJson()).toList(), + 'locktime': BytesUtils.toHexString(locktime), + 'version': BytesUtils.toHexString(version), + 'witnesses': witnesses.map((e) => e.toJson()).toList() }; } diff --git a/lib/src/bitcoin/script/witness.dart b/lib/src/bitcoin/script/witness.dart index 075726f..47c29c0 100644 --- a/lib/src/bitcoin/script/witness.dart +++ b/lib/src/bitcoin/script/witness.dart @@ -15,11 +15,10 @@ class TxWitnessInput { /// returns a serialized byte version of the witness items list List toBytes() { - List stackBytes = []; + var stackBytes = []; for (final item in stack) { - final List itemBytes = - IntUtils.prependVarint(BytesUtils.fromHexString(item)); + final itemBytes = IntUtils.prependVarint(BytesUtils.fromHexString(item)); stackBytes = [...stackBytes, ...itemBytes]; } @@ -27,7 +26,7 @@ class TxWitnessInput { } Map toJson() { - return {"stack": stack}; + return {'stack': stack}; } @override diff --git a/lib/src/bitcoin_cash/bcmr.dart b/lib/src/bitcoin_cash/bcmr.dart index 58ccc41..9d97032 100644 --- a/lib/src/bitcoin_cash/bcmr.dart +++ b/lib/src/bitcoin_cash/bcmr.dart @@ -4,7 +4,7 @@ import 'package:blockchain_utils/blockchain_utils.dart'; /// Bitcoin Cash Metadata Registries Script to convert uris and content hash to bitcoin output script class BCMR implements BitcoinScriptOutput { /// Bitcoin Cash Metadata Registries PREFIX - static const String _pcmrInHex = "42434d52"; + static const String _pcmrInHex = '42434d52'; BCMR({required this.uris, required this.hash}) : assert( () { @@ -16,8 +16,8 @@ class BCMR implements BitcoinScriptOutput { return true; }(), uris.isEmpty - ? "URIs must not be empty." - : "The BCMR hash should be the SHA-256 hash of the URI contents", + ? 'URIs must not be empty.' + : 'The BCMR hash should be the SHA-256 hash of the URI contents', ); /// list of uris @@ -29,7 +29,7 @@ class BCMR implements BitcoinScriptOutput { /// 'script' property from the interface to define the specific script for Bitcoin Cash Metadata Registries OP_RETURN script. @override Script get script => Script(script: [ - "OP_RETURN", + 'OP_RETURN', _pcmrInHex, hash, ...uris.map((e) => BytesUtils.toHexString(StringUtils.encode(e))) diff --git a/lib/src/bitcoin_cash/bcmr_registery.dart b/lib/src/bitcoin_cash/bcmr_registery.dart index 80b0e1a..3df2009 100644 --- a/lib/src/bitcoin_cash/bcmr_registery.dart +++ b/lib/src/bitcoin_cash/bcmr_registery.dart @@ -314,7 +314,7 @@ class NftCategoryField { const NftCategoryField({required this.identifier}); final Map identifier; factory NftCategoryField.fromJson(Map json) { - final Map parsedIdentifier = {}; + final parsedIdentifier = {}; json.forEach((key, value) { parsedIdentifier[key] = NftCategoryFieldType.fromJson(value); }); @@ -699,26 +699,17 @@ class ChainSnapshot extends IdentitySnapshot { : null, ); } - ChainSnapshot( - {required String name, - required String? description, - required List? tags, - required String? migrated, - required TokenCategory token, - required String? status, - required String? splitId, - required URIs? uris, - required Extensions? extensions}) - : super( - name: name, - description: description, - tags: tags, - migrated: migrated, - token: token, - status: status, - splitId: splitId, - uris: uris, - extensions: extensions); + const ChainSnapshot({ + required super.name, + required TokenCategory super.token, + super.description, + super.tags, + super.migrated, + super.status, + super.splitId, + super.uris, + super.extensions, + }); } class RegistryTimestampKeyedValues { @@ -731,8 +722,7 @@ class RegistryTimestampKeyedValues { } class ChainHistory extends RegistryTimestampKeyedValues { - const ChainHistory({required Map timestampMap}) - : super(timestampMap: timestampMap); + const ChainHistory({required super.timestampMap}); factory ChainHistory.fromJson(Map json) { return ChainHistory( @@ -744,8 +734,7 @@ class ChainHistory extends RegistryTimestampKeyedValues { } class IdentityHistory extends RegistryTimestampKeyedValues { - const IdentityHistory({required Map timestampMap}) - : super(timestampMap: timestampMap); + const IdentityHistory({required super.timestampMap}); factory IdentityHistory.fromJson(Map json) { return IdentityHistory( @@ -988,7 +977,7 @@ class Registry { }); Map toJson() { - final Map js = { + final js = { r'$schema': schema, 'version': version.toJson(), 'latestRevision': latestRevision, @@ -1005,21 +994,21 @@ class Registry { for (final i in identities!.entries) { jsIdentities[i.key] = i.value.toJson(); } - js["identities"] = jsIdentities; + js['identities'] = jsIdentities; } if (chains != null) { final jsChains = {}; for (final i in chains!.entries) { jsChains[i.key] = i.value.toJson(); } - js["chains"] = jsChains; + js['chains'] = jsChains; } if (tags != null) { final jsTags = {}; for (final i in tags!.entries) { jsTags[i.key] = i.value.toJson(); } - js["tags"] = jsTags; + js['tags'] = jsTags; } return js..removeWhere((key, value) => value == null); } diff --git a/lib/src/cash_token/cash_token.dart b/lib/src/cash_token/cash_token.dart index a28eaaf..7a86d9b 100644 --- a/lib/src/cash_token/cash_token.dart +++ b/lib/src/cash_token/cash_token.dart @@ -34,17 +34,17 @@ class CashTokenCapability { /// (NFTs without a capability) cannot have their commitment modified when spent. static const CashTokenCapability noCapability = - CashTokenCapability._(0x00, "none"); + CashTokenCapability._(0x00, 'none'); /// Each Mutable token (NFTs with the mutable capability) allows the spending transaction /// to create one NFT of the same category, with any commitment and (optionally) the mutable capability. static const CashTokenCapability mutable = - CashTokenCapability._(0x01, "mutable"); + CashTokenCapability._(0x01, 'mutable'); /// Minting tokens (NFTs with the minting capability) allow the spending transaction to create any number of new NFTs of the same category, /// each with any commitment and (optionally) the minting or mutable capability. static const CashTokenCapability minting = - CashTokenCapability._(0x02, "minting"); + CashTokenCapability._(0x02, 'minting'); /// static int _getCapability(int bitfield) { @@ -60,11 +60,11 @@ class CashTokenCapability { /// correct capality from bitfield static CashTokenCapability fromBitfield(int bitfield) { try { - final int intCapability = _getCapability(bitfield); + final intCapability = _getCapability(bitfield); return values.firstWhere((element) => element.value == intCapability); } on StateError { throw const DartBitcoinPluginException( - "Invalid CashToken NFT Capability"); + 'Invalid CashToken NFT Capability'); } } @@ -74,7 +74,7 @@ class CashTokenCapability { return values.firstWhere((element) => element.name == name); } on StateError { throw const DartBitcoinPluginException( - "Invalid CashToken NFT Capability Name"); + 'Invalid CashToken NFT Capability Name'); } } @@ -111,20 +111,20 @@ class CashTokenUtils { bool hasAmount = false, bool hasCommitmentLength = false, CashTokenCapability? capability}) { - int capabilityInt = 0; + var capabilityInt = 0; if (hasNFT) { if (capability != null) { // throw const MessageException("Capability is necessary for NFTs."); capabilityInt = capability.value; } } - final int nft = hasNFT ? _hasNFT : 0; - int commitmentLength = 0; + final nft = hasNFT ? _hasNFT : 0; + var commitmentLength = 0; if (hasNFT && hasCommitmentLength) { commitmentLength = hasCommitmentLength ? _hasCommitmentLength : 0; } - final int amount = hasAmount ? _hasAmount : 0; + final amount = hasAmount ? _hasAmount : 0; return nft | commitmentLength | amount | capabilityInt; } @@ -160,8 +160,8 @@ class CashTokenUtils { } static Tuple _decodeVarintBigInt(List byteint) { - final int ni = byteint[0]; - int size = 0; + final ni = byteint[0]; + var size = 0; if (ni < 253) { return Tuple(BigInt.from(ni), 1); @@ -208,7 +208,7 @@ class CashTokenUtils { /// [bitfield]: The bitfield to be validated. /// Returns true if the bitfield is valid, otherwise false. static bool isValidBitfield(int bitfield) { - final int highNibble = bitfield & 0xF0; + final highNibble = bitfield & 0xF0; if (highNibble >= 0x80 || highNibble == 0x00) { return false; } @@ -230,17 +230,17 @@ class CashTokenUtils { class CashToken { factory CashToken.fromJson(Map json) { - final String category = json["category"]; - final BigInt amount = BigintUtils.tryParse(json["amount"]) ?? BigInt.zero; + final String category = json['category']; + final amount = BigintUtils.tryParse(json['amount']) ?? BigInt.zero; CashTokenCapability? capability; List? commitment; - if (json.containsKey("nft")) { - capability = CashTokenCapability.fromName(json["nft"]["capability"]); - commitment = ((json["nft"]["commitment"] ?? "") as String).isEmpty + if (json.containsKey('nft')) { + capability = CashTokenCapability.fromName(json['nft']['capability']); + commitment = ((json['nft']['commitment'] ?? '') as String).isEmpty ? null - : BytesUtils.fromHexString(json["nft"]["commitment"]); + : BytesUtils.fromHexString(json['nft']['commitment']); } - final int bitfield = CashTokenUtils.buildBitfield( + final bitfield = CashTokenUtils.buildBitfield( hasNFT: capability != null, capability: capability ?? CashTokenCapability.noCapability, hasAmount: amount > BigInt.zero, @@ -274,31 +274,31 @@ class CashToken { List? commitment, required int bitfield}) { if (!CashTokenUtils.isValidBitfield(bitfield)) { - throw const DartBitcoinPluginException("Invalid bitfield"); + throw const DartBitcoinPluginException('Invalid bitfield'); } if (CashTokenUtils.hasAmount(bitfield) && amount == null) { throw const DartBitcoinPluginException( - "Invalid cash token: the bitfield indicates an amount, but the amount is null."); + 'Invalid cash token: the bitfield indicates an amount, but the amount is null.'); } if (amount != null) { if (amount < BigInt.zero || amount > CashTokenUtils.maxTokenAmount) { throw const DartBitcoinPluginException( - "Invalid amount. Amount must be between zero and 99."); + 'Invalid amount. Amount must be between zero and 99.'); } } if (!StringUtils.isHexBytes(category)) { throw const DartBitcoinPluginException( - "Invalid category hexadecimal bytes."); + 'Invalid category hexadecimal bytes.'); } final toBytes = BytesUtils.fromHexString(category); if (toBytes.length != CashTokenUtils.idBytesLength) { throw const DartBitcoinPluginException( - "Invalid category. The category should consist of 32 bytes."); + 'Invalid category. The category should consist of 32 bytes.'); } if (CashTokenUtils.hasCommitmentLength(bitfield) && (commitment == null || commitment.isEmpty)) { throw const DartBitcoinPluginException( - "Invalid cash token: the bitfield indicates an commitment, but the commitment is null or empty."); + 'Invalid cash token: the bitfield indicates an commitment, but the commitment is null or empty.'); } return CashToken.noValidate( category: category, @@ -311,14 +311,14 @@ class CashToken { scriptBytes[0] != CashTokenUtils.cashTokenPrefix) { return const Tuple(null, 0); } - int cursor = 1; - final List id = + var cursor = 1; + final id = scriptBytes.sublist(cursor, cursor + CashTokenUtils.idBytesLength); cursor += CashTokenUtils.idBytesLength; - final int bitfield = scriptBytes[cursor]; + final bitfield = scriptBytes[cursor]; cursor += 1; - List commitment = []; + var commitment = []; if (CashTokenUtils.hasCommitmentLength(bitfield)) { final vi = IntUtils.decodeVarint( scriptBytes.sublist(cursor, scriptBytes.length)); @@ -326,7 +326,7 @@ class CashToken { commitment = scriptBytes.sublist(cursor, cursor + vi.item1); cursor += vi.item1; } - BigInt amount = BigInt.zero; + var amount = BigInt.zero; if (CashTokenUtils.hasAmount(bitfield)) { final vi = CashTokenUtils._decodeVarintBigInt( scriptBytes.sublist(cursor, scriptBytes.length)); @@ -352,7 +352,7 @@ class CashToken { /// /// Returns a list of integers representing the serialized byte representation of the [CashToken]. List toBytes() { - final DynamicByteTracker bytes = DynamicByteTracker(); + final bytes = DynamicByteTracker(); bytes.add([CashTokenUtils.cashTokenPrefix]); bytes.add(BytesUtils.fromHexString(category).reversed.toList()); bytes.add([bitfield]); @@ -415,15 +415,15 @@ class CashToken { hasCommitment ? BytesUtils.toHexString(commitment) : null; Map toJson() { return { - "category": category, - "amount": amount.toString(), - "bitfield": bitfield, - "commitment": BytesUtils.toHexString(commitment), + 'category': category, + 'amount': amount.toString(), + 'bitfield': bitfield, + 'commitment': BytesUtils.toHexString(commitment), }; } @override String toString() { - return "CashToken{bitfield: $bitfield, commitment: $commitmentInHex, amount: $amount, category: $category}"; + return 'CashToken{bitfield: $bitfield, commitment: $commitmentInHex, amount: $amount, category: $category}'; } } diff --git a/lib/src/crypto/crypto.dart b/lib/src/crypto/crypto.dart index bf5c6cf..79079aa 100644 --- a/lib/src/crypto/crypto.dart +++ b/lib/src/crypto/crypto.dart @@ -1,4 +1,4 @@ -library crypto; +library; import 'package:bitcoin_base/src/bitcoin/script/op_code/constant_lib.dart'; import 'package:blockchain_utils/crypto/quick_crypto.dart'; @@ -30,5 +30,5 @@ List toTapleafTaggedHash(List scriptBytes) { BitcoinOpCodeConst.LEAF_VERSION_TAPSCRIPT, ...IntUtils.prependVarint(scriptBytes) ]; - return taggedHash(leafVarBytes, "TapLeaf"); + return taggedHash(leafVarBytes, 'TapLeaf'); } diff --git a/lib/src/crypto/keypair/ec_private.dart b/lib/src/crypto/keypair/ec_private.dart index d5c5735..af1a731 100644 --- a/lib/src/crypto/keypair/ec_private.dart +++ b/lib/src/crypto/keypair/ec_private.dart @@ -4,7 +4,7 @@ import 'package:blockchain_utils/blockchain_utils.dart'; /// Represents an ECDSA private key. class ECPrivate { final Bip32PrivateKey prive; - ECPrivate(this.prive); + const ECPrivate(this.prive); /// creates an object from hex factory ECPrivate.fromHex(String keyHex) { @@ -30,15 +30,11 @@ class ECPrivate { } /// returns as WIFC (compressed) or WIF format (string) - String toWif({bool compressed = true, BitcoinNetwork? network}) { - List bytes = [ - ...(network ?? BitcoinNetwork.mainnet).wifNetVer, - ...toBytes() - ]; - if (compressed) { - bytes = [...bytes, 0x01]; - } - return Base58Encoder.checkEncode(bytes); + String toWif( + {PubKeyModes pubKeyMode = PubKeyModes.compressed, + BitcoinNetwork network = BitcoinNetwork.mainnet}) { + return WifEncoder.encode(toBytes(), + netVer: network.wifNetVer, pubKeyMode: pubKeyMode); } /// returns the key's raw bytes @@ -62,7 +58,7 @@ class ECPrivate { String signInput(List txDigest, {int sigHash = BitcoinOpCodeConst.SIGHASH_ALL}) { final btcSigner = BitcoinSigner.fromKeyBytes(toBytes()); - List signature = btcSigner.signTransaction(txDigest); + var signature = btcSigner.signTransaction(txDigest); signature = [...signature, sigHash]; return BytesUtils.toHexString(signature); } @@ -70,7 +66,7 @@ class ECPrivate { String signSchnorr(List txDigest, {int sighash = BitcoinOpCodeConst.TAPROOT_SIGHASH_ALL}) { final btcSigner = BitcoinSigner.fromKeyBytes(toBytes()); - List signatur = btcSigner.signSchnorrTransaction(txDigest, + var signatur = btcSigner.signSchnorrTransaction(txDigest, tapScripts: [], tweak: false); if (sighash != BitcoinOpCodeConst.TAPROOT_SIGHASH_ALL) { signatur = [...signatur, sighash]; @@ -89,12 +85,12 @@ class ECPrivate { } return true; }(), - "When the tweak is false, the `tapScripts` are ignored, to use the tap script path, you need to consider the tweak value to be true."); + 'When the tweak is false, the `tapScripts` are ignored, to use the tap script path, you need to consider the tweak value to be true.'); final tapScriptBytes = !tweak ? [] : tapScripts.map((e) => e.map((e) => e.toBytes()).toList()).toList(); final btcSigner = BitcoinSigner.fromKeyBytes(toBytes()); - List signatur = btcSigner.signSchnorrTransaction(txDigest, + var signatur = btcSigner.signSchnorrTransaction(txDigest, tapScripts: tapScriptBytes, tweak: tweak); if (sighash != BitcoinOpCodeConst.TAPROOT_SIGHASH_ALL) { signatur = [...signatur, sighash]; diff --git a/lib/src/crypto/keypair/ec_public.dart b/lib/src/crypto/keypair/ec_public.dart index 26eaed4..4be69d3 100644 --- a/lib/src/crypto/keypair/ec_public.dart +++ b/lib/src/crypto/keypair/ec_public.dart @@ -3,6 +3,8 @@ import 'package:bitcoin_base/src/bitcoin/script/script.dart'; import 'package:bitcoin_base/src/exception/exception.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; +typedef PublicKeyType = PubKeyModes; + class ECPublic { final Bip32PublicKey publicKey; const ECPublic._(this.publicKey); @@ -10,7 +12,7 @@ class ECPublic { factory ECPublic.fromBip32(Bip32PublicKey publicKey) { if (publicKey.curveType != EllipticCurveTypes.secp256k1) { throw const DartBitcoinPluginException( - "invalid public key curve for bitcoin"); + 'invalid public key curve for bitcoin'); } return ECPublic._(publicKey); } @@ -29,8 +31,8 @@ class ECPublic { /// toHex converts the ECPublic key to a hex-encoded string. /// If 'compressed' is true, the key is in compressed format. - String toHex({bool compressed = true}) { - if (compressed) { + String toHex({PublicKeyType mode = PublicKeyType.compressed}) { + if (mode.isCompressed) { return BytesUtils.toHexString(publicKey.compressed); } return BytesUtils.toHexString(publicKey.uncompressed); @@ -38,22 +40,22 @@ class ECPublic { /// _toHash160 computes the RIPEMD160 hash of the ECPublic key. /// If 'compressed' is true, the key is in compressed format. - List _toHash160({bool compressed = true}) { - final bytes = BytesUtils.fromHexString(toHex(compressed: compressed)); + List _toHash160({PublicKeyType mode = PublicKeyType.compressed}) { + final bytes = BytesUtils.fromHexString(toHex(mode: mode)); return QuickCrypto.hash160(bytes); } /// toHash160 computes the RIPEMD160 hash of the ECPublic key. /// If 'compressed' is true, the key is in compressed format. - String toHash160({bool compressed = true}) { - final bytes = BytesUtils.fromHexString(toHex(compressed: compressed)); + String toHash160({PublicKeyType mode = PublicKeyType.compressed}) { + final bytes = BytesUtils.fromHexString(toHex(mode: mode)); return BytesUtils.toHexString(QuickCrypto.hash160(bytes)); } /// toAddress generates a P2PKH (Pay-to-Public-Key-Hash) address from the ECPublic key. /// If 'compressed' is true, the key is in compressed format. - P2pkhAddress toAddress({bool compressed = true}) { - final h16 = _toHash160(compressed: compressed); + P2pkhAddress toAddress({PublicKeyType mode = PublicKeyType.compressed}) { + final h16 = _toHash160(mode: mode); final toHex = BytesUtils.toHexString(h16); return P2pkhAddress.fromHash160(addrHash: toHex); } @@ -69,23 +71,24 @@ class ECPublic { /// toP2pkAddress generates a P2PK (Pay-to-Public-Key) address from the ECPublic key. /// If 'compressed' is true, the key is in compressed format. - P2pkAddress toP2pkAddress({bool compressed = true}) { - final h = toHex(compressed: compressed); + P2pkAddress toP2pkAddress({PublicKeyType mode = PublicKeyType.compressed}) { + final h = toHex(mode: mode); return P2pkAddress(publicKey: h); } /// toRedeemScript generates a redeem script from the ECPublic key. /// If 'compressed' is true, the key is in compressed format. - Script toRedeemScript({bool compressed = true}) { - final redeem = toHex(compressed: compressed); - return Script(script: [redeem, "OP_CHECKSIG"]); + Script toRedeemScript({PublicKeyType mode = PublicKeyType.compressed}) { + final redeem = toHex(mode: mode); + return Script(script: [redeem, 'OP_CHECKSIG']); } /// toP2pkhInP2sh generates a P2SH (Pay-to-Script-Hash) address /// wrapping a P2PK (Pay-to-Public-Key) script derived from the ECPublic key. /// If 'compressed' is true, the key is in compressed format. - P2shAddress toP2pkhInP2sh({bool compressed = true, useBCHP2sh32 = false}) { - final addr = toAddress(compressed: compressed); + P2shAddress toP2pkhInP2sh( + {PublicKeyType mode = PublicKeyType.compressed, useBCHP2sh32 = false}) { + final addr = toAddress(mode: mode); final script = addr.toScriptPubKey(); if (useBCHP2sh32) { return P2shAddress.fromHash160( @@ -101,8 +104,9 @@ class ECPublic { /// wrapping a P2PK (Pay-to-Public-Key) script derived from the ECPublic key. /// If 'compressed' is true, the key is in compressed format. P2shAddress toP2pkInP2sh( - {bool compressed = true, bool useBCHP2sh32 = false}) { - final script = toRedeemScript(compressed: compressed); + {PublicKeyType mode = PublicKeyType.compressed, + bool useBCHP2sh32 = false}) { + final script = toRedeemScript(mode: mode); if (useBCHP2sh32) { return P2shAddress.fromHash160( addrHash: BytesUtils.toHexString( @@ -133,7 +137,7 @@ class ECPublic { /// toP2wshScript generates a P2WSH (Pay-to-Witness-Script-Hash) script /// derived from the ECPublic key. If 'compressed' is true, the key is in compressed format. Script toP2wshScript() { - return Script(script: ['OP_1', toHex(), "OP_1", "OP_CHECKMULTISIG"]); + return Script(script: ['OP_1', toHex(), 'OP_1', 'OP_CHECKMULTISIG']); } /// toP2wshAddress generates a P2WSH (Pay-to-Witness-Script-Hash) address diff --git a/lib/src/exception/exception.dart b/lib/src/exception/exception.dart index 09652ba..0e031c3 100644 --- a/lib/src/exception/exception.dart +++ b/lib/src/exception/exception.dart @@ -1,7 +1,5 @@ import 'package:blockchain_utils/blockchain_utils.dart'; class DartBitcoinPluginException extends BlockchainUtilsException { - const DartBitcoinPluginException(String message, - {Map? details}) - : super(message, details: details); + const DartBitcoinPluginException(super.message, {super.details}); } diff --git a/lib/src/models/network.dart b/lib/src/models/network.dart index d3372de..89b24b6 100644 --- a/lib/src/models/network.dart +++ b/lib/src/models/network.dart @@ -23,7 +23,7 @@ abstract class BasedUtxoNetwork implements Enumerate { abstract final List supportedAddress; @override - operator ==(other) { + bool operator ==(other) { if (identical(other, this)) return true; return other is BasedUtxoNetwork && other.runtimeType == runtimeType && @@ -48,7 +48,7 @@ abstract class BasedUtxoNetwork implements Enumerate { BitcoinSVNetwork.testnet, PepeNetwork.mainnet, ElectraProtocolNetwork.mainnet, - ElectraProtocolNetwork.testnet, + ElectraProtocolNetwork.testnet ]; static BasedUtxoNetwork fromName(String name) { @@ -65,11 +65,11 @@ abstract class BasedUtxoNetwork implements Enumerate { class BitcoinSVNetwork implements BasedUtxoNetwork { /// Mainnet configuration with associated `CoinConf`. static const BitcoinSVNetwork mainnet = - BitcoinSVNetwork._("BitcoinSVMainnet", CoinsConf.bitcoinSvMainNet); + BitcoinSVNetwork._('BitcoinSVMainnet', CoinsConf.bitcoinSvMainNet); /// Testnet configuration with associated `CoinConf`. static const BitcoinSVNetwork testnet = - BitcoinSVNetwork._("BitcoinSVTestnet", CoinsConf.bitcoinSvTestNet); + BitcoinSVNetwork._('BitcoinSVTestnet', CoinsConf.bitcoinSvTestNet); /// Overrides the `conf` property from `BasedUtxoNetwork` with the associated `CoinConf`. @override @@ -117,11 +117,11 @@ class BitcoinSVNetwork implements BasedUtxoNetwork { class BitcoinNetwork implements BasedUtxoNetwork { /// Mainnet configuration with associated `CoinConf`. static const BitcoinNetwork mainnet = - BitcoinNetwork._("bitcoinMainnet", CoinsConf.bitcoinMainNet); + BitcoinNetwork._('bitcoinMainnet', CoinsConf.bitcoinMainNet); /// Testnet configuration with associated `CoinConf`. static const BitcoinNetwork testnet = - BitcoinNetwork._("bitcoinTestnet", CoinsConf.bitcoinTestNet); + BitcoinNetwork._('bitcoinTestnet', CoinsConf.bitcoinTestNet); /// Overrides the `conf` property from `BasedUtxoNetwork` with the associated `CoinConf`. @override @@ -190,11 +190,11 @@ class BitcoinNetwork implements BasedUtxoNetwork { class LitecoinNetwork implements BasedUtxoNetwork { /// Mainnet configuration with associated `CoinConf`. static const LitecoinNetwork mainnet = - LitecoinNetwork._("litecoinMainnet", CoinsConf.litecoinMainNet); + LitecoinNetwork._('litecoinMainnet', CoinsConf.litecoinMainNet); /// Testnet configuration with associated `CoinConf`. static const LitecoinNetwork testnet = - LitecoinNetwork._("litecoinTestnet", CoinsConf.litecoinTestNet); + LitecoinNetwork._('litecoinTestnet', CoinsConf.litecoinTestNet); /// Overrides the `conf` property from `BasedUtxoNetwork` with the associated `CoinConf`. @override @@ -255,11 +255,11 @@ class LitecoinNetwork implements BasedUtxoNetwork { class DashNetwork implements BasedUtxoNetwork { /// Mainnet configuration with associated `CoinConf`. static const DashNetwork mainnet = - DashNetwork._("dashMainnet", CoinsConf.dashMainNet); + DashNetwork._('dashMainnet', CoinsConf.dashMainNet); /// Testnet configuration with associated `CoinConf`. static const DashNetwork testnet = - DashNetwork._("dashTestnet", CoinsConf.dashTestNet); + DashNetwork._('dashTestnet', CoinsConf.dashTestNet); /// Overrides the `conf` property from `BasedUtxoNetwork` with the associated `CoinConf`. @override @@ -283,7 +283,7 @@ class DashNetwork implements BasedUtxoNetwork { /// Retrieves the Human-Readable Part (HRP) for Pay-to-Witness-Public-Key-Hash (P2WPKH) addresses. @override String get p2wpkhHrp => throw const DartBitcoinPluginException( - "DashNetwork network does not support P2WPKH/P2WSH"); + 'DashNetwork network does not support P2WPKH/P2WSH'); /// Checks if the current network is the mainnet. @override @@ -311,11 +311,11 @@ class DashNetwork implements BasedUtxoNetwork { class DogecoinNetwork implements BasedUtxoNetwork { /// Mainnet configuration with associated `CoinConf`. static const DogecoinNetwork mainnet = - DogecoinNetwork._("dogeMainnet", CoinsConf.dogecoinMainNet); + DogecoinNetwork._('dogeMainnet', CoinsConf.dogecoinMainNet); /// Testnet configuration with associated `CoinConf`. static const DogecoinNetwork testnet = - DogecoinNetwork._("dogeTestnet", CoinsConf.dogecoinTestNet); + DogecoinNetwork._('dogeTestnet', CoinsConf.dogecoinTestNet); /// Overrides the `conf` property from `BasedUtxoNetwork` with the associated `CoinConf`. @override @@ -342,7 +342,7 @@ class DogecoinNetwork implements BasedUtxoNetwork { /// Retrieves the Human-Readable Part (HRP) for Pay-to-Witness-Public-Key-Hash (P2WPKH) addresses. @override String get p2wpkhHrp => throw const DartBitcoinPluginException( - "DogecoinNetwork network does not support P2WPKH/P2WSH"); + 'DogecoinNetwork network does not support P2WPKH/P2WSH'); /// Checks if the current network is the mainnet. @override @@ -367,11 +367,11 @@ class DogecoinNetwork implements BasedUtxoNetwork { class BitcoinCashNetwork implements BasedUtxoNetwork { /// Mainnet configuration with associated `CoinConf`. static const BitcoinCashNetwork mainnet = - BitcoinCashNetwork._("bitcoinCashMainnet", CoinsConf.bitcoinCashMainNet); + BitcoinCashNetwork._('bitcoinCashMainnet', CoinsConf.bitcoinCashMainNet); /// Testnet configuration with associated `CoinConf`. static const BitcoinCashNetwork testnet = - BitcoinCashNetwork._("bitcoinCashTestnet", CoinsConf.bitcoinCashTestNet); + BitcoinCashNetwork._('bitcoinCashTestnet', CoinsConf.bitcoinCashTestNet); /// Overrides the `conf` property from `BasedUtxoNetwork` with the associated `CoinConf`. @override @@ -379,7 +379,6 @@ class BitcoinCashNetwork implements BasedUtxoNetwork { /// Constructor for creating a Bitcoin Cash network with a specific configuration. const BitcoinCashNetwork._(this.value, this.conf); - @override final String value; @@ -411,7 +410,7 @@ class BitcoinCashNetwork implements BasedUtxoNetwork { /// from the associated `CoinConf`. @override String get p2wpkhHrp => throw const DartBitcoinPluginException( - "network does not support p2wpkh HRP"); + 'network does not support p2wpkh HRP'); String get networkHRP => conf.params.p2pkhStdHrp!; @@ -445,7 +444,7 @@ class BitcoinCashNetwork implements BasedUtxoNetwork { class PepeNetwork implements BasedUtxoNetwork { /// Mainnet configuration with associated `CoinConf`. static const PepeNetwork mainnet = - PepeNetwork._("pepecoinMainnet", CoinsConf.pepeMainnet); + PepeNetwork._('pepecoinMainnet', CoinsConf.pepeMainnet); /// Overrides the `conf` property from `BasedUtxoNetwork` with the associated `CoinConf`. @override @@ -472,7 +471,7 @@ class PepeNetwork implements BasedUtxoNetwork { /// Retrieves the Human-Readable Part (HRP) for Pay-to-Witness-Public-Key-Hash (P2WPKH) addresses. @override String get p2wpkhHrp => throw const DartBitcoinPluginException( - "DogecoinNetwork network does not support P2WPKH/P2WSH"); + 'DogecoinNetwork network does not support P2WPKH/P2WSH'); /// Checks if the current network is the mainnet. @override @@ -499,11 +498,11 @@ class PepeNetwork implements BasedUtxoNetwork { class ElectraProtocolNetwork implements BasedUtxoNetwork { /// Mainnet configuration with associated `CoinConf`. static const ElectraProtocolNetwork mainnet = ElectraProtocolNetwork._( - "electraProtocolMainnet", CoinsConf.electraProtocolMainNet); + 'electraProtocolMainnet', CoinsConf.electraProtocolMainNet); /// Testnet configuration with associated `CoinConf`. static const ElectraProtocolNetwork testnet = ElectraProtocolNetwork._( - "electraProtocolTestnet", CoinsConf.electraProtocolTestNet); + 'electraProtocolTestnet', CoinsConf.electraProtocolTestNet); /// Overrides the `conf` property from `BasedUtxoNetwork` with the associated `CoinConf`. @override diff --git a/lib/src/provider/api_provider.dart b/lib/src/provider/api_provider.dart index c043b56..c63f462 100644 --- a/lib/src/provider/api_provider.dart +++ b/lib/src/provider/api_provider.dart @@ -1,5 +1,8 @@ export 'models/models.dart'; -export 'transaction_builder/builder.dart'; -export 'service/services.dart'; -export 'api_provider/providers.dart'; +export 'providers/explorer.dart'; +export 'providers/electrum.dart'; export 'electrum_methods/methods.dart'; +export 'services/electrum.dart'; +export 'services/explorer.dart'; +export 'core/methods.dart'; +export 'core/params.dart'; diff --git a/lib/src/provider/api_provider/electrum_api_provider.dart b/lib/src/provider/api_provider/electrum_api_provider.dart deleted file mode 100644 index 835cc2d..0000000 --- a/lib/src/provider/api_provider/electrum_api_provider.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:bitcoin_base/src/provider/api_provider.dart'; -import 'dart:async'; - -import 'package:blockchain_utils/exception/exceptions.dart'; - -class ElectrumApiProvider { - final BitcoinBaseElectrumRPCService rpc; - ElectrumApiProvider(this.rpc); - int _id = 0; - - /// Sends a request to the Electrum server using the specified [request] parameter. - /// - /// The [timeout] parameter, if provided, sets the maximum duration for the request. - Future request(ElectrumRequest request, - [Duration? timeout]) async { - final id = ++_id; - final params = request.toRequest(id); - final data = await rpc.call(params, timeout); - return request.onResonse(_findResult(data, params)); - } - - dynamic _findResult( - Map data, ElectrumRequestDetails request) { - final error = data["error"]; - if (error != null) { - final code = int.tryParse(error["code"]?.toString() ?? ""); - final message = error['message'] ?? ""; - throw RPCError( - errorCode: code, - message: message, - request: data["request"] ?? request.params, - details: error); - } - - return data["result"]; - } -} diff --git a/lib/src/provider/api_provider/providers.dart b/lib/src/provider/api_provider/providers.dart deleted file mode 100644 index df92a29..0000000 --- a/lib/src/provider/api_provider/providers.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'api_provider.dart'; -export 'electrum_api_provider.dart'; diff --git a/lib/src/provider/constant/constant.dart b/lib/src/provider/constant/constant.dart index 172fdee..f10a9e0 100644 --- a/lib/src/provider/constant/constant.dart +++ b/lib/src/provider/constant/constant.dart @@ -1,18 +1,18 @@ class BtcApiConst { static const String blockCypherBaseURL = - "https://api.blockcypher.com/v1/btc/test3"; - static const String mempoolBaseURL = "https://mempool.space/testnet/api"; + 'https://api.blockcypher.com/v1/btc/test3'; + static const String mempoolBaseURL = 'https://mempool.space/testnet/api'; static const String blockstreamBaseURL = - "https://blockstream.info/testnet/api"; + 'https://blockstream.info/testnet/api'; static const String blockCypherMainBaseURL = - "https://api.blockcypher.com/v1/btc/main"; - static const String mempoolMainBaseURL = "https://mempool.space/api"; - static const String blockstreamMainBaseURL = "https://blockstream.info/api"; + 'https://api.blockcypher.com/v1/btc/main'; + static const String mempoolMainBaseURL = 'https://mempool.space/api'; + static const String blockstreamMainBaseURL = 'https://blockstream.info/api'; // static const String blockCypherDashBaseUri = - "https://api.blockcypher.com/v1/dash/main"; + 'https://api.blockcypher.com/v1/dash/main'; static const String blockCypherDogeBaseUri = - "https://api.blockcypher.com/v1/doge/main"; + 'https://api.blockcypher.com/v1/doge/main'; static const String blockCypherLitecoinBaseUri = - "https://api.blockcypher.com/v1/ltc/main"; + 'https://api.blockcypher.com/v1/ltc/main'; } diff --git a/lib/src/provider/service/electrum/methods.dart b/lib/src/provider/core/methods.dart similarity index 70% rename from lib/src/provider/service/electrum/methods.dart rename to lib/src/provider/core/methods.dart index 027fd44..fb9790c 100644 --- a/lib/src/provider/service/electrum/methods.dart +++ b/lib/src/provider/core/methods.dart @@ -5,119 +5,119 @@ class ElectrumRequestMethods { /// Return a list of peer servers. Despite the name this is not a subscription and the server must send no notifications. static const ElectrumRequestMethods serverPeersSubscribe = - ElectrumRequestMethods._("server.peers.subscribe"); + ElectrumRequestMethods._('server.peers.subscribe'); /// Return a server donation address. static const ElectrumRequestMethods serverDontionAddress = - ElectrumRequestMethods._("server.donation_address"); + ElectrumRequestMethods._('server.donation_address'); /// A newly-started server uses this call to get itself into other servers’ peers lists. It should not be used by wallet clients. static const ElectrumRequestMethods serverAddPeer = - ElectrumRequestMethods._("server.add_peer"); + ElectrumRequestMethods._('server.add_peer'); /// Subscribe to a script hash. static const ElectrumRequestMethods scriptHashSubscribe = - ElectrumRequestMethods._("blockchain.scripthash.subscribe"); + ElectrumRequestMethods._('blockchain.scripthash.subscribe'); /// Unsubscribe from a script hash, preventing future notifications if its status changes. static const ElectrumRequestMethods scriptHashUnSubscribe = - ElectrumRequestMethods._("blockchain.scripthash.unsubscribe"); + ElectrumRequestMethods._('blockchain.scripthash.unsubscribe'); /// Return an ordered list of UTXOs sent to a script hash. static const ElectrumRequestMethods listunspent = - ElectrumRequestMethods._("blockchain.scripthash.listunspent"); + ElectrumRequestMethods._('blockchain.scripthash.listunspent'); /// Return the confirmed and unconfirmed balances of a script hash. static const ElectrumRequestMethods getBalance = - ElectrumRequestMethods._("blockchain.scripthash.get_balance"); + ElectrumRequestMethods._('blockchain.scripthash.get_balance'); /// Return a raw transaction. static const ElectrumRequestMethods getTransaction = - ElectrumRequestMethods._("blockchain.transaction.get"); + ElectrumRequestMethods._('blockchain.transaction.get'); /// Return the merkle branch to a confirmed transaction given its hash and height. static const ElectrumRequestMethods getMerkle = - ElectrumRequestMethods._("blockchain.transaction.get_merkle"); + ElectrumRequestMethods._('blockchain.transaction.get_merkle'); /// Return a transaction hash and optionally a merkle proof, given a block height and a position in the block. static const ElectrumRequestMethods idFromPos = - ElectrumRequestMethods._("blockchain.transaction.id_from_pos"); + ElectrumRequestMethods._('blockchain.transaction.id_from_pos'); /// Return a histogram of the fee rates paid by transactions in the memory pool, weighted by transaction size. static const ElectrumRequestMethods getFeeHistogram = - ElectrumRequestMethods._("mempool.get_fee_histogram"); + ElectrumRequestMethods._('mempool.get_fee_histogram'); /// Return the block header at the given height. static const ElectrumRequestMethods blockHeader = - ElectrumRequestMethods._("blockchain.block.header"); + ElectrumRequestMethods._('blockchain.block.header'); /// Return a concatenated chunk of block headers from the main chain. static const ElectrumRequestMethods blockHeaders = - ElectrumRequestMethods._("blockchain.block.headers"); + ElectrumRequestMethods._('blockchain.block.headers'); /// Return the estimated transaction fee per kilobyte for a transaction to be confirmed within a certain number of blocks. static const ElectrumRequestMethods estimateFee = - ElectrumRequestMethods._("blockchain.estimatefee"); + ElectrumRequestMethods._('blockchain.estimatefee'); /// Return the confirmed and unconfirmed history of a script hash. static const ElectrumRequestMethods getHistory = - ElectrumRequestMethods._("blockchain.scripthash.get_history"); + ElectrumRequestMethods._('blockchain.scripthash.get_history'); /// Return the unconfirmed transactions of a script hash. static const ElectrumRequestMethods getMempool = - ElectrumRequestMethods._("blockchain.scripthash.get_mempool"); + ElectrumRequestMethods._('blockchain.scripthash.get_mempool'); /// Broadcast a transaction to the network. static const ElectrumRequestMethods broadCast = - ElectrumRequestMethods._("blockchain.transaction.broadcast"); + ElectrumRequestMethods._('blockchain.transaction.broadcast'); /// Return a banner to be shown in the Electrum console. static const ElectrumRequestMethods serverBanner = - ElectrumRequestMethods._("server.banner"); + ElectrumRequestMethods._('server.banner'); /// Return a list of features and services supported by the server. static const ElectrumRequestMethods serverFeatures = - ElectrumRequestMethods._("server.features"); + ElectrumRequestMethods._('server.features'); /// Ping the server to ensure it is responding, and to keep the session alive. The server may disconnect clients that have sent no requests for roughly 10 minutes. static const ElectrumRequestMethods ping = - ElectrumRequestMethods._("server.ping"); + ElectrumRequestMethods._('server.ping'); /// Identify the client to the server and negotiate the protocol version. Only the first server.version() message is accepted. static const ElectrumRequestMethods version = - ElectrumRequestMethods._("server.version"); + ElectrumRequestMethods._('server.version'); /// Subscribe to receive block headers when a new block is found. static const ElectrumRequestMethods headersSubscribe = - ElectrumRequestMethods._("blockchain.headers.subscribe"); + ElectrumRequestMethods._('blockchain.headers.subscribe'); /// Return the minimum fee a low-priority transaction must pay in order to be accepted to the daemon’s memory pool. static const ElectrumRequestMethods relayFee = - ElectrumRequestMethods._("blockchain.relayfee"); + ElectrumRequestMethods._('blockchain.relayfee'); /// Pass through the masternode announce message to be broadcast by the daemon. static const ElectrumRequestMethods masternodeAnnounceBroadcast = - ElectrumRequestMethods._("masternode.announce.broadcast"); + ElectrumRequestMethods._('masternode.announce.broadcast'); /// Returns the status of masternode. static const ElectrumRequestMethods masternodeSubscribe = - ElectrumRequestMethods._("masternode.subscribe"); + ElectrumRequestMethods._('masternode.subscribe'); /// Returns the list of masternodes. static const ElectrumRequestMethods masternodeList = - ElectrumRequestMethods._("masternode.list"); + ElectrumRequestMethods._('masternode.list'); /// Returns a diff between two deterministic masternode lists. The result also contains proof data. static const ElectrumRequestMethods protxDiff = - ElectrumRequestMethods._("protx.diff"); + ElectrumRequestMethods._('protx.diff'); /// Returns detailed information about a deterministic masternode. static const ElectrumRequestMethods protxInfo = - ElectrumRequestMethods._("protx.info"); + ElectrumRequestMethods._('protx.info'); /// Returns a name resolution proof, suitable for low-latency (single round-trip) resolution. static const ElectrumRequestMethods getValueProof = - ElectrumRequestMethods._("blockchain.name.get_value_proof"); + ElectrumRequestMethods._('blockchain.name.get_value_proof'); @override String toString() { return method; diff --git a/lib/src/provider/core/params.dart b/lib/src/provider/core/params.dart new file mode 100644 index 0000000..36612cf --- /dev/null +++ b/lib/src/provider/core/params.dart @@ -0,0 +1,66 @@ +import 'package:blockchain_utils/blockchain_utils.dart'; + +/// Represents details of an Electrum request, including id, method, and parameters. +class ElectrumRequestDetails extends BaseServiceRequestParams { + const ElectrumRequestDetails( + {required super.requestID, + this.path, + required this.method, + required this.params, + required super.type, + super.headers = ServiceConst.defaultPostHeaders}); + + final String? path; + final String method; + final Map params; + + List toTCPParams() { + final param = '${StringUtils.fromJson(params)}\n'; + return StringUtils.encode(param); + } + + List toWebSocketParams() { + return StringUtils.encode(StringUtils.fromJson(params)); + } + + @override + List? body() { + return toWebSocketParams(); + } + + @override + Map toJson() { + return { + 'method': method, + 'body': params, + }; + } + + @override + Uri toUri(String uri) { + return Uri.parse(uri); + } +} + +/// Abstract class representing an Electrum request with generic result and response types. +abstract class ElectrumRequest + extends BaseServiceRequest { + abstract final String method; + List toJson(); + + @override + ElectrumRequestDetails buildRequest(int requestID) { + final inJson = toJson(); + inJson.removeWhere((v) => v == null); + final params = ServiceProviderUtils.buildJsonRPCParams( + requestId: requestID, method: method, params: inJson); + return ElectrumRequestDetails( + requestID: requestID, + params: params, + method: method, + type: RequestServiceType.post); + } + + @override + RequestServiceType get requestType => RequestServiceType.post; +} diff --git a/lib/src/provider/electrum_methods/methods/add_peer.dart b/lib/src/provider/electrum_methods/methods/add_peer.dart index fb23bba..33d2103 100644 --- a/lib/src/provider/electrum_methods/methods/add_peer.dart +++ b/lib/src/provider/electrum_methods/methods/add_peer.dart @@ -1,10 +1,11 @@ -import 'package:bitcoin_base/src/provider/api_provider.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// A newly-started server uses this call to get itself into other servers’ peers lists. /// It should not be used by wallet clients. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumAddPeer extends ElectrumRequest { - ElectrumAddPeer({required this.features}); +class ElectrumRequestAddPeer extends ElectrumRequest { + ElectrumRequestAddPeer({required this.features}); /// The same information that a call to the sender’s server.features() RPC call would return. final Map features; diff --git a/lib/src/provider/electrum_methods/methods/block_headers.dart b/lib/src/provider/electrum_methods/methods/block_headers.dart index ef75150..dddf3f9 100644 --- a/lib/src/provider/electrum_methods/methods/block_headers.dart +++ b/lib/src/provider/electrum_methods/methods/block_headers.dart @@ -1,10 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return a concatenated chunk of block headers from the main chain. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumBlockHeaders +class ElectrumRequestBlockHeaders extends ElectrumRequest, Map> { - ElectrumBlockHeaders( + ElectrumRequestBlockHeaders( {required this.startHeight, required this.count, required this.cpHeight}); /// The height of the first header requested, a non-negative integer. diff --git a/lib/src/provider/electrum_methods/methods/broad_cast.dart b/lib/src/provider/electrum_methods/methods/broad_cast.dart index fef43d0..b8125e9 100644 --- a/lib/src/provider/electrum_methods/methods/broad_cast.dart +++ b/lib/src/provider/electrum_methods/methods/broad_cast.dart @@ -1,10 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Broadcast a transaction to the network. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumBroadCastTransaction extends ElectrumRequest { - ElectrumBroadCastTransaction({required this.transactionRaw}); +class ElectrumRequestBroadCastTransaction + extends ElectrumRequest { + ElectrumRequestBroadCastTransaction({required this.transactionRaw}); /// The raw transaction as a hexadecimal string. final String transactionRaw; diff --git a/lib/src/provider/electrum_methods/methods/donate_address.dart b/lib/src/provider/electrum_methods/methods/donate_address.dart index 4f59989..c5dfa80 100644 --- a/lib/src/provider/electrum_methods/methods/donate_address.dart +++ b/lib/src/provider/electrum_methods/methods/donate_address.dart @@ -1,8 +1,9 @@ -import 'package:bitcoin_base/src/provider/api_provider.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return a server donation address. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumDonationAddress extends ElectrumRequest { +class ElectrumRequestDonationAddress extends ElectrumRequest { /// server.donation_address @override String get method => ElectrumRequestMethods.serverDontionAddress.method; diff --git a/lib/src/provider/electrum_methods/methods/electrum_version.dart b/lib/src/provider/electrum_methods/methods/electrum_version.dart index 1a1f858..f6ebce4 100644 --- a/lib/src/provider/electrum_methods/methods/electrum_version.dart +++ b/lib/src/provider/electrum_methods/methods/electrum_version.dart @@ -1,9 +1,12 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Identify the client to the server and negotiate the protocol version. Only the first server.version() message is accepted. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumVersion extends ElectrumRequest, List> { - ElectrumVersion({required this.clientName, required this.protocolVersion}); +class ElectrumRequestVersion + extends ElectrumRequest, List> { + ElectrumRequestVersion( + {required this.clientName, required this.protocolVersion}); /// A string identifying the connecting client software. final String clientName; diff --git a/lib/src/provider/electrum_methods/methods/estimate_fee.dart b/lib/src/provider/electrum_methods/methods/estimate_fee.dart index 859dfd8..67c9c56 100644 --- a/lib/src/provider/electrum_methods/methods/estimate_fee.dart +++ b/lib/src/provider/electrum_methods/methods/estimate_fee.dart @@ -1,10 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; import 'package:bitcoin_base/src/utils/btc_utils.dart'; /// Return the estimated transaction fee per kilobyte for a transaction to be confirmed within a certain number of blocks. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumEstimateFee extends ElectrumRequest { - ElectrumEstimateFee({this.numberOfBlock = 2}); +class ElectrumRequestEstimateFee extends ElectrumRequest { + ElectrumRequestEstimateFee({this.numberOfBlock = 2}); /// The number of blocks to target for confirmation. final int numberOfBlock; diff --git a/lib/src/provider/electrum_methods/methods/get_balance.dart b/lib/src/provider/electrum_methods/methods/get_balance.dart index c9a49e0..cce82bb 100644 --- a/lib/src/provider/electrum_methods/methods/get_balance.dart +++ b/lib/src/provider/electrum_methods/methods/get_balance.dart @@ -1,11 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return the confirmed and unconfirmed balances of a script hash. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumGetScriptHashBalance +class ElectrumRequestGetScriptHashBalance extends ElectrumRequest, Map> { - ElectrumGetScriptHashBalance({required this.scriptHash}); + ElectrumRequestGetScriptHashBalance({required this.scriptHash}); /// The script hash as a hexadecimal string (BitcoinBaseAddress.pubKeyHash()) final String scriptHash; diff --git a/lib/src/provider/electrum_methods/methods/get_fee_histogram.dart b/lib/src/provider/electrum_methods/methods/get_fee_histogram.dart index 8c89c23..5394221 100644 --- a/lib/src/provider/electrum_methods/methods/get_fee_histogram.dart +++ b/lib/src/provider/electrum_methods/methods/get_fee_histogram.dart @@ -1,10 +1,10 @@ -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return a histogram of the fee rates paid by transactions in the memory pool, weighted by transaction size. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumGetFeeHistogram - extends ElectrumRequest>, List> { +class ElectrumRequestGetFeeHistogram + extends ElectrumRequest>, List> { /// mempool.get_fee_histogram @override String get method => ElectrumRequestMethods.getFeeHistogram.method; @@ -19,7 +19,9 @@ class ElectrumGetFeeHistogram /// fee uses sat/vbyte as unit, and must be a non-negative integer or float. /// vsize uses vbyte as unit, and must be a non-negative integer. @override - List> onResonse(result) { - return result.map((e) => List.from(e)).toList(); + List> onResonse(result) { + return result + .map((e) => (e as List).map((e) => (e as num).toDouble()).toList()) + .toList(); } } diff --git a/lib/src/provider/electrum_methods/methods/get_history.dart b/lib/src/provider/electrum_methods/methods/get_history.dart index 9f8efa2..ed3a117 100644 --- a/lib/src/provider/electrum_methods/methods/get_history.dart +++ b/lib/src/provider/electrum_methods/methods/get_history.dart @@ -1,11 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return the confirmed and unconfirmed history of a script hash. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumScriptHashGetHistory +class ElectrumRequestScriptHashGetHistory extends ElectrumRequest>, List> { - ElectrumScriptHashGetHistory({required this.scriptHash}); + ElectrumRequestScriptHashGetHistory({required this.scriptHash}); /// The script hash as a hexadecimal string (BitcoinBaseAddress.pubKeyHash()) final String scriptHash; diff --git a/lib/src/provider/electrum_methods/methods/get_mempool.dart b/lib/src/provider/electrum_methods/methods/get_mempool.dart index fcd33a2..abd6fef 100644 --- a/lib/src/provider/electrum_methods/methods/get_mempool.dart +++ b/lib/src/provider/electrum_methods/methods/get_mempool.dart @@ -1,11 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return the unconfirmed transactions of a script hash. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumScriptHashGetMempool +class ElectrumRequestScriptHashGetMempool extends ElectrumRequest>, List> { - ElectrumScriptHashGetMempool({required this.scriptHash}); + ElectrumRequestScriptHashGetMempool({required this.scriptHash}); /// The script hash as a hexadecimal string (BitcoinBaseAddress.pubKeyHash()) final String scriptHash; diff --git a/lib/src/provider/electrum_methods/methods/get_merkle.dart b/lib/src/provider/electrum_methods/methods/get_merkle.dart index a39cd8a..7620749 100644 --- a/lib/src/provider/electrum_methods/methods/get_merkle.dart +++ b/lib/src/provider/electrum_methods/methods/get_merkle.dart @@ -1,11 +1,12 @@ -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return the merkle branch to a confirmed transaction given its hash and height. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumGetMerkle +class ElectrumRequestGetMerkle extends ElectrumRequest, Map> { - ElectrumGetMerkle({required this.transactionHash, required this.height}); + ElectrumRequestGetMerkle( + {required this.transactionHash, required this.height}); /// The transaction hash as a hexadecimal string. final String transactionHash; diff --git a/lib/src/provider/electrum_methods/methods/get_transaction.dart b/lib/src/provider/electrum_methods/methods/get_transaction.dart index f18dd84..3f99f37 100644 --- a/lib/src/provider/electrum_methods/methods/get_transaction.dart +++ b/lib/src/provider/electrum_methods/methods/get_transaction.dart @@ -1,10 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return a raw transaction. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumGetTransaction extends ElectrumRequest { - ElectrumGetTransaction({required this.transactionHash, this.verbose = false}); +class ElectrumRequestGetTransaction extends ElectrumRequest { + ElectrumRequestGetTransaction( + {required this.transactionHash, this.verbose = false}); /// The transaction hash as a hexadecimal string. final String transactionHash; diff --git a/lib/src/provider/electrum_methods/methods/get_unspet.dart b/lib/src/provider/electrum_methods/methods/get_unspet.dart index 2a957d1..0e36cc2 100644 --- a/lib/src/provider/electrum_methods/methods/get_unspet.dart +++ b/lib/src/provider/electrum_methods/methods/get_unspet.dart @@ -1,12 +1,12 @@ import 'package:bitcoin_base/src/provider/models/electrum/electrum_utxo.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return an ordered list of UTXOs sent to a script hash. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumScriptHashListUnspent +class ElectrumRequestScriptHashListUnspent extends ElectrumRequest, List> { - ElectrumScriptHashListUnspent( + ElectrumRequestScriptHashListUnspent( {required this.scriptHash, this.includeTokens = false}); /// The script hash as a hexadecimal string (BitcoinBaseAddress.pubKeyHash()) @@ -21,7 +21,7 @@ class ElectrumScriptHashListUnspent @override List toJson() { - return [scriptHash, if (includeTokens) "include_tokens"]; + return [scriptHash, if (includeTokens) 'include_tokens']; } /// A list of unspent outputs in blockchain order. @@ -30,8 +30,7 @@ class ElectrumScriptHashListUnspent /// Any output that is spent in the mempool does not appear. @override List onResonse(result) { - final List utxos = - result.map((e) => ElectrumUtxo.fromJson(e)).toList(); + final utxos = result.map((e) => ElectrumUtxo.fromJson(e)).toList(); return utxos; } } diff --git a/lib/src/provider/electrum_methods/methods/get_value_proof.dart b/lib/src/provider/electrum_methods/methods/get_value_proof.dart index bebe814..9eddd0c 100644 --- a/lib/src/provider/electrum_methods/methods/get_value_proof.dart +++ b/lib/src/provider/electrum_methods/methods/get_value_proof.dart @@ -1,10 +1,12 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Returns a name resolution proof, suitable for low-latency (single round-trip) resolution. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumGetValueProof +class ElectrumRequestGetValueProof extends ElectrumRequest, dynamic> { - ElectrumGetValueProof({required this.scriptHash, required this.cpHeight}); + ElectrumRequestGetValueProof( + {required this.scriptHash, required this.cpHeight}); /// Script hash of the name being resolved. final String scriptHash; diff --git a/lib/src/provider/electrum_methods/methods/header.dart b/lib/src/provider/electrum_methods/methods/header.dart index 97120b5..1c83926 100644 --- a/lib/src/provider/electrum_methods/methods/header.dart +++ b/lib/src/provider/electrum_methods/methods/header.dart @@ -1,9 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return the block header at the given height. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumBlockHeader extends ElectrumRequest { - ElectrumBlockHeader({required this.startHeight, required this.cpHeight}); +class ElectrumRequestBlockHeader extends ElectrumRequest { + ElectrumRequestBlockHeader( + {required this.startHeight, required this.cpHeight}); final int startHeight; final int cpHeight; diff --git a/lib/src/provider/electrum_methods/methods/headers_subscribe.dart b/lib/src/provider/electrum_methods/methods/headers_subscribe.dart index 651c695..9dc0f18 100644 --- a/lib/src/provider/electrum_methods/methods/headers_subscribe.dart +++ b/lib/src/provider/electrum_methods/methods/headers_subscribe.dart @@ -1,8 +1,9 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Subscribe to receive block headers when a new block is found. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumHeaderSubscribe +class ElectrumRequestHeaderSubscribe extends ElectrumRequest, Map> { /// blockchain.headers.subscribe @override diff --git a/lib/src/provider/electrum_methods/methods/id_from_pos.dart b/lib/src/provider/electrum_methods/methods/id_from_pos.dart index 865f0b2..5f73d57 100644 --- a/lib/src/provider/electrum_methods/methods/id_from_pos.dart +++ b/lib/src/provider/electrum_methods/methods/id_from_pos.dart @@ -1,10 +1,10 @@ -import 'package:bitcoin_base/src/provider/service/electrum/methods.dart'; -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return a transaction hash and optionally a merkle proof, given a block height and a position in the block. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumIdFromPos extends ElectrumRequest { - ElectrumIdFromPos( +class ElectrumRequestIdFromPos extends ElectrumRequest { + ElectrumRequestIdFromPos( {required this.height, required this.txPos, this.merkle = false}); /// The main chain block height, a non-negative integer. diff --git a/lib/src/provider/electrum_methods/methods/masternode_announce_broadcast.dart b/lib/src/provider/electrum_methods/methods/masternode_announce_broadcast.dart index f3169d3..767bd33 100644 --- a/lib/src/provider/electrum_methods/methods/masternode_announce_broadcast.dart +++ b/lib/src/provider/electrum_methods/methods/masternode_announce_broadcast.dart @@ -1,11 +1,13 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Pass through the masternode announce message to be broadcast by the daemon. /// Whenever a masternode comes online or a client is syncing, /// they will send this message which describes the masternode entry and how to validate messages from it. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumMasternodeAnnounceBroadcast extends ElectrumRequest { - ElectrumMasternodeAnnounceBroadcast({required this.signmnb}); +class ElectrumRequestMasternodeAnnounceBroadcast + extends ElectrumRequest { + ElectrumRequestMasternodeAnnounceBroadcast({required this.signmnb}); final String signmnb; /// masternode.announce.broadcast diff --git a/lib/src/provider/electrum_methods/methods/masternode_list.dart b/lib/src/provider/electrum_methods/methods/masternode_list.dart index 437dc3b..d2b3195 100644 --- a/lib/src/provider/electrum_methods/methods/masternode_list.dart +++ b/lib/src/provider/electrum_methods/methods/masternode_list.dart @@ -1,10 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Returns the list of masternodes. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumMasternodeList +class ElectrumRequestMasternodeList extends ElectrumRequest, List> { - ElectrumMasternodeList({required this.payees}); + ElectrumRequestMasternodeList({required this.payees}); /// An array of masternode payee addresses. final List payees; diff --git a/lib/src/provider/electrum_methods/methods/masternode_subscribe.dart b/lib/src/provider/electrum_methods/methods/masternode_subscribe.dart index 2734415..c96846a 100644 --- a/lib/src/provider/electrum_methods/methods/masternode_subscribe.dart +++ b/lib/src/provider/electrum_methods/methods/masternode_subscribe.dart @@ -1,9 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Returns the status of masternode. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumMasternodeSubscribe extends ElectrumRequest { - ElectrumMasternodeSubscribe({required this.collateral}); +class ElectrumRequestMasternodeSubscribe + extends ElectrumRequest { + ElectrumRequestMasternodeSubscribe({required this.collateral}); /// The txId and the index of the collateral. Example ("8c59133e714797650cf69043d05e409bbf45670eed7c4e4a386e52c46f1b5e24-0") final String collateral; diff --git a/lib/src/provider/electrum_methods/methods/ping.dart b/lib/src/provider/electrum_methods/methods/ping.dart index 4d41704..70ebb73 100644 --- a/lib/src/provider/electrum_methods/methods/ping.dart +++ b/lib/src/provider/electrum_methods/methods/ping.dart @@ -1,8 +1,9 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Ping the server to ensure it is responding, and to keep the session alive. The server may disconnect clients that have sent no requests for roughly 10 minutes. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumPing extends ElectrumRequest { +class ElectrumRequestPing extends ElectrumRequest { @override String get method => ElectrumRequestMethods.ping.method; diff --git a/lib/src/provider/electrum_methods/methods/protx_diff.dart b/lib/src/provider/electrum_methods/methods/protx_diff.dart index cca5d7d..0872cf9 100644 --- a/lib/src/provider/electrum_methods/methods/protx_diff.dart +++ b/lib/src/provider/electrum_methods/methods/protx_diff.dart @@ -1,9 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Returns a diff between two deterministic masternode lists. The result also contains proof data.. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumProtXDiff extends ElectrumRequest, dynamic> { - ElectrumProtXDiff({required this.baseHeight, required this.height}); +class ElectrumRequestProtXDiff + extends ElectrumRequest, dynamic> { + ElectrumRequestProtXDiff({required this.baseHeight, required this.height}); /// The starting block height final int baseHeight; diff --git a/lib/src/provider/electrum_methods/methods/protx_info.dart b/lib/src/provider/electrum_methods/methods/protx_info.dart index 7685699..ee4f083 100644 --- a/lib/src/provider/electrum_methods/methods/protx_info.dart +++ b/lib/src/provider/electrum_methods/methods/protx_info.dart @@ -1,9 +1,11 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Returns detailed information about a deterministic masternode. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumProtXInfo extends ElectrumRequest, dynamic> { - ElectrumProtXInfo({required this.protxHash}); +class ElectrumRequestProtXInfo + extends ElectrumRequest, dynamic> { + ElectrumRequestProtXInfo({required this.protxHash}); /// The hash of the initial ProRegTx final String protxHash; diff --git a/lib/src/provider/electrum_methods/methods/relay_fee.dart b/lib/src/provider/electrum_methods/methods/relay_fee.dart index 267dccf..c19502c 100644 --- a/lib/src/provider/electrum_methods/methods/relay_fee.dart +++ b/lib/src/provider/electrum_methods/methods/relay_fee.dart @@ -1,9 +1,10 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; import 'package:bitcoin_base/src/utils/btc_utils.dart'; /// Return the minimum fee a low-priority transaction must pay in order to be accepted to the daemon’s memory pool. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumRelayFee extends ElectrumRequest { +class ElectrumRequestRelayFee extends ElectrumRequest { /// blockchain.relayfee @override String get method => ElectrumRequestMethods.relayFee.method; diff --git a/lib/src/provider/electrum_methods/methods/scripthash_unsubscribe.dart b/lib/src/provider/electrum_methods/methods/scripthash_unsubscribe.dart index 4990b6d..f5d4ea9 100644 --- a/lib/src/provider/electrum_methods/methods/scripthash_unsubscribe.dart +++ b/lib/src/provider/electrum_methods/methods/scripthash_unsubscribe.dart @@ -1,9 +1,10 @@ -import 'package:bitcoin_base/src/provider/api_provider.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Unsubscribe from a script hash, preventing future notifications if its status changes. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumScriptHashUnSubscribe extends ElectrumRequest { - ElectrumScriptHashUnSubscribe({required this.scriptHash}); +class ElectrumRequestScriptHashUnSubscribe extends ElectrumRequest { + ElectrumRequestScriptHashUnSubscribe({required this.scriptHash}); /// The script hash as a hexadecimal string (BitcoinBaseAddress.pubKeyHash()) final String scriptHash; diff --git a/lib/src/provider/electrum_methods/methods/server_banner.dart b/lib/src/provider/electrum_methods/methods/server_banner.dart index 92e3ab4..5ef4fad 100644 --- a/lib/src/provider/electrum_methods/methods/server_banner.dart +++ b/lib/src/provider/electrum_methods/methods/server_banner.dart @@ -1,8 +1,9 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return a banner to be shown in the Electrum console. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumServerBanner extends ElectrumRequest { +class ElectrumRequestServerBanner extends ElectrumRequest { @override String get method => ElectrumRequestMethods.serverBanner.method; diff --git a/lib/src/provider/electrum_methods/methods/server_features.dart b/lib/src/provider/electrum_methods/methods/server_features.dart index 7e9c939..ccc88c0 100644 --- a/lib/src/provider/electrum_methods/methods/server_features.dart +++ b/lib/src/provider/electrum_methods/methods/server_features.dart @@ -1,8 +1,9 @@ -import 'package:bitcoin_base/src/provider/service/electrum/electrum.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return a list of features and services supported by the server. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumServerFeatures extends ElectrumRequest { +class ElectrumRequestServerFeatures extends ElectrumRequest { /// server.features @override String get method => ElectrumRequestMethods.serverFeatures.method; diff --git a/lib/src/provider/electrum_methods/methods/server_peer_subscribe.dart b/lib/src/provider/electrum_methods/methods/server_peer_subscribe.dart index d1a3db5..1034eb1 100644 --- a/lib/src/provider/electrum_methods/methods/server_peer_subscribe.dart +++ b/lib/src/provider/electrum_methods/methods/server_peer_subscribe.dart @@ -1,8 +1,9 @@ -import 'package:bitcoin_base/src/provider/api_provider.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Return a list of peer servers. Despite the name this is not a subscription and the server must send no notifications.. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumServerPeersSubscribe +class ElectrumRequestServerPeersSubscribe extends ElectrumRequest, List> { /// server.peers.subscribe @override diff --git a/lib/src/provider/electrum_methods/methods/status.dart b/lib/src/provider/electrum_methods/methods/status.dart index f12a0fa..0a3b978 100644 --- a/lib/src/provider/electrum_methods/methods/status.dart +++ b/lib/src/provider/electrum_methods/methods/status.dart @@ -1,10 +1,11 @@ -import 'package:bitcoin_base/src/provider/api_provider.dart'; +import 'package:bitcoin_base/src/provider/core/methods.dart'; +import 'package:bitcoin_base/src/provider/core/params.dart'; /// Subscribe to a script hash. /// https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html -class ElectrumScriptHashSubscribe +class ElectrumRequestScriptHashSubscribe extends ElectrumRequest, dynamic> { - ElectrumScriptHashSubscribe({required this.scriptHash}); + ElectrumRequestScriptHashSubscribe({required this.scriptHash}); /// /// The script hash as a hexadecimal string (BitcoinBaseAddress.pubKeyHash()) final String scriptHash; diff --git a/lib/src/provider/models/block_cypher/block_cypher_models.dart b/lib/src/provider/models/block_cypher/block_cypher_models.dart index 9d49f11..759c8f3 100644 --- a/lib/src/provider/models/block_cypher/block_cypher_models.dart +++ b/lib/src/provider/models/block_cypher/block_cypher_models.dart @@ -99,7 +99,7 @@ class BlockCypherUtxo { } List toUtxoWithOwner(UtxoAddressDetails owner) { - final List utxos = txRefs.map((ref) { + final utxos = txRefs.map((ref) { return UtxoWithAddress( utxo: ref.toUtxo(owner.address.type), ownerDetails: owner, diff --git a/lib/src/provider/models/config.dart b/lib/src/provider/models/config.dart index fbbda69..6e9b89e 100644 --- a/lib/src/provider/models/config.dart +++ b/lib/src/provider/models/config.dart @@ -24,8 +24,8 @@ class APIConfig { } String getUtxoUrl(String address) { - final String baseUrl = url; - return baseUrl.replaceAll("###", address); + final baseUrl = url; + return baseUrl.replaceAll('###', address); } String getFeeApiUrl() { @@ -33,18 +33,18 @@ class APIConfig { } String getTransactionUrl(String transactionId) { - final String baseUrl = transaction; - return baseUrl.replaceAll("###", transactionId); + final baseUrl = transaction; + return baseUrl.replaceAll('###', transactionId); } String getTransactionsUrl(String address) { - final String baseUrl = transactions; - return baseUrl.replaceAll("###", address); + final baseUrl = transactions; + return baseUrl.replaceAll('###', address); } String getBlockHeight(int blockHaight) { - final String baseUrl = blockHeight; - return baseUrl.replaceAll("###", "$blockHaight"); + final baseUrl = blockHeight; + return baseUrl.replaceAll('###', '$blockHaight'); } factory APIConfig.fromBlockCypher(BasedUtxoNetwork network) { @@ -67,19 +67,19 @@ class APIConfig { break; default: throw DartBitcoinPluginException( - "blockcypher does not support ${network.conf.coinName.name}, u must use your own provider"); + 'blockcypher does not support ${network.conf.coinName.name}, u must use your own provider'); } return APIConfig( url: - "$baseUrl/addrs/###/?unspentOnly=true&includeScript=true&limit=2000", + '$baseUrl/addrs/###/?unspentOnly=true&includeScript=true&limit=2000', feeRate: baseUrl, - transaction: "$baseUrl/txs/###", - sendTransaction: "$baseUrl/txs/push", + transaction: '$baseUrl/txs/###', + sendTransaction: '$baseUrl/txs/push', apiType: APIType.blockCypher, - transactions: "$baseUrl/addrs/###/full?limit=200", + transactions: '$baseUrl/addrs/###/full?limit=200', network: network, - blockHeight: "$baseUrl/blocks/###"); + blockHeight: '$baseUrl/blocks/###'); } factory APIConfig.mempool(BasedUtxoNetwork network) { @@ -93,18 +93,18 @@ class APIConfig { break; default: throw DartBitcoinPluginException( - "mempool does not support ${network.conf.coinName.name}"); + 'mempool does not support ${network.conf.coinName.name}'); } return APIConfig( - url: "$baseUrl/address/###/utxo", - feeRate: "$baseUrl/v1/fees/recommended", - transaction: "$baseUrl/tx/###", - sendTransaction: "$baseUrl/tx", + url: '$baseUrl/address/###/utxo', + feeRate: '$baseUrl/v1/fees/recommended', + transaction: '$baseUrl/tx/###', + sendTransaction: '$baseUrl/tx', apiType: APIType.mempool, - transactions: "$baseUrl/address/###/txs", + transactions: '$baseUrl/address/###/txs', network: network, - blockHeight: "$baseUrl/block-height/###"); + blockHeight: '$baseUrl/block-height/###'); } APIConfig( diff --git a/lib/src/provider/models/electrum/electrum_utxo.dart b/lib/src/provider/models/electrum/electrum_utxo.dart index 9fd9abc..0c168e2 100644 --- a/lib/src/provider/models/electrum/electrum_utxo.dart +++ b/lib/src/provider/models/electrum/electrum_utxo.dart @@ -5,14 +5,14 @@ import 'package:bitcoin_base/src/provider/api_provider.dart'; class ElectrumUtxo implements UTXO { factory ElectrumUtxo.fromJson(Map json) { CashToken? token; - if (json.containsKey("token_data")) { - token = CashToken.fromJson(json["token_data"]); + if (json.containsKey('token_data')) { + token = CashToken.fromJson(json['token_data']); } return ElectrumUtxo._( - height: json["height"], - txId: json["tx_hash"], - vout: json["tx_pos"], - value: BigInt.parse((json["value"].toString())), + height: json['height'], + txId: json['tx_hash'], + vout: json['tx_pos'], + value: BigInt.parse((json['value'].toString())), token: token); } const ElectrumUtxo._( diff --git a/lib/src/provider/models/fee_rate/fee_rate.dart b/lib/src/provider/models/fee_rate/fee_rate.dart index e3885e5..ec94008 100644 --- a/lib/src/provider/models/fee_rate/fee_rate.dart +++ b/lib/src/provider/models/fee_rate/fee_rate.dart @@ -50,7 +50,7 @@ class BitcoinFeeRate { BigInt getEstimate(int trSize, {BigInt? customFeeRatePerKb, BitcoinFeeRateType feeRateType = BitcoinFeeRateType.medium}) { - final BigInt feeRate = customFeeRatePerKb ?? _feeRatrete(feeRateType); + final feeRate = customFeeRatePerKb ?? _feeRatrete(feeRateType); final trSizeBigInt = BigInt.from(trSize); return (trSizeBigInt * feeRate) ~/ BigInt.from(1000); } @@ -100,6 +100,6 @@ BigInt _parseMempoolFees(dynamic data) { return BigInt.from((data * kb)); } else { throw DartBitcoinPluginException( - "cannot parse mempool fees excepted double, string got ${data.runtimeType}"); + 'cannot parse mempool fees excepted double, string got ${data.runtimeType}'); } } diff --git a/lib/src/provider/models/mempool/mempol_models.dart b/lib/src/provider/models/mempool/mempol_models.dart index d194d57..46cd8c8 100644 --- a/lib/src/provider/models/mempool/mempol_models.dart +++ b/lib/src/provider/models/mempool/mempol_models.dart @@ -186,7 +186,7 @@ class MempolUtxo implements UTXO { extension MempoolUtxoExtentions on List { List toUtxoWithOwnerList(UtxoAddressDetails owner) { - final List utxos = map((e) => UtxoWithAddress( + final utxos = map((e) => UtxoWithAddress( utxo: BitcoinUtxo( txHash: e.txid, value: e.value, diff --git a/lib/src/provider/models/multisig_script.dart b/lib/src/provider/models/multisig_script.dart index 28a05c3..15603d1 100644 --- a/lib/src/provider/models/multisig_script.dart +++ b/lib/src/provider/models/multisig_script.dart @@ -6,7 +6,7 @@ import 'package:blockchain_utils/blockchain_utils.dart'; /// signers in a multi-signature scheme. A multi-signature signer typically includes /// information about their public key and weight within the scheme. class MultiSignatureSigner { - MultiSignatureSigner._(this.publicKey, this.weight, this.isCompressed); + MultiSignatureSigner._(this.publicKey, this.weight, this.keyType); /// PublicKey returns the public key associated with the signer. final String publicKey; @@ -15,7 +15,7 @@ class MultiSignatureSigner { /// The weight is used to determine the number of signatures required for a valid transaction. final int weight; - final bool isCompressed; + final PublicKeyType keyType; /// creates a new instance of a multi-signature signer with the /// specified public key and weight. @@ -23,7 +23,7 @@ class MultiSignatureSigner { {required String publicKey, required int weight}) { ECPublic.fromHex(publicKey); return MultiSignatureSigner._( - publicKey, weight, BtcUtils.hasCompressedPubKeyLength(publicKey)); + publicKey, weight, BtcUtils.isCompressedPubKey(publicKey)); } } @@ -56,7 +56,7 @@ class MultiSignatureAddress { BitcoinBaseAddress toP2wshAddress({required BasedUtxoNetwork network}) { if (network is! LitecoinNetwork && network is! BitcoinNetwork) { throw DartBitcoinPluginException( - "${network.conf.coinName.name} Bitcoin forks that do not support Segwit. use toP2shAddress"); + '${network.conf.coinName.name} Bitcoin forks that do not support Segwit. use toP2shAddress'); } if (!canSelectSegwit) { throw const DartBitcoinPluginException( @@ -102,7 +102,7 @@ class MultiSignatureAddress { return toP2shAddress(addressType as P2shAddressType); default: throw const DartBitcoinPluginException( - "invalid multisig address type. use of of them [BitcoinAddressType.p2wsh, BitcoinAddressType.p2wshInP2sh, BitcoinAddressType.p2pkhInP2sh]"); + 'invalid multisig address type. use of of them [BitcoinAddressType.p2wsh, BitcoinAddressType.p2wshInP2sh, BitcoinAddressType.p2pkhInP2sh]'); } } @@ -144,6 +144,6 @@ class MultiSignatureAddress { signers: signers, threshold: threshold, multiSigScript: script, - canSelectSegwit: signers.every((e) => e.isCompressed)); + canSelectSegwit: signers.every((e) => e.keyType.isCompressed)); } } diff --git a/lib/src/provider/models/utxo_details.dart b/lib/src/provider/models/utxo_details.dart index ea987b6..abb5a1c 100644 --- a/lib/src/provider/models/utxo_details.dart +++ b/lib/src/provider/models/utxo_details.dart @@ -7,7 +7,7 @@ abstract class UTXO { class UtxoAddressDetails { /// PublicKey is the public key associated with the UTXO owner. - final String? _publicKey; + final String? publicKey; /// Address is the Bitcoin address associated with the UTXO owner. final BitcoinBaseAddress address; @@ -17,13 +17,9 @@ class UtxoAddressDetails { final MultiSignatureAddress? _multiSigAddress; UtxoAddressDetails._({ - required String publicKey, + required String this.publicKey, required this.address, - }) : _multiSigAddress = null, - _publicKey = publicKey; - - /// The public key format (compressed or uncompressed) is crucial for non-SegWit addresses. - /// If your address is non-SegWit, ensure you use the correct public key format. + }) : _multiSigAddress = null; factory UtxoAddressDetails( {required String publicKey, required BitcoinBaseAddress address}) { ECPublic.fromHex(publicKey); @@ -32,11 +28,11 @@ class UtxoAddressDetails { UtxoAddressDetails.multiSigAddress( {required MultiSignatureAddress multiSigAddress, required this.address}) - : _publicKey = null, + : publicKey = null, _multiSigAddress = multiSigAddress; UtxoAddressDetails.watchOnly(this.address) - : _publicKey = null, + : publicKey = null, _multiSigAddress = null; } @@ -50,32 +46,30 @@ class UtxoWithAddress { final UtxoAddressDetails ownerDetails; const UtxoWithAddress._( - {required this.utxo, - required this.ownerDetails, - required this.isCompressed}); + {required this.utxo, required this.ownerDetails, required this.keyType}); factory UtxoWithAddress( {required BitcoinUtxo utxo, required UtxoAddressDetails ownerDetails}) { return UtxoWithAddress._( utxo: utxo, ownerDetails: ownerDetails, - isCompressed: ownerDetails._publicKey != null && !utxo.isSegwit - ? BtcUtils.hasCompressedPubKeyLength(ownerDetails._publicKey!) - : true); + keyType: ownerDetails.publicKey != null && !utxo.isSegwit + ? BtcUtils.isCompressedPubKey(ownerDetails.publicKey!) + : PublicKeyType.compressed); } ECPublic public() { if (isMultiSig()) { throw const DartBitcoinPluginException( - "Cannot access public key in multi-signature address"); + 'Cannot access public key in multi-signature address'); } - if (ownerDetails._publicKey == null) { + if (ownerDetails.publicKey == null) { throw const DartBitcoinPluginException( - "Cannot access public key in watch only address; use UtxoAddressDetails constractor instead `UtxoAddressDetails.watchOnly`"); + 'Cannot access public key in watch only address; use UtxoAddressDetails constractor instead `UtxoAddressDetails.watchOnly`'); } - return ECPublic.fromHex(ownerDetails._publicKey!); + return ECPublic.fromHex(ownerDetails.publicKey!); } - final bool isCompressed; + final PublicKeyType keyType; bool isMultiSig() { return ownerDetails._multiSigAddress != null; @@ -84,7 +78,7 @@ class UtxoWithAddress { MultiSignatureAddress get multiSigAddress => isMultiSig() ? ownerDetails._multiSigAddress! : throw const DartBitcoinPluginException( - "The address is not associated with a multi-signature setup"); + 'The address is not associated with a multi-signature setup'); } /// Abstract base class representing a generic Bitcoin output. @@ -219,7 +213,7 @@ class BitcoinUtxo { required BitcoinAddressType scriptType, int? blockHeight, CashToken? token}) { - final bool isP2shSegwit = scriptType == P2shAddressType.p2wpkhInP2sh || + final isP2shSegwit = scriptType == P2shAddressType.p2wpkhInP2sh || scriptType == P2shAddressType.p2wshInP2sh; return BitcoinUtxo._( txHash: txHash, @@ -249,7 +243,7 @@ class BitcoinUtxo { @override String toString() { - return "txid: $txHash vout: $vout script: ${scriptType.value} value: $value blockHeight: $blockHeight"; + return 'txid: $txHash vout: $vout script: ${scriptType.value} value: $value blockHeight: $blockHeight'; } } @@ -257,7 +251,7 @@ class BitcoinUtxo { extension Calculate on List { /// sum of utxos network values BigInt sumOfUtxosValue() { - BigInt sum = BigInt.zero; + var sum = BigInt.zero; for (final utxo in this) { sum += utxo.utxo.value; } @@ -266,7 +260,7 @@ extension Calculate on List { /// sum of utxos cash token (FToken) amounts Map sumOfTokenUtxos() { - final Map tokens = {}; + final tokens = {}; for (final utxo in this) { if (utxo.utxo.token == null) continue; final token = utxo.utxo.token!; diff --git a/lib/src/provider/providers/electrum.dart b/lib/src/provider/providers/electrum.dart new file mode 100644 index 0000000..b98116e --- /dev/null +++ b/lib/src/provider/providers/electrum.dart @@ -0,0 +1,57 @@ +import 'package:bitcoin_base/src/provider/core/params.dart'; +import 'package:bitcoin_base/src/provider/services/electrum.dart'; +import 'package:blockchain_utils/blockchain_utils.dart'; +import 'dart:async'; + +class ElectrumProvider extends BaseProvider { + final ElectrumServiceProvider rpc; + ElectrumProvider(this.rpc); + + /// The unique identifier for each JSON-RPC request. + int _id = 0; + + /// Sends a request to the Electrum server using the specified [request] parameter. + /// + /// The [timeout] parameter, if provided, sets the maximum duration for the request. + @override + Future request( + BaseServiceRequest + request, + {Duration? timeout}) async { + final r = await requestDynamic(request, timeout: timeout); + return request.onResonse(r); + } + + /// Sends a request to the Electrum server using the specified [request] parameter. + /// + /// The [timeout] parameter, if provided, sets the maximum duration for the request. + @override + Future requestDynamic( + BaseServiceRequest + request, + {Duration? timeout}) async { + final params = request.buildRequest(_id++); + final response = + await rpc.doRequest>(params, timeout: timeout); + return _findResult(params: params, response: response); + } + + SERVICERESPONSE _findResult( + {required BaseServiceResponse> response, + required ElectrumRequestDetails params}) { + final data = response.getResult(params); + final error = data['error']; + if (error != null) { + final errorJson = StringUtils.tryToJson>(error); + final code = IntUtils.tryParse(errorJson?['code']); + final message = errorJson?['message']?.toString(); + throw RPCError( + errorCode: code, + message: message ?? error.toString(), + request: params.toJson(), + details: errorJson); + } + return ServiceProviderUtils.parseResponse( + object: data['result'], params: params); + } +} diff --git a/lib/src/provider/api_provider/api_provider.dart b/lib/src/provider/providers/explorer.dart similarity index 82% rename from lib/src/provider/api_provider/api_provider.dart rename to lib/src/provider/providers/explorer.dart index 1dc5c81..c0cc0e6 100644 --- a/lib/src/provider/api_provider/api_provider.dart +++ b/lib/src/provider/providers/explorer.dart @@ -1,13 +1,13 @@ import 'dart:convert'; import 'package:bitcoin_base/src/provider/models/models.dart'; -import 'package:bitcoin_base/src/provider/service/http/http_service.dart'; +import 'package:bitcoin_base/src/provider/services/explorer.dart'; import 'package:bitcoin_base/src/models/network.dart'; import 'package:blockchain_utils/utils/string/string.dart'; class ApiProvider { ApiProvider( {required this.api, Map? header, required this.service}) - : _header = header ?? {"Content-Type": "application/json"}; + : _header = header ?? {'Content-Type': 'application/json'}; factory ApiProvider.fromMempool(BasedUtxoNetwork network, ApiService service, {Map? header}) { final api = APIConfig.mempool(network); @@ -29,20 +29,20 @@ class ApiProvider { return response; } - Future _postReqiest(String url, Object? data) async { + Future _postRequest(String url, Object? data) async { final response = await service.post(url, body: data, headers: _header); return response; } Future> testmempool(List params) async { - final Map data = { - "jsonrpc": "2.0", - "method": "testmempoolaccept", - "id": DateTime.now().millisecondsSinceEpoch.toString(), - "params": params + final data = { + 'jsonrpc': '2.0', + 'method': 'testmempoolaccept', + 'id': DateTime.now().millisecondsSinceEpoch.toString(), + 'params': params }; - final response = await _postReqiest>( - "https://btc.getblock.io/786c97b8-f53f-427b-80f7-9af7bd5bdb84/testnet/", + final response = await _postRequest>( + 'https://btc.getblock.io/786c97b8-f53f-427b-80f7-9af7bd5bdb84/testnet/', json.encode(data)); return response; } @@ -70,15 +70,15 @@ class ApiProvider { switch (api.apiType) { case APIType.mempool: - final response = await _postReqiest(url, txDigest); + final response = await _postRequest(url, txDigest); return response; default: - final Map digestData = {"tx": txDigest}; - final response = await _postReqiest>( + final digestData = {'tx': txDigest}; + final response = await _postRequest>( url, json.encode(digestData)); BlockCypherTransaction? tr; - if (response["tx"] != null) { - tr = BlockCypherTransaction.fromJson(response["tx"]); + if (response['tx'] != null) { + tr = BlockCypherTransaction.fromJson(response['tx']); } tr ??= BlockCypherTransaction.fromJson(response); @@ -125,8 +125,8 @@ class ApiProvider { return transactions; default: if (response is Map) { - if (response.containsKey("txs")) { - final transactions = (response["txs"] as List) + if (response.containsKey('txs')) { + final transactions = (response['txs'] as List) .map((e) => BlockCypherTransaction.fromJson(e) as T) .toList(); return transactions; @@ -148,7 +148,7 @@ class ApiProvider { return response; default: final toJson = StringUtils.toJson>(response); - return toJson["hash"]; + return toJson['hash']; } } diff --git a/lib/src/provider/service/electrum/electrum.dart b/lib/src/provider/service/electrum/electrum.dart deleted file mode 100644 index c8b56be..0000000 --- a/lib/src/provider/service/electrum/electrum.dart +++ /dev/null @@ -1,3 +0,0 @@ -export 'methods.dart'; -export 'params.dart'; -export 'service.dart'; diff --git a/lib/src/provider/service/electrum/params.dart b/lib/src/provider/service/electrum/params.dart deleted file mode 100644 index da5a07a..0000000 --- a/lib/src/provider/service/electrum/params.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:blockchain_utils/blockchain_utils.dart'; - -/// Abstract class representing parameters for Electrum requests. -abstract class ElectrumRequestParams { - abstract final String method; - List toJson(); -} - -/// Represents details of an Electrum request, including id, method, and parameters. -class ElectrumRequestDetails { - const ElectrumRequestDetails({ - required this.id, - required this.method, - required this.params, - }); - - final int id; - - final String method; - - final Map params; - - List toTCPParams() { - final param = "${StringUtils.fromJson(params)}\n"; - return StringUtils.encode(param); - } - - List toWebSocketParams() { - return StringUtils.encode(StringUtils.fromJson(params)); - } -} - -/// Abstract class representing an Electrum request with generic result and response types. -abstract class ElectrumRequest - implements ElectrumRequestParams { - String? get validate => null; - - RESULT onResonse(RESPONSE result) { - return result as RESULT; - } - - ElectrumRequestDetails toRequest(int requestId) { - final List inJson = toJson(); - inJson.removeWhere((v) => v == null); - final params = { - "jsonrpc": "2.0", - "method": method, - "params": inJson, - "id": requestId, - }; - return ElectrumRequestDetails( - id: requestId, params: params, method: method); - } -} diff --git a/lib/src/provider/service/electrum/service.dart b/lib/src/provider/service/electrum/service.dart deleted file mode 100644 index 889b194..0000000 --- a/lib/src/provider/service/electrum/service.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:bitcoin_base/src/provider/service/electrum/params.dart'; - -/// A mixin for providing JSON-RPC service functionality. -mixin BitcoinBaseElectrumRPCService { - /// Represents the URL endpoint for JSON-RPC calls. - String get url; - - /// Makes an HTTP GET request to the Tron network with the specified [params]. - /// - /// The optional [timeout] parameter sets the maximum duration for the request. - Future> call(ElectrumRequestDetails params, - [Duration? timeout]); -} diff --git a/lib/src/provider/service/services.dart b/lib/src/provider/service/services.dart deleted file mode 100644 index 69edf79..0000000 --- a/lib/src/provider/service/services.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'http/http_service.dart'; -export 'electrum/electrum.dart'; diff --git a/lib/src/provider/services/electrum.dart b/lib/src/provider/services/electrum.dart new file mode 100644 index 0000000..37a1ea0 --- /dev/null +++ b/lib/src/provider/services/electrum.dart @@ -0,0 +1,10 @@ +import 'package:bitcoin_base/src/provider/core/params.dart'; +import 'package:blockchain_utils/service/models/params.dart'; + +/// A mixin defining the service provider contract for interacting with the bitcoin (elctrum) network. +mixin ElectrumServiceProvider + implements BaseServiceProvider { + @override + Future> doRequest(ElectrumRequestDetails params, + {Duration? timeout}); +} diff --git a/lib/src/provider/service/http/http_service.dart b/lib/src/provider/services/explorer.dart similarity index 88% rename from lib/src/provider/service/http/http_service.dart rename to lib/src/provider/services/explorer.dart index 99631b8..8ab80bd 100644 --- a/lib/src/provider/service/http/http_service.dart +++ b/lib/src/provider/services/explorer.dart @@ -13,6 +13,6 @@ abstract class ApiService { /// - [headers]: A map of headers to be included in the request. /// - [body]: The request body, typically in JSON format. Future post(String url, - {Map headers = const {"Content-Type": "application/json"}, + {Map headers = const {'Content-Type': 'application/json'}, Object? body}); } diff --git a/lib/src/provider/transaction_builder/builder.dart b/lib/src/transaction_builder/builder.dart similarity index 100% rename from lib/src/provider/transaction_builder/builder.dart rename to lib/src/transaction_builder/builder.dart diff --git a/lib/src/provider/transaction_builder/core.dart b/lib/src/transaction_builder/core.dart similarity index 100% rename from lib/src/provider/transaction_builder/core.dart rename to lib/src/transaction_builder/core.dart diff --git a/lib/src/provider/transaction_builder/forked_transaction_builder.dart b/lib/src/transaction_builder/forked_transaction_builder.dart similarity index 89% rename from lib/src/provider/transaction_builder/forked_transaction_builder.dart rename to lib/src/transaction_builder/forked_transaction_builder.dart index 1c7c55a..0980e9b 100644 --- a/lib/src/provider/transaction_builder/forked_transaction_builder.dart +++ b/lib/src/transaction_builder/forked_transaction_builder.dart @@ -47,7 +47,7 @@ class ForkedTransactionBuilder implements BasedBitcoinTransacationBuilder { void _validateBuilder() { if (network is! BitcoinCashNetwork && network is! BitcoinSVNetwork) { throw const DartBitcoinPluginException( - "invalid network. use ForkedTransactionBuilder for BitcoinCashNetwork and BSVNetwork otherwise use BitcoinTransactionBuilder"); + 'invalid network. use ForkedTransactionBuilder for BitcoinCashNetwork and BSVNetwork otherwise use BitcoinTransactionBuilder'); } /// validate every address is related to network @@ -103,8 +103,8 @@ class ForkedTransactionBuilder implements BasedBitcoinTransacationBuilder { isFakeTransaction: true); /// 72 bytes (64 byte signature, 6-7 byte Der encoding length + sighash) - const String fakeECDSASignatureBytes = - "010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"; + const fakeECDSASignatureBytes = + '010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101'; final transaction = transactionBuilder .buildTransaction((trDigest, utxo, multiSigPublicKey, int sighash) { @@ -129,29 +129,28 @@ class ForkedTransactionBuilder implements BasedBitcoinTransacationBuilder { return script; default: throw DartBitcoinPluginException( - "unsuported multi-sig type ${utxo.utxo.scriptType} for ${network.conf.coinName.name}"); + 'unsuported multi-sig type ${utxo.utxo.scriptType} for ${network.conf.coinName.name}'); } } final senderPub = utxo.public(); - final bool isCompressed = utxo.isCompressed; switch (utxo.utxo.scriptType) { case PubKeyAddressType.p2pk: case P2shAddressType.p2pkInP2sh: case P2shAddressType.p2pkInP2shwt: case P2shAddressType.p2pkInP2sh32: case P2shAddressType.p2pkInP2sh32wt: - return senderPub.toRedeemScript(compressed: isCompressed); + return senderPub.toRedeemScript(mode: utxo.keyType); case P2pkhAddressType.p2pkh: case P2shAddressType.p2pkhInP2sh: case P2shAddressType.p2pkhInP2sh32: case P2pkhAddressType.p2pkhwt: case P2shAddressType.p2pkhInP2shwt: case P2shAddressType.p2pkhInP2sh32wt: - return senderPub.toAddress(compressed: isCompressed).toScriptPubKey(); + return senderPub.toAddress(mode: utxo.keyType).toScriptPubKey(); default: throw DartBitcoinPluginException( - "${utxo.utxo.scriptType} does not sudpport on ${network.conf.coinName.name}"); + '${utxo.utxo.scriptType} does not sudpport on ${network.conf.coinName.name}'); } } @@ -210,29 +209,27 @@ that demonstrate the right to spend the bitcoins associated with the correspondi */ List _buildUnlockingScript(String signedDigest, UtxoWithAddress utx) { final senderPub = utx.public(); - final bool isCompressed = utx.isCompressed; switch (utx.utxo.scriptType) { case PubKeyAddressType.p2pk: return [signedDigest]; case P2pkhAddressType.p2pkh: case P2pkhAddressType.p2pkhwt: - return [signedDigest, senderPub.toHex(compressed: isCompressed)]; + return [signedDigest, senderPub.toHex(mode: utx.keyType)]; case P2shAddressType.p2pkhInP2sh: case P2shAddressType.p2pkhInP2shwt: case P2shAddressType.p2pkhInP2sh32: case P2shAddressType.p2pkhInP2sh32wt: - final script = - senderPub.toAddress(compressed: isCompressed).toScriptPubKey(); + final script = senderPub.toAddress(mode: utx.keyType).toScriptPubKey(); return [ signedDigest, - senderPub.toHex(compressed: isCompressed), + senderPub.toHex(mode: utx.keyType), script.toHex() ]; case P2shAddressType.p2pkInP2sh: case P2shAddressType.p2pkInP2shwt: case P2shAddressType.p2pkInP2sh32: case P2shAddressType.p2pkInP2sh32wt: - final script = senderPub.toRedeemScript(compressed: isCompressed); + final script = senderPub.toRedeemScript(mode: utx.keyType); return [signedDigest, script.toHex()]; default: throw DartBitcoinPluginException( @@ -241,7 +238,7 @@ that demonstrate the right to spend the bitcoins associated with the correspondi } Tuple, List> _buildInputs() { - List sortedUtxos = List.from(utxosInfo); + var sortedUtxos = List.from(utxosInfo); if (inputOrdering == BitcoinOrdering.shuffle) { sortedUtxos = sortedUtxos..shuffle(); @@ -257,8 +254,7 @@ that demonstrate the right to spend the bitcoins associated with the correspondi }, ); } - final List inputs = - sortedUtxos.map((e) => e.utxo.toInput()).toList(); + final inputs = sortedUtxos.map((e) => e.utxo.toInput()).toList(); if (enableRBF && inputs.isNotEmpty) { inputs[0] = inputs[0] .copyWith(sequence: BitcoinOpCodeConst.REPLACE_BY_FEE_SEQUENCE); @@ -268,7 +264,7 @@ that demonstrate the right to spend the bitcoins associated with the correspondi } List _buildOutputs() { - List outputs = outPuts + var outputs = outPuts .where((element) => element is! BitcoinBurnableOutput) .map((e) => e.toOutput) .toList(); @@ -304,12 +300,12 @@ be retrieved by anyone who examines the blockchain's history. */ Script _opReturn(String message) { final toHex = BytesUtils.toHexString(StringUtils.toBytes(message)); - return Script(script: ["OP_RETURN", toHex]); + return Script(script: ['OP_RETURN', toHex]); } /// Total amount to spend excluding fees BigInt _sumOutputAmounts(List outputs) { - BigInt sum = BigInt.zero; + var sum = BigInt.zero; for (final e in outputs) { sum += e.amount; } @@ -318,7 +314,7 @@ be retrieved by anyone who examines the blockchain's history. /// Total token amount to spend. Map _sumTokenOutputAmounts(List outputs) { - final Map tokens = {}; + final tokens = {}; for (final utxo in outputs) { if (utxo.cashToken == null) continue; final token = utxo.cashToken!; @@ -342,9 +338,9 @@ be retrieved by anyone who examines the blockchain's history. if (sumAmountsWithFee != sumUtxoAmount) { throw DartBitcoinPluginException('Sum value of utxo not spending', details: { - "inputAmount": sumUtxoAmount, - "fee": fee, - "outputAmount": sumOutputAmounts + 'inputAmount': sumUtxoAmount, + 'fee': fee, + 'outputAmount': sumOutputAmounts }); } @@ -355,7 +351,7 @@ be retrieved by anyone who examines the blockchain's history. final sumTokenOutputAmouts = _sumTokenOutputAmounts(outputs); for (final i in sumOfTokenUtxos.entries) { if (sumTokenOutputAmouts[i.key] != i.value) { - BigInt amount = sumTokenOutputAmouts[i.key] ?? BigInt.zero; + var amount = sumTokenOutputAmouts[i.key] ?? BigInt.zero; amount += outPuts .whereType() .where((element) => element.categoryID == i.key) @@ -368,9 +364,9 @@ be retrieved by anyone who examines the blockchain's history. throw DartBitcoinPluginException( 'Sum token value of UTXOs not spending. use BitcoinBurnableOutput if you want to burn tokens.', details: { - "token": i.key, - "inputValue": i.value, - "outputValue": amount + 'token': i.key, + 'inputValue': i.value, + 'outputValue': amount }); } } @@ -392,7 +388,7 @@ be retrieved by anyone who examines the blockchain's history. if (hasBurnableOutput) continue; throw DartBitcoinPluginException( 'Some NFTs in the inputs lack the corresponding spending in the outputs. If you intend to burn tokens, consider utilizing the BitcoinBurnableOutput.', - details: {"category id": token.category}); + details: {'category id': token.category}); } } } @@ -400,27 +396,27 @@ be retrieved by anyone who examines the blockchain's history. @override Map getSignatureCount() { final sortedInputs = _buildInputs(); - final List inputs = sortedInputs.item1; - final List utxos = sortedInputs.item2; - final Map count = {}; + final inputs = sortedInputs.item1; + final utxos = sortedInputs.item2; + final count = {}; - for (int i = 0; i < inputs.length; i++) { + for (var i = 0; i < inputs.length; i++) { final indexUtxo = utxos[i]; if (indexUtxo.isMultiSig()) { final multiSigAddress = indexUtxo.multiSigAddress; - int sumMultiSigWeight = 0; + var sumMultiSigWeight = 0; final mutlsiSigSignatures = []; - for (int ownerIndex = 0; + for (var ownerIndex = 0; ownerIndex < multiSigAddress.signers.length; ownerIndex++) { - for (int weight = 0; + for (var weight = 0; weight < multiSigAddress.signers[ownerIndex].weight; weight++) { if (mutlsiSigSignatures.length >= multiSigAddress.threshold) { break; } - mutlsiSigSignatures.add(""); + mutlsiSigSignatures.add(''); count[multiSigAddress.signers[ownerIndex].publicKey] = (count[multiSigAddress.signers[ownerIndex].publicKey] ?? 0) + 1; } @@ -431,7 +427,7 @@ be retrieved by anyone who examines the blockchain's history. } if (sumMultiSigWeight < multiSigAddress.threshold) { throw const DartBitcoinPluginException( - "some multisig signature does not exist"); + 'some multisig signature does not exist'); } continue; } @@ -446,9 +442,9 @@ be retrieved by anyone who examines the blockchain's history. /// build inputs final sortedInputs = _buildInputs(); - final List inputs = sortedInputs.item1; + final inputs = sortedInputs.item1; - final List utxos = sortedInputs.item2; + final utxos = sortedInputs.item2; /// build outout final outputs = _buildOutputs(); @@ -475,11 +471,11 @@ be retrieved by anyone who examines the blockchain's history. // transaction = transaction.copyWith(inputs: inputs); final transaction = BtcTransaction(inputs: inputs, outputs: outputs, hasSegwit: false); - const int sighash = + const sighash = BitcoinOpCodeConst.SIGHASH_ALL | BitcoinOpCodeConst.SIGHASH_FORKED; /// Well, now let's do what we want for each input - for (int i = 0; i < inputs.length; i++) { + for (var i = 0; i < inputs.length; i++) { final indexUtxo = utxos[i]; /// We receive the owner's ScriptPubKey @@ -496,16 +492,16 @@ be retrieved by anyone who examines the blockchain's history. /// handle multisig address if (indexUtxo.isMultiSig()) { final multiSigAddress = indexUtxo.multiSigAddress; - int sumMultiSigWeight = 0; + var sumMultiSigWeight = 0; final mutlsiSigSignatures = []; - for (int ownerIndex = 0; + for (var ownerIndex = 0; ownerIndex < multiSigAddress.signers.length; ownerIndex++) { /// now we need sign the transaction digest final sig = sign(digest, indexUtxo, multiSigAddress.signers[ownerIndex].publicKey, sighash); if (sig.isEmpty) continue; - for (int weight = 0; + for (var weight = 0; weight < multiSigAddress.signers[ownerIndex].weight; weight++) { if (mutlsiSigSignatures.length >= multiSigAddress.threshold) { @@ -520,7 +516,7 @@ be retrieved by anyone who examines the blockchain's history. } if (sumMultiSigWeight < multiSigAddress.threshold) { throw const DartBitcoinPluginException( - "some multisig signature does not exist"); + 'some multisig signature does not exist'); } _addScripts( @@ -529,7 +525,8 @@ be retrieved by anyone who examines the blockchain's history. } /// now we need sign the transaction digest - final sig = sign(digest, indexUtxo, indexUtxo.public().toHex(), sighash); + final sig = + sign(digest, indexUtxo, indexUtxo.ownerDetails.publicKey!, sighash); _addScripts(input: inputs[i], signatures: [sig], utxo: indexUtxo); } final ea = BtcTransaction.fromRaw(transaction.serialize()); @@ -543,9 +540,9 @@ be retrieved by anyone who examines the blockchain's history. /// build inputs final sortedInputs = _buildInputs(); - final List inputs = sortedInputs.item1; + final inputs = sortedInputs.item1; - final List utxos = sortedInputs.item2; + final utxos = sortedInputs.item2; /// build outout final outputs = _buildOutputs(); @@ -570,11 +567,11 @@ be retrieved by anyone who examines the blockchain's history. final transaction = BtcTransaction(inputs: inputs, outputs: outputs, hasSegwit: false); - const int sighash = + const sighash = BitcoinOpCodeConst.SIGHASH_ALL | BitcoinOpCodeConst.SIGHASH_FORKED; /// Well, now let's do what we want for each input - for (int i = 0; i < inputs.length; i++) { + for (var i = 0; i < inputs.length; i++) { final indexUtxo = utxos[i]; /// We receive the owner's ScriptPubKey @@ -591,9 +588,9 @@ be retrieved by anyone who examines the blockchain's history. /// handle multisig address if (indexUtxo.isMultiSig()) { final multiSigAddress = indexUtxo.multiSigAddress; - int sumMultiSigWeight = 0; + var sumMultiSigWeight = 0; final mutlsiSigSignatures = []; - for (int ownerIndex = 0; + for (var ownerIndex = 0; ownerIndex < multiSigAddress.signers.length; ownerIndex++) { /// now we need sign the transaction digest @@ -601,7 +598,7 @@ be retrieved by anyone who examines the blockchain's history. multiSigAddress.signers[ownerIndex].publicKey, sighash); if (sig.isEmpty) continue; - for (int weight = 0; + for (var weight = 0; weight < multiSigAddress.signers[ownerIndex].weight; weight++) { if (mutlsiSigSignatures.length >= multiSigAddress.threshold) { @@ -617,7 +614,7 @@ be retrieved by anyone who examines the blockchain's history. } if (sumMultiSigWeight < multiSigAddress.threshold) { throw const DartBitcoinPluginException( - "some multisig signature does not exist"); + 'some multisig signature does not exist'); } _addScripts( @@ -626,8 +623,8 @@ be retrieved by anyone who examines the blockchain's history. } /// now we need sign the transaction digest - final sig = - await sign(digest, indexUtxo, indexUtxo.public().toHex(), sighash); + final sig = await sign( + digest, indexUtxo, indexUtxo.ownerDetails.publicKey!, sighash); _addScripts(input: inputs[i], signatures: [sig], utxo: indexUtxo); } return transaction; diff --git a/lib/src/provider/transaction_builder/transaction_builder.dart b/lib/src/transaction_builder/transaction_builder.dart similarity index 87% rename from lib/src/provider/transaction_builder/transaction_builder.dart rename to lib/src/transaction_builder/transaction_builder.dart index ba0afd6..57aafa8 100644 --- a/lib/src/provider/transaction_builder/transaction_builder.dart +++ b/lib/src/transaction_builder/transaction_builder.dart @@ -49,14 +49,14 @@ class BitcoinTransactionBuilder implements BasedBitcoinTransacationBuilder { void _validateBuilder() { if (network is BitcoinCashNetwork || network is BitcoinSVNetwork) { throw const DartBitcoinPluginException( - "invalid network for BitcoinCashNetwork and BSVNetwork use ForkedTransactionBuilder"); + 'invalid network for BitcoinCashNetwork and BSVNetwork use ForkedTransactionBuilder'); } final token = utxosInfo.any((element) => element.utxo.token != null); final tokenInput = outPuts.whereType(); final burn = outPuts.whereType(); if (token || tokenInput.isNotEmpty || burn.isNotEmpty) { throw const DartBitcoinPluginException( - "Cash Token only work on Bitcoin cash network"); + 'Cash Token only work on Bitcoin cash network'); } for (final i in utxosInfo) { /// Verify each input for its association with this network's address. Raise an exception if the address is incorrect. @@ -113,16 +113,19 @@ class BitcoinTransactionBuilder implements BasedBitcoinTransacationBuilder { ); /// 64 byte schnorr signature length - const String fakeSchnorSignaturBytes = - "01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"; + const fakeSchnorSignaturBytes = + '01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101'; /// 72 bytes (64 byte signature, 6-7 byte Der encoding length) - const String fakeECDSASignatureBytes = - "010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"; + const fakeECDSASignatureBytes = + '010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101'; final transaction = transactionBuilder .buildTransaction((trDigest, utxo, multiSigPublicKey, int sighash) { if (utxo.utxo.isP2tr) { + if (sighash != BitcoinOpCodeConst.TAPROOT_SIGHASH_ALL) { + return '${fakeSchnorSignaturBytes}01'; + } return fakeSchnorSignaturBytes; } else { return fakeECDSASignatureBytes; @@ -194,23 +197,21 @@ class BitcoinTransactionBuilder implements BasedBitcoinTransacationBuilder { return script; default: throw DartBitcoinPluginException( - "unsuported multi-sig type ${utxo.utxo.scriptType}"); + 'unsuported multi-sig type ${utxo.utxo.scriptType}'); } } final senderPub = utxo.public(); switch (utxo.utxo.scriptType) { case PubKeyAddressType.p2pk: - return senderPub.toRedeemScript(compressed: utxo.isCompressed); + return senderPub.toRedeemScript(mode: utxo.keyType); case SegwitAddressType.p2wsh: if (isTaproot) { return senderPub.toP2wshAddress().toScriptPubKey(); } return senderPub.toP2wshScript(); case P2pkhAddressType.p2pkh: - return senderPub - .toAddress(compressed: utxo.isCompressed) - .toScriptPubKey(); + return senderPub.toAddress(mode: utxo.keyType).toScriptPubKey(); case SegwitAddressType.p2wpkh: if (isTaproot) { return senderPub.toSegwitAddress().toScriptPubKey(); @@ -220,13 +221,9 @@ class BitcoinTransactionBuilder implements BasedBitcoinTransacationBuilder { return senderPub.toTaprootAddress().toScriptPubKey(); case P2shAddressType.p2pkhInP2sh: if (isTaproot) { - return senderPub - .toP2pkhInP2sh(compressed: utxo.isCompressed) - .toScriptPubKey(); + return senderPub.toP2pkhInP2sh(mode: utxo.keyType).toScriptPubKey(); } - return senderPub - .toAddress(compressed: utxo.isCompressed) - .toScriptPubKey(); + return senderPub.toAddress(mode: utxo.keyType).toScriptPubKey(); case P2shAddressType.p2wpkhInP2sh: if (isTaproot) { return senderPub.toP2wpkhInP2sh().toScriptPubKey(); @@ -239,13 +236,11 @@ class BitcoinTransactionBuilder implements BasedBitcoinTransacationBuilder { return senderPub.toP2wshScript(); case P2shAddressType.p2pkInP2sh: if (isTaproot) { - return senderPub - .toP2pkInP2sh(compressed: utxo.isCompressed) - .toScriptPubKey(); + return senderPub.toP2pkInP2sh(mode: utxo.keyType).toScriptPubKey(); } - return senderPub.toRedeemScript(compressed: utxo.isCompressed); + return senderPub.toRedeemScript(mode: utxo.keyType); } - throw const DartBitcoinPluginException("invalid bitcoin address type"); + throw const DartBitcoinPluginException('invalid bitcoin address type'); } /// generateTransactionDigest generates and returns a transaction digest for a given input in the context of a Bitcoin @@ -323,7 +318,7 @@ class BitcoinTransactionBuilder implements BasedBitcoinTransacationBuilder { return [p2wsh.toScriptPubKey().toHex()]; default: throw DartBitcoinPluginException( - "Invalid p2sh nested segwit type ${utxo.utxo.scriptType.value}"); + 'Invalid p2sh nested segwit type ${utxo.utxo.scriptType.value}'); } } final senderPub = utxo.public(); @@ -336,7 +331,7 @@ class BitcoinTransactionBuilder implements BasedBitcoinTransacationBuilder { return [script.toHex()]; default: throw DartBitcoinPluginException( - "Invalid p2sh nested segwit type ${utxo.utxo.scriptType.value}"); + 'Invalid p2sh nested segwit type ${utxo.utxo.scriptType.value}'); } } @@ -362,35 +357,30 @@ that demonstrate the right to spend the bitcoins associated with the correspondi return [signedDigest, senderPub.toHex()]; default: throw DartBitcoinPluginException( - "invalid segwit address type ${utx.utxo.scriptType.value}"); + 'invalid segwit address type ${utx.utxo.scriptType.value}'); } } else { - final bool isCompressed = utx.isCompressed; + final mode = utx.keyType; switch (utx.utxo.scriptType) { case PubKeyAddressType.p2pk: return [signedDigest]; case P2pkhAddressType.p2pkh: - return [signedDigest, senderPub.toHex(compressed: isCompressed)]; + return [signedDigest, senderPub.toHex(mode: mode)]; case P2shAddressType.p2pkhInP2sh: - final script = - senderPub.toAddress(compressed: isCompressed).toScriptPubKey(); - return [ - signedDigest, - senderPub.toHex(compressed: isCompressed), - script.toHex() - ]; + final script = senderPub.toAddress(mode: mode).toScriptPubKey(); + return [signedDigest, senderPub.toHex(mode: mode), script.toHex()]; case P2shAddressType.p2pkInP2sh: - final script = senderPub.toRedeemScript(compressed: isCompressed); + final script = senderPub.toRedeemScript(mode: mode); return [signedDigest, script.toHex()]; default: throw DartBitcoinPluginException( - "invalid address type ${utx.utxo.scriptType.value}"); + 'invalid address type ${utx.utxo.scriptType.value}'); } } } Tuple, List> _buildInputs() { - List sortedUtxos = List.from(utxosInfo); + var sortedUtxos = List.from(utxosInfo); if (inputOrdering == BitcoinOrdering.shuffle) { sortedUtxos = sortedUtxos..shuffle(); @@ -406,8 +396,7 @@ that demonstrate the right to spend the bitcoins associated with the correspondi }, ); } - final List inputs = - sortedUtxos.map((e) => e.utxo.toInput()).toList(); + final inputs = sortedUtxos.map((e) => e.utxo.toInput()).toList(); if (enableRBF && inputs.isNotEmpty) { inputs[0] = inputs[0] .copyWith(sequence: BitcoinOpCodeConst.REPLACE_BY_FEE_SEQUENCE); @@ -417,7 +406,7 @@ that demonstrate the right to spend the bitcoins associated with the correspondi } List _buildOutputs() { - List outputs = outPuts.map((e) => e.toOutput).toList(); + var outputs = outPuts.map((e) => e.toOutput).toList(); if (memo != null) { outputs .add(TxOutput(amount: BigInt.zero, scriptPubKey: _opReturn(memo!))); @@ -439,8 +428,8 @@ that demonstrate the right to spend the bitcoins associated with the correspondi } for (final i in outputs) { if (i.amount.isNegative) { - throw DartBitcoinPluginException("Some output has negative amount.", - details: {"output": i.amount}); + throw DartBitcoinPluginException('Some output has negative amount.', + details: {'output': i.amount}); } } return List.unmodifiable(outputs); @@ -452,12 +441,12 @@ that demonstrate the right to spend the bitcoins associated with the correspondi /// be retrieved by anyone who examines the blockchain's history. Script _opReturn(String message) { final toHex = BytesUtils.toHexString(StringUtils.toBytes(message)); - return Script(script: ["OP_RETURN", toHex]); + return Script(script: ['OP_RETURN', toHex]); } /// Total amount to spend excluding fees BigInt _sumOutputAmounts(List outputs) { - BigInt sum = BigInt.zero; + var sum = BigInt.zero; for (final e in outputs) { sum += e.amount; } @@ -469,9 +458,9 @@ that demonstrate the right to spend the bitcoins associated with the correspondi /// build inputs final sortedInputs = _buildInputs(); - final List inputs = sortedInputs.item1; + final inputs = sortedInputs.item1; - final List utxos = sortedInputs.item2; + final utxos = sortedInputs.item2; /// build outout final outputs = _buildOutputs(); @@ -497,7 +486,7 @@ that demonstrate the right to spend the bitcoins associated with the correspondi } /// create new transaction with inputs and outputs and isSegwit transaction or not - BtcTransaction transaction = + var transaction = BtcTransaction(inputs: inputs, outputs: outputs, hasSegwit: hasSegwit); /// we define empty witnesses. maybe the transaction is segwit and We need this @@ -505,8 +494,8 @@ that demonstrate the right to spend the bitcoins associated with the correspondi /// when the transaction is taproot and we must use getTaproot tansaction digest /// we need all of inputs amounts and owner script pub keys - List taprootAmounts = []; - List