Compare commits
10 Commits
b95af3a649
...
fd50aa9db5
Author | SHA1 | Date |
---|---|---|
dsc | fd50aa9db5 | 4 months ago |
Omar Hatem | d756b367d3 | 5 months ago |
Matthew Fosse | 2ff81df9e7 | 5 months ago |
Serhii | 049e4def27 | 5 months ago |
Serhii | faf151a4dc | 5 months ago |
Adegoke David | ef7762eaca | 5 months ago |
Matthew Fosse | 7ce387c130 | 5 months ago |
Konstantin Ullrich | 72777fbf2c | 5 months ago |
Serhii | 2138c35e38 | 5 months ago |
Matthew Fosse | d370c754c5 | 5 months ago |
@ -0,0 +1,11 @@
|
||||
package com.cakewallet.wownero;
|
||||
|
||||
import io.flutter.app.FlutterApplication;
|
||||
import io.flutter.plugin.common.PluginRegistry;
|
||||
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
|
||||
public class Application extends FlutterApplication implements PluginRegistrantCallback {
|
||||
@Override
|
||||
public void registerWith(PluginRegistry registry) {}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.cakewallet.wownero;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import io.flutter.embedding.android.FlutterFragmentActivity;
|
||||
import io.flutter.embedding.engine.FlutterEngine;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.unstoppabledomains.resolution.DomainResolution;
|
||||
import com.unstoppabledomains.resolution.Resolution;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class MainActivity extends FlutterFragmentActivity {
|
||||
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
|
||||
final int UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK = 24;
|
||||
|
||||
@Override
|
||||
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
|
||||
GeneratedPluginRegistrant.registerWith(flutterEngine);
|
||||
|
||||
MethodChannel utilsChannel =
|
||||
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),
|
||||
UTILS_CHANNEL);
|
||||
|
||||
utilsChannel.setMethodCallHandler(this::handle);
|
||||
}
|
||||
|
||||
private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
try {
|
||||
switch (call.method) {
|
||||
case "enableWakeScreen":
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
handler.post(() -> result.success(true));
|
||||
break;
|
||||
case "disableWakeScreen":
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
handler.post(() -> result.success(true));
|
||||
break;
|
||||
case "sec_random":
|
||||
int count = call.argument("count");
|
||||
SecureRandom random = new SecureRandom();
|
||||
byte bytes[] = new byte[count];
|
||||
random.nextBytes(bytes);
|
||||
handler.post(() -> result.success(bytes));
|
||||
break;
|
||||
case "getUnstoppableDomainAddress":
|
||||
int version = Build.VERSION.SDK_INT;
|
||||
if (version >= UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK) {
|
||||
getUnstoppableDomainAddress(call, result);
|
||||
} else {
|
||||
handler.post(() -> result.success(""));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
handler.post(() -> result.notImplemented());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
handler.post(() -> result.error("UNCAUGHT_ERROR", e.getMessage(), null));
|
||||
}
|
||||
}
|
||||
|
||||
private void getUnstoppableDomainAddress(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
||||
DomainResolution resolution = new Resolution();
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
String domain = call.argument("domain");
|
||||
String ticker = call.argument("ticker");
|
||||
|
||||
AsyncTask.execute(() -> {
|
||||
try {
|
||||
String address = resolution.getAddress(domain, ticker);
|
||||
handler.post(() -> result.success(address));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Expected Address, but got " + e.getMessage());
|
||||
handler.post(() -> result.success(""));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 49 KiB |
@ -1,6 +1,6 @@
|
||||
-
|
||||
uri: polygon-rpc.com
|
||||
-
|
||||
uri: polygon-bor.publicnode.com
|
||||
-
|
||||
uri: polygon-rpc.com
|
||||
-
|
||||
uri: polygon.llamarpc.com
|
@ -0,0 +1,16 @@
|
||||
-
|
||||
uri: nyc.muchwow.lol:34568
|
||||
is_default: true
|
||||
useSSL: false
|
||||
-
|
||||
uri: amsterdam.muchwow.lol:34568
|
||||
is_default: false
|
||||
useSSL: false
|
||||
-
|
||||
uri: singapore.muchwow.lol:34568
|
||||
is_default: false
|
||||
useSSL: false
|
||||
-
|
||||
uri: suchwow.xyz:34568
|
||||
is_default: false
|
||||
useSSL: false
|
@ -0,0 +1,18 @@
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:cw_core/crypto_amount_format.dart';
|
||||
|
||||
const wowneroAmountLength = 12;
|
||||
const wowneroAmountDivider = 100000000000;
|
||||
final wowneroAmountFormat = NumberFormat()
|
||||
..maximumFractionDigits = wowneroAmountLength
|
||||
..minimumFractionDigits = 1;
|
||||
|
||||
String wowneroAmountToString({required int amount}) => wowneroAmountFormat
|
||||
.format(cryptoAmountToDouble(amount: amount, divider: wowneroAmountDivider))
|
||||
.replaceAll(',', '');
|
||||
|
||||
double wowneroAmountToDouble({required int amount}) =>
|
||||
cryptoAmountToDouble(amount: amount, divider: wowneroAmountDivider);
|
||||
|
||||
int wowneroParseAmount({required String amount}) =>
|
||||
(double.parse(amount) * wowneroAmountDivider).round();
|
@ -0,0 +1,38 @@
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/wownero_amount_format.dart';
|
||||
|
||||
class WowneroBalance extends Balance {
|
||||
WowneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
|
||||
: formattedFullBalance = wowneroAmountToString(amount: fullBalance),
|
||||
formattedUnlockedBalance = wowneroAmountToString(amount: unlockedBalance - frozenBalance),
|
||||
formattedLockedBalance =
|
||||
wowneroAmountToString(amount: frozenBalance + fullBalance - unlockedBalance),
|
||||
super(unlockedBalance, fullBalance);
|
||||
|
||||
WowneroBalance.fromString(
|
||||
{required this.formattedFullBalance,
|
||||
required this.formattedUnlockedBalance,
|
||||
this.formattedLockedBalance = '0.0'})
|
||||
: fullBalance = wowneroParseAmount(amount: formattedFullBalance),
|
||||
unlockedBalance = wowneroParseAmount(amount: formattedUnlockedBalance),
|
||||
frozenBalance = wowneroParseAmount(amount: formattedLockedBalance),
|
||||
super(wowneroParseAmount(amount: formattedUnlockedBalance),
|
||||
wowneroParseAmount(amount: formattedFullBalance));
|
||||
|
||||
final int fullBalance;
|
||||
final int unlockedBalance;
|
||||
final int frozenBalance;
|
||||
final String formattedFullBalance;
|
||||
final String formattedUnlockedBalance;
|
||||
final String formattedLockedBalance;
|
||||
|
||||
@override
|
||||
String get formattedUnAvailableBalance =>
|
||||
formattedLockedBalance == '0.0' ? '' : formattedLockedBalance;
|
||||
|
||||
@override
|
||||
String get formattedAvailableBalance => formattedUnlockedBalance;
|
||||
|
||||
@override
|
||||
String get formattedAdditionalBalance => formattedFullBalance;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
class WowneroWalletKeys {
|
||||
const WowneroWalletKeys(
|
||||
{required this.privateSpendKey,
|
||||
required this.privateViewKey,
|
||||
required this.publicSpendKey,
|
||||
required this.publicViewKey});
|
||||
|
||||
final String publicViewKey;
|
||||
final String privateViewKey;
|
||||
final String publicSpendKey;
|
||||
final String privateSpendKey;
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
import 'dart:io';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
String backupFileName(String originalPath) {
|
||||
final pathParts = originalPath.split('/');
|
||||
final newName = '#_${pathParts.last}';
|
||||
pathParts.removeLast();
|
||||
pathParts.add(newName);
|
||||
return pathParts.join('/');
|
||||
}
|
||||
|
||||
Future<void> backupWalletFiles(String name) async {
|
||||
final path = await pathForWallet(name: name, type: WalletType.wownero);
|
||||
final cacheFile = File(path);
|
||||
final keysFile = File('$path.keys');
|
||||
final addressListFile = File('$path.address.txt');
|
||||
final newCacheFilePath = backupFileName(cacheFile.path);
|
||||
final newKeysFilePath = backupFileName(keysFile.path);
|
||||
final newAddressListFilePath = backupFileName(addressListFile.path);
|
||||
|
||||
if (cacheFile.existsSync()) {
|
||||
await cacheFile.copy(newCacheFilePath);
|
||||
}
|
||||
|
||||
if (keysFile.existsSync()) {
|
||||
await keysFile.copy(newKeysFilePath);
|
||||
}
|
||||
|
||||
if (addressListFile.existsSync()) {
|
||||
await addressListFile.copy(newAddressListFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restoreWalletFiles(String name) async {
|
||||
final walletDirPath = await pathForWalletDir(name: name, type: WalletType.wownero);
|
||||
final cacheFilePath = '$walletDirPath/$name';
|
||||
final keysFilePath = '$walletDirPath/$name.keys';
|
||||
final addressListFilePath = '$walletDirPath/$name.address.txt';
|
||||
final backupCacheFile = File(backupFileName(cacheFilePath));
|
||||
final backupKeysFile = File(backupFileName(keysFilePath));
|
||||
final backupAddressListFile = File(backupFileName(addressListFilePath));
|
||||
|
||||
if (backupCacheFile.existsSync()) {
|
||||
await backupCacheFile.copy(cacheFilePath);
|
||||
}
|
||||
|
||||
if (backupKeysFile.existsSync()) {
|
||||
await backupKeysFile.copy(keysFilePath);
|
||||
}
|
||||
|
||||
if (backupAddressListFile.existsSync()) {
|
||||
await backupAddressListFile.copy(addressListFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> backupWalletFilesExists(String name) async {
|
||||
final walletDirPath = await pathForWalletDir(name: name, type: WalletType.wownero);
|
||||
final cacheFilePath = '$walletDirPath/$name';
|
||||
final keysFilePath = '$walletDirPath/$name.keys';
|
||||
final addressListFilePath = '$walletDirPath/$name.address.txt';
|
||||
final backupCacheFile = File(backupFileName(cacheFilePath));
|
||||
final backupKeysFile = File(backupFileName(keysFilePath));
|
||||
final backupAddressListFile = File(backupFileName(addressListFilePath));
|
||||
|
||||
return backupCacheFile.existsSync()
|
||||
&& backupKeysFile.existsSync()
|
||||
&& backupAddressListFile.existsSync();
|
||||
}
|
||||
|
||||
Future<void> removeCache(String name) async {
|
||||
final path = await pathForWallet(name: name, type: WalletType.wownero);
|
||||
final cacheFile = File(path);
|
||||
|
||||
if (cacheFile.existsSync()) {
|
||||
cacheFile.deleteSync();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restoreOrResetWalletFiles(String name) async {
|
||||
final backupsExists = await backupWalletFilesExists(name);
|
||||
|
||||
if (backupsExists) {
|
||||
await restoreWalletFiles(name);
|
||||
}
|
||||
|
||||
removeCache(name);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
.DS_Store
|
||||
.dart_tool/
|
||||
|
||||
.packages
|
||||
.pub/
|
||||
|
||||
build/
|
||||
|
||||
ios/External/
|
||||
android/.externalNativeBuild/
|
||||
android/.cxx/
|
@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 398e4272a2e43d7daab75f225a13422e384ee0cd
|
||||
channel: dev
|
||||
|
||||
project_type: plugin
|
@ -0,0 +1,3 @@
|
||||
## 0.0.1
|
||||
|
||||
* TODO: wow.
|
@ -0,0 +1 @@
|
||||
TODO: Add your license here.
|
@ -0,0 +1,5 @@
|
||||
# cw_wownero
|
||||
|
||||
This project is part of Cake Wallet app.
|
||||
|
||||
Copyright (c) 2022 Cake Technologies LLC.
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/>
|
||||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
|
||||
<classpathentry kind="output" path="bin/default"/>
|
||||
</classpath>
|
@ -0,0 +1,8 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>cw_wownero</name>
|
||||
<comment>Project android created by Buildship.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -0,0 +1,13 @@
|
||||
arguments=
|
||||
auto.sync=false
|
||||
build.scans.enabled=false
|
||||
connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.0-20191016123526+0000))
|
||||
connection.project.dir=../../android
|
||||
eclipse.preferences.version=1
|
||||
gradle.user.home=
|
||||
java.home=
|
||||
jvm.arguments=
|
||||
offline.mode=false
|
||||
override.workspace.settings=true
|
||||
show.console.view=true
|
||||
show.executions.view=true
|
@ -0,0 +1,232 @@
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
add_library( cw_wownero
|
||||
SHARED
|
||||
./jni/wownero_jni.cpp
|
||||
../ios/Classes/wownero_api.cpp)
|
||||
|
||||
find_library( log-lib log )
|
||||
|
||||
set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../../cw_shared_external/ios/External/android)
|
||||
|
||||
############
|
||||
# libsodium
|
||||
############
|
||||
|
||||
add_library(sodium STATIC IMPORTED)
|
||||
set_target_properties(sodium PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libsodium.a)
|
||||
|
||||
############
|
||||
# OpenSSL
|
||||
############
|
||||
|
||||
add_library(crypto STATIC IMPORTED)
|
||||
set_target_properties(crypto PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libcrypto.a)
|
||||
|
||||
add_library(ssl STATIC IMPORTED)
|
||||
set_target_properties(ssl PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libssl.a)
|
||||
|
||||
############
|
||||
# Boost
|
||||
############
|
||||
|
||||
add_library(boost_chrono STATIC IMPORTED)
|
||||
set_target_properties(boost_chrono PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_chrono.a)
|
||||
|
||||
add_library(boost_date_time STATIC IMPORTED)
|
||||
set_target_properties(boost_date_time PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_date_time.a)
|
||||
|
||||
add_library(boost_filesystem STATIC IMPORTED)
|
||||
set_target_properties(boost_filesystem PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_filesystem.a)
|
||||
|
||||
add_library(boost_program_options STATIC IMPORTED)
|
||||
set_target_properties(boost_program_options PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_program_options.a)
|
||||
|
||||
add_library(boost_regex STATIC IMPORTED)
|
||||
set_target_properties(boost_regex PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_regex.a)
|
||||
|
||||
add_library(boost_serialization STATIC IMPORTED)
|
||||
set_target_properties(boost_serialization PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_serialization.a)
|
||||
|
||||
add_library(boost_system STATIC IMPORTED)
|
||||
set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_system.a)
|
||||
|
||||
add_library(boost_thread STATIC IMPORTED)
|
||||
set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_thread.a)
|
||||
|
||||
add_library(boost_wserialization STATIC IMPORTED)
|
||||
set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_wserialization.a)
|
||||
|
||||
#############
|
||||
# Wownero
|
||||
#############
|
||||
|
||||
add_library(wallet_api STATIC IMPORTED)
|
||||
set_target_properties(wallet_api PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libwallet_api.a)
|
||||
|
||||
add_library(wallet STATIC IMPORTED)
|
||||
set_target_properties(wallet PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libwallet.a)
|
||||
|
||||
add_library(cryptonote_core STATIC IMPORTED)
|
||||
set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcryptonote_core.a)
|
||||
|
||||
add_library(cryptonote_basic STATIC IMPORTED)
|
||||
set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcryptonote_basic.a)
|
||||
|
||||
add_library(cryptonote_format_utils_basic STATIC IMPORTED)
|
||||
set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcryptonote_format_utils_basic.a)
|
||||
|
||||
add_library(mnemonics STATIC IMPORTED)
|
||||
set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libmnemonics.a)
|
||||
|
||||
add_library(common STATIC IMPORTED)
|
||||
set_target_properties(common PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcommon.a)
|
||||
|
||||
add_library(cncrypto STATIC IMPORTED)
|
||||
set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcncrypto.a)
|
||||
|
||||
add_library(ringct STATIC IMPORTED)
|
||||
set_target_properties(ringct PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libringct.a)
|
||||
|
||||
add_library(ringct_basic STATIC IMPORTED)
|
||||
set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libringct_basic.a)
|
||||
|
||||
add_library(blockchain_db STATIC IMPORTED)
|
||||
set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libblockchain_db.a)
|
||||
|
||||
add_library(lmdb STATIC IMPORTED)
|
||||
set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/liblmdb.a)
|
||||
|
||||
add_library(easylogging STATIC IMPORTED)
|
||||
set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libeasylogging.a)
|
||||
|
||||
add_library(unbound STATIC IMPORTED)
|
||||
set_target_properties(unbound PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libunbound.a)
|
||||
|
||||
add_library(epee STATIC IMPORTED)
|
||||
set_target_properties(epee PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libepee.a)
|
||||
|
||||
add_library(blocks STATIC IMPORTED)
|
||||
set_target_properties(blocks PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libblocks.a)
|
||||
|
||||
add_library(checkpoints STATIC IMPORTED)
|
||||
set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcheckpoints.a)
|
||||
|
||||
add_library(device STATIC IMPORTED)
|
||||
set_target_properties(device PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libdevice.a)
|
||||
|
||||
add_library(device_trezor STATIC IMPORTED)
|
||||
set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libdevice_trezor.a)
|
||||
|
||||
add_library(multisig STATIC IMPORTED)
|
||||
set_target_properties(multisig PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libmultisig.a)
|
||||
|
||||
add_library(version STATIC IMPORTED)
|
||||
set_target_properties(version PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libversion.a)
|
||||
|
||||
add_library(net STATIC IMPORTED)
|
||||
set_target_properties(net PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libnet.a)
|
||||
|
||||
add_library(hardforks STATIC IMPORTED)
|
||||
set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libhardforks.a)
|
||||
|
||||
add_library(randomx STATIC IMPORTED)
|
||||
set_target_properties(randomx PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/librandomx.a)
|
||||
|
||||
add_library(rpc_base STATIC IMPORTED)
|
||||
set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/librpc_base.a)
|
||||
|
||||
add_library(wallet-crypto STATIC IMPORTED)
|
||||
set_target_properties(wallet-crypto PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libwallet-crypto.a)
|
||||
|
||||
set(WALLET_CRYPTO "")
|
||||
|
||||
if(${ANDROID_ABI} STREQUAL "x86_64")
|
||||
set(WALLET_CRYPTO "wallet-crypto")
|
||||
endif()
|
||||
|
||||
include_directories( ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/include )
|
||||
|
||||
target_link_libraries( cw_wownero
|
||||
|
||||
wallet_api
|
||||
wallet
|
||||
cryptonote_core
|
||||
cryptonote_basic
|
||||
cryptonote_format_utils_basic
|
||||
mnemonics
|
||||
ringct
|
||||
ringct_basic
|
||||
net
|
||||
common
|
||||
cncrypto
|
||||
blockchain_db
|
||||
lmdb
|
||||
easylogging
|
||||
unbound
|
||||
epee
|
||||
blocks
|
||||
checkpoints
|
||||
device
|
||||
device_trezor
|
||||
multisig
|
||||
version
|
||||
randomx
|
||||
hardforks
|
||||
rpc_base
|
||||
${WALLET_CRYPTO}
|
||||
|
||||
boost_chrono
|
||||
boost_date_time
|
||||
boost_filesystem
|
||||
boost_program_options
|
||||
boost_regex
|
||||
boost_serialization
|
||||
boost_system
|
||||
boost_thread
|
||||
boost_wserialization
|
||||
|
||||
ssl
|
||||
crypto
|
||||
|
||||
sodium
|
||||
|
||||
${log-lib} )
|
@ -0,0 +1,49 @@
|
||||
group 'com.cakewallet.wownero'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.7.10'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
@ -0,0 +1,74 @@
|
||||
#include <string.h>
|
||||
#include <jni.h>
|
||||
#include "../../ios/Classes/wownero_api.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_cakewallet_wownero_WowneroApi_setNodeAddressJNI(
|
||||
JNIEnv *env,
|
||||
jobject inst,
|
||||
jstring uri,
|
||||
jstring login,
|
||||
jstring password,
|
||||
jboolean use_ssl,
|
||||
jboolean is_light_wallet) {
|
||||
const char *_uri = env->GetStringUTFChars(uri, 0);
|
||||
const char *_login = "";
|
||||
const char *_password = "";
|
||||
char *error;
|
||||
|
||||
if (login != NULL) {
|
||||
_login = env->GetStringUTFChars(login, 0);
|
||||
}
|
||||
|
||||
if (password != NULL) {
|
||||
_password = env->GetStringUTFChars(password, 0);
|
||||
}
|
||||
char *__uri = (char*) _uri;
|
||||
char *__login = (char*) _login;
|
||||
char *__password = (char*) _password;
|
||||
bool inited = setup_node(__uri, __login, __password, false, false, error);
|
||||
|
||||
if (!inited) {
|
||||
env->ThrowNew(env->FindClass("java/lang/Exception"), error);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_cakewallet_wownero_WowneroApi_connectToNodeJNI(
|
||||
JNIEnv *env,
|
||||
jobject inst) {
|
||||
char *error;
|
||||
bool is_connected = connect_to_node(error);
|
||||
|
||||
if (!is_connected) {
|
||||
env->ThrowNew(env->FindClass("java/lang/Exception"), error);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_cakewallet_wownero_WowneroApi_startSyncJNI(
|
||||
JNIEnv *env,
|
||||
jobject inst) {
|
||||
start_refresh();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_cakewallet_wownero_WowneroApi_loadWalletJNI(
|
||||
JNIEnv *env,
|
||||
jobject inst,
|
||||
jstring path,
|
||||
jstring password) {
|
||||
char *_path = (char *) env->GetStringUTFChars(path, 0);
|
||||
char *_password = (char *) env->GetStringUTFChars(password, 0);
|
||||
|
||||
load_wallet(_path, _password, 0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
rootProject.name = 'cw_wownero'
|
@ -0,0 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.cakewallet.wownero">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
@ -0,0 +1,74 @@
|
||||
package com.cakewallet.cw_wownero
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.AsyncTask
|
||||
import android.os.Looper
|
||||
import android.os.Handler
|
||||
import android.os.Process
|
||||
|
||||
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
|
||||
import io.flutter.plugin.common.PluginRegistry.Registrar
|
||||
|
||||
class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
|
||||
override fun doInBackground(vararg params: Void?): Void? {
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
|
||||
handler()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
class CwWowneroPlugin: MethodCallHandler {
|
||||
companion object {
|
||||
// val wowneroApi = WowneroApi()
|
||||
val main = Handler(Looper.getMainLooper());
|
||||
|
||||
init {
|
||||
System.loadLibrary("cw_wownero")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun registerWith(registrar: Registrar) {
|
||||
val channel = MethodChannel(registrar.messenger(), "cw_wownero")
|
||||
channel.setMethodCallHandler(CwWowneroPlugin())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMethodCall(call: MethodCall, result: Result) {
|
||||
if (call.method == "setupNode") {
|
||||
val uri = call.argument("address") ?: ""
|
||||
val login = call.argument("login") ?: ""
|
||||
val password = call.argument("password") ?: ""
|
||||
val useSSL = false
|
||||
val isLightWallet = false
|
||||
// doAsync {
|
||||
// try {
|
||||
// wowneroApi.setNodeAddressJNI(uri, login, password, useSSL, isLightWallet)
|
||||
// main.post({
|
||||
// result.success(true)
|
||||
// });
|
||||
// } catch(e: Throwable) {
|
||||
// main.post({
|
||||
// result.error("CONNECTION_ERROR", e.message, null)
|
||||
// });
|
||||
// }
|
||||
// }.execute()
|
||||
}
|
||||
if (call.method == "startSync") {
|
||||
// doAsync {
|
||||
// wowneroApi.startSyncJNI()
|
||||
// main.post({
|
||||
// result.success(true)
|
||||
// });
|
||||
// }.execute()
|
||||
}
|
||||
if (call.method == "loadWallet") {
|
||||
val path = call.argument("path") ?: ""
|
||||
val password = call.argument("password") ?: ""
|
||||
// wowneroApi.loadWalletJNI(path, password)
|
||||
result.success(true)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
.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/flutter_export_environment.sh
|
@ -0,0 +1,23 @@
|
||||
#include <stdint.h>
|
||||
|
||||
struct CWWowneroWalletListener;
|
||||
|
||||
typedef int8_t (*on_new_block_callback)(uint64_t height);
|
||||
typedef int8_t (*on_need_to_refresh_callback)();
|
||||
|
||||
typedef struct CWWowneroWalletListener
|
||||
{
|
||||
// on_money_spent_callback *on_money_spent;
|
||||
// on_money_received_callback *on_money_received;
|
||||
// on_unconfirmed_money_received_callback *on_unconfirmed_money_received;
|
||||
// on_new_block_callback *on_new_block;
|
||||
// on_updated_callback *on_updated;
|
||||
// on_refreshed_callback *on_refreshed;
|
||||
|
||||
on_new_block_callback on_new_block;
|
||||
} CWWowneroWalletListener;
|
||||
|
||||
struct TestListener {
|
||||
// int8_t x;
|
||||
on_new_block_callback on_new_block;
|
||||
};
|
@ -0,0 +1,4 @@
|
||||
#import <Flutter/Flutter.h>
|
||||
|
||||
@interface CwWowneroPlugin : NSObject<FlutterPlugin>
|
||||
@end
|
@ -0,0 +1,8 @@
|
||||
#import "CwWowneroPlugin.h"
|
||||
#import <cw_wownero/cw_wownero-Swift.h>
|
||||
|
||||
@implementation CwWowneroPlugin
|
||||
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
|
||||
[SwiftCwWowneroPlugin registerWithRegistrar:registrar];
|
||||
}
|
||||
@end
|
@ -0,0 +1,14 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
public class SwiftCwWowneroPlugin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let channel = FlutterMethodChannel(name: "cw_wownero", binaryMessenger: registrar.messenger())
|
||||
let instance = SwiftCwWowneroPlugin()
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
result("iOS " + UIDevice.current.systemVersion)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,39 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "CwWalletListener.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool create_wallet(char *path, char *password, char *language, int32_t networkType, char *error);
|
||||
bool restore_wallet_from_seed(char *path, char *password, char *seed, int32_t networkType, uint64_t restoreHeight, char *error);
|
||||
bool restore_wallet_from_keys(char *path, char *password, char *language, char *address, char *viewKey, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error);
|
||||
void load_wallet(char *path, char *password, int32_t nettype);
|
||||
bool is_wallet_exist(char *path);
|
||||
|
||||
char *get_filename();
|
||||
const char *seed();
|
||||
char *get_address(uint32_t account_index, uint32_t address_index);
|
||||
uint64_t get_full_balance(uint32_t account_index);
|
||||
uint64_t get_unlocked_balance(uint32_t account_index);
|
||||
uint64_t get_current_height();
|
||||
uint64_t get_node_height();
|
||||
|
||||
bool is_connected();
|
||||
|
||||
bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error);
|
||||
bool connect_to_node(char *error);
|
||||
void start_refresh();
|
||||
void set_refresh_from_block_height(uint64_t height);
|
||||
void set_recovering_from_seed(bool is_recovery);
|
||||
void store(char *path);
|
||||
|
||||
void set_trusted_daemon(bool arg);
|
||||
bool trusted_daemon();
|
||||
char *sign_message(char *message, char *address);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,50 @@
|
||||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint cw_wownero.podspec' to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'cw_wownero'
|
||||
s.version = '0.0.2'
|
||||
s.summary = 'Cake Wallet Wownero'
|
||||
s.description = 'Cake Wallet wrapper over Wownero project'
|
||||
s.homepage = 'http://cakewallet.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'CakeWallet' => 'support@cakewallet.com' }
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.public_header_files = 'Classes/**/*.h, Classes/*.h, ../shared_external/ios/libs/monero/include/src/**/*.h, ../shared_external/ios/libs/monero/include/contrib/**/*.h, ../shared_external/ios/libs/monero/include/../shared_external/ios/**/*.h'
|
||||
s.dependency 'Flutter'
|
||||
s.dependency 'cw_shared_external'
|
||||
s.platform = :ios, '10.0'
|
||||
s.swift_version = '5.0'
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS' => 'arm64', 'ENABLE_BITCODE' => 'NO' }
|
||||
s.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/Classes/*.h" }
|
||||
|
||||
s.subspec 'OpenSSL' do |openssl|
|
||||
openssl.preserve_paths = '../../../../../cw_shared_external/ios/External/ios/include/**/*.h'
|
||||
openssl.vendored_libraries = '../../../../../cw_shared_external/ios/External/ios/lib/libcrypto.a', '../../../../../cw_shared_external/ios/External/ios/lib/libssl.a'
|
||||
openssl.libraries = 'ssl', 'crypto'
|
||||
openssl.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/include/**" }
|
||||
end
|
||||
|
||||
s.subspec 'Sodium' do |sodium|
|
||||
sodium.preserve_paths = '../../../../../cw_shared_external/ios/External/ios/include/**/*.h'
|
||||
sodium.vendored_libraries = '../../../../../cw_shared_external/ios/External/ios/lib/libsodium.a'
|
||||
sodium.libraries = 'sodium'
|
||||
sodium.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/include/**" }
|
||||
end
|
||||
|
||||
s.subspec 'Boost' do |boost|
|
||||
boost.preserve_paths = '../../../../../cw_shared_external/ios/External/ios/include/**/*.h',
|
||||
boost.vendored_libraries = '../../../../../cw_shared_external/ios/External/ios/lib/libboost.a',
|
||||
boost.libraries = 'boost'
|
||||
boost.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/include/**" }
|
||||
end
|
||||
|
||||
s.subspec 'Wownero' do |wownero|
|
||||
wownero.preserve_paths = 'External/ios/include/**/*.h'
|
||||
wownero.vendored_libraries = 'External/ios/lib/libwownero.a'
|
||||
wownero.libraries = 'wownero'
|
||||
wownero.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/include" }
|
||||
end
|
||||
end
|
@ -0,0 +1,83 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:cw_wownero/api/signatures.dart';
|
||||
import 'package:cw_wownero/api/types.dart';
|
||||
import 'package:cw_wownero/api/wownero_api.dart';
|
||||
import 'package:cw_wownero/api/structs/account_row.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_wownero/api/wallet.dart';
|
||||
|
||||
final accountSizeNative = wowneroApi
|
||||
.lookup<NativeFunction<account_size>>('account_size')
|
||||
.asFunction<SubaddressSize>();
|
||||
|
||||
final accountRefreshNative = wowneroApi
|
||||
.lookup<NativeFunction<account_refresh>>('account_refresh')
|
||||
.asFunction<AccountRefresh>();
|
||||
|
||||
final accountGetAllNative = wowneroApi
|
||||
.lookup<NativeFunction<account_get_all>>('account_get_all')
|
||||
.asFunction<AccountGetAll>();
|
||||
|
||||
final accountAddNewNative = wowneroApi
|
||||
.lookup<NativeFunction<account_add_new>>('account_add_row')
|
||||
.asFunction<AccountAddNew>();
|
||||
|
||||
final accountSetLabelNative = wowneroApi
|
||||
.lookup<NativeFunction<account_set_label>>('account_set_label_row')
|
||||
.asFunction<AccountSetLabel>();
|
||||
|
||||
bool isUpdating = false;
|
||||
|
||||
void refreshAccounts() {
|
||||
try {
|
||||
isUpdating = true;
|
||||
accountRefreshNative();
|
||||
isUpdating = false;
|
||||
} catch (e) {
|
||||
isUpdating = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
List<AccountRow> getAllAccount() {
|
||||
final size = accountSizeNative();
|
||||
final accountAddressesPointer = accountGetAllNative();
|
||||
final accountAddresses = accountAddressesPointer.asTypedList(size);
|
||||
|
||||
return accountAddresses
|
||||
.map((addr) => Pointer<AccountRow>.fromAddress(addr).ref)
|
||||
.toList();
|
||||
}
|
||||
|
||||
void addAccountSync({required String label}) {
|
||||
final labelPointer = label.toNativeUtf8();
|
||||
accountAddNewNative(labelPointer);
|
||||
calloc.free(labelPointer);
|
||||
}
|
||||
|
||||
void setLabelForAccountSync({required int accountIndex, required String label}) {
|
||||
final labelPointer = label.toNativeUtf8();
|
||||
accountSetLabelNative(accountIndex, labelPointer);
|
||||
calloc.free(labelPointer);
|
||||
}
|
||||
|
||||
void _addAccount(String label) => addAccountSync(label: label);
|
||||
|
||||
void _setLabelForAccount(Map<String, dynamic> args) {
|
||||
final label = args['label'] as String;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
|
||||
setLabelForAccountSync(label: label, accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
Future<void> addAccount({required String label}) async {
|
||||
await compute(_addAccount, label);
|
||||
await store();
|
||||
}
|
||||
|
||||
Future<void> setLabelForAccount({required int accountIndex, required String label}) async {
|
||||
await compute(
|
||||
_setLabelForAccount, {'accountIndex': accountIndex, 'label': label});
|
||||
await store();
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:cw_wownero/api/signatures.dart';
|
||||
import 'package:cw_wownero/api/structs/coins_info_row.dart';
|
||||
import 'package:cw_wownero/api/types.dart';
|
||||
import 'package:cw_wownero/api/wownero_api.dart';
|
||||
|
||||
final refreshCoinsNative = wowneroApi
|
||||
.lookup<NativeFunction<refresh_coins>>('refresh_coins')
|
||||
.asFunction<RefreshCoins>();
|
||||
|
||||
final coinsCountNative = wowneroApi
|
||||
.lookup<NativeFunction<coins_count>>('coins_count')
|
||||
.asFunction<CoinsCount>();
|
||||
|
||||
final coinNative = wowneroApi
|
||||
.lookup<NativeFunction<coin>>('coin')
|
||||
.asFunction<GetCoin>();
|
||||
|
||||
final freezeCoinNative = wowneroApi
|
||||
.lookup<NativeFunction<freeze_coin>>('freeze_coin')
|
||||
.asFunction<FreezeCoin>();
|
||||
|
||||
final thawCoinNative = wowneroApi
|
||||
.lookup<NativeFunction<thaw_coin>>('thaw_coin')
|
||||
.asFunction<ThawCoin>();
|
||||
|
||||
void refreshCoins(int accountIndex) => refreshCoinsNative(accountIndex);
|
||||
|
||||
int countOfCoins() => coinsCountNative();
|
||||
|
||||
CoinsInfoRow getCoin(int index) => coinNative(index).ref;
|
||||
|
||||
void freezeCoin(int index) => freezeCoinNative(index);
|
||||
|
||||
void thawCoin(int index) => thawCoinNative(index);
|
@ -0,0 +1,8 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
String convertUTF8ToString({required Pointer<Utf8> pointer}) {
|
||||
final str = pointer.toDartString();
|
||||
calloc.free(pointer);
|
||||
return str;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class ConnectionToNodeException implements Exception {
|
||||
ConnectionToNodeException({required this.message});
|
||||
|
||||
final String message;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
class CreationTransactionException implements Exception {
|
||||
CreationTransactionException({required this.message});
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class SetupWalletException implements Exception {
|
||||
SetupWalletException({required this.message});
|
||||
|
||||
final String message;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
class WalletCreationException implements Exception {
|
||||
WalletCreationException({required this.message});
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
class WalletOpeningException implements Exception {
|
||||
WalletOpeningException({required this.message});
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class WalletRestoreFromKeysException implements Exception {
|
||||
WalletRestoreFromKeysException({required this.message});
|
||||
|
||||
final String message;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class WalletRestoreFromSeedException implements Exception {
|
||||
WalletRestoreFromSeedException({required this.message});
|
||||
|
||||
final String message;
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:cw_wownero/api/structs/coins_info_row.dart';
|
||||
import 'package:cw_wownero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_wownero/api/structs/transaction_info_row.dart';
|
||||
import 'package:cw_wownero/api/structs/ut8_box.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
typedef create_wallet = Int8 Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Pointer<Utf8>);
|
||||
|
||||
typedef restore_wallet_from_seed = Int8 Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
||||
|
||||
typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
||||
|
||||
typedef restore_wallet_from_spend_key = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
||||
|
||||
typedef is_wallet_exist = Int8 Function(Pointer<Utf8>);
|
||||
|
||||
typedef load_wallet = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Int8);
|
||||
|
||||
typedef error_string = Pointer<Utf8> Function();
|
||||
|
||||
typedef get_filename = Pointer<Utf8> Function();
|
||||
|
||||
typedef get_seed = Pointer<Utf8> Function();
|
||||
|
||||
typedef get_address = Pointer<Utf8> Function(Int32, Int32);
|
||||
|
||||
typedef get_full_balanace = Int64 Function(Int32);
|
||||
|
||||
typedef get_unlocked_balanace = Int64 Function(Int32);
|
||||
|
||||
typedef get_current_height = Int64 Function();
|
||||
|
||||
typedef get_node_height = Int64 Function();
|
||||
|
||||
typedef is_connected = Int8 Function();
|
||||
|
||||
typedef setup_node = Int8 Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, Int8, Int8, Pointer<Utf8>?, Pointer<Utf8>);
|
||||
|
||||
typedef start_refresh = Void Function();
|
||||
|
||||
typedef connect_to_node = Int8 Function();
|
||||
|
||||
typedef set_refresh_from_block_height = Void Function(Int64);
|
||||
|
||||
typedef set_recovering_from_seed = Void Function(Int8);
|
||||
|
||||
typedef store_c = Void Function(Pointer<Utf8>);
|
||||
|
||||
typedef set_password = Int8 Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
|
||||
|
||||
typedef set_listener = Void Function();
|
||||
|
||||
typedef get_syncing_height = Int64 Function();
|
||||
|
||||
typedef is_needed_to_refresh = Int8 Function();
|
||||
|
||||
typedef is_new_transaction_exist = Int8 Function();
|
||||
|
||||
typedef subaddrress_size = Int32 Function();
|
||||
|
||||
typedef subaddrress_refresh = Void Function(Int32);
|
||||
|
||||
typedef subaddress_get_all = Pointer<Int64> Function();
|
||||
|
||||
typedef subaddress_add_new = Void Function(Int32 accountIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef subaddress_set_label = Void Function(
|
||||
Int32 accountIndex, Int32 addressIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef account_size = Int32 Function();
|
||||
|
||||
typedef account_refresh = Void Function();
|
||||
|
||||
typedef account_get_all = Pointer<Int64> Function();
|
||||
|
||||
typedef account_add_new = Void Function(Pointer<Utf8> label);
|
||||
|
||||
typedef account_set_label = Void Function(Int32 accountIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef transactions_refresh = Void Function();
|
||||
|
||||
typedef get_transaction = Pointer<TransactionInfoRow> Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef get_tx_key = Pointer<Utf8>? Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef transactions_count = Int64 Function();
|
||||
|
||||
typedef transactions_get_all = Pointer<Int64> Function();
|
||||
|
||||
typedef transaction_create = Int8 Function(
|
||||
Pointer<Utf8> address,
|
||||
Pointer<Utf8> paymentId,
|
||||
Pointer<Utf8> amount,
|
||||
Int8 priorityRaw,
|
||||
Int32 subaddrAccount,
|
||||
Pointer<Pointer<Utf8>> preferredInputs,
|
||||
Int32 preferredInputsSize,
|
||||
Pointer<Utf8Box> error,
|
||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
||||
|
||||
typedef transaction_create_mult_dest = Int8 Function(
|
||||
Pointer<Pointer<Utf8>> addresses,
|
||||
Pointer<Utf8> paymentId,
|
||||
Pointer<Pointer<Utf8>> amounts,
|
||||
Int32 size,
|
||||
Int8 priorityRaw,
|
||||
Int32 subaddrAccount,
|
||||
Pointer<Pointer<Utf8>> preferredInputs,
|
||||
Int32 preferredInputsSize,
|
||||
Pointer<Utf8Box> error,
|
||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
||||
|
||||
typedef transaction_commit = Int8 Function(Pointer<PendingTransactionRaw>, Pointer<Utf8Box>);
|
||||
|
||||
typedef secret_view_key = Pointer<Utf8> Function();
|
||||
|
||||
typedef public_view_key = Pointer<Utf8> Function();
|
||||
|
||||
typedef secret_spend_key = Pointer<Utf8> Function();
|
||||
|
||||
typedef public_spend_key = Pointer<Utf8> Function();
|
||||
|
||||
typedef close_current_wallet = Void Function();
|
||||
|
||||
typedef on_startup = Void Function();
|
||||
|
||||
typedef rescan_blockchain = Void Function();
|
||||
|
||||
typedef get_subaddress_label = Pointer<Utf8> Function(Int32 accountIndex, Int32 addressIndex);
|
||||
|
||||
typedef set_trusted_daemon = Void Function(Int8 trusted);
|
||||
|
||||
typedef trusted_daemon = Int8 Function();
|
||||
|
||||
typedef refresh_coins = Void Function(Int32 accountIndex);
|
||||
|
||||
typedef coins_count = Int64 Function();
|
||||
|
||||
// typedef coins_from_txid = Pointer<CoinsInfoRow> Function(Pointer<Utf8> txid);
|
||||
|
||||
typedef coin = Pointer<CoinsInfoRow> Function(Int32 index);
|
||||
|
||||
typedef freeze_coin = Void Function(Int32 index);
|
||||
|
||||
typedef thaw_coin = Void Function(Int32 index);
|
||||
|
||||
typedef sign_message = Pointer<Utf8> Function(Pointer<Utf8> message, Pointer<Utf8> address);
|
@ -0,0 +1,11 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class AccountRow extends Struct {
|
||||
@Int64()
|
||||
external int id;
|
||||
external Pointer<Utf8> label;
|
||||
|
||||
String getLabel() => label.toDartString();
|
||||
int getId() => id;
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class CoinsInfoRow extends Struct {
|
||||
@Int64()
|
||||
external int blockHeight;
|
||||
|
||||
external Pointer<Utf8> hash;
|
||||
|
||||
@Uint64()
|
||||
external int internalOutputIndex;
|
||||
|
||||
@Uint64()
|
||||
external int globalOutputIndex;
|
||||
|
||||
@Int8()
|
||||
external int spent;
|
||||
|
||||
@Int8()
|
||||
external int frozen;
|
||||
|
||||
@Uint64()
|
||||
external int spentHeight;
|
||||
|
||||
@Uint64()
|
||||
external int amount;
|
||||
|
||||
@Int8()
|
||||
external int rct;
|
||||
|
||||
@Int8()
|
||||
external int keyImageKnown;
|
||||
|
||||
@Uint64()
|
||||
external int pkIndex;
|
||||
|
||||
@Uint32()
|
||||
external int subaddrIndex;
|
||||
|
||||
@Uint32()
|
||||
external int subaddrAccount;
|
||||
|
||||
external Pointer<Utf8> address;
|
||||
|
||||
external Pointer<Utf8> addressLabel;
|
||||
|
||||
external Pointer<Utf8> keyImage;
|
||||
|
||||
@Uint64()
|
||||
external int unlockTime;
|
||||
|
||||
@Int8()
|
||||
external int unlocked;
|
||||
|
||||
external Pointer<Utf8> pubKey;
|
||||
|
||||
@Int8()
|
||||
external int coinbase;
|
||||
|
||||
external Pointer<Utf8> description;
|
||||
|
||||
String getHash() => hash.toDartString();
|
||||
|
||||
String getAddress() => address.toDartString();
|
||||
|
||||
String getAddressLabel() => addressLabel.toDartString();
|
||||
|
||||
String getKeyImage() => keyImage.toDartString();
|
||||
|
||||
String getPubKey() => pubKey.toDartString();
|
||||
|
||||
String getDescription() => description.toDartString();
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class PendingTransactionRaw extends Struct {
|
||||
@Int64()
|
||||
external int amount;
|
||||
|
||||
@Int64()
|
||||
external int fee;
|
||||
|
||||
external Pointer<Utf8> hash;
|
||||
|
||||
external Pointer<Utf8> hex;
|
||||
|
||||
external Pointer<Utf8> txKey;
|
||||
|
||||
String getHash() => hash.toDartString();
|
||||
|
||||
String getHex() => hex.toDartString();
|
||||
|
||||
String getKey() => txKey.toDartString();
|
||||
}
|
||||
|
||||
class PendingTransactionDescription {
|
||||
PendingTransactionDescription({
|
||||
required this.amount,
|
||||
required this.fee,
|
||||
required this.hash,
|
||||
required this.hex,
|
||||
required this.txKey,
|
||||
required this.pointerAddress});
|
||||
|
||||
final int amount;
|
||||
final int fee;
|
||||
final String hash;
|
||||
final String hex;
|
||||
final String txKey;
|
||||
final int pointerAddress;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class SubaddressRow extends Struct {
|
||||
@Int64()
|
||||
external int id;
|
||||
external Pointer<Utf8> address;
|
||||
external Pointer<Utf8> label;
|
||||
|
||||
String getLabel() => label.toDartString();
|
||||
String getAddress() => address.toDartString();
|
||||
int getId() => id;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class TransactionInfoRow extends Struct {
|
||||
@Uint64()
|
||||
external int amount;
|
||||
|
||||
@Uint64()
|
||||
external int fee;
|
||||
|
||||
@Uint64()
|
||||
external int blockHeight;
|
||||
|
||||
@Uint64()
|
||||
external int confirmations;
|
||||
|
||||
@Uint32()
|
||||
external int subaddrAccount;
|
||||
|
||||
@Int8()
|
||||
external int direction;
|
||||
|
||||
@Int8()
|
||||
external int isPending;
|
||||
|
||||
@Uint32()
|
||||
external int subaddrIndex;
|
||||
|
||||
external Pointer<Utf8> hash;
|
||||
|
||||
external Pointer<Utf8> paymentId;
|
||||
|
||||
@Int64()
|
||||
external int datetime;
|
||||
|
||||
int getDatetime() => datetime;
|
||||
int getAmount() => amount >= 0 ? amount : amount * -1;
|
||||
bool getIsPending() => isPending != 0;
|
||||
String getHash() => hash.toDartString();
|
||||
String getPaymentId() => paymentId.toDartString();
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class Utf8Box extends Struct {
|
||||
external Pointer<Utf8> value;
|
||||
|
||||
String getValue() => value.toDartString();
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_wownero/api/signatures.dart';
|
||||
import 'package:cw_wownero/api/types.dart';
|
||||
import 'package:cw_wownero/api/wownero_api.dart';
|
||||
import 'package:cw_wownero/api/structs/subaddress_row.dart';
|
||||
import 'package:cw_wownero/api/wallet.dart';
|
||||
|
||||
final subaddressSizeNative = wowneroApi
|
||||
.lookup<NativeFunction<subaddrress_size>>('subaddrress_size')
|
||||
.asFunction<SubaddressSize>();
|
||||
|
||||
final subaddressRefreshNative = wowneroApi
|
||||
.lookup<NativeFunction<subaddrress_refresh>>('subaddress_refresh')
|
||||
.asFunction<SubaddressRefresh>();
|
||||
|
||||
final subaddrressGetAllNative = wowneroApi
|
||||
.lookup<NativeFunction<subaddress_get_all>>('subaddrress_get_all')
|
||||
.asFunction<SubaddressGetAll>();
|
||||
|
||||
final subaddrressAddNewNative = wowneroApi
|
||||
.lookup<NativeFunction<subaddress_add_new>>('subaddress_add_row')
|
||||
.asFunction<SubaddressAddNew>();
|
||||
|
||||
final subaddrressSetLabelNative = wowneroApi
|
||||
.lookup<NativeFunction<subaddress_set_label>>('subaddress_set_label')
|
||||
.asFunction<SubaddressSetLabel>();
|
||||
|
||||
bool isUpdating = false;
|
||||
|
||||
void refreshSubaddresses({required int accountIndex}) {
|
||||
try {
|
||||
isUpdating = true;
|
||||
subaddressRefreshNative(accountIndex);
|
||||
isUpdating = false;
|
||||
} catch (e) {
|
||||
isUpdating = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
List<SubaddressRow> getAllSubaddresses() {
|
||||
final size = subaddressSizeNative();
|
||||
final subaddressAddressesPointer = subaddrressGetAllNative();
|
||||
final subaddressAddresses = subaddressAddressesPointer.asTypedList(size);
|
||||
|
||||
return subaddressAddresses
|
||||
.map((addr) => Pointer<SubaddressRow>.fromAddress(addr).ref)
|
||||
.toList();
|
||||
}
|
||||
|
||||
void addSubaddressSync({required int accountIndex, required String label}) {
|
||||
final labelPointer = label.toNativeUtf8();
|
||||
subaddrressAddNewNative(accountIndex, labelPointer);
|
||||
calloc.free(labelPointer);
|
||||
}
|
||||
|
||||
void setLabelForSubaddressSync(
|
||||
{required int accountIndex, required int addressIndex, required String label}) {
|
||||
final labelPointer = label.toNativeUtf8();
|
||||
subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer);
|
||||
calloc.free(labelPointer);
|
||||
}
|
||||
|
||||
void _addSubaddress(Map<String, dynamic> args) {
|
||||
final label = args['label'] as String;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
|
||||
addSubaddressSync(accountIndex: accountIndex, label: label);
|
||||
}
|
||||
|
||||
void _setLabelForSubaddress(Map<String, dynamic> args) {
|
||||
final label = args['label'] as String;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
final addressIndex = args['addressIndex'] as int;
|
||||
|
||||
setLabelForSubaddressSync(
|
||||
accountIndex: accountIndex, addressIndex: addressIndex, label: label);
|
||||
}
|
||||
|
||||
Future addSubaddress({required int accountIndex, required String label}) async {
|
||||
await compute<Map<String, Object>, void>(
|
||||
_addSubaddress, {'accountIndex': accountIndex, 'label': label});
|
||||
await store();
|
||||
}
|
||||
|
||||
Future setLabelForSubaddress(
|
||||
{required int accountIndex, required int addressIndex, required String label}) async {
|
||||
await compute<Map<String, Object>, void>(_setLabelForSubaddress, {
|
||||
'accountIndex': accountIndex,
|
||||
'addressIndex': addressIndex,
|
||||
'label': label
|
||||
});
|
||||
await store();
|
||||
}
|
@ -0,0 +1,281 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:cw_wownero/api/convert_utf8_to_string.dart';
|
||||
import 'package:cw_wownero/api/exceptions/creation_transaction_exception.dart';
|
||||
import 'package:cw_wownero/api/wownero_api.dart';
|
||||
import 'package:cw_wownero/api/wownero_output.dart';
|
||||
import 'package:cw_wownero/api/signatures.dart';
|
||||
import 'package:cw_wownero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_wownero/api/structs/transaction_info_row.dart';
|
||||
import 'package:cw_wownero/api/structs/ut8_box.dart';
|
||||
import 'package:cw_wownero/api/types.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
final transactionsRefreshNative = wowneroApi
|
||||
.lookup<NativeFunction<transactions_refresh>>('transactions_refresh')
|
||||
.asFunction<TransactionsRefresh>();
|
||||
|
||||
final transactionsCountNative = wowneroApi
|
||||
.lookup<NativeFunction<transactions_count>>('transactions_count')
|
||||
.asFunction<TransactionsCount>();
|
||||
|
||||
final transactionsGetAllNative = wowneroApi
|
||||
.lookup<NativeFunction<transactions_get_all>>('transactions_get_all')
|
||||
.asFunction<TransactionsGetAll>();
|
||||
|
||||
final transactionCreateNative = wowneroApi
|
||||
.lookup<NativeFunction<transaction_create>>('transaction_create')
|
||||
.asFunction<TransactionCreate>();
|
||||
|
||||
final transactionCreateMultDestNative = wowneroApi
|
||||
.lookup<NativeFunction<transaction_create_mult_dest>>('transaction_create_mult_dest')
|
||||
.asFunction<TransactionCreateMultDest>();
|
||||
|
||||
final transactionCommitNative = wowneroApi
|
||||
.lookup<NativeFunction<transaction_commit>>('transaction_commit')
|
||||
.asFunction<TransactionCommit>();
|
||||
|
||||
final getTxKeyNative =
|
||||
wowneroApi.lookup<NativeFunction<get_tx_key>>('get_tx_key').asFunction<GetTxKey>();
|
||||
|
||||
final getTransactionNative = wowneroApi
|
||||
.lookup<NativeFunction<get_transaction>>('get_transaction')
|
||||
.asFunction<GetTransaction>();
|
||||
|
||||
String getTxKey(String txId) {
|
||||
final txIdPointer = txId.toNativeUtf8();
|
||||
final keyPointer = getTxKeyNative(txIdPointer);
|
||||
|
||||
calloc.free(txIdPointer);
|
||||
|
||||
if (keyPointer != null) {
|
||||
return convertUTF8ToString(pointer: keyPointer);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
void refreshTransactions() => transactionsRefreshNative();
|
||||
|
||||
int countOfTransactions() => transactionsCountNative();
|
||||
|
||||
List<TransactionInfoRow> getAllTransactions() {
|
||||
final size = transactionsCountNative();
|
||||
final transactionsPointer = transactionsGetAllNative();
|
||||
final transactionsAddresses = transactionsPointer.asTypedList(size);
|
||||
|
||||
return transactionsAddresses
|
||||
.map((addr) => Pointer<TransactionInfoRow>.fromAddress(addr).ref)
|
||||
.toList();
|
||||
}
|
||||
|
||||
TransactionInfoRow getTransaction(String txId) {
|
||||
final txIdPointer = txId.toNativeUtf8();
|
||||
return getTransactionNative(txIdPointer).ref;
|
||||
}
|
||||
|
||||
PendingTransactionDescription createTransactionSync(
|
||||
{required String address,
|
||||
required String paymentId,
|
||||
required int priorityRaw,
|
||||
String? amount,
|
||||
int accountIndex = 0,
|
||||
List<String> preferredInputs = const []}) {
|
||||
final addressPointer = address.toNativeUtf8();
|
||||
final paymentIdPointer = paymentId.toNativeUtf8();
|
||||
final amountPointer = amount != null ? amount.toNativeUtf8() : nullptr;
|
||||
|
||||
final int preferredInputsSize = preferredInputs.length;
|
||||
final List<Pointer<Utf8>> preferredInputsPointers =
|
||||
preferredInputs.map((output) => output.toNativeUtf8()).toList();
|
||||
final Pointer<Pointer<Utf8>> preferredInputsPointerPointer = calloc(preferredInputsSize);
|
||||
|
||||
for (int i = 0; i < preferredInputsSize; i++) {
|
||||
preferredInputsPointerPointer[i] = preferredInputsPointers[i];
|
||||
}
|
||||
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
|
||||
final created = transactionCreateNative(
|
||||
addressPointer,
|
||||
paymentIdPointer,
|
||||
amountPointer,
|
||||
priorityRaw,
|
||||
accountIndex,
|
||||
preferredInputsPointerPointer,
|
||||
preferredInputsSize,
|
||||
errorMessagePointer,
|
||||
pendingTransactionRawPointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(preferredInputsPointerPointer);
|
||||
|
||||
preferredInputsPointers.forEach((element) => calloc.free(element));
|
||||
|
||||
calloc.free(addressPointer);
|
||||
calloc.free(paymentIdPointer);
|
||||
|
||||
if (amountPointer != nullptr) {
|
||||
calloc.free(amountPointer);
|
||||
}
|
||||
|
||||
if (!created) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
calloc.free(errorMessagePointer);
|
||||
throw CreationTransactionException(message: message);
|
||||
}
|
||||
|
||||
return PendingTransactionDescription(
|
||||
amount: pendingTransactionRawPointer.ref.amount,
|
||||
fee: pendingTransactionRawPointer.ref.fee,
|
||||
hash: pendingTransactionRawPointer.ref.getHash(),
|
||||
hex: pendingTransactionRawPointer.ref.getHex(),
|
||||
txKey: pendingTransactionRawPointer.ref.getKey(),
|
||||
pointerAddress: pendingTransactionRawPointer.address);
|
||||
}
|
||||
|
||||
PendingTransactionDescription createTransactionMultDestSync(
|
||||
{required List<MoneroOutput> outputs,
|
||||
required String paymentId,
|
||||
required int priorityRaw,
|
||||
int accountIndex = 0,
|
||||
List<String> preferredInputs = const []}) {
|
||||
final int size = outputs.length;
|
||||
final List<Pointer<Utf8>> addressesPointers =
|
||||
outputs.map((output) => output.address.toNativeUtf8()).toList();
|
||||
final Pointer<Pointer<Utf8>> addressesPointerPointer = calloc(size);
|
||||
final List<Pointer<Utf8>> amountsPointers =
|
||||
outputs.map((output) => output.amount.toNativeUtf8()).toList();
|
||||
final Pointer<Pointer<Utf8>> amountsPointerPointer = calloc(size);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
addressesPointerPointer[i] = addressesPointers[i];
|
||||
amountsPointerPointer[i] = amountsPointers[i];
|
||||
}
|
||||
|
||||
final int preferredInputsSize = preferredInputs.length;
|
||||
final List<Pointer<Utf8>> preferredInputsPointers =
|
||||
preferredInputs.map((output) => output.toNativeUtf8()).toList();
|
||||
final Pointer<Pointer<Utf8>> preferredInputsPointerPointer = calloc(preferredInputsSize);
|
||||
|
||||
for (int i = 0; i < preferredInputsSize; i++) {
|
||||
preferredInputsPointerPointer[i] = preferredInputsPointers[i];
|
||||
}
|
||||
|
||||
final paymentIdPointer = paymentId.toNativeUtf8();
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
|
||||
final created = transactionCreateMultDestNative(
|
||||
addressesPointerPointer,
|
||||
paymentIdPointer,
|
||||
amountsPointerPointer,
|
||||
size,
|
||||
priorityRaw,
|
||||
accountIndex,
|
||||
preferredInputsPointerPointer,
|
||||
preferredInputsSize,
|
||||
errorMessagePointer,
|
||||
pendingTransactionRawPointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(addressesPointerPointer);
|
||||
calloc.free(amountsPointerPointer);
|
||||
calloc.free(preferredInputsPointerPointer);
|
||||
|
||||
addressesPointers.forEach((element) => calloc.free(element));
|
||||
amountsPointers.forEach((element) => calloc.free(element));
|
||||
preferredInputsPointers.forEach((element) => calloc.free(element));
|
||||
|
||||
calloc.free(paymentIdPointer);
|
||||
|
||||
if (!created) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
calloc.free(errorMessagePointer);
|
||||
throw CreationTransactionException(message: message);
|
||||
}
|
||||
|
||||
return PendingTransactionDescription(
|
||||
amount: pendingTransactionRawPointer.ref.amount,
|
||||
fee: pendingTransactionRawPointer.ref.fee,
|
||||
hash: pendingTransactionRawPointer.ref.getHash(),
|
||||
hex: pendingTransactionRawPointer.ref.getHex(),
|
||||
txKey: pendingTransactionRawPointer.ref.getKey(),
|
||||
pointerAddress: pendingTransactionRawPointer.address);
|
||||
}
|
||||
|
||||
void commitTransactionFromPointerAddress({required int address}) =>
|
||||
commitTransaction(transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address));
|
||||
|
||||
void commitTransaction({required Pointer<PendingTransactionRaw> transactionPointer}) {
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final isCommited = transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
|
||||
|
||||
if (!isCommited) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
calloc.free(errorMessagePointer);
|
||||
throw CreationTransactionException(message: message);
|
||||
}
|
||||
}
|
||||
|
||||
PendingTransactionDescription _createTransactionSync(Map args) {
|
||||
final address = args['address'] as String;
|
||||
final paymentId = args['paymentId'] as String;
|
||||
final amount = args['amount'] as String?;
|
||||
final priorityRaw = args['priorityRaw'] as int;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
final preferredInputs = args['preferredInputs'] as List<String>;
|
||||
|
||||
return createTransactionSync(
|
||||
address: address,
|
||||
paymentId: paymentId,
|
||||
amount: amount,
|
||||
priorityRaw: priorityRaw,
|
||||
accountIndex: accountIndex,
|
||||
preferredInputs: preferredInputs);
|
||||
}
|
||||
|
||||
PendingTransactionDescription _createTransactionMultDestSync(Map args) {
|
||||
final outputs = args['outputs'] as List<MoneroOutput>;
|
||||
final paymentId = args['paymentId'] as String;
|
||||
final priorityRaw = args['priorityRaw'] as int;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
final preferredInputs = args['preferredInputs'] as List<String>;
|
||||
|
||||
return createTransactionMultDestSync(
|
||||
outputs: outputs,
|
||||
paymentId: paymentId,
|
||||
priorityRaw: priorityRaw,
|
||||
accountIndex: accountIndex,
|
||||
preferredInputs: preferredInputs);
|
||||
}
|
||||
|
||||
Future<PendingTransactionDescription> createTransaction(
|
||||
{required String address,
|
||||
required int priorityRaw,
|
||||
String? amount,
|
||||
String paymentId = '',
|
||||
int accountIndex = 0,
|
||||
List<String> preferredInputs = const []}) =>
|
||||
compute(_createTransactionSync, {
|
||||
'address': address,
|
||||
'paymentId': paymentId,
|
||||
'amount': amount,
|
||||
'priorityRaw': priorityRaw,
|
||||
'accountIndex': accountIndex,
|
||||
'preferredInputs': preferredInputs
|
||||
});
|
||||
|
||||
Future<PendingTransactionDescription> createTransactionMultDest(
|
||||
{required List<MoneroOutput> outputs,
|
||||
required int priorityRaw,
|
||||
String paymentId = '',
|
||||
int accountIndex = 0,
|
||||
List<String> preferredInputs = const []}) =>
|
||||
compute(_createTransactionMultDestSync, {
|
||||
'outputs': outputs,
|
||||
'paymentId': paymentId,
|
||||
'priorityRaw': priorityRaw,
|
||||
'accountIndex': accountIndex,
|
||||
'preferredInputs': preferredInputs
|
||||
});
|
@ -0,0 +1,153 @@
|
||||
import 'dart:ffi';
|
||||
import 'package:cw_wownero/api/structs/coins_info_row.dart';
|
||||
import 'package:cw_wownero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_wownero/api/structs/transaction_info_row.dart';
|
||||
import 'package:cw_wownero/api/structs/ut8_box.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
typedef CreateWallet = int Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, Pointer<Utf8>);
|
||||
|
||||
typedef RestoreWalletFromSeed = int Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
||||
|
||||
typedef RestoreWalletFromKeys = int Function(Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
||||
|
||||
typedef RestoreWalletFromSpendKey = int Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
||||
|
||||
typedef IsWalletExist = int Function(Pointer<Utf8>);
|
||||
|
||||
typedef LoadWallet = int Function(Pointer<Utf8>, Pointer<Utf8>, int);
|
||||
|
||||
typedef ErrorString = Pointer<Utf8> Function();
|
||||
|
||||
typedef GetFilename = Pointer<Utf8> Function();
|
||||
|
||||
typedef GetSeed = Pointer<Utf8> Function();
|
||||
|
||||
typedef GetAddress = Pointer<Utf8> Function(int, int);
|
||||
|
||||
typedef GetFullBalance = int Function(int);
|
||||
|
||||
typedef GetUnlockedBalance = int Function(int);
|
||||
|
||||
typedef GetCurrentHeight = int Function();
|
||||
|
||||
typedef GetNodeHeight = int Function();
|
||||
|
||||
typedef IsConnected = int Function();
|
||||
|
||||
typedef SetupNode = int Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, int, int, Pointer<Utf8>?, Pointer<Utf8>);
|
||||
|
||||
typedef StartRefresh = void Function();
|
||||
|
||||
typedef ConnectToNode = int Function();
|
||||
|
||||
typedef SetRefreshFromBlockHeight = void Function(int);
|
||||
|
||||
typedef SetRecoveringFromSeed = void Function(int);
|
||||
|
||||
typedef Store = void Function(Pointer<Utf8>);
|
||||
|
||||
typedef SetPassword = int Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
|
||||
|
||||
typedef SetListener = void Function();
|
||||
|
||||
typedef GetSyncingHeight = int Function();
|
||||
|
||||
typedef IsNeededToRefresh = int Function();
|
||||
|
||||
typedef IsNewTransactionExist = int Function();
|
||||
|
||||
typedef SubaddressSize = int Function();
|
||||
|
||||
typedef SubaddressRefresh = void Function(int);
|
||||
|
||||
typedef SubaddressGetAll = Pointer<Int64> Function();
|
||||
|
||||
typedef SubaddressAddNew = void Function(int accountIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef SubaddressSetLabel = void Function(
|
||||
int accountIndex, int addressIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef AccountSize = int Function();
|
||||
|
||||
typedef AccountRefresh = void Function();
|
||||
|
||||
typedef AccountGetAll = Pointer<Int64> Function();
|
||||
|
||||
typedef AccountAddNew = void Function(Pointer<Utf8> label);
|
||||
|
||||
typedef AccountSetLabel = void Function(int accountIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef TransactionsRefresh = void Function();
|
||||
|
||||
typedef GetTransaction = Pointer<TransactionInfoRow> Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef GetTxKey = Pointer<Utf8>? Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef TransactionsCount = int Function();
|
||||
|
||||
typedef TransactionsGetAll = Pointer<Int64> Function();
|
||||
|
||||
typedef TransactionCreate = int Function(
|
||||
Pointer<Utf8> address,
|
||||
Pointer<Utf8> paymentId,
|
||||
Pointer<Utf8> amount,
|
||||
int priorityRaw,
|
||||
int subaddrAccount,
|
||||
Pointer<Pointer<Utf8>> preferredInputs,
|
||||
int preferredInputsSize,
|
||||
Pointer<Utf8Box> error,
|
||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
||||
|
||||
typedef TransactionCreateMultDest = int Function(
|
||||
Pointer<Pointer<Utf8>> addresses,
|
||||
Pointer<Utf8> paymentId,
|
||||
Pointer<Pointer<Utf8>> amounts,
|
||||
int size,
|
||||
int priorityRaw,
|
||||
int subaddrAccount,
|
||||
Pointer<Pointer<Utf8>> preferredInputs,
|
||||
int preferredInputsSize,
|
||||
Pointer<Utf8Box> error,
|
||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
||||
|
||||
typedef TransactionCommit = int Function(Pointer<PendingTransactionRaw>, Pointer<Utf8Box>);
|
||||
|
||||
typedef SecretViewKey = Pointer<Utf8> Function();
|
||||
|
||||
typedef PublicViewKey = Pointer<Utf8> Function();
|
||||
|
||||
typedef SecretSpendKey = Pointer<Utf8> Function();
|
||||
|
||||
typedef PublicSpendKey = Pointer<Utf8> Function();
|
||||
|
||||
typedef CloseCurrentWallet = void Function();
|
||||
|
||||
typedef OnStartup = void Function();
|
||||
|
||||
typedef RescanBlockchainAsync = void Function();
|
||||
|
||||
typedef GetSubaddressLabel = Pointer<Utf8> Function(
|
||||
int accountIndex,
|
||||
int addressIndex);
|
||||
|
||||
typedef SetTrustedDaemon = void Function(int);
|
||||
|
||||
typedef TrustedDaemon = int Function();
|
||||
|
||||
typedef RefreshCoins = void Function(int);
|
||||
|
||||
typedef CoinsCount = int Function();
|
||||
|
||||
typedef GetCoin = Pointer<CoinsInfoRow> Function(int);
|
||||
|
||||
typedef FreezeCoin = void Function(int);
|
||||
|
||||
typedef ThawCoin = void Function(int);
|
||||
|
||||
typedef SignMessage = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>);
|
@ -0,0 +1,399 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:cw_wownero/api/structs/ut8_box.dart';
|
||||
import 'package:cw_wownero/api/convert_utf8_to_string.dart';
|
||||
import 'package:cw_wownero/api/signatures.dart';
|
||||
import 'package:cw_wownero/api/types.dart';
|
||||
import 'package:cw_wownero/api/wownero_api.dart';
|
||||
import 'package:cw_wownero/api/exceptions/setup_wallet_exception.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
int _boolToInt(bool value) => value ? 1 : 0;
|
||||
|
||||
final getFileNameNative = wowneroApi
|
||||
.lookup<NativeFunction<get_filename>>('get_filename')
|
||||
.asFunction<GetFilename>();
|
||||
|
||||
final getSeedNative =
|
||||
wowneroApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>();
|
||||
|
||||
final getAddressNative = wowneroApi
|
||||
.lookup<NativeFunction<get_address>>('get_address')
|
||||
.asFunction<GetAddress>();
|
||||
|
||||
final getFullBalanceNative = wowneroApi
|
||||
.lookup<NativeFunction<get_full_balanace>>('get_full_balance')
|
||||
.asFunction<GetFullBalance>();
|
||||
|
||||
final getUnlockedBalanceNative = wowneroApi
|
||||
.lookup<NativeFunction<get_unlocked_balanace>>('get_unlocked_balance')
|
||||
.asFunction<GetUnlockedBalance>();
|
||||
|
||||
final getCurrentHeightNative = wowneroApi
|
||||
.lookup<NativeFunction<get_current_height>>('get_current_height')
|
||||
.asFunction<GetCurrentHeight>();
|
||||
|
||||
final getNodeHeightNative = wowneroApi
|
||||
.lookup<NativeFunction<get_node_height>>('get_node_height')
|
||||
.asFunction<GetNodeHeight>();
|
||||
|
||||
final isConnectedNative = wowneroApi
|
||||
.lookup<NativeFunction<is_connected>>('is_connected')
|
||||
.asFunction<IsConnected>();
|
||||
|
||||
final setupNodeNative = wowneroApi
|
||||
.lookup<NativeFunction<setup_node>>('setup_node')
|
||||
.asFunction<SetupNode>();
|
||||
|
||||
final startRefreshNative = wowneroApi
|
||||
.lookup<NativeFunction<start_refresh>>('start_refresh')
|
||||
.asFunction<StartRefresh>();
|
||||
|
||||
final connecToNodeNative = wowneroApi
|
||||
.lookup<NativeFunction<connect_to_node>>('connect_to_node')
|
||||
.asFunction<ConnectToNode>();
|
||||
|
||||
final setRefreshFromBlockHeightNative = wowneroApi
|
||||
.lookup<NativeFunction<set_refresh_from_block_height>>(
|
||||
'set_refresh_from_block_height')
|
||||
.asFunction<SetRefreshFromBlockHeight>();
|
||||
|
||||
final setRecoveringFromSeedNative = wowneroApi
|
||||
.lookup<NativeFunction<set_recovering_from_seed>>(
|
||||
'set_recovering_from_seed')
|
||||
.asFunction<SetRecoveringFromSeed>();
|
||||
|
||||
final storeNative =
|
||||
wowneroApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
|
||||
|
||||
final setPasswordNative =
|
||||
wowneroApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
|
||||
|
||||
final setListenerNative = wowneroApi
|
||||
.lookup<NativeFunction<set_listener>>('set_listener')
|
||||
.asFunction<SetListener>();
|
||||
|
||||
final getSyncingHeightNative = wowneroApi
|
||||
.lookup<NativeFunction<get_syncing_height>>('get_syncing_height')
|
||||
.asFunction<GetSyncingHeight>();
|
||||
|
||||
final isNeededToRefreshNative = wowneroApi
|
||||
.lookup<NativeFunction<is_needed_to_refresh>>('is_needed_to_refresh')
|
||||
.asFunction<IsNeededToRefresh>();
|
||||
|
||||
final isNewTransactionExistNative = wowneroApi
|
||||
.lookup<NativeFunction<is_new_transaction_exist>>(
|
||||
'is_new_transaction_exist')
|
||||
.asFunction<IsNewTransactionExist>();
|
||||
|
||||
final getSecretViewKeyNative = wowneroApi
|
||||
.lookup<NativeFunction<secret_view_key>>('secret_view_key')
|
||||
.asFunction<SecretViewKey>();
|
||||
|
||||
final getPublicViewKeyNative = wowneroApi
|
||||
.lookup<NativeFunction<public_view_key>>('public_view_key')
|
||||
.asFunction<PublicViewKey>();
|
||||
|
||||
final getSecretSpendKeyNative = wowneroApi
|
||||
.lookup<NativeFunction<secret_spend_key>>('secret_spend_key')
|
||||
.asFunction<SecretSpendKey>();
|
||||
|
||||
final getPublicSpendKeyNative = wowneroApi
|
||||
.lookup<NativeFunction<secret_view_key>>('public_spend_key')
|
||||
.asFunction<PublicSpendKey>();
|
||||
|
||||
final closeCurrentWalletNative = wowneroApi
|
||||
.lookup<NativeFunction<close_current_wallet>>('close_current_wallet')
|
||||
.asFunction<CloseCurrentWallet>();
|
||||
|
||||
final onStartupNative = wowneroApi
|
||||
.lookup<NativeFunction<on_startup>>('on_startup')
|
||||
.asFunction<OnStartup>();
|
||||
|
||||
final rescanBlockchainAsyncNative = wowneroApi
|
||||
.lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain')
|
||||
.asFunction<RescanBlockchainAsync>();
|
||||
|
||||
final getSubaddressLabelNative = wowneroApi
|
||||
.lookup<NativeFunction<get_subaddress_label>>('get_subaddress_label')
|
||||
.asFunction<GetSubaddressLabel>();
|
||||
|
||||
final setTrustedDaemonNative = wowneroApi
|
||||
.lookup<NativeFunction<set_trusted_daemon>>('set_trusted_daemon')
|
||||
.asFunction<SetTrustedDaemon>();
|
||||
|
||||
final trustedDaemonNative = wowneroApi
|
||||
.lookup<NativeFunction<trusted_daemon>>('trusted_daemon')
|
||||
.asFunction<TrustedDaemon>();
|
||||
|
||||
final signMessageNative = wowneroApi
|
||||
.lookup<NativeFunction<sign_message>>('sign_message')
|
||||
.asFunction<SignMessage>();
|
||||
|
||||
int getSyncingHeight() => getSyncingHeightNative();
|
||||
|
||||
bool isNeededToRefresh() => isNeededToRefreshNative() != 0;
|
||||
|
||||
bool isNewTransactionExist() => isNewTransactionExistNative() != 0;
|
||||
|
||||
String getFilename() => convertUTF8ToString(pointer: getFileNameNative());
|
||||
|
||||
String getSeed() => convertUTF8ToString(pointer: getSeedNative());
|
||||
|
||||
String getAddress({int accountIndex = 0, int addressIndex = 0}) =>
|
||||
convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex));
|
||||
|
||||
int getFullBalance({int accountIndex = 0}) =>
|
||||
getFullBalanceNative(accountIndex);
|
||||
|
||||
int getUnlockedBalance({int accountIndex = 0}) =>
|
||||
getUnlockedBalanceNative(accountIndex);
|
||||
|
||||
int getCurrentHeight() => getCurrentHeightNative();
|
||||
|
||||
int getNodeHeightSync() => getNodeHeightNative();
|
||||
|
||||
bool isConnectedSync() => isConnectedNative() != 0;
|
||||
|
||||
bool setupNodeSync(
|
||||
{required String address,
|
||||
String? login,
|
||||
String? password,
|
||||
bool useSSL = false,
|
||||
bool isLightWallet = false,
|
||||
String? socksProxyAddress}) {
|
||||
final addressPointer = address.toNativeUtf8();
|
||||
Pointer<Utf8>? loginPointer;
|
||||
Pointer<Utf8>? socksProxyAddressPointer;
|
||||
Pointer<Utf8>? passwordPointer;
|
||||
|
||||
if (login != null) {
|
||||
loginPointer = login.toNativeUtf8();
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
passwordPointer = password.toNativeUtf8();
|
||||
}
|
||||
|
||||
if (socksProxyAddress != null) {
|
||||
socksProxyAddressPointer = socksProxyAddress.toNativeUtf8();
|
||||
}
|
||||
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isSetupNode = setupNodeNative(
|
||||
addressPointer,
|
||||
loginPointer,
|
||||
passwordPointer,
|
||||
_boolToInt(useSSL),
|
||||
_boolToInt(isLightWallet),
|
||||
socksProxyAddressPointer,
|
||||
errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(addressPointer);
|
||||
|
||||
if (loginPointer != null) {
|
||||
calloc.free(loginPointer);
|
||||
}
|
||||
|
||||
if (passwordPointer != null) {
|
||||
calloc.free(passwordPointer);
|
||||
}
|
||||
|
||||
if (!isSetupNode) {
|
||||
throw SetupWalletException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
|
||||
return isSetupNode;
|
||||
}
|
||||
|
||||
void startRefreshSync() => startRefreshNative();
|
||||
|
||||
Future<bool> connectToNode() async => connecToNodeNative() != 0;
|
||||
|
||||
void setRefreshFromBlockHeight({required int height}) =>
|
||||
setRefreshFromBlockHeightNative(height);
|
||||
|
||||
void setRecoveringFromSeed({required bool isRecovery}) =>
|
||||
setRecoveringFromSeedNative(_boolToInt(isRecovery));
|
||||
|
||||
void storeSync() {
|
||||
final pathPointer = ''.toNativeUtf8();
|
||||
storeNative(pathPointer);
|
||||
calloc.free(pathPointer);
|
||||
}
|
||||
|
||||
void setPasswordSync(String password) {
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
|
||||
calloc.free(passwordPointer);
|
||||
|
||||
if (!changed) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
calloc.free(errorMessagePointer);
|
||||
throw Exception(message);
|
||||
}
|
||||
|
||||
calloc.free(errorMessagePointer);
|
||||
}
|
||||
|
||||
void closeCurrentWallet() => closeCurrentWalletNative();
|
||||
|
||||
String getSecretViewKey() =>
|
||||
convertUTF8ToString(pointer: getSecretViewKeyNative());
|
||||
|
||||
String getPublicViewKey() =>
|
||||
convertUTF8ToString(pointer: getPublicViewKeyNative());
|
||||
|
||||
String getSecretSpendKey() =>
|
||||
convertUTF8ToString(pointer: getSecretSpendKeyNative());
|
||||
|
||||
String getPublicSpendKey() =>
|
||||
convertUTF8ToString(pointer: getPublicSpendKeyNative());
|
||||
|
||||
class SyncListener {
|
||||
SyncListener(this.onNewBlock, this.onNewTransaction)
|
||||
: _cachedBlockchainHeight = 0,
|
||||
_lastKnownBlockHeight = 0,
|
||||
_initialSyncHeight = 0;
|
||||
|
||||
|
||||
void Function(int, int, double) onNewBlock;
|
||||
void Function() onNewTransaction;
|
||||
|
||||
Timer? _updateSyncInfoTimer;
|
||||
int _cachedBlockchainHeight;
|
||||
int _lastKnownBlockHeight;
|
||||
int _initialSyncHeight;
|
||||
|
||||
Future<int> getNodeHeightOrUpdate(int baseHeight) async {
|
||||
if (_cachedBlockchainHeight < baseHeight || _cachedBlockchainHeight == 0) {
|
||||
_cachedBlockchainHeight = await getNodeHeight();
|
||||
}
|
||||
|
||||
return _cachedBlockchainHeight;
|
||||
}
|
||||
|
||||
void start() {
|
||||
_cachedBlockchainHeight = 0;
|
||||
_lastKnownBlockHeight = 0;
|
||||
_initialSyncHeight = 0;
|
||||
_updateSyncInfoTimer ??=
|
||||
Timer.periodic(Duration(milliseconds: 1200), (_) async {
|
||||
if (isNewTransactionExist()) {
|
||||
onNewTransaction();
|
||||
}
|
||||
|
||||
var syncHeight = getSyncingHeight();
|
||||
|
||||
if (syncHeight <= 0) {
|
||||
syncHeight = getCurrentHeight();
|
||||
}
|
||||
|
||||
if (_initialSyncHeight <= 0) {
|
||||
_initialSyncHeight = syncHeight;
|
||||
}
|
||||
|
||||
final bchHeight = await getNodeHeightOrUpdate(syncHeight);
|
||||
|
||||
if (_lastKnownBlockHeight == syncHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
_lastKnownBlockHeight = syncHeight;
|
||||
final track = bchHeight - _initialSyncHeight;
|
||||
final diff = track - (bchHeight - syncHeight);
|
||||
final ptc = diff <= 0 ? 0.0 : diff / track;
|
||||
final left = bchHeight - syncHeight;
|
||||
|
||||
if (syncHeight < 0 || left < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Actual new height; 2. Blocks left to finish; 3. Progress in percents;
|
||||
onNewBlock.call(syncHeight, left, ptc);
|
||||
});
|
||||
}
|
||||
|
||||
void stop() => _updateSyncInfoTimer?.cancel();
|
||||
}
|
||||
|
||||
SyncListener setListeners(void Function(int, int, double) onNewBlock,
|
||||
void Function() onNewTransaction) {
|
||||
final listener = SyncListener(onNewBlock, onNewTransaction);
|
||||
setListenerNative();
|
||||
return listener;
|
||||
}
|
||||
|
||||
void onStartup() => onStartupNative();
|
||||
|
||||
void _storeSync(Object _) => storeSync();
|
||||
|
||||
bool _setupNodeSync(Map<String, Object?> args) {
|
||||
final address = args['address'] as String;
|
||||
final login = (args['login'] ?? '') as String;
|
||||
final password = (args['password'] ?? '') as String;
|
||||
final useSSL = args['useSSL'] as bool;
|
||||
final isLightWallet = args['isLightWallet'] as bool;
|
||||
final socksProxyAddress = (args['socksProxyAddress'] ?? '') as String;
|
||||
|
||||
return setupNodeSync(
|
||||
address: address,
|
||||
login: login,
|
||||
password: password,
|
||||
useSSL: useSSL,
|
||||
isLightWallet: isLightWallet,
|
||||
socksProxyAddress: socksProxyAddress);
|
||||
}
|
||||
|
||||
bool _isConnected(Object _) => isConnectedSync();
|
||||
|
||||
int _getNodeHeight(Object _) => getNodeHeightSync();
|
||||
|
||||
void startRefresh() => startRefreshSync();
|
||||
|
||||
Future<void> setupNode(
|
||||
{required String address,
|
||||
String? login,
|
||||
String? password,
|
||||
bool useSSL = false,
|
||||
String? socksProxyAddress,
|
||||
bool isLightWallet = false}) =>
|
||||
compute<Map<String, Object?>, void>(_setupNodeSync, {
|
||||
'address': address,
|
||||
'login': login ,
|
||||
'password': password,
|
||||
'useSSL': useSSL,
|
||||
'isLightWallet': isLightWallet,
|
||||
'socksProxyAddress': socksProxyAddress
|
||||
});
|
||||
|
||||
Future<void> store() => compute<int, void>(_storeSync, 0);
|
||||
|
||||
Future<bool> isConnected() => compute(_isConnected, 0);
|
||||
|
||||
Future<int> getNodeHeight() => compute(_getNodeHeight, 0);
|
||||
|
||||
void rescanBlockchainAsync() => rescanBlockchainAsyncNative();
|
||||
|
||||
String getSubaddressLabel(int accountIndex, int addressIndex) {
|
||||
return convertUTF8ToString(pointer: getSubaddressLabelNative(accountIndex, addressIndex));
|
||||
}
|
||||
|
||||
Future setTrustedDaemon(bool trusted) async => setTrustedDaemonNative(_boolToInt(trusted));
|
||||
|
||||
Future<bool> trustedDaemon() async => trustedDaemonNative() != 0;
|
||||
|
||||
String signMessage(String message, {String address = ""}) {
|
||||
final messagePointer = message.toNativeUtf8();
|
||||
final addressPointer = address.toNativeUtf8();
|
||||
|
||||
final signature = convertUTF8ToString(pointer: signMessageNative(messagePointer, addressPointer));
|
||||
calloc.free(messagePointer);
|
||||
calloc.free(addressPointer);
|
||||
|
||||
return signature;
|
||||
}
|
@ -0,0 +1,333 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:cw_wownero/api/convert_utf8_to_string.dart';
|
||||
import 'package:cw_wownero/api/exceptions/wallet_creation_exception.dart';
|
||||
import 'package:cw_wownero/api/exceptions/wallet_opening_exception.dart';
|
||||
import 'package:cw_wownero/api/exceptions/wallet_restore_from_keys_exception.dart';
|
||||
import 'package:cw_wownero/api/exceptions/wallet_restore_from_seed_exception.dart';
|
||||
import 'package:cw_wownero/api/wownero_api.dart';
|
||||
import 'package:cw_wownero/api/signatures.dart';
|
||||
import 'package:cw_wownero/api/types.dart';
|
||||
import 'package:cw_wownero/api/wallet.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
final createWalletNative = wowneroApi
|
||||
.lookup<NativeFunction<create_wallet>>('create_wallet')
|
||||
.asFunction<CreateWallet>();
|
||||
|
||||
final restoreWalletFromSeedNative = wowneroApi
|
||||
.lookup<NativeFunction<restore_wallet_from_seed>>(
|
||||
'restore_wallet_from_seed')
|
||||
.asFunction<RestoreWalletFromSeed>();
|
||||
|
||||
final restoreWalletFromKeysNative = wowneroApi
|
||||
.lookup<NativeFunction<restore_wallet_from_keys>>(
|
||||
'restore_wallet_from_keys')
|
||||
.asFunction<RestoreWalletFromKeys>();
|
||||
|
||||
final restoreWalletFromSpendKeyNative = wowneroApi
|
||||
.lookup<NativeFunction<restore_wallet_from_spend_key>>(
|
||||
'restore_wallet_from_spend_key')
|
||||
.asFunction<RestoreWalletFromSpendKey>();
|
||||
|
||||
final isWalletExistNative = wowneroApi
|
||||
.lookup<NativeFunction<is_wallet_exist>>('is_wallet_exist')
|
||||
.asFunction<IsWalletExist>();
|
||||
|
||||
final loadWalletNative = wowneroApi
|
||||
.lookup<NativeFunction<load_wallet>>('load_wallet')
|
||||
.asFunction<LoadWallet>();
|
||||
|
||||
final errorStringNative = wowneroApi
|
||||
.lookup<NativeFunction<error_string>>('error_string')
|
||||
.asFunction<ErrorString>();
|
||||
|
||||
void createWalletSync(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String language,
|
||||
int nettype = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final languagePointer = language.toNativeUtf8();
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isWalletCreated = createWalletNative(pathPointer, passwordPointer,
|
||||
languagePointer, nettype, errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
calloc.free(languagePointer);
|
||||
|
||||
if (!isWalletCreated) {
|
||||
throw WalletCreationException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
|
||||
// setupNodeSync(address: "node.wowneroworld.com:18089");
|
||||
}
|
||||
|
||||
bool isWalletExistSync({required String path}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final isExist = isWalletExistNative(pathPointer) != 0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
|
||||
return isExist;
|
||||
}
|
||||
|
||||
void restoreWalletFromSeedSync(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String seed,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final seedPointer = seed.toNativeUtf8();
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isWalletRestored = restoreWalletFromSeedNative(
|
||||
pathPointer,
|
||||
passwordPointer,
|
||||
seedPointer,
|
||||
nettype,
|
||||
restoreHeight,
|
||||
errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
calloc.free(seedPointer);
|
||||
|
||||
if (!isWalletRestored) {
|
||||
throw WalletRestoreFromSeedException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
}
|
||||
|
||||
void restoreWalletFromKeysSync(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String language,
|
||||
required String address,
|
||||
required String viewKey,
|
||||
required String spendKey,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final languagePointer = language.toNativeUtf8();
|
||||
final addressPointer = address.toNativeUtf8();
|
||||
final viewKeyPointer = viewKey.toNativeUtf8();
|
||||
final spendKeyPointer = spendKey.toNativeUtf8();
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isWalletRestored = restoreWalletFromKeysNative(
|
||||
pathPointer,
|
||||
passwordPointer,
|
||||
languagePointer,
|
||||
addressPointer,
|
||||
viewKeyPointer,
|
||||
spendKeyPointer,
|
||||
nettype,
|
||||
restoreHeight,
|
||||
errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
calloc.free(languagePointer);
|
||||
calloc.free(addressPointer);
|
||||
calloc.free(viewKeyPointer);
|
||||
calloc.free(spendKeyPointer);
|
||||
|
||||
if (!isWalletRestored) {
|
||||
throw WalletRestoreFromKeysException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
}
|
||||
|
||||
void restoreWalletFromSpendKeySync(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String seed,
|
||||
required String language,
|
||||
required String spendKey,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final seedPointer = seed.toNativeUtf8();
|
||||
final languagePointer = language.toNativeUtf8();
|
||||
final spendKeyPointer = spendKey.toNativeUtf8();
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isWalletRestored = restoreWalletFromSpendKeyNative(
|
||||
pathPointer,
|
||||
passwordPointer,
|
||||
seedPointer,
|
||||
languagePointer,
|
||||
spendKeyPointer,
|
||||
nettype,
|
||||
restoreHeight,
|
||||
errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
calloc.free(languagePointer);
|
||||
calloc.free(spendKeyPointer);
|
||||
|
||||
storeSync();
|
||||
|
||||
if (!isWalletRestored) {
|
||||
throw WalletRestoreFromKeysException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
}
|
||||
|
||||
void loadWallet({
|
||||
required String path,
|
||||
required String password,
|
||||
int nettype = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final loaded = loadWalletNative(pathPointer, passwordPointer, nettype) != 0;
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
|
||||
if (!loaded) {
|
||||
throw WalletOpeningException(
|
||||
message: convertUTF8ToString(pointer: errorStringNative()));
|
||||
}
|
||||
}
|
||||
|
||||
void _createWallet(Map<String, dynamic> args) {
|
||||
final path = args['path'] as String;
|
||||
final password = args['password'] as String;
|
||||
final language = args['language'] as String;
|
||||
|
||||
createWalletSync(path: path, password: password, language: language);
|
||||
}
|
||||
|
||||
void _restoreFromSeed(Map<String, dynamic> args) {
|
||||
final path = args['path'] as String;
|
||||
final password = args['password'] as String;
|
||||
final seed = args['seed'] as String;
|
||||
final restoreHeight = args['restoreHeight'] as int;
|
||||
|
||||
restoreWalletFromSeedSync(
|
||||
path: path, password: password, seed: seed, restoreHeight: restoreHeight);
|
||||
}
|
||||
|
||||
void _restoreFromKeys(Map<String, dynamic> args) {
|
||||
final path = args['path'] as String;
|
||||
final password = args['password'] as String;
|
||||
final language = args['language'] as String;
|
||||
final restoreHeight = args['restoreHeight'] as int;
|
||||
final address = args['address'] as String;
|
||||
final viewKey = args['viewKey'] as String;
|
||||
final spendKey = args['spendKey'] as String;
|
||||
|
||||
restoreWalletFromKeysSync(
|
||||
path: path,
|
||||
password: password,
|
||||
language: language,
|
||||
restoreHeight: restoreHeight,
|
||||
address: address,
|
||||
viewKey: viewKey,
|
||||
spendKey: spendKey);
|
||||
}
|
||||
|
||||
void _restoreFromSpendKey(Map<String, dynamic> args) {
|
||||
final path = args['path'] as String;
|
||||
final password = args['password'] as String;
|
||||
final seed = args['seed'] as String;
|
||||
final language = args['language'] as String;
|
||||
final spendKey = args['spendKey'] as String;
|
||||
final restoreHeight = args['restoreHeight'] as int;
|
||||
|
||||
restoreWalletFromSpendKeySync(
|
||||
path: path,
|
||||
password: password,
|
||||
seed: seed,
|
||||
language: language,
|
||||
restoreHeight: restoreHeight,
|
||||
spendKey: spendKey);
|
||||
}
|
||||
|
||||
Future<void> _openWallet(Map<String, String> args) async =>
|
||||
loadWallet(path: args['path'] as String, password: args['password'] as String);
|
||||
|
||||
bool _isWalletExist(String path) => isWalletExistSync(path: path);
|
||||
|
||||
void openWallet({required String path, required String password, int nettype = 0}) async =>
|
||||
loadWallet(path: path, password: password, nettype: nettype);
|
||||
|
||||
Future<void> openWalletAsync(Map<String, String> args) async =>
|
||||
compute(_openWallet, args);
|
||||
|
||||
Future<void> createWallet(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String language,
|
||||
int nettype = 0}) async =>
|
||||
compute(_createWallet, {
|
||||
'path': path,
|
||||
'password': password,
|
||||
'language': language,
|
||||
'nettype': nettype
|
||||
});
|
||||
|
||||
Future<void> restoreFromSeed(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String seed,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) async =>
|
||||
compute<Map<String, Object>, void>(_restoreFromSeed, {
|
||||
'path': path,
|
||||
'password': password,
|
||||
'seed': seed,
|
||||
'nettype': nettype,
|
||||
'restoreHeight': restoreHeight
|
||||
});
|
||||
|
||||
Future<void> restoreFromKeys(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String language,
|
||||
required String address,
|
||||
required String viewKey,
|
||||
required String spendKey,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) async =>
|
||||
compute<Map<String, Object>, void>(_restoreFromKeys, {
|
||||
'path': path,
|
||||
'password': password,
|
||||
'language': language,
|
||||
'address': address,
|
||||
'viewKey': viewKey,
|
||||
'spendKey': spendKey,
|
||||
'nettype': nettype,
|
||||
'restoreHeight': restoreHeight
|
||||
});
|
||||
|
||||
Future<void> restoreFromSpendKey(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String seed,
|
||||
required String language,
|
||||
required String spendKey,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) async =>
|
||||
compute<Map<String, Object>, void>(_restoreFromSpendKey, {
|
||||
'path': path,
|
||||
'password': password,
|
||||
'seed': seed,
|
||||
'language': language,
|
||||
'spendKey': spendKey,
|
||||
'nettype': nettype,
|
||||
'restoreHeight': restoreHeight
|
||||
});
|
||||
|
||||
Future<bool> isWalletExist({required String path}) => compute(_isWalletExist, path);
|
@ -0,0 +1,6 @@
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
|
||||
final DynamicLibrary wowneroApi = Platform.isAndroid
|
||||
? DynamicLibrary.open("libcw_wownero.so")
|
||||
: DynamicLibrary.open("cw_wownero.framework/cw_wownero");
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue