268 lines
7.0 KiB
Dart
268 lines
7.0 KiB
Dart
import 'dart:async';
|
|
import 'dart:ffi';
|
|
import 'package:ffi/ffi.dart';
|
|
import 'package:isolate/ports.dart';
|
|
|
|
import 'ffi.dart' as native;
|
|
|
|
/// Language
|
|
enum Language {
|
|
/// English
|
|
english,
|
|
|
|
/// French
|
|
french,
|
|
}
|
|
|
|
/// New wallet
|
|
class NewWallet {
|
|
/// DEWIF: Encrypted wallet
|
|
String dewif;
|
|
|
|
/// Pin code
|
|
String pin;
|
|
|
|
/// Public key
|
|
String publicKey;
|
|
|
|
NewWallet._(this.dewif, this.pin, this.publicKey);
|
|
}
|
|
|
|
/// Pin code length
|
|
enum PinLength {
|
|
/// 6 characters
|
|
six,
|
|
|
|
/// 8 characters
|
|
eight,
|
|
|
|
/// 10 characters
|
|
ten,
|
|
}
|
|
|
|
/// DUBP Rust utilities
|
|
///
|
|
/// All the functions of this package are static methods of this
|
|
/// class `DubpRust`.
|
|
class DubpRust {
|
|
/// Must be called only once at the start of your application.
|
|
static void setup() {
|
|
native.store_dart_post_cobject(NativeApi.postCObject);
|
|
print("Dubp Setup Done");
|
|
}
|
|
|
|
/// Generate a random mnemonic
|
|
static Future<String> genMnemonic({Language language = Language.english}) {
|
|
final completer = Completer<String>();
|
|
final sendPort =
|
|
singleCompletePort<String, List>(completer, callback: _handleErr);
|
|
native.gen_mnemonic(
|
|
sendPort.nativePort,
|
|
language.index,
|
|
);
|
|
return completer.future;
|
|
}
|
|
|
|
static Future<String> _genPin(PinLength pinLength) {
|
|
final completer = Completer<String>();
|
|
final sendPort =
|
|
singleCompletePort<String, List>(completer, callback: _handleErr);
|
|
switch (pinLength) {
|
|
case PinLength.ten:
|
|
native.gen_pin10(
|
|
sendPort.nativePort,
|
|
);
|
|
break;
|
|
case PinLength.eight:
|
|
native.gen_pin8(
|
|
sendPort.nativePort,
|
|
);
|
|
break;
|
|
case PinLength.six:
|
|
default:
|
|
native.gen_pin6(
|
|
sendPort.nativePort,
|
|
);
|
|
break;
|
|
}
|
|
return completer.future;
|
|
}
|
|
|
|
/// Change the pin code that encrypts the `dewif` keypair.
|
|
static Future<NewWallet> changeDewifPin(
|
|
{String currency = "g1",
|
|
String dewif,
|
|
String oldPin,
|
|
PinLength newPinLength = PinLength.six}) async {
|
|
// pin
|
|
String newPin = await _genPin(newPinLength);
|
|
// dewif
|
|
String newDewif;
|
|
{
|
|
final completer = Completer<String>();
|
|
final sendPort =
|
|
singleCompletePort<String, List>(completer, callback: _handleErr);
|
|
native.change_dewif_pin(
|
|
sendPort.nativePort,
|
|
Utf8.toUtf8(currency),
|
|
Utf8.toUtf8(dewif),
|
|
Utf8.toUtf8(oldPin),
|
|
Utf8.toUtf8(newPin),
|
|
);
|
|
newDewif = await completer.future;
|
|
}
|
|
// publicKey
|
|
String publicKey;
|
|
{
|
|
final completer = Completer<String>();
|
|
final sendPort =
|
|
singleCompletePort<String, List>(completer, callback: _handleErr);
|
|
native.get_dewif_pubkey(
|
|
sendPort.nativePort,
|
|
Utf8.toUtf8(currency),
|
|
Utf8.toUtf8(newDewif),
|
|
Utf8.toUtf8(newPin),
|
|
);
|
|
publicKey = await completer.future;
|
|
}
|
|
|
|
return Future.value(NewWallet._(newDewif, newPin, publicKey));
|
|
}
|
|
|
|
/// Generate a wallet from a mnemonic phrase.
|
|
///
|
|
/// If the mnemonic is not in English, you must indicate the language of
|
|
/// the mnemonic (necessary for the verification of its validity).
|
|
///
|
|
/// If the wallet to be generated is not dedicated to the Ğ1 currency, you
|
|
/// must indicate the currency for which this wallet will be used.
|
|
static Future<NewWallet> genWalletFromMnemonic(
|
|
{String currency = "g1",
|
|
Language language = Language.english,
|
|
String mnemonic,
|
|
PinLength pinLength = PinLength.six}) async {
|
|
// pin
|
|
String pin = await _genPin(pinLength);
|
|
// publicKey
|
|
String publicKey;
|
|
{
|
|
final completer = Completer<String>();
|
|
final sendPort =
|
|
singleCompletePort<String, List>(completer, callback: _handleErr);
|
|
native.mnemonic_to_pubkey(
|
|
sendPort.nativePort,
|
|
language.index,
|
|
Utf8.toUtf8(mnemonic),
|
|
);
|
|
publicKey = await completer.future;
|
|
}
|
|
// dewif
|
|
String dewif;
|
|
{
|
|
final completer = Completer<String>();
|
|
final sendPort =
|
|
singleCompletePort<String, List>(completer, callback: _handleErr);
|
|
native.gen_dewif(
|
|
sendPort.nativePort,
|
|
Utf8.toUtf8(currency),
|
|
language.index,
|
|
Utf8.toUtf8(mnemonic),
|
|
Utf8.toUtf8(pin),
|
|
);
|
|
dewif = await completer.future;
|
|
}
|
|
return Future.value(NewWallet._(dewif, pin, publicKey));
|
|
}
|
|
|
|
/// Get pulblic key (in base 58) of `dewif` keypair.
|
|
static Future<String> getDewifPublicKey(
|
|
{String currency = "g1", String dewif, String pin}) async {
|
|
final completer = Completer<String>();
|
|
final sendPort =
|
|
singleCompletePort<String, List>(completer, callback: _handleErr);
|
|
native.get_dewif_pubkey(
|
|
sendPort.nativePort,
|
|
Utf8.toUtf8(currency),
|
|
Utf8.toUtf8(dewif),
|
|
Utf8.toUtf8(pin),
|
|
);
|
|
return completer.future;
|
|
}
|
|
|
|
/// Sign the message `message` with `dewif` keypair encryted in DEWIF format.
|
|
///
|
|
/// If you have several messages to sign, use `signSeveral` method instead.
|
|
static Future<String> sign(
|
|
{String currency = "g1", String dewif, String pin, String message}) {
|
|
final completer = Completer<String>();
|
|
final sendPort =
|
|
singleCompletePort<String, List>(completer, callback: _handleErr);
|
|
native.sign(
|
|
sendPort.nativePort,
|
|
Utf8.toUtf8(currency),
|
|
Utf8.toUtf8(dewif),
|
|
Utf8.toUtf8(pin),
|
|
Utf8.toUtf8(message),
|
|
);
|
|
return completer.future;
|
|
}
|
|
|
|
/// Sign several messages `messages` with `dewif` keypair encryted in DEWIF
|
|
/// format.
|
|
///
|
|
/// This method is optimized to sign several messages at once. If you have
|
|
/// several messages to sign, avoid calling the `sign` method for each
|
|
/// message. Use this `signSeveral` method instead.
|
|
static Future<List<String>> signSeveral(
|
|
{String currency = "g1",
|
|
String dewif,
|
|
String pin,
|
|
List<String> messages}) {
|
|
final completer = Completer<List<String>>();
|
|
final sendPort = singleCompletePort<List<String>, List>(completer,
|
|
callback: _handleErrList);
|
|
|
|
native.sign_several(
|
|
sendPort.nativePort,
|
|
Utf8.toUtf8(currency),
|
|
Utf8.toUtf8(dewif),
|
|
Utf8.toUtf8(pin),
|
|
messages.length,
|
|
_listStringToPtr(messages),
|
|
);
|
|
|
|
return completer.future;
|
|
}
|
|
|
|
static Pointer<Pointer<Utf8>> _listStringToPtr(List<String> list) {
|
|
final listUtf8 = list.map(Utf8.toUtf8).toList();
|
|
final Pointer<Pointer<Utf8>> ptr = allocate(count: listUtf8.length);
|
|
for (var i = 0; i < listUtf8.length; i++) {
|
|
ptr[i] = listUtf8[i];
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
static String _handleErr(List res) {
|
|
final List<String> arr = res.cast();
|
|
if (arr.length == 1) {
|
|
return arr[0];
|
|
} else {
|
|
final error = arr[1];
|
|
print(error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
static List<String> _handleErrList(List res) {
|
|
final List<String> arr = res.cast();
|
|
if (arr.isNotEmpty && arr[0].isEmpty) {
|
|
final error = arr[1];
|
|
print(error);
|
|
throw error;
|
|
} else {
|
|
return arr;
|
|
}
|
|
}
|
|
}
|