feat: Add Tari wallet support

This commit introduces initial support for the Tari wallet, including new credential handling, transaction history setup, and wallet restoration. It also updates dependencies and adds a mock environment for testing Tari wallet services.
This commit is contained in:
Konstantin Ullrich 2025-04-22 20:55:35 +02:00
parent 8181ce3e52
commit 2c26920b24
No known key found for this signature in database
GPG key ID: 6B3199AD9B3D23B8
21 changed files with 401 additions and 65 deletions

BIN
assets/images/tari.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View file

@ -234,7 +234,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
static const zano = CryptoCurrency(title: 'ZANO', tag: 'ZANO', fullName: 'Zano', raw: 96, name: 'zano', iconPath: 'assets/images/zano_icon.png', decimals: 12);
static const flip = CryptoCurrency(title: 'FLIP', tag: 'ETH', fullName: 'Chainflip', raw: 97, name: 'flip', iconPath: 'assets/images/flip_icon.png', decimals: 18);
static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Digital Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png', decimals: 18);
static const tari = CryptoCurrency(title: 'tXTR', fullName: 'Tari', raw: 99, name: 'tari', iconPath: 'assets/images/.png', decimals: 18); // ToDo
static const tari = CryptoCurrency(title: 'tXTR', fullName: 'Tari', raw: 99, name: 'tari', iconPath: 'assets/images/tari.png', decimals: 8);
static final Map<int, CryptoCurrency> _rawCurrencyMap =
[...all, ...havenCurrencies].fold<Map<int, CryptoCurrency>>(<int, CryptoCurrency>{}, (acc, item) {

View file

@ -106,6 +106,7 @@ class Node extends HiveObject with Keyable {
case WalletType.decred:
return Uri.parse(
"http${isSSL ? "s" : ""}://$uriRaw${path!.startsWith("/") || path!.isEmpty ? path : "/$path"}");
case WalletType.tari: // ToDo: Maybe connect to node
case WalletType.none:
throw Exception('Unexpected type ${type.toString()} for Node uri');
}
@ -170,6 +171,8 @@ class Node extends HiveObject with Keyable {
return requestZanoNode();
case WalletType.decred:
return requestDecredNode();
case WalletType.tari:
return requestTariNode();
case WalletType.none:
return false;
}
@ -373,6 +376,21 @@ class Node extends HiveObject with Keyable {
return false;
}
}
Future<bool> requestTariNode() async {
if (uri.host == "default-tari-seed-nodes") {
// Just show default port as ok. The wallet will connect to a list of known
// nodes automatically.
return true;
}
try {
final socket = await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5));
socket.destroy();
return true;
} catch (_) {
return false;
}
}
}
/// https://github.com/ManyMath/digest_auth/

View file

@ -139,7 +139,7 @@ WalletType deserializeFromInt(int raw) {
case 13:
return WalletType.decred;
case 14:
return WalletType.decred;
return WalletType.tari;
default:
throw Exception(
'Unexpected token: $raw for WalletType deserializeFromInt');

View file

@ -13,6 +13,7 @@ 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:cw_tari/transaction_credentials.dart';
import 'package:mobx/mobx.dart';
import 'package:tari/tari.dart' as tari;
@ -37,6 +38,7 @@ abstract class TariWalletBase
}),
super(walletInfo) {
this.walletInfo = walletInfo;
transactionHistory = TariTransactionHistory();
}
final tari.TariWallet _walletFfi;
@ -54,6 +56,8 @@ abstract class TariWalletBase
late ObservableMap<CryptoCurrency, TariBalance> balance;
Future<void> init() async {
walletInfo.address = _walletFfi.getEmojiID().emojiId;
await walletAddresses.init();
await transactionHistory.init();
@ -94,7 +98,9 @@ abstract class TariWalletBase
try {
syncStatus = AttemptingSyncStatus();
// ToDo
_walletFfi.startRecovery((_, int status, int val1, int val2) {
print('recoveryCallback called $status $val1 $val2');
});
syncStatus = SyncedSyncStatus();
} catch (e) {
@ -104,6 +110,9 @@ abstract class TariWalletBase
@override
Future<PendingTransaction> createTransaction(Object credentials) async {
final tariCredentials = credentials as TariTransactionCredentials;
// _walletFfi.sendTx(destination, amount, feePerGram, message, isOneSided)
// ToDo
throw UnimplementedError();
}
@ -129,7 +138,7 @@ abstract class TariWalletBase
}
@override
String? get seed => _walletFfi.getMnemonic();
String get seed => _walletFfi.getMnemonic();
@override
String? get privateKey => null;

View file

@ -1,7 +1,6 @@
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';
@ -11,6 +10,7 @@ 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/ffi.dart' as tariffi;
import 'package:tari/tari.dart' as tari;
class TariNewWalletCredentials extends WalletCredentials {
@ -73,7 +73,7 @@ class TariWalletService extends WalletService<
try {
final path = await pathForWallet(name: credentials.name, type: getType());
final connection = tari.getTorConnection();
final connection = tariffi.FFITariTransportConfig();
final config = tari.getWalletConfig(
path: path,
transport: connection,
@ -125,7 +125,7 @@ class TariWalletService extends WalletService<
Future<TariWallet> openWallet(String name, String password) async {
try {
final path = await pathForWallet(name: name, type: getType());
final connection = tari.getTorConnection();
final connection = tariffi.FFITariTransportConfig();
final config = tari.getWalletConfig(
path: path,
transport: connection,
@ -225,7 +225,7 @@ class TariWalletService extends WalletService<
try {
final path = await pathForWallet(name: credentials.name, type: getType());
final connection = tari.getTorConnection();
final connection = tariffi.FFITariTransportConfig();
final config = tari.getWalletConfig(
path: path,
transport: connection,
@ -234,7 +234,6 @@ class TariWalletService extends WalletService<
commsConfig: config,
passphrase: credentials.password!,
mnemonic: credentials.mnemonic,
seedPassphrase: credentials.passphrase ?? "",
logPath: "$path/logs/wallet.log",
callbackReceivedTransaction: CallbackPlaceholders.callbackReceivedTransaction,
callbackReceivedTransactionReply: CallbackPlaceholders.callbackReceivedTransactionReply,

View file

@ -0,0 +1,8 @@
import 'package:cw_core/output_info.dart';
class TariTransactionCredentials {
TariTransactionCredentials(this.outputs, {this.feeRate});
final List<OutputInfo> outputs;
final int? feeRate;
}

View file

@ -23,5 +23,6 @@ dev_dependencies:
flutter_lints: ^5.0.0
build_runner: ^2.4.7
mobx_codegen: ^2.0.7
mockito: ^5.4.5
flutter:

View file

@ -0,0 +1,29 @@
import 'package:mockito/mockito.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
class MockPathProviderPlatform extends Mock
with MockPlatformInterfaceMixin
implements PathProviderPlatform {
Future<String> getTemporaryPath() => throw UnimplementedError();
Future<String> getApplicationSupportPath() => throw UnimplementedError();
Future<String> getLibraryPath() => throw UnimplementedError();
Future<String> getApplicationDocumentsPath() async => "./test/data";
Future<String> getExternalStoragePath() => throw UnimplementedError();
Future<List<String>> getExternalCachePaths() => throw UnimplementedError();
Future<String> getDownloadsPath() => throw UnimplementedError();
@override
Future<String?> getApplicationCachePath() => throw UnimplementedError();
@override
Future<List<String>?> getExternalStoragePaths({StorageDirectory? type}) =>
throw UnimplementedError();
}

View file

@ -0,0 +1,99 @@
import 'dart:io';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cw_tari/tari_wallet_service.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hive/hive.dart';
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
import 'mock/path_provider.dart';
Future<void> main() async {
print(Directory.current);
group("TariWalletService Tests", () {
Hive.init('./test/data/db');
late TariWalletService walletService;
setUpAll(() async {
PathProviderPlatform.instance = MockPathProviderPlatform();
final Box<WalletInfo> walletInfoSource =
await Hive.openBox('testWalletInfo');
walletService = TariWalletService(walletInfoSource);
});
tearDownAll(() {
Directory('./test/data').deleteSync(recursive: true);
});
group("Create wallet", () {
test("Create Tari Wallet", () async {
final credentials = _getTestCreateCredentials(name: 'Create Wallet');
final wallet = await walletService.create(credentials);
expect(wallet.seed.split(" ").length, 24);
});
});
group("Restore wallet", () {
test('Tari Seed', () async {
final credentials = _getTestRestoreCredentials(
name: 'Restore Wallet',
mnemonic:
'park snow bring damp venture palm rocket cactus hole hunt save broken swallow coach state relief census pride penalty sound jazz romance obvious canyon');
final wallet = await walletService.restoreFromSeed(credentials);
expect(wallet.walletAddresses.primaryAddress,
'🌈🌊🏁🚲🍌😱💦🔫🍋📎👣🐛🌙🤖👀💻🌊🏰🏆🎷🤢🚜🎷🎯🍺👾🛵🐼🎰🍒🚽🔔🐑🎰🔨🦀🍣🍍🏭😇🎻🍀💨👖👛💐🔧🍐🎁🐯🏰🍚🌽🧢🎡🚂🎡🍩🐮🚢🚦💼🤠💍🤠🎓🔒');
});
});
});
}
TariRestoreWalletFromSeedCredentials _getTestRestoreCredentials({
required String name,
required String mnemonic,
}) {
final credentials = TariRestoreWalletFromSeedCredentials(
name: name, mnemonic: mnemonic, passphrase: '', password: "test");
credentials.walletInfo = WalletInfo.external(
id: WalletBase.idFor(name, WalletType.monero),
name: name,
type: WalletType.monero,
isRecovery: true,
restoreHeight: credentials.height ?? 0,
date: DateTime.now(),
path: '',
dirPath: '',
address: '',
);
return credentials;
}
TariNewWalletCredentials _getTestCreateCredentials({
required String name,
}) {
final credentials = TariNewWalletCredentials(
name: name,
password: "test",
passphrase: '',
);
credentials.walletInfo = WalletInfo.external(
id: WalletBase.idFor(name, WalletType.tari),
name: name,
type: WalletType.tari,
isRecovery: false,
restoreHeight: credentials.height ?? 0,
date: DateTime.now(),
path: '',
dirPath: '',
address: '',
);
return credentials;
}

View file

@ -198,40 +198,40 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/wakelock_plus/ios"
SPEC CHECKSUMS:
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
connectivity_plus: 481668c94744c30c53b8895afb39159d1e619bdf
CryptoSwift: e64e11850ede528a02a0f3e768cec8e9d92ecb90
cw_decred: 9c0e1df74745b51a1289ec5e91fb9e24b68fa14a
cw_mweb: 22cd01dfb8ad2d39b15332006f22046aaa8352a3
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926
cw_decred: a02cf30175a46971c1e2fa22c48407534541edc6
cw_mweb: 3aea2fb35b2bd04d8b2d21b83216f3b8fb768d85
device_display_brightness: 04374ebd653619292c1d996f00f42877ea19f17f
device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89
devicelocale: bd64aa714485a8afdaded0892c1e7d5b7f680cf8
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
fast_scanner: 44c00940355a51258cd6c2085734193cd23d95bc
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
fast_scanner: 2cb1ad3e69e645e9980fb4961396ce5804caa3e3
file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
in_app_review: a31b5257259646ea78e0e35fc914979b0031d011
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
flutter_local_authentication: 989278c681612f1ee0e36019e149137f114b9d7f
flutter_mailer: 3a8cd4f36c960fb04528d5471097270c19fec1c4
flutter_secure_storage: 2c2ff13db9e0a5647389bff88b0ecac56e3f3418
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
in_app_review: 5596fe56fab799e8edb3561c03d053363ab13457
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12
sensitive_clipboard: 161e9abc3d56b3131309d8a321eb4690a803c16b
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sp_scanner: b1bc9321690980bdb44bba7ec85d5543e716d1b5
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56
uni_links: ed8c961e47ed9ce42b6d91e1de8049e38a4b3152
universal_ble: ff19787898040d721109c6324472e5dd4bc86adc
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
PODFILE CHECKSUM: e448f662d4c41f0c0b1ccbb78afd57dbf895a597

View file

@ -33,6 +33,7 @@
CFEFC24F82F78FE747DF1D22 /* LnurlPayInfo.swift in Resources */ = {isa = PBXBuildFile; fileRef = 58C22CBD8C22B9D6023D59F8 /* LnurlPayInfo.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
D0D7A0D4E13F31C4E02E235B /* ReceivePayment.swift in Resources */ = {isa = PBXBuildFile; fileRef = 91C524F800843E0A3F17E004 /* ReceivePayment.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
D3AD73A327249AFE8F016A51 /* BreezSDK.swift in Resources */ = {isa = PBXBuildFile; fileRef = ABD6FCBB0F4244B090459128 /* BreezSDK.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
D756D0B62DB7AC0C006F8689 /* TariWallet.xcframework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D76455EF2DB7A0B000929BAA /* TariWallet.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F5EE19868D6F10D814BF73AD /* SDKNotificationService.swift in Resources */ = {isa = PBXBuildFile; fileRef = 41102141140E57B1DC27FBA1 /* SDKNotificationService.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
/* End PBXBuildFile section */
@ -43,6 +44,7 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
D756D0B62DB7AC0C006F8689 /* TariWallet.xcframework in CopyFiles */,
CE918BF82D533ECE007F186E /* MoneroWallet.xcframework in CopyFiles */,
CE918BFA2D533ED4007F186E /* WowneroWallet.xcframework in CopyFiles */,
CE918BFC2D533ED8007F186E /* ZanoWallet.xcframework in CopyFiles */,
@ -89,6 +91,7 @@
CE918BF92D533ED4007F186E /* WowneroWallet.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = WowneroWallet.xcframework; sourceTree = "<group>"; };
CE918BFB2D533ED8007F186E /* ZanoWallet.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = ZanoWallet.xcframework; sourceTree = "<group>"; };
D139E30AEB36740C21C00A9E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
D76455EF2DB7A0B000929BAA /* TariWallet.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = TariWallet.xcframework; sourceTree = "<group>"; };
D7CD6B6020744E8FA471915D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DCEA540E3586164FB47AD13E /* LnurlPayInvoice.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LnurlPayInvoice.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Task/LnurlPayInvoice.swift"; sourceTree = "<group>"; };
F42258C3697CFE3C8C8D1933 /* ServiceLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServiceLogger.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/ServiceLogger.swift"; sourceTree = "<group>"; };
@ -110,6 +113,7 @@
06957875428D0F5AAE053765 /* Frameworks */ = {
isa = PBXGroup;
children = (
D76455EF2DB7A0B000929BAA /* TariWallet.xcframework */,
CE918BFB2D533ED8007F186E /* ZanoWallet.xcframework */,
CE918BF92D533ED4007F186E /* WowneroWallet.xcframework */,
CE918BF72D533ECE007F186E /* MoneroWallet.xcframework */,

View file

@ -39,7 +39,8 @@ class MenuWidgetState extends State<MenuWidget> {
this.tronIcon = Image.asset('assets/images/trx_icon.png'),
this.wowneroIcon = Image.asset('assets/images/wownero_icon.png'),
this.zanoIcon = Image.asset('assets/images/zano_icon.png'),
this.decredIcon = Image.asset('assets/images/decred_menu.png');
this.decredIcon = Image.asset('assets/images/decred_menu.png'),
this.tariIcon = Image.asset('assets/images/tari.png');
final largeScreen = 731;
@ -66,6 +67,7 @@ class MenuWidgetState extends State<MenuWidget> {
Image wowneroIcon;
Image zanoIcon;
Image decredIcon;
Image tariIcon;
@override
void initState() {
@ -254,6 +256,8 @@ class MenuWidgetState extends State<MenuWidget> {
return zanoIcon;
case WalletType.decred:
return decredIcon;
case WalletType.tari:
return tariIcon;
default:
throw Exception('No icon for ${type.toString()}');
}

View file

@ -5,9 +5,8 @@ class CWTari extends Tari {
return []; // ToDo
}
WalletService createTariWalletService(Box<WalletInfo> walletInfoSource) {
return TariWalletService(walletInfoSource);
}
WalletService createTariWalletService(Box<WalletInfo> walletInfoSource) =>
TariWalletService(walletInfoSource);
WalletCredentials createTariNewWalletCredentials(
{required String name,

View file

@ -16,6 +16,8 @@ class AddressFormatter {
final isMWEB = address.startsWith('ltcmweb');
final chunkSize = walletType != null ? _getChunkSize(walletType) : 4;
if (walletType == WalletType.tari) return Text(address, style: evenTextStyle,);
if (shouldTruncate) {
return _buildTruncatedAddress(
address: cleanAddress,
@ -158,4 +160,4 @@ class AddressFormatter {
return 4;
}
}
}
}

View file

@ -2,6 +2,8 @@ PODS:
- connectivity_plus (0.0.1):
- FlutterMacOS
- ReachabilitySwift
- cw_decred (0.0.1):
- FlutterMacOS
- cw_mweb (0.0.1):
- FlutterMacOS
- device_info_plus (0.0.1):
@ -44,6 +46,7 @@ PODS:
DEPENDENCIES:
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
- cw_decred (from `Flutter/ephemeral/.symlinks/plugins/cw_decred/macos`)
- cw_mweb (from `Flutter/ephemeral/.symlinks/plugins/cw_mweb/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
@ -70,6 +73,8 @@ SPEC REPOS:
EXTERNAL SOURCES:
connectivity_plus:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
cw_decred:
:path: Flutter/ephemeral/.symlinks/plugins/cw_decred/macos
cw_mweb:
:path: Flutter/ephemeral/.symlinks/plugins/cw_mweb/macos
device_info_plus:
@ -106,26 +111,27 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
SPEC CHECKSUMS:
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
cw_mweb: 7440b12ead811dda972a9918442ea2a458e8742c
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
fast_scanner: d31bae07e2653403a69dac99fb710c1722b16a97
flutter_inappwebview_macos: bdf207b8f4ebd58e86ae06cd96b147de99a67c9b
flutter_local_authentication: 85674893931e1c9cfa7c9e4f5973cb8c56b018b0
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
connectivity_plus: e74b9f74717d2d99d45751750e266e55912baeb5
cw_decred: 246ada7e0020a6b29e769f7a26653fcfc0ad752f
cw_mweb: 4746a3b5cc5bd4afe6fadd2481c4f7b239e391d0
device_info_plus: b0fafc687fb901e2af612763340f1b0d4352f8e5
devicelocale: 456a07c045d3113938aa4983065bd8526e2af792
fast_scanner: a4ead8e56f185cd565e25250fdb97fa669ea1d2e
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
flutter_local_authentication: 2f9a2682f498abcc12d7e9729b5007a947170fdc
flutter_secure_storage_macos: 3dacac420d84c4d0dc5e868194ee43c8664ec797
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
in_app_review: a6a031b9acd03c7d103e341aa334adf2c493fb93
in_app_review: 0599bccaed5e02f6bed2b0d30d16f86b63ed8638
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda
share_plus: 1fa619de8392a4398bfaf176d441853922614e89
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sp_scanner: 269d96e0ec3173e69156be7239b95182be3b8303
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sp_scanner: d9316427b628dd86d6e9e3c5d42ed6b4b410157c
universal_ble: ff19787898040d721109c6324472e5dd4bc86adc
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497
PODFILE CHECKSUM: 65ec1541137fb5b35d00490dec1bb48d4d9586bb

View file

@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "Cake Wallet.app"
BuildableName = ".app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@ -31,7 +31,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "Cake Wallet.app"
BuildableName = ".app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@ -54,7 +54,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "Cake Wallet.app"
BuildableName = ".app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@ -71,7 +71,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "Cake Wallet.app"
BuildableName = ".app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>

View file

@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in
CONFIG_ARGS="--monero"
;;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred"
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred --tari"
;;
esac

View file

@ -31,7 +31,7 @@ case $APP_IOS_TYPE in
;;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred"
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred --tari"
;;
esac

157
scripts/ios/gen_framework_tari.sh Executable file
View file

@ -0,0 +1,157 @@
#!/bin/sh
set -e
IOS_DIR="$(pwd)/../../ios"
DYLIB_PATH="$(pwd)/../../scripts/tari"
TMP_DIR="${IOS_DIR}/tmp"
rm -rf "${IOS_DIR:?}/TariWallet.xcframework"
rm -rf "${IOS_DIR:?}/TariWallet.framework"
rm -rf "$TMP_DIR"
mkdir -p "$TMP_DIR"
write_info_plist() {
framework_bundle="$1"
framework_name="$2"
target="$3"
plist_path="${framework_bundle}/Info.plist"
if [[ "x$target" = "xiossimulator" ]]; then
platform="iPhoneSimulator"
dtplatformname="iphonesimulator"
dtsdkname="iphonesimulator17.4"
else
platform="iPhoneOS"
dtplatformname="iphoneos"
dtsdkname="iphoneos17.4"
fi
cat > "$plist_path" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>23E224</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${framework_name}</string>
<key>CFBundleIdentifier</key>
<string>com.fotolockr.${framework_name}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${framework_name}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>???</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>${platform}</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>21E210</string>
<key>DTPlatformName</key>
<string>${dtplatformname}</string>
<key>DTPlatformVersion</key>
<string>17.4</string>
<key>DTSDKBuild</key>
<string>21E210</string>
<key>DTSDKName</key>
<string>${dtsdkname}</string>
<key>DTXcode</key>
<string>1530</string>
<key>DTXcodeBuild</key>
<string>15E204a</string>
<key>MinimumOSVersion</key>
<string>16.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
</dict>
</plist>
EOF
plutil -convert binary1 "$plist_path"
}
create_framework() {
framework_name="$2"
target="$3"
out_dir="$4"
echo "Creating ${framework_name}.framework for target ${target} in ${out_dir}..."
framework_bundle="${out_dir}/${framework_name}.framework"
rm -rf "$framework_bundle"
mkdir -p "$framework_bundle"
input_dylib="${DYLIB_PATH}/aarch64-apple-ios/libminotari_wallet_ffi.dylib"
if [[ ! -f "$input_dylib" ]]; then
echo "Error: Input dylib not found: $input_dylib"
exit 1
fi
lipo -create "$input_dylib" -output "${framework_bundle}/${framework_name}"
echo "Created binary: ${framework_bundle}/${framework_name}"
write_info_plist "$framework_bundle" "$framework_name" "$target"
}
create_xcframework() {
framework_name="$1"
device_framework="$2"
simulator_framework="$3"
xcframework_output="$4"
echo "Creating ${xcframework_output} by bundling:"
echo " Device framework: ${device_framework}"
echo " Simulator framework: ${simulator_framework}"
xcodebuild -create-xcframework \
-framework "$device_framework" \
-output "$xcframework_output"
echo "Created XCFramework: ${xcframework_output}"
}
wallets=("tari")
framework_names=("TariWallet")
for i in "${!wallets[@]}"; do
wallet="${wallets[$i]}"
framework_name="${framework_names[$i]}"
device_out="${TMP_DIR}/${framework_name}_device"
simulator_out="${TMP_DIR}/${framework_name}_simulator"
rm -rf "$device_out" "$simulator_out"
mkdir -p "$device_out" "$simulator_out"
create_framework "$wallet" "$framework_name" "ios" "$device_out"
# create_framework "$wallet" "$framework_name" "iossimulator" "$simulator_out"
device_framework="${device_out}/${framework_name}.framework"
simulator_framework="${simulator_out}/${framework_name}.framework"
xcframework_output="${IOS_DIR}/${framework_name}.xcframework"
rm -rf "$xcframework_output"
create_xcframework "$framework_name" "$device_framework" "$simulator_framework" "$xcframework_output"
done
echo "All XCFrameworks created successfully."
rm -rf "$TMP_DIR"

View file

@ -11,6 +11,7 @@ const tronOutputPath = 'lib/tron/tron.dart';
const wowneroOutputPath = 'lib/wownero/wownero.dart';
const zanoOutputPath = 'lib/zano/zano.dart';
const decredOutputPath = 'lib/decred/decred.dart';
const tariOutputPath = 'lib/tari/tari.dart';
const walletTypesPath = 'lib/wallet_types.g.dart';
const secureStoragePath = 'lib/core/secure_storage.dart';
const pubspecDefaultPath = 'pubspec_default.yaml';
@ -1386,7 +1387,7 @@ abstract class Decred {
}
Future<void> generateTari(bool hasImplementation) async {
final outputFile = File(decredOutputPath);
final outputFile = File(tariOutputPath);
const tariCommonHeaders = """
import 'package:cw_core/crypto_amount_format.dart';
import 'package:cw_core/transaction_priority.dart';
@ -1674,7 +1675,7 @@ Future<void> generateWalletTypes({
outputContent += '\tWalletType.wownero,\n';
}
if (hasWownero) {
if (hasTari) {
outputContent += '\tWalletType.tari,\n';
}