Merge branch 'main' of https://github.com/cake-tech/cake_wallet into bitcoin-derivations

This commit is contained in:
fosse 2023-10-18 09:16:31 -04:00
commit cead157c93
13 changed files with 78 additions and 58 deletions

View file

@ -1,5 +1,3 @@
Add Nano wallet
Add WalletConnect to connect your ETH wallet with your favorite dApp
Support getting Addresses from ENS and Mastodon
Add BitcoinCash (BCH)
Bug fixes
Minor enhancements
Accessibility enhancements

View file

@ -272,7 +272,7 @@ SPEC CHECKSUMS:
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d

View file

@ -248,6 +248,7 @@ Future<void> setup({
required Box<Order> ordersSource,
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfoSource,
required FlutterSecureStorage secureStorage,
}) async {
_walletInfoSource = walletInfoSource;
_nodeSource = nodeSource;
@ -289,7 +290,7 @@ Future<void> setup({
getIt.registerFactory<Box<Node>>(() => _nodeSource);
getIt.registerFactory<Box<Node>>(() => _powNodeSource, instanceName: Node.boxName + "pow");
getIt.registerSingleton<FlutterSecureStorage>(FlutterSecureStorage());
getIt.registerSingleton<FlutterSecureStorage>(secureStorage);
getIt.registerSingleton(AuthenticationStore());
getIt.registerSingleton<WalletListStore>(WalletListStore());
getIt.registerSingleton(NodeListStoreBase.instance);

View file

@ -46,7 +46,13 @@ class AddressResolver {
}
final match = RegExp(addressPattern).firstMatch(raw);
return match?.group(0)?.replaceAll(RegExp('[^0-9a-zA-Z_]'), '');
return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_|ban_'), (Match match) {
String group = match.group(0)!;
if (group.startsWith('bitcoincash:') || group.startsWith('nano_') || group.startsWith('ban_')) {
return group;
}
return '';
});
}
Future<ParsedAddress> resolve(String text, String ticker) async {
@ -59,16 +65,11 @@ class AddressResolver {
if (addressFromBio != null) {
return ParsedAddress.fetchTwitterAddress(address: addressFromBio, name: text);
}
final tweets = twitterUser.tweets;
if (tweets != null) {
var subString = StringBuffer();
tweets.forEach((item) {
subString.writeln(item.text);
});
final userTweetsText = subString.toString();
final addressFromPinnedTweet =
extractAddressByType(raw: userTweetsText, type: CryptoCurrency.fromString(ticker));
final pinnedTweet = twitterUser.pinnedTweet?.text;
if (pinnedTweet != null) {
final addressFromPinnedTweet =
extractAddressByType(raw: pinnedTweet, type: CryptoCurrency.fromString(ticker));
if (addressFromPinnedTweet != null) {
return ParsedAddress.fetchTwitterAddress(address: addressFromPinnedTweet, name: text);
}

View file

@ -206,7 +206,8 @@ Future<void> initialSetup(
transactionDescriptionBox: transactionDescriptions,
ordersSource: ordersSource,
anonpayInvoiceInfoSource: anonpayInvoiceInfo,
unspentCoinsInfoSource: unspentCoinsInfoSource);
unspentCoinsInfoSource: unspentCoinsInfoSource,
secureStorage: secureStorage);
await bootstrap(navigatorKey);
monero?.onStartup();
}

View file

@ -1,7 +1,8 @@
import 'dart:convert';
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/twitter/twitter_user.dart';
import 'package:http/http.dart' as http;
import 'package:cake_wallet/.secrets.g.dart' as secrets;
class TwitterApi {
static const twitterBearerToken = secrets.twitterBearerToken;
@ -10,28 +11,49 @@ class TwitterApi {
static const userPath = '/2/users/by/username/';
static Future<TwitterUser> lookupUserByName({required String userName}) async {
final queryParams = {'user.fields': 'description', 'expansions': 'pinned_tweet_id'};
final queryParams = {
'user.fields': 'description',
'expansions': 'pinned_tweet_id',
'tweet.fields': 'note_tweet'
};
final headers = {'authorization': 'Bearer $twitterBearerToken'};
final uri = Uri(
scheme: httpsScheme,
host: apiHost,
path: userPath + userName,
queryParameters: queryParams,
);
scheme: httpsScheme,
host: apiHost,
path: userPath + userName,
queryParameters: queryParams);
var response = await http.get(uri, headers: headers);
final response = await http.get(uri, headers: headers).catchError((error) {
throw Exception('HTTP request failed: $error');
});
if (response.statusCode != 200) {
throw Exception('Unexpected http status: ${response.statusCode}');
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final Map<String, dynamic> responseJSON = jsonDecode(response.body) as Map<String, dynamic>;
if (responseJSON['errors'] != null) {
throw Exception(responseJSON['errors'][0]['detail']);
}
return TwitterUser.fromJson(responseJSON);
return TwitterUser.fromJson(responseJSON, _getPinnedTweet(responseJSON));
}
static Tweet? _getPinnedTweet(Map<String, dynamic> responseJSON) {
final tweetId = responseJSON['data']['pinned_tweet_id'] as String?;
if (tweetId == null || responseJSON['includes'] == null) return null;
final tweetIncludes = List.from(responseJSON['includes']['tweets'] as List);
final pinnedTweetData = tweetIncludes.firstWhere(
(tweet) => tweet['id'] == tweetId,
orElse: () => null,
) as Map<String, dynamic>?;
if (pinnedTweetData == null) return null;
final pinnedTweetText =
(pinnedTweetData['note_tweet']?['text'] ?? pinnedTweetData['text']) as String;
return Tweet(id: tweetId, text: pinnedTweetText);
}
}

View file

@ -4,25 +4,21 @@ class TwitterUser {
required this.username,
required this.name,
required this.description,
this.tweets});
this.pinnedTweet});
final String id;
final String username;
final String name;
final String description;
final List<Tweet>? tweets;
final Tweet? pinnedTweet;
factory TwitterUser.fromJson(Map<String, dynamic> json) {
factory TwitterUser.fromJson(Map<String, dynamic> json, [Tweet? pinnedTweet]) {
return TwitterUser(
id: json['data']['id'] as String,
username: json['data']['username'] as String,
name: json['data']['name'] as String,
description: json['data']['description'] as String? ?? '',
tweets: json['includes'] != null
? List.from(json['includes']['tweets'] as List)
.map((e) => Tweet.fromJson(e as Map<String, dynamic>))
.toList()
: null,
pinnedTweet: pinnedTweet,
);
}
}

View file

@ -349,27 +349,27 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
Object _credentials() {
final priority = _settingsStore.priority[wallet.type];
if (priority == null && (wallet.type != WalletType.nano && wallet.type != WalletType.banano)) {
throw Exception('Priority is null for wallet type: ${wallet.type}');
}
switch (wallet.type) {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
if (priority == null) throw Exception('Priority is null for wallet type: ${wallet.type}');
return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority);
return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority!);
case WalletType.monero:
if (priority == null) throw Exception('Priority is null for wallet type: ${wallet.type}');
return monero!
.createMoneroTransactionCreationCredentials(outputs: outputs, priority: priority);
.createMoneroTransactionCreationCredentials(outputs: outputs, priority: priority!);
case WalletType.haven:
if (priority == null) throw Exception('Priority is null for wallet type: ${wallet.type}');
return haven!.createHavenTransactionCreationCredentials(
outputs: outputs, priority: priority, assetType: selectedCryptoCurrency.title);
outputs: outputs, priority: priority!, assetType: selectedCryptoCurrency.title);
case WalletType.ethereum:
if (priority == null) throw Exception('Priority is null for wallet type: ${wallet.type}');
return ethereum!.createEthereumTransactionCredentials(outputs,
priority: priority, currency: selectedCryptoCurrency);
priority: priority!, currency: selectedCryptoCurrency);
case WalletType.nano:
return nano!.createNanoTransactionCredentials(outputs);
default:

View file

@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_ANDROID_TYPE=$1
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.7.0"
MONERO_COM_BUILD_NUMBER=61
MONERO_COM_VERSION="1.7.1"
MONERO_COM_BUILD_NUMBER=62
MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app"
MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.10.0"
CAKEWALLET_BUILD_NUMBER=175
CAKEWALLET_VERSION="4.10.1"
CAKEWALLET_BUILD_NUMBER=176
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
CAKEWALLET_SCHEME="cakewallet"

0
scripts/ios/app_config.sh Normal file → Executable file
View file

View file

@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_IOS_TYPE=$1
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.7.0"
MONERO_COM_BUILD_NUMBER=59
MONERO_COM_VERSION="1.7.1"
MONERO_COM_BUILD_NUMBER=60
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.10.0"
CAKEWALLET_BUILD_NUMBER=189
CAKEWALLET_VERSION="4.10.1"
CAKEWALLET_BUILD_NUMBER=190
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
HAVEN_NAME="Haven"

View file

@ -15,8 +15,8 @@ if [ -n "$1" ]; then
fi
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.3.0"
CAKEWALLET_BUILD_NUMBER=36
CAKEWALLET_VERSION="1.3.1"
CAKEWALLET_BUILD_NUMBER=37
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then

View file

@ -52,8 +52,8 @@ Future<void> generateBitcoin(bool hasImplementation) async {
final outputFile = File(bitcoinOutputPath);
const bitcoinCommonHeaders = """
import 'dart:typed_data';
import 'package:cake_wallet/entities/unspent_transaction_output.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/unspent_transaction_output.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/transaction_priority.dart';
@ -113,7 +113,7 @@ abstract class Bitcoin {
int formatterStringDoubleToBitcoinAmount(String amount);
String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate);
List<BitcoinUnspent> getUnspents(Object wallet);
List<Unspent> getUnspents(Object wallet);
void updateUnspents(Object wallet);
WalletService createBitcoinWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource);
WalletService createLitecoinWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource);
@ -596,7 +596,7 @@ Future<void> generateBitcoinCash(bool hasImplementation) async {
const bitcoinCashCommonHeaders = """
import 'dart:typed_data';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_core/unspent_transaction_output.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/wallet_credentials.dart';
@ -606,6 +606,7 @@ import 'package:hive/hive.dart';
""";
const bitcoinCashCWHeaders = """
import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
""";
const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';";
const bitcoinCashContent = """