mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
feat: Add initial Tari wallet support
This commit introduces support for the Tari wallet, including its transaction priorities, node list paths, wallet services, and related configurations. It also integrates Tari functionality across wallet creation, address handling, fees, seed validation, and exchange views.
This commit is contained in:
parent
baea28abaf
commit
641bf6a6fa
30 changed files with 527 additions and 26 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -140,6 +140,7 @@ lib/tron/tron.dart
|
|||
lib/wownero/wownero.dart
|
||||
lib/zano/zano.dart
|
||||
lib/decred/decred.dart
|
||||
lib/tari/tari.dart
|
||||
|
||||
ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png
|
||||
ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_120.png
|
||||
|
|
0
assets/tari_node_list.yml
Normal file
0
assets/tari_node_list.yml
Normal file
|
@ -1,5 +1,6 @@
|
|||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/monero_amount_format.dart';
|
||||
import 'package:tari/tari.dart' as tari;
|
||||
|
||||
class TariBalance extends Balance {
|
||||
TariBalance({required this.fullBalance, required this.unlockedBalance})
|
||||
|
@ -9,18 +10,13 @@ class TariBalance extends Balance {
|
|||
moneroAmountToString(amount: unlockedBalance),
|
||||
super(unlockedBalance, fullBalance);
|
||||
|
||||
factory TariBalance.fromFfi((int, int, int, int) result) {
|
||||
final availableBalance = result.$1;
|
||||
final pendingIncoming = result.$2;
|
||||
final pendingOutgoing = result.$3;
|
||||
final timeLockedBalance = result.$4;
|
||||
|
||||
factory TariBalance.fromTariBalanceInfo(tari.TariBalanceInfo result) {
|
||||
return TariBalance(
|
||||
fullBalance: availableBalance +
|
||||
pendingIncoming +
|
||||
pendingOutgoing +
|
||||
timeLockedBalance,
|
||||
unlockedBalance: availableBalance);
|
||||
fullBalance: result.available +
|
||||
result.pendingIncoming +
|
||||
result.pendingOutgoing +
|
||||
result.timeLocked,
|
||||
unlockedBalance: result.available);
|
||||
}
|
||||
|
||||
final int fullBalance;
|
||||
|
|
|
@ -10,36 +10,36 @@ import 'package:cw_core/wallet_base.dart';
|
|||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_keys_file.dart';
|
||||
import 'package:cw_tari/tari_balance.dart';
|
||||
import 'package:cw_tari/tari_transaction_history.dart';
|
||||
import 'package:cw_tari/tari_transaction_info.dart';
|
||||
import 'package:cw_tari/tari_wallet_addresses.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:tari/tari.dart';
|
||||
import 'package:tari/tari.dart' as tari;
|
||||
|
||||
part 'tari_wallet.g.dart';
|
||||
|
||||
abstract class TariWallet = TariWalletBase with _$TariWallet;
|
||||
class TariWallet = TariWalletBase with _$TariWallet;
|
||||
|
||||
abstract class TariWalletBase extends WalletBase<
|
||||
TariBalance,
|
||||
EVMChainTransactionHistory,
|
||||
EVMChainTransactionInfo> with Store, WalletKeysFile {
|
||||
abstract class TariWalletBase
|
||||
extends WalletBase<TariBalance, TariTransactionHistory, TariTransactionInfo>
|
||||
with Store, WalletKeysFile {
|
||||
TariWalletBase({
|
||||
required WalletInfo walletInfo,
|
||||
required String password,
|
||||
required TariWalletFfi walletFfi,
|
||||
required tari.TariWallet walletFfi,
|
||||
}) : syncStatus = const NotConnectedSyncStatus(),
|
||||
walletAddresses = TariWalletAddresses(walletInfo),
|
||||
_password = password,
|
||||
_walletFfi = walletFfi,
|
||||
balance = ObservableMap<CryptoCurrency, TariBalance>.of({
|
||||
CryptoCurrency.tari: TariBalance.fromFfi(walletFfi.getBalance()),
|
||||
CryptoCurrency.tari:
|
||||
TariBalance.fromTariBalanceInfo(walletFfi.getBalance()),
|
||||
}),
|
||||
super(walletInfo) {
|
||||
this.walletInfo = walletInfo;
|
||||
transactionHistory =
|
||||
setUpTransactionHistory(walletInfo, password);
|
||||
}
|
||||
|
||||
final TariWalletFfi _walletFfi;
|
||||
final tari.TariWallet _walletFfi;
|
||||
final String _password;
|
||||
|
||||
@override
|
||||
|
@ -108,9 +108,8 @@ abstract class TariWalletBase extends WalletBase<
|
|||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<Map<String, EVMChainTransactionInfo>> fetchTransactions() async {
|
||||
Future<Map<String, TariTransactionInfo>> fetchTransactions() async {
|
||||
// ToDo
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
@ -144,7 +143,8 @@ abstract class TariWalletBase extends WalletBase<
|
|||
|
||||
@override
|
||||
Future<void> updateBalance() async {
|
||||
balance[CryptoCurrency.tari] = TariBalance.fromFfi(_walletFfi.getBalance());
|
||||
balance[CryptoCurrency.tari] =
|
||||
TariBalance.fromTariBalanceInfo(_walletFfi.getBalance());
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:developer';
|
|||
import 'package:cw_core/wallet_addresses.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'tari_addresses.g.dart';
|
||||
part 'tari_wallet_addresses.g.dart';
|
||||
|
||||
class TariWalletAddresses = TariWalletAddressesBase with _$TariWalletAddresses;
|
||||
|
||||
|
|
276
cw_tari/lib/tari_wallet_service.dart
Normal file
276
cw_tari/lib/tari_wallet_service.dart
Normal file
|
@ -0,0 +1,276 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_tari/callback.dart';
|
||||
import 'package:cw_tari/tari_wallet.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:tari/tari.dart' as tari;
|
||||
|
||||
class TariNewWalletCredentials extends WalletCredentials {
|
||||
TariNewWalletCredentials({
|
||||
required super.name,
|
||||
super.walletInfo,
|
||||
super.password,
|
||||
super.passphrase,
|
||||
});
|
||||
}
|
||||
|
||||
class TariRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
TariRestoreWalletFromSeedCredentials({required super.name,
|
||||
required this.mnemonic,
|
||||
super.passphrase,
|
||||
super.height = 0,
|
||||
super.password});
|
||||
|
||||
final String mnemonic;
|
||||
}
|
||||
|
||||
class MoneroWalletLoadingException implements Exception {
|
||||
@override
|
||||
String toString() => 'Failure to load the wallet.';
|
||||
}
|
||||
|
||||
class TariRestoreWalletFromKeysCredentials extends WalletCredentials {
|
||||
TariRestoreWalletFromKeysCredentials({required String name,
|
||||
required String password,
|
||||
required this.language,
|
||||
required this.address,
|
||||
required this.viewKey,
|
||||
required this.spendKey,
|
||||
int height = 0})
|
||||
: super(name: name, password: password, height: height);
|
||||
|
||||
final String language;
|
||||
final String address;
|
||||
final String viewKey;
|
||||
final String spendKey;
|
||||
}
|
||||
|
||||
class TariWalletService extends WalletService<
|
||||
TariNewWalletCredentials,
|
||||
TariRestoreWalletFromSeedCredentials,
|
||||
TariRestoreWalletFromKeysCredentials,
|
||||
TariNewWalletCredentials> {
|
||||
TariWalletService(this.walletInfoSource);
|
||||
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
static bool walletFilesExist(String path) => !File(path).existsSync();
|
||||
|
||||
@override
|
||||
WalletType getType() => WalletType.tari;
|
||||
|
||||
@override
|
||||
Future<TariWallet> create(TariNewWalletCredentials credentials,
|
||||
{bool? isTestnet}) async {
|
||||
try {
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
|
||||
final connection = tari.getTorConnection();
|
||||
final config = tari.getWalletConfig(
|
||||
path: path,
|
||||
transport: connection,
|
||||
);
|
||||
final tariWallet = tari.createWallet(
|
||||
commsConfig: config,
|
||||
passphrase: credentials.password!,
|
||||
logPath: "$path/logs/wallet.log",
|
||||
callbackReceivedTransaction: CallbackPlaceholders.callbackReceivedTransaction,
|
||||
callbackReceivedTransactionReply: CallbackPlaceholders.callbackReceivedTransactionReply,
|
||||
callbackReceivedFinalizedTransaction: CallbackPlaceholders.callbackReceivedFinalizedTransaction,
|
||||
callbackReceivedTransactionBroadcast: CallbackPlaceholders.callbackTransactionBroadcast,
|
||||
callbackReceivedTransactionMined: CallbackPlaceholders.callbackTransactionMined,
|
||||
callbackReceivedTransactionMinedUnconfirmed: CallbackPlaceholders.callbackTransactionMinedUnconfirmed,
|
||||
callbackFauxTransactionMinedConfirmed: CallbackPlaceholders.callbackFauxTransactionConfirmed,
|
||||
callbackFauxTransactionMinedUnconfirmed: CallbackPlaceholders.callbackFauxTransactionUnconfirmed,
|
||||
callbackTransactionSendResult: CallbackPlaceholders.callbackTransactionSendResult,
|
||||
callbackTransactionCancellation: CallbackPlaceholders.callbackTransactionCancellation,
|
||||
callbackTxoValidationComplete: CallbackPlaceholders.callbackTxoValidationComplete,
|
||||
callbackContactsLivenessDataUpdated: CallbackPlaceholders.callbackContactsLivenessDataUpdated,
|
||||
callbackBalanceUpdated: CallbackPlaceholders.callbackBalanceUpdated,
|
||||
callbackTransactionValidationComplete: CallbackPlaceholders.callbackTransactionValidationComplete,
|
||||
callbackSafMessagesReceived: CallbackPlaceholders.callbackSafMessagesReceived,
|
||||
callbackConnectivityStatus: CallbackPlaceholders.callbackConnectivityStatus,
|
||||
callbackWalletScannedHeight: CallbackPlaceholders.callbackWalletScannedHeight,
|
||||
callbackBaseNodeState: CallbackPlaceholders.callbackBaseNodeState,
|
||||
);
|
||||
|
||||
final wallet = TariWallet(
|
||||
walletInfo: credentials.walletInfo!,
|
||||
password: credentials.password!,
|
||||
walletFfi: tariWallet,
|
||||
);
|
||||
await wallet.init();
|
||||
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception for wallet list service.
|
||||
printV('MoneroWalletsManager Error: ${e.toString()}');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isWalletExit(String name) async =>
|
||||
File(await pathForWallet(name: name, type: getType())).exists();
|
||||
|
||||
@override
|
||||
Future<TariWallet> openWallet(String name, String password) async {
|
||||
try {
|
||||
final path = await pathForWallet(name: name, type: getType());
|
||||
final connection = tari.getTorConnection();
|
||||
final config = tari.getWalletConfig(
|
||||
path: path,
|
||||
transport: connection,
|
||||
);
|
||||
final tariWallet = tari.createWallet(
|
||||
commsConfig: config,
|
||||
passphrase: password,
|
||||
logPath: "$path/logs/wallet.log",
|
||||
callbackReceivedTransaction: CallbackPlaceholders.callbackReceivedTransaction,
|
||||
callbackReceivedTransactionReply: CallbackPlaceholders.callbackReceivedTransactionReply,
|
||||
callbackReceivedFinalizedTransaction: CallbackPlaceholders.callbackReceivedFinalizedTransaction,
|
||||
callbackReceivedTransactionBroadcast: CallbackPlaceholders.callbackTransactionBroadcast,
|
||||
callbackReceivedTransactionMined: CallbackPlaceholders.callbackTransactionMined,
|
||||
callbackReceivedTransactionMinedUnconfirmed: CallbackPlaceholders.callbackTransactionMinedUnconfirmed,
|
||||
callbackFauxTransactionMinedConfirmed: CallbackPlaceholders.callbackFauxTransactionConfirmed,
|
||||
callbackFauxTransactionMinedUnconfirmed: CallbackPlaceholders.callbackFauxTransactionUnconfirmed,
|
||||
callbackTransactionSendResult: CallbackPlaceholders.callbackTransactionSendResult,
|
||||
callbackTransactionCancellation: CallbackPlaceholders.callbackTransactionCancellation,
|
||||
callbackTxoValidationComplete: CallbackPlaceholders.callbackTxoValidationComplete,
|
||||
callbackContactsLivenessDataUpdated: CallbackPlaceholders.callbackContactsLivenessDataUpdated,
|
||||
callbackBalanceUpdated: CallbackPlaceholders.callbackBalanceUpdated,
|
||||
callbackTransactionValidationComplete: CallbackPlaceholders.callbackTransactionValidationComplete,
|
||||
callbackSafMessagesReceived: CallbackPlaceholders.callbackSafMessagesReceived,
|
||||
callbackConnectivityStatus: CallbackPlaceholders.callbackConnectivityStatus,
|
||||
callbackWalletScannedHeight: CallbackPlaceholders.callbackWalletScannedHeight,
|
||||
callbackBaseNodeState: CallbackPlaceholders.callbackBaseNodeState,
|
||||
);
|
||||
|
||||
final walletInfo = walletInfoSource.values
|
||||
.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
|
||||
final wallet = TariWallet(
|
||||
walletInfo: walletInfo,
|
||||
password: password,
|
||||
walletFfi: tariWallet,
|
||||
);
|
||||
|
||||
|
||||
await wallet.init();
|
||||
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
printV(e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> remove(String wallet) async {
|
||||
final path = await pathForWalletDir(name: wallet, type: getType());
|
||||
|
||||
final file = Directory(path);
|
||||
final isExist = file.existsSync();
|
||||
|
||||
if (isExist) {
|
||||
await file.delete(recursive: true);
|
||||
}
|
||||
|
||||
final walletInfo = walletInfoSource.values
|
||||
.firstWhere((info) => info.id == WalletBase.idFor(wallet, getType()));
|
||||
await walletInfoSource.delete(walletInfo.key);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> rename(String currentName, String password,
|
||||
String newName) async {
|
||||
final currentWalletInfo = walletInfoSource.values.firstWhere(
|
||||
(info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||
|
||||
throw UnimplementedError();
|
||||
|
||||
// await currentWallet.renameWalletFiles(newName);
|
||||
//
|
||||
// final newWalletInfo = currentWalletInfo;
|
||||
// newWalletInfo.id = WalletBase.idFor(newName, getType());
|
||||
// newWalletInfo.name = newName;
|
||||
//
|
||||
// await walletInfoSource.put(currentWalletInfo.key, newWalletInfo);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TariWallet> restoreFromKeys(
|
||||
TariRestoreWalletFromKeysCredentials credentials,
|
||||
{bool? isTestnet}) async {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TariWallet> restoreFromHardwareWallet(
|
||||
TariNewWalletCredentials credentials) async {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TariWallet> restoreFromSeed(
|
||||
TariRestoreWalletFromSeedCredentials credentials,
|
||||
{bool? isTestnet}) async {
|
||||
try {
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
|
||||
final connection = tari.getTorConnection();
|
||||
final config = tari.getWalletConfig(
|
||||
path: path,
|
||||
transport: connection,
|
||||
);
|
||||
final tariWallet = tari.createWallet(
|
||||
commsConfig: config,
|
||||
passphrase: credentials.password!,
|
||||
mnemonic: credentials.mnemonic,
|
||||
seedPassphrase: credentials.passphrase ?? "",
|
||||
logPath: "$path/logs/wallet.log",
|
||||
callbackReceivedTransaction: CallbackPlaceholders.callbackReceivedTransaction,
|
||||
callbackReceivedTransactionReply: CallbackPlaceholders.callbackReceivedTransactionReply,
|
||||
callbackReceivedFinalizedTransaction: CallbackPlaceholders.callbackReceivedFinalizedTransaction,
|
||||
callbackReceivedTransactionBroadcast: CallbackPlaceholders.callbackTransactionBroadcast,
|
||||
callbackReceivedTransactionMined: CallbackPlaceholders.callbackTransactionMined,
|
||||
callbackReceivedTransactionMinedUnconfirmed: CallbackPlaceholders.callbackTransactionMinedUnconfirmed,
|
||||
callbackFauxTransactionMinedConfirmed: CallbackPlaceholders.callbackFauxTransactionConfirmed,
|
||||
callbackFauxTransactionMinedUnconfirmed: CallbackPlaceholders.callbackFauxTransactionUnconfirmed,
|
||||
callbackTransactionSendResult: CallbackPlaceholders.callbackTransactionSendResult,
|
||||
callbackTransactionCancellation: CallbackPlaceholders.callbackTransactionCancellation,
|
||||
callbackTxoValidationComplete: CallbackPlaceholders.callbackTxoValidationComplete,
|
||||
callbackContactsLivenessDataUpdated: CallbackPlaceholders.callbackContactsLivenessDataUpdated,
|
||||
callbackBalanceUpdated: CallbackPlaceholders.callbackBalanceUpdated,
|
||||
callbackTransactionValidationComplete: CallbackPlaceholders.callbackTransactionValidationComplete,
|
||||
callbackSafMessagesReceived: CallbackPlaceholders.callbackSafMessagesReceived,
|
||||
callbackConnectivityStatus: CallbackPlaceholders.callbackConnectivityStatus,
|
||||
callbackWalletScannedHeight: CallbackPlaceholders.callbackWalletScannedHeight,
|
||||
callbackBaseNodeState: CallbackPlaceholders.callbackBaseNodeState,
|
||||
);
|
||||
final wallet = TariWallet(
|
||||
walletInfo: credentials.walletInfo!,
|
||||
walletFfi: tariWallet,
|
||||
password: credentials.password!);
|
||||
await wallet.init();
|
||||
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception for wallet list service.
|
||||
printV('MoneroWalletsManager Error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool requireHardwareWalletConnection(String name) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -21,5 +21,7 @@ dev_dependencies:
|
|||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
build_runner: ^2.4.7
|
||||
mobx_codegen: ^2.0.7
|
||||
|
||||
flutter:
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:cake_wallet/monero/monero.dart';
|
|||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/solana/solana.dart';
|
||||
import 'package:cake_wallet/tari/tari.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cake_wallet/wownero/wownero.dart';
|
||||
import 'package:cake_wallet/zano/zano.dart';
|
||||
|
@ -50,6 +51,8 @@ class SeedValidator extends Validator<MnemonicItem> {
|
|||
return zano!.getWordList(language);
|
||||
case WalletType.decred:
|
||||
return decred!.getDecredWordList();
|
||||
case WalletType.tari:
|
||||
return tari!.getTariWordList(language);
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
return [];
|
||||
|
|
|
@ -91,6 +91,7 @@ class WalletCreationService {
|
|||
case WalletType.banano:
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
case WalletType.tari:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
|||
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
||||
import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/background_sync_page.dart';
|
||||
import 'package:cake_wallet/tari/tari.dart';
|
||||
import 'package:cake_wallet/view_model/dev/monero_background_sync.dart';
|
||||
import 'package:cake_wallet/view_model/link_view_model.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
|
@ -1115,6 +1116,8 @@ Future<void> setup({
|
|||
return zano!.createZanoWalletService(_walletInfoSource);
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
case WalletType.tari:
|
||||
return tari!.createTariWalletService(_walletInfoSource);
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
|
||||
|
|
|
@ -46,6 +46,7 @@ const wowneroDefaultNodeUri = 'node3.monerodevs.org:34568';
|
|||
const zanoDefaultNodeUri = 'zano.cakewallet.com:11211';
|
||||
const moneroWorldNodeUri = '.moneroworld.com';
|
||||
const decredDefaultUri = "default-spv-nodes";
|
||||
const tariDefaultUri = ''; // ToDo
|
||||
|
||||
Future<void> defaultSettingsMigration(
|
||||
{required int version,
|
||||
|
@ -617,6 +618,8 @@ String _getDefaultNodeUri(WalletType type) {
|
|||
return zanoDefaultNodeUri;
|
||||
case WalletType.decred:
|
||||
return decredDefaultUri;
|
||||
case WalletType.tari:
|
||||
return tariDefaultUri;
|
||||
case WalletType.banano:
|
||||
case WalletType.none:
|
||||
return '';
|
||||
|
|
|
@ -46,6 +46,9 @@ Future<List<Node>> loadDefaultNodes(WalletType type) async {
|
|||
case WalletType.decred:
|
||||
path = 'assets/decred_node_list.yml';
|
||||
break;
|
||||
case WalletType.tari:
|
||||
path = 'assets/tari_node_list.yml';
|
||||
break;
|
||||
case WalletType.banano:
|
||||
case WalletType.none:
|
||||
path = '';
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
|||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/tari/tari.dart';
|
||||
import 'package:cake_wallet/wownero/wownero.dart';
|
||||
import 'package:cake_wallet/zano/zano.dart';
|
||||
import 'package:cake_wallet/decred/decred.dart';
|
||||
|
@ -35,6 +36,8 @@ List<TransactionPriority> priorityForWalletType(WalletType type) {
|
|||
return zano!.getTransactionPriorities();
|
||||
case WalletType.decred:
|
||||
return decred!.getTransactionPriorities();
|
||||
case WalletType.tari:
|
||||
return tari!.getTransactionPriorities();
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
return [];
|
||||
|
|
|
@ -17,6 +17,7 @@ bool isBIP39Wallet(WalletType walletType) {
|
|||
case WalletType.haven:
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
case WalletType.tari:
|
||||
case WalletType.none:
|
||||
return false;
|
||||
}
|
||||
|
|
43
lib/tari/cw_tari.dart
Normal file
43
lib/tari/cw_tari.dart
Normal file
|
@ -0,0 +1,43 @@
|
|||
part of 'tari.dart';
|
||||
|
||||
class CWTari extends Tari {
|
||||
List<String> getTariWordList(String language) {
|
||||
return []; // ToDo
|
||||
}
|
||||
|
||||
WalletService createTariWalletService(Box<WalletInfo> walletInfoSource) {
|
||||
return TariWalletService(walletInfoSource);
|
||||
}
|
||||
|
||||
WalletCredentials createTariNewWalletCredentials(
|
||||
{required String name,
|
||||
WalletInfo? walletInfo,
|
||||
String? password,
|
||||
String? passphrase}) =>
|
||||
TariNewWalletCredentials(
|
||||
name: name,
|
||||
walletInfo: walletInfo,
|
||||
password: password,
|
||||
passphrase: passphrase);
|
||||
|
||||
WalletCredentials createTariRestoreWalletFromSeedCredentials(
|
||||
{required String name,
|
||||
required String mnemonic,
|
||||
required String password,
|
||||
String? passphrase}) =>
|
||||
TariRestoreWalletFromSeedCredentials(
|
||||
name: name,
|
||||
mnemonic: mnemonic,
|
||||
password: password,
|
||||
passphrase: passphrase);
|
||||
|
||||
String getAddress(WalletBase wallet) =>
|
||||
(wallet as TariWallet).walletAddresses.address;
|
||||
|
||||
List<TransactionPriority> getTransactionPriorities() {
|
||||
return []; // ToDo
|
||||
}
|
||||
|
||||
double formatterTariAmountToDouble({required int amount}) =>
|
||||
cryptoAmountToDouble(amount: amount, divider: 1000000);
|
||||
}
|
|
@ -56,6 +56,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
|||
case WalletType.haven:
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
case WalletType.tari:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -697,6 +697,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
case WalletType.tron:
|
||||
case WalletType.wownero:
|
||||
case WalletType.decred:
|
||||
case WalletType.tari:
|
||||
return true;
|
||||
case WalletType.zano:
|
||||
case WalletType.haven:
|
||||
|
|
|
@ -215,6 +215,7 @@ abstract class HomeSettingsViewModelBase with Store {
|
|||
case WalletType.wownero:
|
||||
case WalletType.bitcoinCash:
|
||||
case WalletType.decred:
|
||||
case WalletType.tari:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:cake_wallet/nano/nano.dart';
|
|||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/solana/solana.dart';
|
||||
import 'package:cake_wallet/tari/tari.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cake_wallet/wownero/wownero.dart';
|
||||
import 'package:cake_wallet/zano/zano.dart';
|
||||
|
@ -224,6 +225,11 @@ class TransactionListItem extends ActionListItem with Keyable {
|
|||
cryptoAmount: decred!.formatterDecredAmountToDouble(amount: transaction.amount),
|
||||
price: price);
|
||||
break;
|
||||
case WalletType.tari:
|
||||
amount = calculateFiatAmountRaw(
|
||||
cryptoAmount: tari!.formatterTariAmountToDouble(amount: transaction.amount),
|
||||
price: price);
|
||||
break;
|
||||
case WalletType.none:
|
||||
case WalletType.banano:
|
||||
case WalletType.haven:
|
||||
|
|
|
@ -783,6 +783,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
depositCurrency = CryptoCurrency.dcr;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
break;
|
||||
case WalletType.tari:
|
||||
depositCurrency = CryptoCurrency.tari;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
break;
|
||||
case WalletType.none:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
|
|||
case WalletType.bitcoin:
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
case WalletType.tari:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor
|
|||
case WalletType.banano:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.tari:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ abstract class OutputBase with Store {
|
|||
case WalletType.banano:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.tari:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -302,6 +303,7 @@ abstract class OutputBase with Store {
|
|||
case WalletType.zano:
|
||||
case WalletType.nano:
|
||||
case WalletType.decred:
|
||||
case WalletType.tari:
|
||||
maximumFractionDigits = 12;
|
||||
break;
|
||||
case WalletType.bitcoin:
|
||||
|
|
|
@ -88,6 +88,9 @@ abstract class TransactionDetailsViewModelBase with Store {
|
|||
case WalletType.decred:
|
||||
_addDecredListItems(tx, dateFormat);
|
||||
break;
|
||||
case WalletType.tari:
|
||||
_addTariListItems(tx, dateFormat);
|
||||
break;
|
||||
case WalletType.none:
|
||||
case WalletType.banano:
|
||||
break;
|
||||
|
@ -193,6 +196,7 @@ abstract class TransactionDetailsViewModelBase with Store {
|
|||
return 'https://explorer.zano.org/transaction/${txId}';
|
||||
case WalletType.decred:
|
||||
return 'https://${wallet.isTestnet ? "testnet" : "dcrdata"}.decred.org/tx/${txId.split(':')[0]}';
|
||||
case WalletType.tari: // ToDo (Konsti)
|
||||
case WalletType.none:
|
||||
return '';
|
||||
}
|
||||
|
@ -227,6 +231,7 @@ abstract class TransactionDetailsViewModelBase with Store {
|
|||
return S.current.view_transaction_on + 'explorer.zano.org';
|
||||
case WalletType.decred:
|
||||
return S.current.view_transaction_on + 'dcrdata.decred.org';
|
||||
case WalletType.tari: // ToDo (Konsti)
|
||||
case WalletType.none:
|
||||
return '';
|
||||
}
|
||||
|
@ -854,4 +859,22 @@ abstract class TransactionDetailsViewModelBase with Store {
|
|||
StandartListItem(title: S.current.transaction_details_title, value: comment),
|
||||
]);
|
||||
}
|
||||
|
||||
void _addTariListItems(TransactionInfo tx, DateFormat dateFormat) {
|
||||
// ToDo (Konsti)
|
||||
// final comment = tx.additionalInfo['comment'] as String?;
|
||||
// items.addAll([
|
||||
// StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
|
||||
// StandartListItem(
|
||||
// title: 'Asset ID', value: tx.additionalInfo['assetId'] as String? ?? "Unknown asset id"),
|
||||
// StandartListItem(
|
||||
// title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
|
||||
// StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
|
||||
// StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
|
||||
// if (tx.feeFormatted()?.isNotEmpty ?? false)
|
||||
// StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
|
||||
// if (comment != null && comment.isNotEmpty)
|
||||
// StandartListItem(title: S.current.transaction_details_title, value: comment),
|
||||
// ]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,6 +237,36 @@ class DecredURI extends PaymentURI {
|
|||
}
|
||||
}
|
||||
|
||||
class TariURI extends PaymentURI {
|
||||
TariURI(
|
||||
{required this.network, required super.amount, required super.address});
|
||||
|
||||
final String network;
|
||||
|
||||
// tari://nextnet/profile?alias=Aurora%20User%20%F0%9F%8F%81%F0%9F%9A%B2%F0%9F%8D%8C&tariAddress=349jdYen2RMBGeWm1SyUBzEsfqSJ9NGGiZXAsWUK3TQQbdeQ3wJJnjRwi1EzUqxdAhNQ4YcRmFFDLvtXxx8kBgBboXb
|
||||
// tari://nextnet/transactions/send?tariAddress=349jdYen2RMBGeWm1SyUBzEsfqSJ9NGGiZXAsWUK3TQQbdeQ3wJJnjRwi1EzUqxdAhNQ4YcRmFFDLvtXxx8kBgBboXb&amount=5000000
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
final queryParams = <String, String>{};
|
||||
final pathParts = <String>[network];
|
||||
|
||||
if (amount.isNotEmpty) {
|
||||
queryParams["amount"] = amount;
|
||||
pathParts.addAll(["transactions","send"]);
|
||||
} else {
|
||||
queryParams["alias"] = "CakeWallet User";
|
||||
pathParts.add("profile");
|
||||
}
|
||||
|
||||
queryParams["tariAddress"] = address;
|
||||
|
||||
final uri = Uri(scheme: "tari", pathSegments: pathParts, queryParameters: queryParams);
|
||||
|
||||
return uri.toString();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store {
|
||||
WalletAddressListViewModelBase({
|
||||
required AppStore appStore,
|
||||
|
@ -331,6 +361,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
|||
return ZanoURI(amount: amount, address: address.address);
|
||||
case WalletType.decred:
|
||||
return DecredURI(amount: amount, address: address.address);
|
||||
case WalletType.tari:
|
||||
return TariURI(amount: amount, address: address.address, network: 'nextnet'); // ToDo: Fix for mainnet
|
||||
case WalletType.none:
|
||||
throw Exception('Unexpected type: ${type.toString()}');
|
||||
}
|
||||
|
|
|
@ -163,6 +163,7 @@ abstract class WalletKeysViewModelBase with Store {
|
|||
case WalletType.bitcoinCash:
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.tari: // ToDo (Konsti)
|
||||
// final keys = bitcoin!.getWalletKeys(_appStore.wallet!);
|
||||
//
|
||||
// items.addAll([
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:cake_wallet/core/new_wallet_arguments.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/tari/tari.dart';
|
||||
import 'package:cake_wallet/zano/zano.dart';
|
||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||
import 'package:cake_wallet/solana/solana.dart';
|
||||
|
@ -70,6 +71,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
|||
return seedSettingsViewModel.nanoSeedType == NanoSeedType.bip39
|
||||
? advancedPrivacySettingsViewModel.seedPhraseLength.value
|
||||
: 24;
|
||||
case WalletType.tari:
|
||||
case WalletType.none:
|
||||
return 24;
|
||||
case WalletType.haven:
|
||||
|
@ -164,6 +166,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
|||
);
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredNewWalletCredentials(name: name);
|
||||
case WalletType.tari:
|
||||
return tari!.createTariNewWalletCredentials(name: name);
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
throw Exception('Unexpected type: ${type.toString()}');
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:cake_wallet/nano/nano.dart';
|
|||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/solana/solana.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/tari/tari.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cake_wallet/decred/decred.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
|
@ -65,6 +66,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
case WalletType.litecoin:
|
||||
case WalletType.bitcoinCash:
|
||||
case WalletType.zano:
|
||||
case WalletType.tari:
|
||||
case WalletType.none:
|
||||
availableModes = [WalletRestoreMode.seed];
|
||||
break;
|
||||
|
@ -182,6 +184,12 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
mnemonic: seed,
|
||||
password: password,
|
||||
);
|
||||
case WalletType.tari:
|
||||
return tari!.createTariRestoreWalletFromSeedCredentials(
|
||||
name: name,
|
||||
mnemonic: seed,
|
||||
password: password,
|
||||
);
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group("PaymentURI", () {
|
||||
|
||||
group("TariURI", () {
|
||||
test("uri with amont", () {
|
||||
final uri = TariURI(network: "nextnet", amount: "5000000", address: "349jdYen2RMBGeWm1SyUBzEsfqSJ9NGGiZXAsWUK3TQQbdeQ3wJJnjRwi1EzUqxdAhNQ4YcRmFFDLvtXxx8kBgBboXb");
|
||||
|
||||
expect(uri.toString(), "tari://nextnet/transactions/send?tariAddress=349jdYen2RMBGeWm1SyUBzEsfqSJ9NGGiZXAsWUK3TQQbdeQ3wJJnjRwi1EzUqxdAhNQ4YcRmFFDLvtXxx8kBgBboXb&amount=5000000");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -30,6 +30,7 @@ Future<void> main(List<String> args) async {
|
|||
final hasWownero = args.contains('${prefix}wownero');
|
||||
final hasZano = args.contains('${prefix}zano');
|
||||
final hasDecred = args.contains('${prefix}decred');
|
||||
final hasTari = args.contains('${prefix}tari');
|
||||
final excludeFlutterSecureStorage = args.contains('${prefix}excludeFlutterSecureStorage');
|
||||
|
||||
await generateBitcoin(hasBitcoin);
|
||||
|
@ -44,6 +45,7 @@ Future<void> main(List<String> args) async {
|
|||
await generateZano(hasZano);
|
||||
// await generateBanano(hasEthereum);
|
||||
await generateDecred(hasDecred);
|
||||
await generateTari(hasTari);
|
||||
|
||||
await generatePubspec(
|
||||
hasMonero: hasMonero,
|
||||
|
@ -59,6 +61,7 @@ Future<void> main(List<String> args) async {
|
|||
hasWownero: hasWownero,
|
||||
hasZano: hasZano,
|
||||
hasDecred: hasDecred,
|
||||
hasTari: hasTari,
|
||||
);
|
||||
await generateWalletTypes(
|
||||
hasMonero: hasMonero,
|
||||
|
@ -73,6 +76,7 @@ Future<void> main(List<String> args) async {
|
|||
hasWownero: hasWownero,
|
||||
hasZano: hasZano,
|
||||
hasDecred: hasDecred,
|
||||
hasTari: hasTari,
|
||||
);
|
||||
await injectSecureStorage(!excludeFlutterSecureStorage);
|
||||
}
|
||||
|
@ -1377,6 +1381,54 @@ abstract class Decred {
|
|||
await outputFile.writeAsString(output);
|
||||
}
|
||||
|
||||
Future<void> generateTari(bool hasImplementation) async {
|
||||
final outputFile = File(decredOutputPath);
|
||||
const tariCommonHeaders = """
|
||||
import 'package:cw_core/crypto_amount_format.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/wallet_base.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 tariCWHeaders = """
|
||||
import 'package:cw_tari/tari_wallet.dart';
|
||||
import 'package:cw_tari/tari_wallet_service.dart';
|
||||
""";
|
||||
const tariCwPart = "part 'cw_tari.dart';";
|
||||
const tariContent = """
|
||||
|
||||
abstract class Tari {
|
||||
List<String> getTariWordList(String language);
|
||||
WalletService createTariWalletService(Box<WalletInfo> walletInfoSource);
|
||||
WalletCredentials createTariNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? passphrase});
|
||||
WalletCredentials createTariRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
|
||||
|
||||
String getAddress(WalletBase wallet);
|
||||
|
||||
List<TransactionPriority> getTransactionPriorities();
|
||||
double formatterTariAmountToDouble({required int amount});
|
||||
}
|
||||
""";
|
||||
|
||||
const tariEmptyDefinition = 'Tari? tari;\n';
|
||||
const tariCWDefinition = 'Tari? tari = CWTari();\n';
|
||||
|
||||
final output = '$tariCommonHeaders\n' +
|
||||
(hasImplementation ? '$tariCWHeaders\n' : '\n') +
|
||||
(hasImplementation ? '$tariCwPart\n\n' : '\n') +
|
||||
(hasImplementation ? tariCWDefinition : tariEmptyDefinition) +
|
||||
'\n' +
|
||||
tariContent;
|
||||
|
||||
if (outputFile.existsSync()) {
|
||||
await outputFile.delete();
|
||||
}
|
||||
|
||||
await outputFile.writeAsString(output);
|
||||
}
|
||||
|
||||
Future<void> generatePubspec({
|
||||
required bool hasMonero,
|
||||
required bool hasBitcoin,
|
||||
|
@ -1391,6 +1443,7 @@ Future<void> generatePubspec({
|
|||
required bool hasWownero,
|
||||
required bool hasZano,
|
||||
required bool hasDecred,
|
||||
required bool hasTari,
|
||||
}) async {
|
||||
const cwCore = """
|
||||
cw_core:
|
||||
|
@ -1455,6 +1508,10 @@ Future<void> generatePubspec({
|
|||
cw_decred:
|
||||
path: ./cw_decred
|
||||
""";
|
||||
const cwTari = """
|
||||
cw_tari:
|
||||
path: ./cw_tari
|
||||
""";
|
||||
final inputFile = File(pubspecOutputPath);
|
||||
final inputText = await inputFile.readAsString();
|
||||
final inputLines = inputText.split('\n');
|
||||
|
@ -1520,6 +1577,10 @@ Future<void> generatePubspec({
|
|||
output += '\n$cwZano';
|
||||
}
|
||||
|
||||
if (hasTari) {
|
||||
output += '\n$cwTari';
|
||||
}
|
||||
|
||||
final outputLines = output.split('\n');
|
||||
inputLines.insertAll(dependenciesIndex + 1, outputLines);
|
||||
final outputContent = inputLines.join('\n');
|
||||
|
@ -1545,6 +1606,7 @@ Future<void> generateWalletTypes({
|
|||
required bool hasWownero,
|
||||
required bool hasZano,
|
||||
required bool hasDecred,
|
||||
required bool hasTari,
|
||||
}) async {
|
||||
final walletTypesFile = File(walletTypesPath);
|
||||
|
||||
|
@ -1608,6 +1670,10 @@ Future<void> generateWalletTypes({
|
|||
outputContent += '\tWalletType.wownero,\n';
|
||||
}
|
||||
|
||||
if (hasWownero) {
|
||||
outputContent += '\tWalletType.tari,\n';
|
||||
}
|
||||
|
||||
outputContent += '];\n';
|
||||
await walletTypesFile.writeAsString(outputContent);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue