diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 47378eef5..648798ba6 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -93,6 +93,7 @@ jobs: cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs - name: Add secrets diff --git a/.gitignore b/.gitignore index 6fd8f33d6..4381469f7 100644 --- a/.gitignore +++ b/.gitignore @@ -124,6 +124,7 @@ lib/bitcoin/bitcoin.dart lib/monero/monero.dart lib/haven/haven.dart lib/ethereum/ethereum.dart +lib/bitcoin_cash/bitcoin_cash.dart ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_120.png diff --git a/cw_bitcoin_cash/.gitignore b/cw_bitcoin_cash/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/cw_bitcoin_cash/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/cw_bitcoin_cash/.metadata b/cw_bitcoin_cash/.metadata new file mode 100644 index 000000000..4161da6ea --- /dev/null +++ b/cw_bitcoin_cash/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + channel: stable + +project_type: package diff --git a/cw_bitcoin_cash/CHANGELOG.md b/cw_bitcoin_cash/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/cw_bitcoin_cash/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/cw_bitcoin_cash/LICENSE b/cw_bitcoin_cash/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/cw_bitcoin_cash/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/cw_bitcoin_cash/README.md b/cw_bitcoin_cash/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/cw_bitcoin_cash/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/cw_bitcoin_cash/analysis_options.yaml b/cw_bitcoin_cash/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/cw_bitcoin_cash/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/cw_bitcoin_cash/lib/cw_bitcoin_cash.dart b/cw_bitcoin_cash/lib/cw_bitcoin_cash.dart new file mode 100644 index 000000000..732474ac4 --- /dev/null +++ b/cw_bitcoin_cash/lib/cw_bitcoin_cash.dart @@ -0,0 +1,9 @@ +library cw_bitcoin_cash; + +export 'src/bitcoin_cash_base.dart'; + +/// A Calculator. +class Calculator { + /// Returns [value] plus 1. + int addOne(int value) => value + 1; +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_balance.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_balance.dart new file mode 100644 index 000000000..fd484af81 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_balance.dart @@ -0,0 +1,13 @@ +import 'package:cw_core/balance.dart'; + +class BitcoinCashBalance extends Balance { + BitcoinCashBalance(this.balance) : super(balance, balance); + + final int balance; + + @override + String get formattedAdditionalBalance => balance.toString(); + + @override + String get formattedAvailableBalance => balance.toString(); +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_base.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_base.dart new file mode 100644 index 000000000..e80df0763 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_base.dart @@ -0,0 +1,11 @@ +export 'bitcoin_cash_balance.dart'; +export 'bitcoin_cash_client.dart'; +export 'bitcoin_cash_transaction_history.dart'; +export 'bitcoin_cash_transaction_info.dart'; +export 'bitcoin_cash_transaction_priority.dart'; +export 'bitcoin_cash_wallet.dart'; +export 'bitcoin_cash_wallet_addresses.dart'; +export 'bitcoin_cash_wallet_creation_credentials.dart'; +export 'bitcoin_cash_wallet_service.dart'; +export 'exceptions/exceptions.dart'; +export 'mnemonic.dart'; diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_client.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_client.dart new file mode 100644 index 000000000..8632c7fba --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_client.dart @@ -0,0 +1 @@ +class BitcoinCashClient {} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_pending_transaction.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_pending_transaction.dart new file mode 100644 index 000000000..417f8d19a --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_pending_transaction.dart @@ -0,0 +1,25 @@ +import 'package:cw_core/pending_transaction.dart'; + +class BitcoinCashPendingTransaction with PendingTransaction { + @override + // TODO: implement amountFormatted + String get amountFormatted => throw UnimplementedError('amountFormatted is not implemented'); + + @override + Future commit() { + // TODO: implement commit + throw UnimplementedError('commit is not implemented'); + } + + @override + // TODO: implement feeFormatted + String get feeFormatted => throw UnimplementedError('feeFormatted is not implemented'); + + @override + // TODO: implement hex + String get hex => throw UnimplementedError('hex is not implemented'); + + @override + // TODO: implement id + String get id => throw UnimplementedError('id is not implemented'); +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_history.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_history.dart new file mode 100644 index 000000000..ec5873e59 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_history.dart @@ -0,0 +1,38 @@ +import 'dart:core'; + +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:mobx/mobx.dart'; + +import 'bitcoin_cash_transaction_info.dart'; + +part 'bitcoin_cash_transaction_history.g.dart'; + +class BitcoinCashTransactionHistory = BitcoinCashTransactionHistoryBase + with _$BitcoinCashTransactionHistory; + +abstract class BitcoinCashTransactionHistoryBase + extends TransactionHistoryBase with Store { + BitcoinCashTransactionHistoryBase({required this.walletInfo, required String password}) + : _password = password, + _height = 0 { + transactions = ObservableMap(); + } + + final WalletInfo walletInfo; + String _password; + int _height; + + @override + Future save() async { + // TODO: implement + UnimplementedError('save() is not implemented'); + } + + @override + void addOne(BitcoinCashTransactionInfo transaction) => transactions[transaction.id] = transaction; + + @override + void addMany(Map transactions) => + this.transactions.addAll(transactions); +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_info.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_info.dart new file mode 100644 index 000000000..fc2cd85dc --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_info.dart @@ -0,0 +1,68 @@ +import 'package:cw_core/format_amount.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_info.dart'; + +class BitcoinCashTransactionInfo extends TransactionInfo { + BitcoinCashTransactionInfo({ + required this.id, + required this.height, + required this.amount, + required this.fee, + this.tokenSymbol = "BCH", + this.exponent = 18, + required this.direction, + required this.isPending, + required this.date, + required this.confirmations, + }); + + final String id; + final int height; + final int amount; + final int exponent; + final TransactionDirection direction; + final DateTime date; + final bool isPending; + final int fee; + final int confirmations; + final String tokenSymbol; + String? _fiatAmount; + + @override + String amountFormatted() => + '${formatAmount((BigInt.from(amount) / BigInt.from(10).pow(exponent)).toString())} $tokenSymbol'; + + @override + String fiatAmount() => _fiatAmount ?? ''; + + @override + void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); + + @override + String feeFormatted() => '${(BigInt.from(fee) / BigInt.from(10).pow(exponent)).toString()} BCH'; + + factory BitcoinCashTransactionInfo.fromJson(Map data) { + return BitcoinCashTransactionInfo( + id: data['id'] as String, + height: data['height'] as int, + amount: data['amount'] as int, + fee: data['fee'] as int, + direction: parseTransactionDirectionFromInt(data['direction'] as int), + date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int), + isPending: data['isPending'] as bool, + confirmations: data['confirmations'] as int); + } + + Map toJson() { + final m = {}; + m['id'] = id; + m['height'] = height; + m['amount'] = amount; + m['direction'] = direction.index; + m['date'] = date.millisecondsSinceEpoch; + m['isPending'] = isPending; + m['confirmations'] = confirmations; + m['fee'] = fee; + return m; + } +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_priority.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_priority.dart new file mode 100644 index 000000000..971480270 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_transaction_priority.dart @@ -0,0 +1,9 @@ +import 'package:cw_core/transaction_priority.dart'; + +class BitcoinCashTransactionPriority extends TransactionPriority{ + BitcoinCashTransactionPriority({required super.title, required super.raw}); + + static BitcoinCashTransactionPriority deserialize ({required int raw}) { + throw UnimplementedError('BitcoinCashTransactionPriority.deserialize() is not implemented'); + } +} \ No newline at end of file diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart new file mode 100644 index 000000000..eadf30673 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -0,0 +1,90 @@ +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cw_bitcoin/bitcoin_address_record.dart'; +import 'package:cw_bitcoin/electrum_balance.dart'; +import 'package:cw_bitcoin/electrum_wallet.dart'; +import 'package:cw_bitcoin/electrum_wallet_snapshot.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; + +import 'bitcoin_cash_base.dart'; + +part 'bitcoin_cash_wallet.g.dart'; + +class BitcoinCashWallet = BitcoinCashWalletBase with _$BitcoinCashWallet; + +abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { + BitcoinCashWalletBase( + {required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + List? initialAddresses, + ElectrumBalance? initialBalance, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) + : super( + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + networkType: bitcoin.bitcoin, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: seedBytes, + currency: CryptoCurrency.bch) { + walletAddresses = BitcoinCashWalletAddresses(walletInfo, + electrumClient: electrumClient, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: hd, + //TODO: BCH check if this is correct + networkType: networkType); + } + + static Future create( + {required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + List? initialAddresses, + ElectrumBalance? initialBalance, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) async { + return BitcoinCashWallet( + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: await Mnemonic.toSeed(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex); + } + + static Future open({ + required String name, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required String password, + }) async { + final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + return BitcoinCashWallet( + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + initialBalance: snp.balance, + seedBytes: await Mnemonic.toSeed(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex); + } +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart new file mode 100644 index 000000000..c7329f0de --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -0,0 +1,34 @@ +import 'package:bitbox/bitbox.dart' as Bitbox; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cw_bitcoin/bitcoin_address_record.dart'; +import 'package:cw_bitcoin/electrum.dart'; +import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:mobx/mobx.dart'; + +part 'bitcoin_cash_wallet_addresses.g.dart'; + +class BitcoinCashWalletAddresses = BitcoinCashWalletAddressesBase with _$BitcoinCashWalletAddresses; + +abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses with Store { + BitcoinCashWalletAddressesBase(WalletInfo walletInfo, + {required bitcoin.HDWallet mainHd, + required bitcoin.HDWallet sideHd, + required bitcoin.NetworkType networkType, + required ElectrumClient electrumClient, + List? initialAddresses, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) + : super(walletInfo, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: mainHd, + sideHd: sideHd, + electrumClient: electrumClient, + networkType: networkType); + + @override + String getAddress({required int index, required bitcoin.HDWallet hd}) => + hd.address!; +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart new file mode 100644 index 000000000..72caa6c58 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart @@ -0,0 +1,26 @@ +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; + +class BitcoinCashNewWalletCredentials extends WalletCredentials { + BitcoinCashNewWalletCredentials({required String name, WalletInfo? walletInfo}) + : super(name: name, walletInfo: walletInfo); +} + +class BitcoinCashRestoreWalletFromSeedCredentials extends WalletCredentials { + BitcoinCashRestoreWalletFromSeedCredentials( + {required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String mnemonic; +} + +class BitcoinCashRestoreWalletFromWIFCredentials extends WalletCredentials { + BitcoinCashRestoreWalletFromWIFCredentials( + {required String name, required String password, required this.wif, WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String wif; +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart new file mode 100644 index 000000000..0906df73b --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -0,0 +1,91 @@ +import 'dart:io'; + +import 'package:bip39/bip39.dart'; +import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; +import 'package:cw_core/balance.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:collection/collection.dart'; +import 'package:hive/hive.dart'; + +class BitcoinCashWalletService extends WalletService { + BitcoinCashWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); + + final Box walletInfoSource; + final Box unspentCoinsInfoSource; + + @override + WalletType getType() => WalletType.bitcoinCash; + + @override + Future isWalletExit(String name) async => + File(await pathForWallet(name: name, type: getType())).existsSync(); + + @override + Future create( + credentials) async { + final wallet = await BitcoinCashWalletBase.create( + mnemonic: await Mnemonic.generate(), + password: credentials.password!, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.save(); + await wallet.init(); + return wallet; + } + + @override + Future openWallet(String name, String password) async { + final walletInfo = walletInfoSource.values.firstWhereOrNull( + (info) => info.id == WalletBase.idFor(name, getType()))!; + final wallet = await BitcoinCashWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + return wallet; + } + + @override + Future remove(String wallet) { + // TODO: implement remove + throw UnimplementedError('remove() is not implemented'); + } + + @override + Future rename(String currentName, String password, String newName) { + // TODO: implement rename + throw UnimplementedError('rename() is not implemented'); + } + + @override + Future + restoreFromKeys(credentials) { + // TODO: implement restoreFromKeys + throw UnimplementedError('restoreFromKeys() is not implemented'); + } + + @override + Future restoreFromSeed( + BitcoinCashRestoreWalletFromSeedCredentials credentials) async { + if (!validateMnemonic(credentials.mnemonic)) { + throw BitcoinCashMnemonicIsIncorrectException(); + } + + final wallet = await BitcoinCashWalletBase.create( + password: credentials.password!, + mnemonic: credentials.mnemonic, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.save(); + await wallet.init(); + return wallet; + } +} diff --git a/cw_bitcoin_cash/lib/src/exceptions/bitcoin_cash_mnemonic_is_incorrect_exception.dart b/cw_bitcoin_cash/lib/src/exceptions/bitcoin_cash_mnemonic_is_incorrect_exception.dart new file mode 100644 index 000000000..7cce59085 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/exceptions/bitcoin_cash_mnemonic_is_incorrect_exception.dart @@ -0,0 +1,5 @@ +class BitcoinCashMnemonicIsIncorrectException implements Exception { + @override + String toString() => + 'Bitcoin Cash mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; +} diff --git a/cw_bitcoin_cash/lib/src/exceptions/exceptions.dart b/cw_bitcoin_cash/lib/src/exceptions/exceptions.dart new file mode 100644 index 000000000..746e3248a --- /dev/null +++ b/cw_bitcoin_cash/lib/src/exceptions/exceptions.dart @@ -0,0 +1 @@ +export 'bitcoin_cash_mnemonic_is_incorrect_exception.dart'; \ No newline at end of file diff --git a/cw_bitcoin_cash/lib/src/mnemonic.dart b/cw_bitcoin_cash/lib/src/mnemonic.dart new file mode 100644 index 000000000..b1f1ee984 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/mnemonic.dart @@ -0,0 +1,11 @@ +import 'dart:typed_data'; + +import 'package:bip39/bip39.dart' as bip39; + +class Mnemonic { + /// Generate bip39 mnemonic + static String generate({int strength = 128}) => bip39.generateMnemonic(strength: strength); + + /// Create root seed from mnemonic + static Uint8List toSeed(String mnemonic) => bip39.mnemonicToSeed(mnemonic); +} diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..7d9244fbe --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/borod/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.0/ \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..e71a16d23 --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..e0f0a47bc --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000..2e1de87a7 --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift b/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 000000000..e777c67df --- /dev/null +++ b/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,12 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import path_provider_foundation + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) +} diff --git a/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig new file mode 100644 index 000000000..2f46994d3 --- /dev/null +++ b/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -0,0 +1,11 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=C:\Users\borod\flutter +FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=0.0.1 +FLUTTER_BUILD_NUMBER=0.0.1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh b/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh new file mode 100644 index 000000000..2a3bcca5a --- /dev/null +++ b/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=C:\Users\borod\flutter" +export "FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=0.0.1" +export "FLUTTER_BUILD_NUMBER=0.0.1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml new file mode 100644 index 000000000..8a354f0e7 --- /dev/null +++ b/cw_bitcoin_cash/pubspec.yaml @@ -0,0 +1,76 @@ +name: cw_bitcoin_cash +description: A new Flutter package project. +version: 0.0.1 +publish_to: none +author: Cake Wallet +homepage: https://cakewallet.com + +environment: + sdk: '>=2.19.0 <3.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + bip39: ^1.0.6 + bip32: ^2.0.0 + path_provider: ^2.0.11 + mobx: ^2.0.7+4 + flutter_mobx: ^2.0.6+1 + cw_core: + path: ../cw_core + cw_bitcoin: + path: ../cw_bitcoin + bitcoin_flutter: + git: + url: https://github.com/cake-tech/bitcoin_flutter.git + ref: cake-update-v2 + bitbox: + git: + url: https://github.com/Serhii-Borodenko/cw_bitbox.git + ref: main + + + +dev_dependencies: + flutter_test: + sdk: flutter + build_runner: ^2.1.11 + mobx_codegen: ^2.0.7 + hive_generator: ^1.1.3 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + +# To add assets to your package, add an assets section, like this: +# assets: +# - images/a_dot_burr.jpeg +# - images/a_dot_ham.jpeg +# +# For details regarding assets in packages, see +# https://flutter.dev/assets-and-images/#from-packages +# +# An image asset can refer to one or more resolution-specific "variants", see +# https://flutter.dev/assets-and-images/#resolution-aware + +# To add custom fonts to your package, add a fonts section here, +# in this "flutter" section. Each entry in this list should have a +# "family" key with the font family name, and a "fonts" key with a +# list giving the asset and other descriptors for the font. For +# example: +# fonts: +# - family: Schyler +# fonts: +# - asset: fonts/Schyler-Regular.ttf +# - asset: fonts/Schyler-Italic.ttf +# style: italic +# - family: Trajan Pro +# fonts: +# - asset: fonts/TrajanPro.ttf +# - asset: fonts/TrajanPro_Bold.ttf +# weight: 700 +# + diff --git a/cw_bitcoin_cash/test/cw_bitcoin_cash_test.dart b/cw_bitcoin_cash/test/cw_bitcoin_cash_test.dart new file mode 100644 index 000000000..f06646a8f --- /dev/null +++ b/cw_bitcoin_cash/test/cw_bitcoin_cash_test.dart @@ -0,0 +1,12 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; + +void main() { + test('adds one to input values', () { + final calculator = Calculator(); + expect(calculator.addOne(2), 3); + expect(calculator.addOne(-7), -6); + expect(calculator.addOne(0), 1); + }); +} diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..8b6d4680a --- /dev/null +++ b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..dc139d85a --- /dev/null +++ b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake b/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000..b93c4c30c --- /dev/null +++ b/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/cw_core/lib/currency_for_wallet_type.dart b/cw_core/lib/currency_for_wallet_type.dart index 8ac8c1fc6..584adb197 100644 --- a/cw_core/lib/currency_for_wallet_type.dart +++ b/cw_core/lib/currency_for_wallet_type.dart @@ -13,6 +13,8 @@ CryptoCurrency currencyForWalletType(WalletType type) { return CryptoCurrency.xhv; case WalletType.ethereum: return CryptoCurrency.eth; + case WalletType.bitcoinCash: + return CryptoCurrency.bch; default: throw Exception('Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType'); } diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index 62c2ad410..3555ba2ab 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -10,6 +10,7 @@ const walletTypes = [ WalletType.litecoin, WalletType.haven, WalletType.ethereum, + WalletType.bitcoinCash, ]; @HiveType(typeId: WALLET_TYPE_TYPE_ID) @@ -31,6 +32,9 @@ enum WalletType { @HiveField(5) ethereum, + + @HiveField(6) + bitcoinCash, } int serializeToInt(WalletType type) { @@ -45,6 +49,8 @@ int serializeToInt(WalletType type) { return 3; case WalletType.ethereum: return 4; + case WalletType.bitcoinCash: + return 5; default: return -1; } @@ -62,6 +68,8 @@ WalletType deserializeFromInt(int raw) { return WalletType.haven; case 4: return WalletType.ethereum; + case 4: + return WalletType.bitcoinCash; default: throw Exception('Unexpected token: $raw for WalletType deserializeFromInt'); } @@ -79,6 +87,8 @@ String walletTypeToString(WalletType type) { return 'Haven'; case WalletType.ethereum: return 'Ethereum'; + case WalletType.bitcoinCash: + return 'Bitcoin Cash'; default: return ''; } @@ -96,6 +106,8 @@ String walletTypeToDisplayName(WalletType type) { return 'Haven (XHV)'; case WalletType.ethereum: return 'Ethereum (ETH)'; + case WalletType.bitcoinCash: + return 'Bitcoin Cash (BCH)'; default: return ''; } @@ -113,6 +125,8 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type) { return CryptoCurrency.xhv; case WalletType.ethereum: return CryptoCurrency.eth; + case WalletType.bitcoinCash: + return CryptoCurrency.bch; default: throw Exception('Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency'); } diff --git a/lib/bitcoin_cash/cw_bitcoin_cash.dart b/lib/bitcoin_cash/cw_bitcoin_cash.dart new file mode 100644 index 000000000..f098c5234 --- /dev/null +++ b/lib/bitcoin_cash/cw_bitcoin_cash.dart @@ -0,0 +1,168 @@ +part of 'bitcoin_cash.dart'; + +class CWBitcoinCash extends BitcoinCash { + @override + String getMnemonic(int? strength) => Mnemonic.generate(); + + @override + Uint8List getSeedFromMnemonic(String seed) => Mnemonic.toSeed(seed); + + @override + WalletService createBitcoinCashWalletService( + Box walletInfoSource, Box unspentCoinSource) { + return BitcoinCashWalletService(walletInfoSource, unspentCoinSource); + } + + @override + WalletCredentials createBitcoinCashNewWalletCredentials({ + required String name, + WalletInfo? walletInfo, + }) => + BitcoinCashNewWalletCredentials(name: name, walletInfo: walletInfo); + +// @override +// TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium; +// +// @override +// WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({ +// required String name, +// required String mnemonic, +// required String password}) +// => BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password); +// +// @override +// WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({ +// required String name, +// required String password, +// required String wif, +// WalletInfo? walletInfo}) +// => BitcoinRestoreWalletFromWIFCredentials(name: name, password: password, wif: wif, walletInfo: walletInfo); +// +// @override +// WalletCredentials createBitcoinNewWalletCredentials({ +// required String name, +// WalletInfo? walletInfo}) +// => BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo); +// +// +// @override +// Map getWalletKeys(Object wallet) { +// final bitcoinWallet = wallet as ElectrumWallet; +// final keys = bitcoinWallet.keys; +// +// return { +// 'wif': keys.wif, +// 'privateKey': keys.privateKey, +// 'publicKey': keys.publicKey +// }; +// } +// +// @override +// List getTransactionPriorities() +// => BitcoinTransactionPriority.all; +// +// List getLitecoinTransactionPriorities() +// => LitecoinTransactionPriority.all; +// +// @override +// TransactionPriority deserializeBitcoinTransactionPriority(int raw) +// => BitcoinTransactionPriority.deserialize(raw: raw); +// +// @override +// TransactionPriority deserializeLitecoinTransactionPriority(int raw) +// => LitecoinTransactionPriority.deserialize(raw: raw); +// +// @override +// int getFeeRate(Object wallet, TransactionPriority priority) { +// final bitcoinWallet = wallet as ElectrumWallet; +// return bitcoinWallet.feeRate(priority); +// } +// +// @override +// Future generateNewAddress(Object wallet) async { +// final bitcoinWallet = wallet as ElectrumWallet; +// await bitcoinWallet.walletAddresses.generateNewAddress(); +// } +// +// @override +// Object createBitcoinTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}) +// => BitcoinTransactionCredentials( +// outputs.map((out) => OutputInfo( +// fiatAmount: out.fiatAmount, +// cryptoAmount: out.cryptoAmount, +// address: out.address, +// note: out.note, +// sendAll: out.sendAll, +// extractedAddress: out.extractedAddress, +// isParsedAddress: out.isParsedAddress, +// formattedCryptoAmount: out.formattedCryptoAmount)) +// .toList(), +// priority: priority as BitcoinTransactionPriority, +// feeRate: feeRate); +// +// @override +// Object createBitcoinTransactionCredentialsRaw(List outputs, {TransactionPriority? priority, required int feeRate}) +// => BitcoinTransactionCredentials( +// outputs, +// priority: priority != null ? priority as BitcoinTransactionPriority : null, +// feeRate: feeRate); +// +// @override +// List getAddresses(Object wallet) { +// final bitcoinWallet = wallet as ElectrumWallet; +// return bitcoinWallet.walletAddresses.addresses +// .map((BitcoinAddressRecord addr) => addr.address) +// .toList(); +// } +// +// @override +// String getAddress(Object wallet) { +// final bitcoinWallet = wallet as ElectrumWallet; +// return bitcoinWallet.walletAddresses.address; +// } +// +// @override +// String formatterBitcoinAmountToString({required int amount}) +// => bitcoinAmountToString(amount: amount); +// +// @override +// double formatterBitcoinAmountToDouble({required int amount}) +// => bitcoinAmountToDouble(amount: amount); +// +// @override +// int formatterStringDoubleToBitcoinAmount(String amount) +// => stringDoubleToBitcoinAmount(amount); +// +// @override +// String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate) +// => (priority as BitcoinTransactionPriority).labelWithRate(rate); +// +// void updateUnspents(Object wallet) async { +// final bitcoinWallet = wallet as ElectrumWallet; +// await bitcoinWallet.updateUnspent(); +// } +// +// WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource) { +// return BitcoinWalletService(walletInfoSource, unspentCoinSource); +// } +// +// WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource) { +// return LitecoinWalletService(walletInfoSource, unspentCoinSource); +// } +// +// @override +// TransactionPriority getBitcoinTransactionPriorityMedium() +// => BitcoinTransactionPriority.medium; +// +// @override +// TransactionPriority getLitecoinTransactionPriorityMedium() +// => LitecoinTransactionPriority.medium; +// +// @override +// TransactionPriority getBitcoinTransactionPrioritySlow() +// => BitcoinTransactionPriority.slow; +// +// @override +// TransactionPriority getLitecoinTransactionPrioritySlow() +// => LitecoinTransactionPriority.slow; +} diff --git a/model_generator.sh b/model_generator.sh index d6e417843..17531009a 100644 --- a/model_generator.sh +++ b/model_generator.sh @@ -3,4 +3,5 @@ cd cw_monero && flutter pub get && flutter packages pub run build_runner build - cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs \ No newline at end of file diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh index 72703150a..76cb0c8ca 100755 --- a/scripts/android/pubspec_gen.sh +++ b/scripts/android/pubspec_gen.sh @@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --bitcoinCash" ;; $HAVEN) CONFIG_ARGS="--haven" diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh index 470f47efc..2ede037b0 100755 --- a/scripts/ios/app_config.sh +++ b/scripts/ios/app_config.sh @@ -23,9 +23,11 @@ case $APP_IOS_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --bitcoinCash" ;; $HAVEN) + + CONFIG_ARGS="--haven" ;; esac diff --git a/tool/configure.dart b/tool/configure.dart index 3d846e8a6..7c151f93e 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -4,6 +4,7 @@ const bitcoinOutputPath = 'lib/bitcoin/bitcoin.dart'; const moneroOutputPath = 'lib/monero/monero.dart'; const havenOutputPath = 'lib/haven/haven.dart'; const ethereumOutputPath = 'lib/ethereum/ethereum.dart'; +const bitcoinCashOutputPath = 'lib/bitcoin_cash/bitcoin_cash.dart'; const walletTypesPath = 'lib/wallet_types.g.dart'; const pubspecDefaultPath = 'pubspec_default.yaml'; const pubspecOutputPath = 'pubspec.yaml'; @@ -14,12 +15,14 @@ Future main(List args) async { final hasMonero = args.contains('${prefix}monero'); final hasHaven = args.contains('${prefix}haven'); final hasEthereum = args.contains('${prefix}ethereum'); + final hasBitcoinCash = args.contains('${prefix}bitcoinCash'); await generateBitcoin(hasBitcoin); await generateMonero(hasMonero); await generateHaven(hasHaven); await generateEthereum(hasEthereum); - await generatePubspec(hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum); - await generateWalletTypes(hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum); + await generateBitcoinCash(hasBitcoinCash); + await generatePubspec(hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum, hasBitcoinCash: hasBitcoinCash); + await generateWalletTypes(hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum, hasBitcoinCash: hasBitcoinCash); } Future generateBitcoin(bool hasImplementation) async { @@ -555,7 +558,49 @@ abstract class Ethereum { await outputFile.writeAsString(output); } -Future generatePubspec({required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum}) async { +Future generateBitcoinCash(bool hasImplementation) async { + + final outputFile = File(bitcoinCashOutputPath); + const bitcoinCashCommonHeaders = """ +import 'dart:typed_data'; + +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:hive/hive.dart'; +"""; + const bitcoinCashCWHeaders = """ +import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; +"""; + const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';"; + const bitcoinCashContent = """ +abstract class BitcoinCash { + String getMnemonic(int? strength); + Uint8List getSeedFromMnemonic(String seed); + WalletService createBitcoinCashWalletService(Box walletInfoSource, Box unspentCoinSource); + WalletCredentials createBitcoinCashNewWalletCredentials({required String name, WalletInfo? walletInfo}); +} + """; + + const bitcoinCashEmptyDefinition = 'BitcoinCash? bitcoinCash;\n'; + const bitcoinCashCWDefinition = 'BitcoinCash? bitcoinCash = CWBitcoinCash();\n'; + + final output = '$bitcoinCashCommonHeaders\n' + + (hasImplementation ? '$bitcoinCashCWHeaders\n' : '\n') + + (hasImplementation ? '$bitcoinCashCwPart\n\n' : '\n') + + (hasImplementation ? bitcoinCashCWDefinition : bitcoinCashEmptyDefinition) + + '\n' + + bitcoinCashContent; + + if (outputFile.existsSync()) { + await outputFile.delete(); + } + + await outputFile.writeAsString(output); +} + +Future generatePubspec({required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum, required bool hasBitcoinCash}) async { const cwCore = """ cw_core: path: ./cw_core @@ -580,6 +625,10 @@ Future generatePubspec({required bool hasMonero, required bool hasBitcoin, cw_ethereum: path: ./cw_ethereum """; + const cwBitcoinCash = """ + cw_bitcoin_cash: + path: ./cw_bitcoin_cash + """; final inputFile = File(pubspecOutputPath); final inputText = await inputFile.readAsString(); final inputLines = inputText.split('\n'); @@ -604,6 +653,10 @@ Future generatePubspec({required bool hasMonero, required bool hasBitcoin, output += '\n$cwEthereum'; } + if (hasBitcoinCash) { + output += '\n$cwBitcoinCash'; + } + final outputLines = output.split('\n'); inputLines.insertAll(dependenciesIndex + 1, outputLines); final outputContent = inputLines.join('\n'); @@ -616,7 +669,7 @@ Future generatePubspec({required bool hasMonero, required bool hasBitcoin, await outputFile.writeAsString(outputContent); } -Future generateWalletTypes({required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum}) async { +Future generateWalletTypes({required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum, required bool hasBitcoinCash}) async { final walletTypesFile = File(walletTypesPath); if (walletTypesFile.existsSync()) { @@ -643,6 +696,10 @@ Future generateWalletTypes({required bool hasMonero, required bool hasBitc outputContent += '\tWalletType.litecoin,\n'; } + if (hasBitcoinCash) { + outputContent += '\tWalletType.bitcoinCash,\n'; + } + if (hasHaven) { outputContent += '\tWalletType.haven,\n'; }