parent
6b7045934a
commit
130e0b9642
|
@ -1,5 +1,4 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:warp_api/warp_api.dart';
|
||||
|
@ -60,7 +59,7 @@ class AccountManagerState extends State<AccountManagerPage> {
|
|||
itemCount: _accounts.list.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final a = _accounts.list[index];
|
||||
final weight = settings.coins[a.coin].active == a.id ? FontWeight.bold : FontWeight.normal;
|
||||
final weight = a.active ? FontWeight.bold : FontWeight.normal;
|
||||
final zbal = a.balance / ZECUNIT;
|
||||
final tbal = a.tbalance / ZECUNIT;
|
||||
final balance = zbal + tbal;
|
||||
|
@ -165,7 +164,6 @@ class AccountManagerState extends State<AccountManagerPage> {
|
|||
|
||||
_selectAccount(Account account) async {
|
||||
active.setActiveAccount(account.coin, account.id);
|
||||
active.refreshAccount();
|
||||
if (syncStatus.accountRestored) {
|
||||
syncStatus.setAccountRestored(false);
|
||||
final height = await rescanDialog(context);
|
||||
|
|
|
@ -6,9 +6,7 @@ import 'package:mobx/mobx.dart';
|
|||
import 'db.dart';
|
||||
import 'package:warp_api/warp_api.dart';
|
||||
|
||||
import 'backup.dart';
|
||||
import 'coin/coin.dart';
|
||||
import 'coin/zcash.dart';
|
||||
import 'main.dart';
|
||||
import 'store.dart';
|
||||
|
||||
|
@ -19,6 +17,7 @@ class Account {
|
|||
final int id;
|
||||
final String name;
|
||||
final int balance;
|
||||
bool active = false;
|
||||
int tbalance = 0;
|
||||
|
||||
Account(this.coin, this.id, this.name, this.balance, this.tbalance);
|
||||
|
@ -40,9 +39,14 @@ class AccountList {
|
|||
void refresh() {
|
||||
List<Account> _list = [];
|
||||
for (var coin in coins) {
|
||||
_list.addAll(WarpApi.getAccountList(coin.coin).map((a) => Account(
|
||||
coin.coin, a.id, a.name!, a.balance, 0)
|
||||
));
|
||||
var accounts = WarpApi.getAccountList(coin.coin).map((a) => Account(
|
||||
coin.coin, a.id, a.name!, a.balance, 0)
|
||||
).toList();
|
||||
final id = WarpApi.getActiveAccountId(coin.coin);
|
||||
if (id != 0) {
|
||||
accounts.firstWhere((a) => a.id == id).active = true;
|
||||
}
|
||||
_list.addAll(accounts);
|
||||
}
|
||||
list = _list;
|
||||
}
|
||||
|
@ -66,15 +70,6 @@ class AccountList {
|
|||
refresh();
|
||||
}
|
||||
|
||||
void saveActive(int coin, int id) {
|
||||
settings.coins[coin].active = id;
|
||||
Future.microtask(() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final def = settings.coins[coin].def;
|
||||
prefs.setInt("${def.ticker}.active", id);
|
||||
});
|
||||
}
|
||||
|
||||
Account get(int coin, int id) => list.firstWhere((e) => e.coin == coin && e.id == id, orElse: () => emptyAccount);
|
||||
}
|
||||
|
||||
|
@ -139,17 +134,16 @@ abstract class _ActiveAccount with Store {
|
|||
}
|
||||
else if (aid != active.toId()) {
|
||||
setActiveAccount(aid.coin, aid.id);
|
||||
refreshAccount();
|
||||
}
|
||||
}
|
||||
|
||||
AccountId? getAvailableId(AccountId aid) {
|
||||
final nid = getAvailableIdForCoin(aid.coin, aid.id);
|
||||
final nid = getActiveAccountId(aid.coin);
|
||||
if (nid.id != 0) return nid;
|
||||
for (var coin_data in settings.coins) {
|
||||
// look for an account in any other coin
|
||||
if (coin_data.coin != coin) {
|
||||
final nid = getAvailableIdForCoin(coin_data.coin, coin_data.active);
|
||||
final nid = getActiveAccountId(coin_data.coin);
|
||||
if (nid.id != 0)
|
||||
return nid;
|
||||
}
|
||||
|
@ -158,30 +152,27 @@ abstract class _ActiveAccount with Store {
|
|||
return null;
|
||||
}
|
||||
|
||||
// check that the account still exists
|
||||
// if not, pick any account
|
||||
// if there are none, return 0
|
||||
AccountId getAvailableIdForCoin(int coin, int id) {
|
||||
final newId = WarpApi.getAvailableAccountId(coin, id);
|
||||
return AccountId(coin, newId);
|
||||
AccountId getActiveAccountId(int coin) {
|
||||
final id = WarpApi.getActiveAccountId(coin);
|
||||
return AccountId(coin, id);
|
||||
}
|
||||
|
||||
@action
|
||||
void setActiveAccount(int _coin, int _id) {
|
||||
coin = _coin;
|
||||
id = _id;
|
||||
|
||||
void setActiveAccount(int coin, int id) {
|
||||
WarpApi.setActiveAccount(coin, id);
|
||||
Future.microtask(() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.setInt('coin', coin);
|
||||
prefs.setInt('account', id);
|
||||
});
|
||||
WarpApi.setActiveAccount(coin, id);
|
||||
if (coin != this.coin || id != this.id) {
|
||||
this.coin = coin;
|
||||
this.id = id;
|
||||
_refreshAccount();
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
void refreshAccount() {
|
||||
final dbr = DbReader(coin, id);
|
||||
void _refreshAccount() {
|
||||
coinDef = settings.coins[coin].def;
|
||||
|
||||
final accounts = AccountList();
|
||||
|
@ -221,7 +212,6 @@ abstract class _ActiveAccount with Store {
|
|||
|
||||
@action
|
||||
void updateBalances() {
|
||||
final dbr = DbReader(coin, id);
|
||||
final initialized = balances.initialized;
|
||||
final prevBalance = balances.balance;
|
||||
final b = WarpApi.getBalance(coin, id, syncStatus.confirmHeight);
|
||||
|
|
|
@ -85,12 +85,11 @@ StreamSubscription? subUniLinks;
|
|||
void handleUri(BuildContext context, Uri uri) {
|
||||
final scheme = uri.scheme;
|
||||
final coinDef = settings.coins.firstWhere((c) => c.def.currency == scheme);
|
||||
final id = settings.coins[coinDef.coin].active;
|
||||
if (id != 0) {
|
||||
active.setActiveAccount(coinDef.coin, id);
|
||||
Navigator.of(context).pushNamed(
|
||||
'/send', arguments: SendPageArgs(uri: uri.toString()));
|
||||
}
|
||||
final coin = coinDef.coin;
|
||||
final id = WarpApi.getActiveAccountId(coin);
|
||||
active.setActiveAccount(coin, id);
|
||||
Navigator.of(context).pushNamed(
|
||||
'/send', arguments: SendPageArgs(uri: uri.toString()));
|
||||
}
|
||||
|
||||
Future<void> initUniLinks(BuildContext context) async {
|
||||
|
@ -112,18 +111,15 @@ void handleQuickAction(BuildContext context, String type) {
|
|||
final t = type.split(".");
|
||||
final coin = int.parse(t[0]);
|
||||
final shortcut = t[1];
|
||||
final a = settings.coins[coin].active;
|
||||
|
||||
if (a != 0) {
|
||||
active.setActiveAccount(coin, a);
|
||||
switch (shortcut) {
|
||||
case 'receive':
|
||||
Navigator.of(context).pushNamed('/receive');
|
||||
break;
|
||||
case 'send':
|
||||
Navigator.of(context).pushNamed('/send');
|
||||
break;
|
||||
}
|
||||
final id = WarpApi.getActiveAccountId(coin);
|
||||
active.setActiveAccount(coin, id);
|
||||
switch (shortcut) {
|
||||
case 'receive':
|
||||
Navigator.of(context).pushNamed('/receive');
|
||||
break;
|
||||
case 'send':
|
||||
Navigator.of(context).pushNamed('/send');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,6 @@ class _AddAccountPageState extends State<AddAccountPage> {
|
|||
]));
|
||||
} else {
|
||||
active.setActiveAccount(_coin, account);
|
||||
active.refreshAccount();
|
||||
final nav = Navigator.of(context);
|
||||
if (_keyController.text != "") {
|
||||
syncStatus.setAccountRestored(true);
|
||||
|
|
|
@ -89,25 +89,18 @@ class SendState extends State<SendPage> {
|
|||
final recipients = widget.args?.recipients ?? [];
|
||||
_usedBalance = recipients.fold(0, (acc, r) => acc + r.amount);
|
||||
|
||||
_newBlockAutorunDispose = autorun((_) {
|
||||
syncStatus.latestHeight;
|
||||
setState(() {});
|
||||
});
|
||||
Future.microtask(syncStatus.update);
|
||||
|
||||
final uri = widget.args?.uri;
|
||||
if (uri != null)
|
||||
Future.microtask(() {
|
||||
_setPaymentURI(uri);
|
||||
});
|
||||
|
||||
active.updateBalances();
|
||||
final balances = active.balances;
|
||||
final sBalance = balances.shieldedBalance;
|
||||
final tBalance = active.tbalance;
|
||||
final excludedBalance = balances.excludedBalance;
|
||||
final underConfirmedBalance = balances.underConfirmedBalance;
|
||||
int? unconfirmedBalance = unconfirmedBalanceStream.value;
|
||||
_sBalance = sBalance;
|
||||
_tBalance = tBalance;
|
||||
_excludedBalance = excludedBalance;
|
||||
_underConfirmedBalance = underConfirmedBalance;
|
||||
_unconfirmedBalance = unconfirmedBalance ?? 0;
|
||||
|
||||
final templateIds = active.dbReader.loadTemplates();
|
||||
_templates = templateIds;
|
||||
}
|
||||
|
@ -139,8 +132,20 @@ class SendState extends State<SendPage> {
|
|||
_memoInitialized = true;
|
||||
}
|
||||
|
||||
var templates = _templates.map((t) => DropdownMenuItem(child: Text(t.title!), value: t)).toList();
|
||||
active.updateBalances();
|
||||
final balances = active.balances;
|
||||
final sBalance = balances.shieldedBalance;
|
||||
final tBalance = active.tbalance;
|
||||
final excludedBalance = balances.excludedBalance;
|
||||
final underConfirmedBalance = balances.underConfirmedBalance;
|
||||
int? unconfirmedBalance = unconfirmedBalanceStream.value;
|
||||
_sBalance = sBalance;
|
||||
_tBalance = tBalance;
|
||||
_excludedBalance = excludedBalance;
|
||||
_underConfirmedBalance = underConfirmedBalance;
|
||||
_unconfirmedBalance = unconfirmedBalance ?? 0;
|
||||
|
||||
var templates = _templates.map((t) => DropdownMenuItem(child: Text(t.title!), value: t)).toList();
|
||||
final addReset = _template != null ? IconButton(onPressed: _resetTemplate, icon: Icon(Icons.close)) : IconButton(onPressed: _addTemplate, icon: Icon(Icons.add));
|
||||
|
||||
return Scaffold(
|
||||
|
|
|
@ -97,7 +97,6 @@ class CoinData = _CoinData with _$CoinData;
|
|||
|
||||
abstract class _CoinData with Store {
|
||||
final int coin;
|
||||
int active = 0;
|
||||
int syncedHeight = 0;
|
||||
final CoinBase def;
|
||||
@observable bool contactsSaved = true;
|
||||
|
@ -269,7 +268,6 @@ abstract class _Settings with Store {
|
|||
|
||||
for (var c in coins) {
|
||||
final ticker = c.def.ticker;
|
||||
c.active = prefs.getInt("$ticker.active") ?? 0;
|
||||
c.contactsSaved = prefs.getBool("$ticker.contacts_saved") ?? true;
|
||||
}
|
||||
|
||||
|
@ -1119,12 +1117,15 @@ class DecodedPaymentURI {
|
|||
}
|
||||
|
||||
class SendPageArgs {
|
||||
final bool isMulti;
|
||||
final ContactT? contact;
|
||||
final String? address;
|
||||
final String? subject;
|
||||
final String? uri;
|
||||
final List<Recipient> recipients;
|
||||
final bool isMulti; // use multi ...
|
||||
final List<Recipient> recipients; // recipients
|
||||
|
||||
final ContactT? contact; // send to contact
|
||||
|
||||
final String? address; // reply to ...
|
||||
final String? subject; // message
|
||||
|
||||
final String? uri; // send to payment URI
|
||||
|
||||
SendPageArgs({this.isMulti = false, this.contact, this.address, this.subject, this.uri, this.recipients = const[]});
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 43c348408b3f673be66863f92e61597e552cd8ce
|
||||
Subproject commit b9726bf29323140f07732ea664fdc1f3447048d7
|
|
@ -426,8 +426,12 @@ class WarpApi {
|
|||
return AccountVec(r).accounts!;
|
||||
}
|
||||
|
||||
static int getAvailableAccountId(int coin, int id) {
|
||||
return unwrapResultU32(warp_api_lib.get_available_account_id(coin, id));
|
||||
static int getActiveAccountId(int coin) {
|
||||
return unwrapResultU32(warp_api_lib.get_active_account(coin));
|
||||
}
|
||||
|
||||
static void setActiveAccountId(int coin, int id) {
|
||||
unwrapResultU8(warp_api_lib.set_active_account(coin, id));
|
||||
}
|
||||
|
||||
static String getTAddr(int coin, int id) {
|
||||
|
|
|
@ -124,21 +124,6 @@ class NativeLibrary {
|
|||
late final _dart_set_active _set_active =
|
||||
_set_active_ptr.asFunction<_dart_set_active>();
|
||||
|
||||
void set_active_account(
|
||||
int coin,
|
||||
int id,
|
||||
) {
|
||||
return _set_active_account(
|
||||
coin,
|
||||
id,
|
||||
);
|
||||
}
|
||||
|
||||
late final _set_active_account_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_set_active_account>>('set_active_account');
|
||||
late final _dart_set_active_account _set_active_account =
|
||||
_set_active_account_ptr.asFunction<_dart_set_active_account>();
|
||||
|
||||
void set_coin_lwd_url(
|
||||
int coin,
|
||||
ffi.Pointer<ffi.Int8> lwd_url,
|
||||
|
@ -920,22 +905,33 @@ class NativeLibrary {
|
|||
late final _dart_get_account_list _get_account_list =
|
||||
_get_account_list_ptr.asFunction<_dart_get_account_list>();
|
||||
|
||||
CResult_u32 get_available_account_id(
|
||||
CResult_u32 get_active_account(
|
||||
int coin,
|
||||
) {
|
||||
return _get_active_account(
|
||||
coin,
|
||||
);
|
||||
}
|
||||
|
||||
late final _get_active_account_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_get_active_account>>('get_active_account');
|
||||
late final _dart_get_active_account _get_active_account =
|
||||
_get_active_account_ptr.asFunction<_dart_get_active_account>();
|
||||
|
||||
CResult_u8 set_active_account(
|
||||
int coin,
|
||||
int id,
|
||||
) {
|
||||
return _get_available_account_id(
|
||||
return _set_active_account(
|
||||
coin,
|
||||
id,
|
||||
);
|
||||
}
|
||||
|
||||
late final _get_available_account_id_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_get_available_account_id>>(
|
||||
'get_available_account_id');
|
||||
late final _dart_get_available_account_id _get_available_account_id =
|
||||
_get_available_account_id_ptr
|
||||
.asFunction<_dart_get_available_account_id>();
|
||||
late final _set_active_account_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_set_active_account>>('set_active_account');
|
||||
late final _dart_set_active_account _set_active_account =
|
||||
_set_active_account_ptr.asFunction<_dart_set_active_account>();
|
||||
|
||||
CResult_____c_char get_t_addr(
|
||||
int coin,
|
||||
|
@ -1462,16 +1458,6 @@ typedef _dart_set_active = void Function(
|
|||
int active,
|
||||
);
|
||||
|
||||
typedef _c_set_active_account = ffi.Void Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 id,
|
||||
);
|
||||
|
||||
typedef _dart_set_active_account = void Function(
|
||||
int coin,
|
||||
int id,
|
||||
);
|
||||
|
||||
typedef _c_set_coin_lwd_url = ffi.Void Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Pointer<ffi.Int8> lwd_url,
|
||||
|
@ -1984,12 +1970,20 @@ typedef _dart_get_account_list = CResult______u8 Function(
|
|||
int coin,
|
||||
);
|
||||
|
||||
typedef _c_get_available_account_id = CResult_u32 Function(
|
||||
typedef _c_get_active_account = CResult_u32 Function(
|
||||
ffi.Uint8 coin,
|
||||
);
|
||||
|
||||
typedef _dart_get_active_account = CResult_u32 Function(
|
||||
int coin,
|
||||
);
|
||||
|
||||
typedef _c_set_active_account = CResult_u8 Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 id,
|
||||
);
|
||||
|
||||
typedef _dart_get_available_account_id = CResult_u32 Function(
|
||||
typedef _dart_set_active_account = CResult_u8 Function(
|
||||
int coin,
|
||||
int id,
|
||||
);
|
||||
|
|
13
pubspec.lock
13
pubspec.lock
|
@ -1085,21 +1085,14 @@ packages:
|
|||
name: sensors_plus
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "2.0.1"
|
||||
sensors_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sensors_plus_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
sensors_plus_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sensors_plus_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.3"
|
||||
share_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1464,4 +1457,4 @@ packages:
|
|||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=2.18.0 <3.0.0"
|
||||
flutter: ">=2.10.0"
|
||||
flutter: ">=2.11.0"
|
||||
|
|
|
@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.2.17+344
|
||||
version: 1.2.17+345
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
@ -64,7 +64,7 @@ dependencies:
|
|||
ref: c2c79def4f7fa8c17e9432ca43d307ba0b4a75a3
|
||||
flutter_speed_dial: ^5.0.0
|
||||
currency_text_input_formatter: ^2.1.2
|
||||
sensors_plus: ^1.1.0
|
||||
sensors_plus: ^2.0.0
|
||||
connectivity_plus: ^2.2.1
|
||||
uni_links: ^0.5.1
|
||||
quick_actions: ^0.6.0
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
# Send YEC & ZEC
|
||||
- Address: Contact, account, address or QR code
|
||||
- Amount in coin & fiat
|
||||
- Max button
|
||||
- Slider
|
||||
- Checkbox "include fee"
|
||||
- Memo
|
||||
- Subject
|
||||
- Body
|
||||
- Reply-To
|
||||
- Send Templates
|
||||
|
||||
# Execution Plan
|
||||
- t2t, t2z, z2t, z2z
|
||||
|
||||
# Receive
|
||||
- Payment URI
|
||||
- T, Z, O address types
|
||||
- Amount & Memo
|
||||
- Diversified Address
|
||||
- Copy address to clipboard
|
||||
|
||||
# Transparent Account
|
||||
- Override derivation path
|
||||
- Shield
|
||||
|
||||
# Synchronization
|
||||
- Recan by date & height
|
||||
|
||||
# Accounts
|
||||
- New, Edit, Delete
|
||||
- Select default
|
||||
- Import seed phrase, sk, vk
|
||||
|
||||
# Backup
|
||||
- Backup data
|
||||
- Save/Load full backup
|
||||
- Convert to Watchonly
|
||||
|
||||
# Contacts
|
||||
- New, Edit, Delete
|
||||
- Save to Blockchain
|
||||
|
||||
# Settings
|
||||
- Fiat currency
|
||||
- number of confirmations
|
||||
|
||||
# Desktop integrations
|
||||
- Send/Receive
|
||||
- QR code reader
|
||||
|
||||
# Cold Wallet
|
||||
- by QR
|
||||
- by File
|
||||
- Broadcast
|
||||
|
||||
# Derivation Tool
|
||||
|
Loading…
Reference in New Issue