cw_decred: add libdcrwallet dependency and link library for android, ios and macos ()

* change cw_decred from package to plugin

* add libdcrwallet dependency and link library for android, ios and macos

* remove spvwallet, make some libdcrwallet fns async, light refactor

* libdcrwallet: use json payload returns

* use specific libwallet commit hash

* decred: fix Rename wallet.

---------

Co-authored-by: JoeGruff <joegruffins@gmail.com>
This commit is contained in:
Wisdom Arerosuoghene 2024-03-06 03:32:15 +01:00 committed by JoeGruff
parent 76283cd82e
commit 2b808ad50a
38 changed files with 910 additions and 344 deletions

39
cw_decred/.gitignore vendored
View file

@ -0,0 +1,39 @@
# 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/
android/.externalNativeBuild/
android/.cxx/
android/libs
ios/External/
macos/External/
libdcrwallet.h
libdcrwallet_bindings.dart

View file

@ -1,10 +1,36 @@
# 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.
# This file should be version controlled.
version:
revision: b1395592de68cc8ac4522094ae59956dd21a91db
channel: stable
revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
channel: unknown
project_type: package
project_type: plugin
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: android
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: ios
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: macos
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View file

@ -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

9
cw_decred/android/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.cxx

View file

@ -0,0 +1,66 @@
group 'com.cakewallet.cw_decred'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 31
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main {
java.srcDirs += 'src/main/kotlin'
jniLibs.srcDirs 'libs' // contains libdcrwallet.so shared libraries
}
}
defaultConfig {
minSdkVersion 16
}
dependencies {
testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation 'org.mockito:mockito-core:5.0.0'
}
testOptions {
unitTests.all {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen {false}
showStandardStreams = true
}
}
}
}

View file

@ -0,0 +1 @@
rootProject.name = 'cw_decred'

View file

@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cakewallet.cw_decred">
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View file

@ -0,0 +1,35 @@
package com.cakewallet.cw_decred
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
/** CwDecredPlugin */
class CwDecredPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cw_decred")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}

38
cw_decred/ios/.gitignore vendored Normal file
View file

@ -0,0 +1,38 @@
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/Generated.xcconfig
/Flutter/ephemeral/
/Flutter/flutter_export_environment.sh

View file

View file

@ -0,0 +1,19 @@
import Flutter
import UIKit
public class CwDecredPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "cw_decred", binaryMessenger: registrar.messenger())
let instance = CwDecredPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("iOS " + UIDevice.current.systemVersion)
default:
result(FlutterMethodNotImplemented)
}
}
}

View file

@ -0,0 +1,22 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint cw_decred.podspec` to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'cw_decred'
s.version = '0.0.1'
s.summary = 'Cake Wallet Decred'
s.description = 'Cake Wallet wrapper over Decred project'
s.homepage = 'http://cakewallet.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Cake Wallet' => 'support@cakewallet.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.platform = :ios, '11.0'
s.vendored_libraries = 'External/lib/libdcrwallet.a'
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', "OTHER_LDFLAGS" => "-force_load $(PODS_TARGET_SRCROOT)/External/lib/libdcrwallet.a -lstdc++" }
s.swift_version = '5.0'
end

View file

@ -1,127 +0,0 @@
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/unspent_transaction_output.dart';
import 'package:cw_decred/balance.dart';
import 'package:cw_decred/pending_transaction.dart';
import 'package:cw_decred/transaction_info.dart';
import 'package:cw_core/transaction_direction.dart';
import 'dart:typed_data';
import 'dart:io';
// Will it work if none of these are async functions?
class SPVWallet {
SPVWallet();
SPVWallet create(Uint8List seed, String password, WalletInfo walletInfo) {
return SPVWallet();
}
SPVWallet load(String password, String name, WalletInfo walletInfo) {
return SPVWallet();
}
DecredBalance balance() {
return DecredBalance(
confirmed: 777,
unconfirmed: 111,
);
}
int feeRate(int priority) {
return 1000;
}
int calculateEstimatedFeeWithFeeRate(int feeRate, int amount) {
// Ideally we create a tx with wallet going to this amount and just return
// the fee we get back.
return 123000;
}
void close() {}
DecredPendingTransaction createTransaction(Object credentials) {
return DecredPendingTransaction(
spv: this,
txid:
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
amount: 12345678,
fee: 1234,
rawHex: "baadbeef");
}
void rescan(int height) {
sleep(Duration(seconds: 10));
}
void startSync() {
sleep(Duration(seconds: 5));
}
SyncStatus syncStatus() {
return SyncedSyncStatus();
}
int height() {
return 400;
}
Map<String, DecredTransactionInfo> transactions() {
final txInfo = DecredTransactionInfo(
id: "3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
amount: 1234567,
fee: 123,
direction: TransactionDirection.outgoing,
isPending: true,
date: DateTime.now(),
height: 0,
confirmations: 0,
to: "DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
);
return {
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02": txInfo
};
}
String newAddress() {
// external
return "DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt";
}
List<String> addresses() {
return [
"DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
"DsVZGfGpd7WVffBZ5wbFZEHLV3FHNmXs9Az"
];
}
List<Unspent> unspents() {
return [
Unspent(
"DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
1234567,
0,
null)
];
}
void changePassword(String newPW) {}
void sendRawTransaction(String rawHex) {}
String signMessage(String message, String? address) {
return "abababababababab";
}
}
Uint8List mnemonicToSeedBytes(String mnemonic) {
return Uint8List(32);
}
String generateMnemonic() {
return "maid upper strategy dove theory dream material cruel season best napkin ethics biology top episode rough hotel flight video target organ six disagree verify maid upper strategy dove theory dream material cruel season best napkin ethics biology top episode rough hotel flight video target organ six disagree verify";
}
bool validateMnemonic(String mnemonic) {
return true;
}

View file

@ -0,0 +1,126 @@
import 'dart:convert';
import 'dart:ffi';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:cw_decred/api/libdcrwallet_bindings.dart';
import 'package:cw_decred/api/util.dart';
final int ErrCodeNotSynced = 1;
final String libraryName =
Platform.isAndroid || Platform.isLinux // TODO: Linux.
? 'libdcrwallet.so'
: 'cw_decred.framework/cw_decred';
final dcrwalletApi = libdcrwallet(DynamicLibrary.open(libraryName));
/// initLibdcrwallet initializes libdcrwallet using the provided logDir and gets
/// it ready for use. This must be done before attempting to create, load or use
/// a wallet.
void initLibdcrwallet(String logDir) {
final cLogDir = logDir.toCString();
final res = executePayloadFn(
fn: () => dcrwalletApi.initialize(cLogDir),
ptrsToFree: [cLogDir],
);
print(res.payload);
}
/// createWalletAsync calls the libdcrwallet's createWallet function
/// asynchronously.
Future<void> createWalletAsync(
{required String name, required String dataDir, required String password}) {
final args = <String, String>{
"name": name,
"dataDir": dataDir,
"password": password,
};
return compute(createWalletSync, args);
}
/// createWalletSync calls the libdcrwallet's createWallet function
/// synchronously.
void createWalletSync(Map<String, String> args) {
final name = args["name"]!.toCString();
final dataDir = args["dataDir"]!.toCString();
final password = args["password"]!.toCString();
final network = "testnet".toCString();
final res = executePayloadFn(
fn: () => dcrwalletApi.createWallet(name, dataDir, network, password),
ptrsToFree: [name, dataDir, network, password],
);
print(res.payload);
}
/// loadWalletAsync calls the libdcrwallet's loadWallet function asynchronously.
Future<void> loadWalletAsync({required String name, required String dataDir}) {
final args = <String, String>{
"name": name,
"dataDir": dataDir,
};
return compute(loadWalletSync, args);
}
/// loadWalletSync calls the libdcrwallet's loadWallet function synchronously.
void loadWalletSync(Map<String, String> args) {
final name = args["name"]!.toCString();
final dataDir = args["dataDir"]!.toCString();
final network = "testnet".toCString();
final res = executePayloadFn(
fn: () => dcrwalletApi.loadWallet(name, dataDir, network),
ptrsToFree: [name, dataDir, network],
);
print(res.payload);
}
void closeWallet(String walletName) {
// TODO.
}
Future<void> changeWalletPassword(
String walletName, String currentPassword, String newPassword) async {
// TODO.
}
String? walletSeed(String walletName, String walletPassword) {
final cName = walletName.toCString();
final pass = walletPassword.toCString();
final res = executePayloadFn(
fn: () => dcrwalletApi.walletSeed(cName, pass),
ptrsToFree: [cName, pass],
);
return res.payload;
}
String? currentReceiveAddress(String walletName) {
final cName = walletName.toCString();
final res = executePayloadFn(
fn: () => dcrwalletApi.currentReceiveAddress(cName),
ptrsToFree: [cName],
skipErrorCheck: true, // errCode is checked below, before checking err
);
if (res.errCode == ErrCodeNotSynced) {
// Wallet is not synced. We do not want to give out a used address so give
// nothing.
return null;
}
checkErr(res.err);
return res.payload;
}
Map balance(String walletName) {
final cName = walletName.toCString();
final res = executePayloadFn(
fn: () => dcrwalletApi.walletBalance(cName),
ptrsToFree: [cName],
);
return jsonDecode(res.payload);
}
int calculateEstimatedFeeWithFeeRate(int feeRate, int amount) {
// Ideally we create a tx with wallet going to this amount and just return
// the fee we get back. TODO.
return 123000;
}

View file

@ -0,0 +1,64 @@
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'dart:convert';
class PayloadResult {
final String payload;
final String err;
final int errCode;
const PayloadResult(this.payload, this.err, this.errCode);
}
// Executes the provided fn and converts the string response to a PayloadReult.
// Returns payload, error code, and error.
PayloadResult executePayloadFn({
required Pointer<Char> fn(),
required List<Pointer> ptrsToFree,
bool skipErrorCheck = false,
}) {
final jsonStr = fn().toDartString();
freePointers(ptrsToFree);
if (jsonStr == null) throw Exception("no json return from wallet library");
final decoded = json.decode(jsonStr);
final err = decoded["error"] ?? "";
if (!skipErrorCheck) {
checkErr(err);
}
final payload = decoded["payload"] ?? "";
final errCode = decoded["errorcode"] ?? -1;
return new PayloadResult(payload, err, errCode);
}
void freePointers(List<Pointer> ptrsToFree) {
for (final ptr in ptrsToFree) {
malloc.free(ptr);
}
}
void checkErr(String err) {
if (err == "") return;
throw Exception(err);
}
extension StringUtil on String {
Pointer<Char> toCString() => toNativeUtf8().cast<Char>();
}
extension CStringUtil on Pointer<Char> {
bool get isNull => address == nullptr.address;
free() {
malloc.free(this);
}
String? toDartString() {
if (isNull) return null;
final str = cast<Utf8>().toDartString();
free();
return str;
}
}

View file

@ -5,6 +5,8 @@ class DecredBalance extends Balance {
const DecredBalance({required this.confirmed, required this.unconfirmed})
: super(confirmed, unconfirmed);
factory DecredBalance.zero() => DecredBalance(confirmed: 0, unconfirmed: 0);
final int confirmed;
final int unconfirmed;

View file

@ -1,28 +0,0 @@
List<String> wordList() {
return [
"maid",
"upper",
"strategy",
"dove",
"theory",
"dream",
"material",
"cruel",
"season",
"best",
"napkin",
"ethics",
"biology",
"top",
"episode",
"rough",
"hotel",
"flight",
"video",
"target",
"organ",
"six",
"disagree",
"verify"
];
}

View file

@ -1,5 +0,0 @@
class DecredMnemonicIsIncorrectException implements Exception {
@override
String toString() =>
'Decred mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.';
}

View file

@ -1,16 +1,13 @@
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_decred/amount_format.dart';
import 'package:cw_decred/api/dcrlibwallet.dart';
class DecredPendingTransaction with PendingTransaction {
DecredPendingTransaction(
{required this.spv,
required this.txid,
{required this.txid,
required this.amount,
required this.fee,
required this.rawHex});
final SPVWallet spv;
final int amount;
final int fee;
final String txid;
@ -30,6 +27,6 @@ class DecredPendingTransaction with PendingTransaction {
@override
Future<void> commit() async {
this.spv.sendRawTransaction(this.rawHex);
// TODO: Submit rawHex using libdcrwallet.
}
}

View file

@ -1,13 +1,16 @@
import 'dart:io';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_decred/pending_transaction.dart';
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_decred/api/libdcrwallet.dart' as libdcrwallet;
import 'package:cw_decred/transaction_history.dart';
import 'package:cw_decred/wallet_addresses.dart';
import 'package:cw_decred/transaction_priority.dart';
import 'package:cw_decred/api/dcrlibwallet.dart';
import 'package:cw_decred/balance.dart';
import 'package:cw_decred/transaction_info.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:mobx/mobx.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/transaction_priority.dart';
@ -23,73 +26,48 @@ class DecredWallet = DecredWalletBase with _$DecredWallet;
abstract class DecredWalletBase extends WalletBase<DecredBalance,
DecredTransactionHistory, DecredTransactionInfo> with Store {
DecredWalletBase(SPVWallet spv, WalletInfo walletInfo)
: this.spv = spv,
balance = ObservableMap<CryptoCurrency, DecredBalance>.of(
{CryptoCurrency.dcr: spv.balance()}),
DecredWalletBase(WalletInfo walletInfo, String password)
: _password = password,
syncStatus = NotConnectedSyncStatus(),
balance = ObservableMap.of({CryptoCurrency.dcr: DecredBalance.zero()}),
super(walletInfo) {
walletAddresses = DecredWalletAddresses(walletInfo);
transactionHistory = DecredTransactionHistory();
walletAddresses = DecredWalletAddresses(walletInfo, spv);
}
final SPVWallet spv;
static Future<DecredWallet> create(
{required String mnemonic,
required String password,
required WalletInfo walletInfo}) async {
final seed = mnemonicToSeedBytes(mnemonic);
final spv = SPVWallet().create(seed, password, walletInfo);
final wallet = DecredWallet(spv, walletInfo);
return wallet;
}
static Future<DecredWallet> open(
{required String password,
required String name,
required WalletInfo walletInfo}) async {
final spv = SPVWallet().load(name, password, walletInfo);
final wallet = DecredWallet(spv, walletInfo);
return wallet;
}
// password is currently only used for seed display, but would likely also be
// required to sign inputs when creating transactions.
final String _password;
// TODO: Set up a way to change the balance and sync status when dcrlibwallet
// changes. Long polling probably?
@override
@observable
late ObservableMap<CryptoCurrency, DecredBalance> balance;
SyncStatus syncStatus;
@override
@observable
SyncStatus syncStatus;
late ObservableMap<CryptoCurrency, DecredBalance> balance;
// @override
// set syncStatus(SyncStatus status);
@override
late DecredWalletAddresses walletAddresses;
@override
String? get seed {
// throw UnimplementedError();
return "";
return libdcrwallet.walletSeed(walletInfo.name, _password);
}
// @override
// String? get privateKey => null;
@override
Object get keys {
// throw UnimplementedError();
return {};
}
@override
late DecredWalletAddresses walletAddresses;
// @override
// set isEnabledAutoGenerateSubaddress(bool value) {}
// @override
// bool get isEnabledAutoGenerateSubaddress => false;
Future<void> init() async {
updateBalance();
// TODO: update other wallet properties such as syncStatus, walletAddresses
// and transactionHistory with data from libdcrwallet.
}
@override
Future<void> connectToNode({required Node node}) async {
@ -99,34 +77,29 @@ abstract class DecredWalletBase extends WalletBase<DecredBalance,
@action
@override
Future<void> startSync() async {
try {
this.spv.startSync();
syncStatus = this.spv.syncStatus();
} catch (e, stacktrace) {
print(stacktrace);
print(e.toString());
syncStatus = FailedSyncStatus();
}
// TODO: call libdcrwallet.spvSync() and update syncStatus.
}
@override
Future<PendingTransaction> createTransaction(Object credentials) async {
return this.spv.createTransaction(credentials);
return DecredPendingTransaction(
txid:
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
amount: 12345678,
fee: 1234,
rawHex: "baadbeef");
}
int feeRate(TransactionPriority priority) {
try {
return this.spv.feeRate(priority.raw);
} catch (_) {
return 0;
}
// TODO
return 1000;
}
@override
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
if (priority is DecredTransactionPriority) {
return this.spv.calculateEstimatedFeeWithFeeRate(
this.spv.feeRate(priority.raw), amount ?? 0);
return libdcrwallet.calculateEstimatedFeeWithFeeRate(
this.feeRate(priority), amount ?? 0);
}
return 0;
@ -134,7 +107,21 @@ abstract class DecredWalletBase extends WalletBase<DecredBalance,
@override
Future<Map<String, DecredTransactionInfo>> fetchTransactions() async {
return this.spv.transactions();
// TODO: Read from libdcrwallet.
final txInfo = DecredTransactionInfo(
id: "3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
amount: 1234567,
fee: 123,
direction: TransactionDirection.outgoing,
isPending: true,
date: DateTime.now(),
height: 0,
confirmations: 0,
to: "DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
);
return {
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02": txInfo
};
}
@override
@ -142,28 +129,27 @@ abstract class DecredWalletBase extends WalletBase<DecredBalance,
@override
Future<void> rescan({required int height}) async {
return spv.rescan(height);
// TODO.
}
@override
void close() {
this.spv.close();
libdcrwallet.closeWallet(walletInfo.name);
}
@override
Future<void> changePassword(String password) async {
return this.spv.changePassword(password);
}
@override
String get password {
// throw UnimplementedError();
return "";
await libdcrwallet.changeWalletPassword(
walletInfo.name, _password, password);
}
@override
Future<void>? updateBalance() async {
balance[CryptoCurrency.dcr] = this.spv.balance();
final balanceMap = libdcrwallet.balance(walletInfo.name);
balance[CryptoCurrency.dcr] = DecredBalance(
confirmed: balanceMap["confirmed"] ?? 0,
unconfirmed: balanceMap["unconfirmed"] ?? 0,
);
}
@override
@ -171,33 +157,33 @@ abstract class DecredWalletBase extends WalletBase<DecredBalance,
onError;
Future<void> renameWalletFiles(String newWalletName) async {
final currentWalletPath =
await pathForWallet(name: walletInfo.name, type: type);
final currentWalletFile = File(currentWalletPath);
final currentDirPath =
await pathForWalletDir(name: walletInfo.name, type: type);
// TODO: Stop the wallet, wait, and restart after.
final newDirPath = await pathForWalletDir(name: newWalletName, type: type);
// Copies current wallet files into new wallet name's dir and files
if (currentWalletFile.existsSync()) {
final newWalletPath =
await pathForWallet(name: newWalletName, type: type);
await currentWalletFile.copy(newWalletPath);
if (File(newDirPath).existsSync()) {
throw "wallet already exists at $newDirPath";
}
;
// Delete old name's dir and files
await Directory(currentDirPath).delete(recursive: true);
await Directory(currentDirPath).rename(newDirPath);
}
@override
String signMessage(String message, {String? address = null}) {
return this.spv.signMessage(message, address);
return ""; // TODO
}
List<Unspent> unspents() {
return this.spv.unspents();
return [
Unspent(
"DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
1234567,
0,
null)
];
}
@override

View file

@ -1,25 +1,23 @@
import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_decred/api/dcrlibwallet.dart';
import 'package:cw_decred/api/libdcrwallet.dart' as libdcrwallet;
class DecredWalletAddresses extends WalletAddresses {
DecredWalletAddresses(WalletInfo walletInfo, SPVWallet spv)
: this.spv = spv,
super(walletInfo);
final SPVWallet spv;
DecredWalletAddresses(WalletInfo walletInfo) : super(walletInfo);
@override
String get address {
return this.spv.newAddress();
return libdcrwallet.currentReceiveAddress(walletInfo.name) ?? '';
}
String generateNewAddress() {
return this.spv.newAddress();
// TODO: generate new external address with libdcrwallet.
return "DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt";
}
List<String> addresses() {
return this.spv.addresses();
final currentAddress = libdcrwallet.currentReceiveAddress(walletInfo.name);
return currentAddress == null ? [] : [currentAddress];
}
@override

View file

@ -1,8 +1,7 @@
import 'dart:io';
import 'package:cw_decred/mnemonic_is_incorrect_exception.dart';
import 'package:cw_decred/api/libdcrwallet.dart';
import 'package:cw_decred/wallet_creation_credentials.dart';
import 'package:cw_decred/wallet.dart';
import 'package:cw_decred/api/dcrlibwallet.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/pathForWallet.dart';
@ -20,28 +19,43 @@ class DecredWalletService extends WalletService<
final Box<WalletInfo> walletInfoSource;
@override
WalletType getType() => WalletType.decred;
static void init() async {
// Use the general path for all dcr wallets as the general log directory.
// Individual wallet paths may be removed if the wallet is deleted.
final dcrLogDir = await pathForWalletDir(name: '', type: WalletType.decred);
initLibdcrwallet(dcrLogDir);
}
@override
Future<DecredWallet> create(DecredNewWalletCredentials credentials,
{bool? isTestnet}) async {
return await DecredWalletBase.create(
mnemonic: generateMnemonic(),
password: credentials.password!,
walletInfo: credentials.walletInfo!);
}
WalletType getType() => WalletType.decred;
@override
Future<bool> isWalletExit(String name) async =>
File(await pathForWallet(name: name, type: getType())).existsSync();
@override
Future<DecredWallet> create(DecredNewWalletCredentials credentials,
{bool? isTestnet}) async {
await createWalletAsync(
name: credentials.walletInfo!.name,
dataDir: credentials.walletInfo!.dirPath,
password: credentials.password!,
);
final wallet = DecredWallet(credentials.walletInfo!, credentials.password!);
await wallet.init();
return wallet;
}
@override
Future<DecredWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = await DecredWalletBase.open(
password: password, name: name, walletInfo: walletInfo);
await loadWalletAsync(
name: walletInfo.name,
dataDir: walletInfo.dirPath,
);
final wallet = DecredWallet(walletInfo, password);
await wallet.init();
return wallet;
}
@ -59,14 +73,15 @@ class DecredWalletService extends WalletService<
String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWallet = await DecredWalletBase.open(
password: password, name: currentName, walletInfo: currentWalletInfo);
final currentWallet = DecredWallet(currentWalletInfo, password);
await currentWallet.renameWalletFiles(newName);
final newDirPath = await pathForWalletDir(name: newName, type: getType());
final newWalletInfo = currentWalletInfo;
newWalletInfo.id = WalletBase.idFor(newName, getType());
newWalletInfo.name = newName;
newWalletInfo.dirPath = newDirPath;
await walletInfoSource.put(currentWalletInfo.key, newWalletInfo);
}
@ -75,15 +90,7 @@ class DecredWalletService extends WalletService<
Future<DecredWallet> restoreFromSeed(
DecredRestoreWalletFromSeedCredentials credentials,
{bool? isTestnet}) async {
if (!validateMnemonic(credentials.mnemonic)) {
throw DecredMnemonicIsIncorrectException();
}
final wallet = await DecredWalletBase.create(
password: credentials.password!,
mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo!);
return wallet;
throw UnimplementedError();
}
@override

View file

@ -0,0 +1,19 @@
import Cocoa
import FlutterMacOS
public class CwDecredPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "cw_decred", binaryMessenger: registrar.messenger)
let instance = CwDecredPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
default:
result(FlutterMethodNotImplemented)
}
}
}

View file

@ -0,0 +1,22 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint cw_decred.podspec` to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'cw_decred'
s.version = '0.0.1'
s.summary = 'Cake Wallet Decred'
s.description = 'Cake Wallet wrapper over Decred project'
s.homepage = 'http://cakewallet.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Cake Wallet' => 'support@cakewallet.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'FlutterMacOS'
s.platform = :osx, '10.11'
s.vendored_libraries = 'External/lib/libdcrwallet.a'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', "OTHER_LDFLAGS" => "-force_load $(PODS_TARGET_SRCROOT)/External/lib/libdcrwallet.a -lstdc++" }
s.swift_version = '5.0'
end

View file

@ -129,6 +129,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.3"
cli_util:
dependency: transitive
description:
name: cli_util
sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7
url: "https://pub.dev"
source: hosted
version: "0.4.0"
clock:
dependency: transitive
description:
@ -208,6 +216,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.0"
ffigen:
dependency: "direct dev"
description:
name: ffigen
sha256: "4bbf1fa19723a90578e991b9a95afca43bea856809890a26609618fa29087427"
url: "https://pub.dev"
source: hosted
version: "7.2.11"
file:
dependency: transitive
description:
@ -546,6 +562,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.3"
quiver:
dependency: transitive
description:
name: quiver
sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47
url: "https://pub.dev"
source: hosted
version: "3.2.1"
shelf:
dependency: transitive
description:
@ -567,6 +591,14 @@ packages:
description: flutter
source: sdk
version: "0.0.99"
socks5_proxy:
dependency: transitive
description:
name: socks5_proxy
sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
source_gen:
dependency: transitive
description:
@ -719,6 +751,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.2"
yaml_edit:
dependency: transitive
description:
name: yaml_edit
sha256: "1579d4a0340a83cf9e4d580ea51a16329c916973bffd5bd4b45e911b25d46bfd"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
sdks:
dart: ">=3.2.0-0 <4.0.0"
flutter: ">=3.7.0"

View file

@ -1,5 +1,5 @@
name: cw_decred
description: A new Flutter package project.
description: A new Flutter plugin project.
version: 0.0.1
publish_to: none
author: Cake Wallet
@ -22,3 +22,62 @@ dev_dependencies:
build_resolvers: ^2.0.9
mobx_codegen: ^2.0.7
hive_generator: ^1.1.3
ffigen: ^7.2.11
ffigen:
name: libdcrwallet
description: Bindings for dcrwallet go library.
output: "lib/api/libdcrwallet_bindings.dart"
headers:
entry-points:
- "lib/api/libdcrwallet.h"
# 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:
# This section identifies this Flutter project as a plugin project.
# The androidPackage and pluginClass identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
platforms:
android:
package: com.cakewallet.cw_decred
pluginClass: CwDecredPlugin
ios:
pluginClass: CwDecredPlugin
macos:
pluginClass: CwDecredPlugin
# To add assets to your plugin 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 plugin 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
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages

View file

@ -24,6 +24,7 @@ PODS:
- Flutter
- cw_mweb (0.0.1):
- Flutter
- cw_decred (0.0.1):
- cw_shared_external (0.0.1):
- cw_shared_external/Boost (= 0.0.1)
- cw_shared_external/OpenSSL (= 0.0.1)
@ -139,6 +140,7 @@ DEPENDENCIES:
- cw_haven (from `.symlinks/plugins/cw_haven/ios`)
- cw_mweb (from `.symlinks/plugins/cw_mweb/ios`)
- cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`)
- cw_decred (from `.symlinks/plugins/cw_decred/ios`)
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
@ -185,6 +187,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/cw_mweb/ios"
cw_shared_external:
:path: ".symlinks/plugins/cw_shared_external/ios"
cw_decred:
:path: ".symlinks/plugins/cw_decred/ios"
device_display_brightness:
:path: ".symlinks/plugins/device_display_brightness/ios"
device_info_plus:
@ -242,6 +246,7 @@ SPEC CHECKSUMS:
cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
cw_mweb: 87af74f9659fed0c1a2cbfb44413f1070e79e3ae
cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
cw_decred: 9c0e1df74745b51a1289ec5e91fb9e24b68fa14a
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926

View file

@ -1,9 +1,15 @@
part of 'decred.dart';
class CWDecred extends Decred {
CWDecred() {
// initialize the service for creating and loading dcr wallets.
DecredWalletService.init();
}
@override
TransactionPriority getMediumTransactionPriority() =>
DecredTransactionPriority.medium;
WalletCredentials createDecredNewWalletCredentials(
{required String name, WalletInfo? walletInfo}) =>
DecredNewWalletCredentials(name: name, walletInfo: walletInfo);
@override
WalletCredentials createDecredRestoreWalletFromSeedCredentials(
@ -13,18 +19,26 @@ class CWDecred extends Decred {
DecredRestoreWalletFromSeedCredentials(
name: name, mnemonic: mnemonic, password: password);
@override
WalletCredentials createDecredNewWalletCredentials(
{required String name, WalletInfo? walletInfo}) =>
DecredNewWalletCredentials(name: name, walletInfo: walletInfo);
@override
List<String> getWordList() => wordList();
WalletService createDecredWalletService(Box<WalletInfo> walletInfoSource) {
return DecredWalletService(walletInfoSource);
}
@override
List<TransactionPriority> getTransactionPriorities() =>
DecredTransactionPriority.all;
@override
TransactionPriority getMediumTransactionPriority() =>
DecredTransactionPriority.medium;
@override
TransactionPriority getDecredTransactionPriorityMedium() =>
DecredTransactionPriority.medium;
@override
TransactionPriority getDecredTransactionPrioritySlow() =>
DecredTransactionPriority.slow;
@override
TransactionPriority deserializeDecredTransactionPriority(int raw) =>
DecredTransactionPriority.deserialize(raw: raw);
@ -35,12 +49,6 @@ class CWDecred extends Decred {
return decredWallet.feeRate(priority);
}
@override
Future<void> generateNewAddress(Object wallet) async {
final decredWallet = wallet as DecredWallet;
await decredWallet.walletAddresses.generateNewAddress();
}
@override
Object createDecredTransactionCredentials(
List<Output> outputs, TransactionPriority priority) =>
@ -56,8 +64,7 @@ class CWDecred extends Decred {
isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount))
.toList(),
priority:
priority != null ? priority as DecredTransactionPriority : null);
priority: priority as DecredTransactionPriority);
@override
List<String> getAddresses(Object wallet) {
@ -71,6 +78,12 @@ class CWDecred extends Decred {
return decredWallet.walletAddresses.address;
}
@override
Future<void> generateNewAddress(Object wallet) async {
final decredWallet = wallet as DecredWallet;
await decredWallet.walletAddresses.generateNewAddress();
}
@override
String formatterDecredAmountToString({required int amount}) =>
decredAmountToString(amount: amount);
@ -90,16 +103,4 @@ class CWDecred extends Decred {
}
void updateUnspents(Object wallet) async {}
WalletService createDecredWalletService(Box<WalletInfo> walletInfoSource) {
return DecredWalletService(walletInfoSource);
}
@override
TransactionPriority getDecredTransactionPriorityMedium() =>
DecredTransactionPriority.medium;
@override
TransactionPriority getDecredTransactionPrioritySlow() =>
DecredTransactionPriority.slow;
}

View file

@ -6,6 +6,7 @@ import FlutterMacOS
import Foundation
import connectivity_plus
import cw_decred
import cw_mweb
import device_info_plus
import devicelocale
@ -24,6 +25,7 @@ import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
CwDecredPlugin.register(with: registry.registrar(forPlugin: "CwDecredPlugin"))
CwMwebPlugin.register(with: registry.registrar(forPlugin: "CwMwebPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))

View file

@ -3,6 +3,7 @@ PODS:
- FlutterMacOS
- ReachabilitySwift
- cw_mweb (0.0.1):
- cw_decred (0.0.1):
- FlutterMacOS
- device_info_plus (0.0.1):
- FlutterMacOS
@ -45,6 +46,7 @@ PODS:
DEPENDENCIES:
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
- cw_mweb (from `Flutter/ephemeral/.symlinks/plugins/cw_mweb/macos`)
- cw_decred (from `Flutter/ephemeral/.symlinks/plugins/cw_decred/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
- fast_scanner (from `Flutter/ephemeral/.symlinks/plugins/fast_scanner/macos`)
@ -72,6 +74,10 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
cw_mweb:
:path: Flutter/ephemeral/.symlinks/plugins/cw_mweb/macos
cw_decred:
:path: Flutter/ephemeral/.symlinks/plugins/cw_decred/macos
cw_monero:
:path: Flutter/ephemeral/.symlinks/plugins/cw_monero/macos
device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
devicelocale:
@ -108,6 +114,8 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
cw_mweb: 7440b12ead811dda972a9918442ea2a458e8742c
cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4
cw_decred: 0c93fbeb31bd97a6ad4ec5680960af0943bfca78
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
fast_scanner: d31bae07e2653403a69dac99fb710c1722b16a97

55
scripts/android/build_decred.sh Executable file
View file

@ -0,0 +1,55 @@
#!/bin/sh
. ./config.sh
CW_DECRED_DIR=${WORKDIR}/cake_wallet/cw_decred
LIBWALLET_PATH="${WORKDIR}/decred/libwallet"
LIBWALLET_URL="https://github.com/itswisdomagain/libwallet.git"
if [ -e $LIBWALLET_PATH ]; then
rm -fr $LIBWALLET_PATH
fi
mkdir -p $LIBWALLET_PATH
git clone $LIBWALLET_URL $LIBWALLET_PATH --branch cgo
cd $LIBWALLET_PATH
export CPATH="$(clang -v 2>&1 | grep "Selected GCC installation" | rev | cut -d' ' -f1 | rev)/include"
for arch in "aarch" "aarch64" "i686" "x86_64"
do
TARGET=""
ARCH_ABI=""
case $arch in
"aarch" )
TARGET="arm"
ARCH_ABI="armeabi-v7a";;
"aarch64" )
TARGET="arm64"
ARCH_ABI="arm64-v8a";;
"i686" )
TARGET="386"
ARCH_ABI="x86";;
"x86_64" )
TARGET="amd64"
ARCH_ABI="x86_64";;
esac
PATH="${TOOLCHAIN_BASE_DIR}_${arch}/bin:${ORIGINAL_PATH}"
if [ -e ./build ]; then
rm -fr ./build
fi
CGO_ENABLED=1 GOOS=android GOARCH=${TARGET} CC=clang CXX=clang++ \
go build -buildmode=c-shared -o ./build/libdcrwallet.so ./cgo
DEST_LIB_DIR=${CW_DECRED_DIR}/android/libs/${ARCH_ABI}
mkdir -p $DEST_LIB_DIR
mv ${LIBWALLET_PATH}/build/libdcrwallet.so $DEST_LIB_DIR
done
HEADER_DIR=$CW_DECRED_DIR/lib/api
mv ${LIBWALLET_PATH}/build/libdcrwallet.h $HEADER_DIR
cd $CW_DECRED_DIR
dart run ffigen

View file

@ -6,3 +6,4 @@
./build_sodium.sh
./build_zmq.sh
./build_haven.sh
./build_decred.sh

View file

@ -28,18 +28,18 @@ universal_sed "s/PRODUCT_BUNDLE_IDENTIFIER = .*;/PRODUCT_BUNDLE_IDENTIFIER = $AP
CONFIG_ARGS=""
case $APP_IOS_TYPE in
$MONERO_COM)
$MONERO_COM)
CONFIG_ARGS="--monero"
;;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero"
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --decred"
if [ "$CW_WITH_HAVEN" = true ];then
CONFIG_ARGS="$CONFIG_ARGS --haven"
fi
;;
$HAVEN)
CONFIG_ARGS="--haven"
;;
esac

33
scripts/ios/build_decred.sh Executable file
View file

@ -0,0 +1,33 @@
#!/bin/sh
. ./config.sh
LIBWALLET_PATH="${EXTERNAL_IOS_SOURCE_DIR}/libwallet"
LIBWALLET_URL="https://github.com/itswisdomagain/libwallet.git"
if [ -e $LIBWALLET_PATH ]; then
rm -fr $LIBWALLET_PATH
fi
mkdir -p $LIBWALLET_PATH
git clone $LIBWALLET_URL $LIBWALLET_PATH --branch cgo
cd $LIBWALLET_PATH
SYSROOT=`xcrun --sdk iphoneos --show-sdk-path`
CLANG="clang -isysroot ${SYSROOT}"
CLANGXX="clang++ -isysroot ${SYSROOT}"
if [ -e ./build ]; then
rm -fr ./build
fi
CGO_ENABLED=1 GOOS=ios GOARCH=arm64 CC=$CLANG CXX=$CLANGXX \
go build -buildmode=c-archive -o ./build/libdcrwallet.a ./cgo || exit 1
CW_DECRED_DIR=${CW_ROOT}/cw_decred
HEADER_DIR=$CW_DECRED_DIR/lib/api
mv ${LIBWALLET_PATH}/build/libdcrwallet.h $HEADER_DIR
DEST_LIB_DIR=${CW_DECRED_DIR}/ios/External/lib
mkdir -p $DEST_LIB_DIR
mv ${LIBWALLET_PATH}/build/libdcrwallet.a $DEST_LIB_DIR
cd $CW_DECRED_DIR
dart run ffigen

View file

@ -7,6 +7,7 @@
# ./build_sodium.sh
# ./build_zmq.sh
# ./build_unbound.sh
# ./build_decred.sh
set -x -e

View file

@ -36,7 +36,7 @@ case $APP_MACOS_TYPE in
$MONERO_COM)
CONFIG_ARGS="--monero";;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero";; #--haven
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --decred";; #--haven
esac
cp -rf pubspec_description.yaml pubspec.yaml

34
scripts/macos/build_decred.sh Executable file
View file

@ -0,0 +1,34 @@
#!/bin/sh
. ./config.sh
LIBWALLET_PATH="${EXTERNAL_MACOS_SOURCE_DIR}/libwallet"
LIBWALLET_URL="https://github.com/itswisdomagain/libwallet.git"
LIBWALLET_COMMIT_HASH=e1b9f6043359d191cfd2fbfaa345396a009d0946
echo "======================= DECRED LIBWALLET ========================="
echo "Cloning DECRED LIBWALLET from - $LIBWALLET_URL"
if [ -e $LIBWALLET_PATH ]; then
rm -fr $LIBWALLET_PATH
fi
mkdir -p $LIBWALLET_PATH
git clone $LIBWALLET_URL $LIBWALLET_PATH --branch cgo
cd $LIBWALLET_PATH
git checkout ${LIBWALLET_COMMIT_HASH}
if [ -e ./build ]; then
rm -fr ./build
fi
go build -buildmode=c-archive -o ./build/libdcrwallet.a ./cgo
CW_DECRED_DIR=${CW_ROOT}/cw_decred
HEADER_DIR=$CW_DECRED_DIR/lib/api
mv ${LIBWALLET_PATH}/build/libdcrwallet.h $HEADER_DIR
DEST_LIB_DIR=${CW_DECRED_DIR}/macos/External/lib
mkdir -p $DEST_LIB_DIR
mv ${LIBWALLET_PATH}/build/libdcrwallet.a $DEST_LIB_DIR
cd $CW_DECRED_DIR
dart run ffigen

View file

@ -1086,12 +1086,15 @@ abstract class BitcoinCash {
""";
const bitcoinCashEmptyDefinition = 'BitcoinCash? bitcoinCash;\n';
const bitcoinCashCWDefinition = 'BitcoinCash? bitcoinCash = CWBitcoinCash();\n';
const bitcoinCashCWDefinition =
'BitcoinCash? bitcoinCash = CWBitcoinCash();\n';
final output = '$bitcoinCashCommonHeaders\n' +
(hasImplementation ? '$bitcoinCashCWHeaders\n' : '\n') +
(hasImplementation ? '$bitcoinCashCwPart\n\n' : '\n') +
(hasImplementation ? bitcoinCashCWDefinition : bitcoinCashEmptyDefinition) +
(hasImplementation
? bitcoinCashCWDefinition
: bitcoinCashEmptyDefinition) +
'\n' +
bitcoinCashContent;
@ -1227,7 +1230,8 @@ abstract class NanoUtil {
""";
const nanoEmptyDefinition = 'Nano? nano;\nNanoUtil? nanoUtil;\n';
const nanoCWDefinition = 'Nano? nano = CWNano();\nNanoUtil? nanoUtil = CWNanoUtil();\n';
const nanoCWDefinition =
'Nano? nano = CWNano();\nNanoUtil? nanoUtil = CWNanoUtil();\n';
final output = '$nanoCommonHeaders\n' +
(hasImplementation ? '$nanoCWHeaders\n' : '\n') +
@ -1410,13 +1414,12 @@ import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/output_info.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/unspent_transaction_output.dart';
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:hive/hive.dart';""";
import 'package:hive/hive.dart';
""";
const decredCWHeaders = """
import 'package:cw_decred/mnemonic.dart';
import 'package:cw_decred/transaction_priority.dart';
import 'package:cw_decred/wallet.dart';
import 'package:cw_decred/wallet_service.dart';
@ -1428,19 +1431,22 @@ import 'package:cw_decred/transaction_credentials.dart';
const decredContent = """
abstract class Decred {
TransactionPriority getMediumTransactionPriority();
WalletCredentials createDecredRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
WalletCredentials createDecredNewWalletCredentials({required String name, WalletInfo? walletInfo});
List<String> getWordList();
WalletCredentials createDecredRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
WalletService createDecredWalletService(Box<WalletInfo> walletInfoSource);
List<TransactionPriority> getTransactionPriorities();
TransactionPriority getMediumTransactionPriority();
TransactionPriority getDecredTransactionPriorityMedium();
TransactionPriority getDecredTransactionPrioritySlow();
TransactionPriority deserializeDecredTransactionPriority(int raw);
int getFeeRate(Object wallet, TransactionPriority priority);
Future<void> generateNewAddress(Object wallet);
Object createDecredTransactionCredentials(List<Output> outputs, TransactionPriority priority);
List<String> getAddresses(Object wallet);
String getAddress(Object wallet);
Future<void> generateNewAddress(Object wallet);
String formatterDecredAmountToString({required int amount});
double formatterDecredAmountToDouble({required int amount});
@ -1448,21 +1454,18 @@ abstract class Decred {
List<Unspent> getUnspents(Object wallet);
void updateUnspents(Object wallet);
WalletService createDecredWalletService(Box<WalletInfo> walletInfoSource);
TransactionPriority getDecredTransactionPriorityMedium();
TransactionPriority getDecredTransactionPrioritySlow();
}
""";
const decredEmptyDefinition = 'Decred? decred;\n';
const decredCWDefinition = 'Decred? decred = CWDecred();\n';
final output = '$decredCommonHeaders\n'
+ (hasImplementation ? '$decredCWHeaders\n' : '\n')
+ (hasImplementation ? '$decredCwPart\n\n' : '\n')
+ (hasImplementation ? decredCWDefinition : decredEmptyDefinition)
+ '\n'
+ decredContent;
final output = '$decredCommonHeaders\n' +
(hasImplementation ? '$decredCWHeaders\n' : '\n') +
(hasImplementation ? '$decredCwPart\n\n' : '\n') +
(hasImplementation ? decredCWDefinition : decredEmptyDefinition) +
'\n' +
decredContent;
if (outputFile.existsSync()) {
await outputFile.delete();