Upgrade flutter to 3.3.8
This commit is contained in:
parent
9bd67de366
commit
5a0dc762fd
|
@ -9,5 +9,14 @@ debug = false
|
|||
[patch."https://github.com/hhanh00/zcash-params.git"]
|
||||
zcash_params = { path = "native/zcash-params" }
|
||||
|
||||
[patch."https://github.com/hhanh00/librustzcash.git"]
|
||||
zcash_client_backend = { path = "librustzcash/zcash_client_backend" }
|
||||
zcash_primitives = { path = "librustzcash/zcash_primitives" }
|
||||
zcash_proofs = { path = "librustzcash/zcash_proofs" }
|
||||
zcash_address = { path = "librustzcash/components/zcash_address" }
|
||||
zcash_encoding = { path = "librustzcash/components/zcash_encoding" }
|
||||
zcash_note_encryption = { path = "librustzcash/components/zcash_note_encryption" }
|
||||
|
||||
[patch.crates-io]
|
||||
jubjub = { git = "https://github.com/hhanh00/jubjub.git", rev = "4a3edf3d242f368b5aa418ec659d01f191127cf3" }
|
||||
zcash_note_encryption = { path = "librustzcash/components/zcash_note_encryption" }
|
||||
|
|
|
@ -288,7 +288,7 @@ class QRAddressState extends State<QRAddressWidget> {
|
|||
? active.taddress
|
||||
: _useSnapAddress
|
||||
? _snapAddress
|
||||
: active.account.address;
|
||||
: active.address;
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,15 +17,18 @@ class Account {
|
|||
final int coin;
|
||||
final int id;
|
||||
final String name;
|
||||
final String address;
|
||||
final int balance;
|
||||
int tbalance = 0;
|
||||
final ShareInfo? share;
|
||||
|
||||
Account(this.coin, this.id, this.name, this.address, this.balance, this.tbalance, this.share);
|
||||
Account(this.coin, this.id, this.name, this.balance, this.tbalance, this.share);
|
||||
|
||||
String get address {
|
||||
return WarpApi.getAddress(this.coin, this.id, settings.uaType);
|
||||
}
|
||||
}
|
||||
|
||||
final Account emptyAccount = Account(0, 0, "", "", 0, 0, null);
|
||||
final Account emptyAccount = Account(0, 0, "", 0, 0, null);
|
||||
|
||||
class AccountManager2 = _AccountManager2 with _$AccountManager2;
|
||||
|
||||
|
@ -94,21 +97,16 @@ abstract class _AccountManager2 with Store {
|
|||
List<Account> accounts = [];
|
||||
|
||||
final List<Map> res = await db.rawQuery(
|
||||
"WITH notes AS (SELECT a.id_account, a.name, a.address, CASE WHEN r.spent IS NULL THEN r.value ELSE 0 END AS nv FROM accounts a LEFT JOIN received_notes r ON a.id_account = r.account),"
|
||||
"accounts2 AS (SELECT id_account, name, address, COALESCE(sum(nv), 0) AS balance FROM notes GROUP by id_account) "
|
||||
"SELECT a.id_account, a.name, a.address, a.balance FROM accounts2 a",
|
||||
"WITH notes AS (SELECT a.id_account, a.name, CASE WHEN r.spent IS NULL THEN r.value ELSE 0 END AS nv FROM accounts a LEFT JOIN received_notes r ON a.id_account = r.account),"
|
||||
"accounts2 AS (SELECT id_account, name, COALESCE(sum(nv), 0) AS balance FROM notes GROUP by id_account) "
|
||||
"SELECT a.id_account, a.name, a.balance FROM accounts2 a",
|
||||
[]);
|
||||
for (var r in res) {
|
||||
final int id = r['id_account'];
|
||||
// final shareInfo = r['secret'] != null
|
||||
// ? ShareInfo(
|
||||
// r['idx'], r['threshold'], r['participants'], r['secret'])
|
||||
// : null; // TODO: Multisig
|
||||
final account = Account(
|
||||
coin,
|
||||
id,
|
||||
r['name'],
|
||||
r['address'],
|
||||
r['balance'],
|
||||
0,
|
||||
null);
|
||||
|
@ -316,7 +314,7 @@ abstract class _ActiveAccount with Store {
|
|||
final dbr = DbReader(coin, id);
|
||||
notes = await dbr.getNotes();
|
||||
txs = await dbr.getTxs();
|
||||
messages = ObservableList.of(await dbr.getMessages(account.address));
|
||||
messages = ObservableList.of(await dbr.getMessages());
|
||||
unread = messages.where((m) => !m.read).length;
|
||||
dataEpoch += 1;
|
||||
}
|
||||
|
@ -474,6 +472,10 @@ abstract class _ActiveAccount with Store {
|
|||
void setBanner(String msg) {
|
||||
banner = msg;
|
||||
}
|
||||
|
||||
String get address { // TODO
|
||||
return account.address;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Backup> getBackup(AccountId account) async {
|
||||
|
|
|
@ -33,7 +33,7 @@ class DbReader {
|
|||
"SELECT SUM(value) AS value FROM received_notes WHERE account = ?1 AND spent = 0",
|
||||
[id])) ?? 0;
|
||||
final underConfirmedBalance = Sqflite.firstIntValue(await db.rawQuery(
|
||||
"SELECT SUM(value) AS value FROM received_notes WHERE account = ?1 AND height > ?2",
|
||||
"SELECT SUM(value) AS value FROM received_notes WHERE account = ?1 AND spent IS NULL AND height > ?2",
|
||||
[id, confirmHeight])) ?? 0;
|
||||
final excludedBalance = Sqflite.firstIntValue(await db.rawQuery(
|
||||
"SELECT SUM(value) FROM received_notes WHERE account = ?1 AND spent IS NULL "
|
||||
|
@ -198,7 +198,7 @@ class DbReader {
|
|||
return accountBalances;
|
||||
}
|
||||
|
||||
Future<List<ZMessage>> getMessages(String myAddress) async {
|
||||
Future<List<ZMessage>> getMessages() async {
|
||||
final List<Map> res = await db.rawQuery(
|
||||
"SELECT m.id, m.id_tx, m.timestamp, m.sender, m.recipient, c.name as scontact, a.name as saccount, c2.name as rcontact, a2.name as raccount, "
|
||||
"subject, body, height, read FROM messages m "
|
||||
|
@ -221,7 +221,7 @@ class DbReader {
|
|||
final subject = row['subject'];
|
||||
final body = row['body'];
|
||||
final read = row['read'] == 1;
|
||||
final incoming = recipient == myAddress;
|
||||
final incoming = false; // TODO: How do we know the message direction when using UA?
|
||||
messages.add(ZMessage(id, txId, incoming, from, to, subject, body, timestamp, height, read));
|
||||
}
|
||||
return messages;
|
||||
|
|
|
@ -29,6 +29,7 @@ class DevPageState extends State<DevPage> {
|
|||
children: [
|
||||
ListTile(title: Text('Import Database'), trailing: Icon(Icons.chevron_right), onTap: _importDb),
|
||||
ListTile(title: Text('Export Database'), trailing: Icon(Icons.chevron_right), onTap: _exportDb),
|
||||
ListTile(title: Text('Sync Stats'), trailing: Icon(Icons.chevron_right), onTap: _syncStats),
|
||||
ListTile(title: Text('Import Sync Data'), trailing: Icon(Icons.chevron_right), onTap: _importSyncData),
|
||||
ListTile(title: Text('Reset Scan State'), trailing: Icon(Icons.chevron_right), onTap: _resetScan),
|
||||
ListTile(title: Text('Reset App'), trailing: Icon(Icons.chevron_right), onTap: _resetApp),
|
||||
|
@ -74,6 +75,10 @@ class DevPageState extends State<DevPage> {
|
|||
}
|
||||
}
|
||||
|
||||
void _syncStats() {
|
||||
Navigator.of(context).pushNamed('/syncstats');
|
||||
}
|
||||
|
||||
Future<void> _importSyncData() async {
|
||||
final s = S.of(context);
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ class HomeState extends State<HomePage> {
|
|||
FlutterForegroundTask.updateService(
|
||||
notificationText: "${progress} %");
|
||||
}
|
||||
syncStats.add(DateTime.now(), syncedHeight.height);
|
||||
} else {
|
||||
WarpApi.mempoolReset();
|
||||
}
|
||||
|
@ -181,6 +182,7 @@ class HomeInnerState extends State<HomeInnerPage> with SingleTickerProviderState
|
|||
final menu = PopupMenuButton<String>(
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem(child: Text('TxPlan'), value: "TxPlan"),
|
||||
PopupMenuItem(child: Text(s.accounts), value: "Accounts"),
|
||||
PopupMenuItem(child: Text(s.backup), value: "Backup"),
|
||||
PopupMenuItem(child: Text(rescanMsg), value: "Rescan"),
|
||||
|
@ -254,6 +256,9 @@ class HomeInnerState extends State<HomeInnerPage> with SingleTickerProviderState
|
|||
|
||||
_onMenu(String choice) {
|
||||
switch (choice) {
|
||||
case "TxPlan":
|
||||
Navigator.of(context).pushNamed('/txplan', arguments: "");
|
||||
break;
|
||||
case "Accounts":
|
||||
Navigator.of(context).pushNamed('/accounts');
|
||||
break;
|
||||
|
|
|
@ -55,6 +55,8 @@ import 'sign.dart';
|
|||
import 'store.dart';
|
||||
import 'theme_editor.dart';
|
||||
import 'transaction.dart';
|
||||
import 'sync_chart.dart';
|
||||
import 'txplan.dart';
|
||||
import 'welcome.dart';
|
||||
|
||||
const ZECUNIT = 100000000.0;
|
||||
|
@ -76,6 +78,7 @@ var settings = Settings();
|
|||
var multipayData = MultiPayStore();
|
||||
var eta = ETAStore();
|
||||
var contacts = ContactStore();
|
||||
var syncStats = SyncStatsStore();
|
||||
var accounts = AccountManager2();
|
||||
var active = ActiveAccount();
|
||||
final messageKey = GlobalKey<MessageTableState>();
|
||||
|
@ -268,6 +271,8 @@ void main() {
|
|||
'/sign': (context) => Sign.init(routeSettings.arguments as String),
|
||||
'/keytool': (context) => KeyToolPage(),
|
||||
'/dev': (context) => DevPage(),
|
||||
'/txplan': (context) => TxPlanPage.fromPlan(routeSettings.arguments as String),
|
||||
'/syncstats': (context) => SyncChartPage(),
|
||||
};
|
||||
return MaterialPageRoute(builder: routes[routeSettings.name]!);
|
||||
},
|
||||
|
@ -788,7 +793,7 @@ Future<void> shieldTAddr(BuildContext context) async {
|
|||
final s = S.of(context);
|
||||
Navigator.of(context).pop();
|
||||
showSnackBar(s.shieldingInProgress, autoClose: true);
|
||||
final txid = await WarpApi.shieldTAddr();
|
||||
final txid = await WarpApi.shieldTAddr(active.coin, active.id);
|
||||
showSnackBar(s.txId(txid));
|
||||
})),
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@ import 'settings.dart';
|
|||
class PaymentURIPage extends StatefulWidget {
|
||||
final String address;
|
||||
|
||||
PaymentURIPage(String? _address): address = _address ?? active.account.address;
|
||||
PaymentURIPage(String? _address): address = _address ?? active.address;
|
||||
|
||||
@override
|
||||
PaymentURIState createState() => PaymentURIState();
|
||||
|
|
|
@ -497,16 +497,12 @@ Future<void> send(BuildContext context, List<Recipient> recipients, bool useTran
|
|||
needClose = false;
|
||||
Navigator.of(context).pop();
|
||||
active.setBanner(s.paymentInProgress);
|
||||
final txId = await WarpApi.sendPayment(active.coin, active.id, recipients,
|
||||
useTransparent, settings.anchorOffset, (progress) {
|
||||
progressPort.sendPort.send(progress);
|
||||
});
|
||||
progressPort.sendPort.send(0);
|
||||
await player.play(AssetSource("success.mp3"));
|
||||
showSnackBar(s.txId(txId));
|
||||
final txPlan = await WarpApi.prepareTx(active.coin, active.id, recipients,
|
||||
useTransparent, settings.anchorOffset);
|
||||
Navigator.pushNamed(context, '/txplan', arguments: txPlan);
|
||||
await active.update();
|
||||
} else {
|
||||
final txjson = WarpApi.prepareTx(
|
||||
final txjson = WarpApi.prepareTx(active.coin, active.id,
|
||||
recipients, useTransparent, settings.anchorOffset);
|
||||
|
||||
if (settings.qrOffline) {
|
||||
|
|
|
@ -43,6 +43,12 @@ class SettingsState extends State<SettingsPage>
|
|||
final simpleMode = settings.simpleMode;
|
||||
_memoController.text = settings.memoSignature ?? s.sendFrom(APP_NAME);
|
||||
|
||||
final uaType = settings.uaType;
|
||||
List<String> uaList = [];
|
||||
if (uaType & 1 != 0) uaList.add('T');
|
||||
if (uaType & 2 != 0) uaList.add('S');
|
||||
if (uaType & 4 != 0) uaList.add('O');
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(s.settings)),
|
||||
body: Padding(
|
||||
|
@ -78,14 +84,6 @@ class SettingsState extends State<SettingsPage>
|
|||
ServerSelect(0),
|
||||
ServerSelect(1)
|
||||
])),
|
||||
// if (!simpleMode) FormBuilderRadioGroup(
|
||||
// orientation: OptionsOrientation.vertical,
|
||||
// name: 'servers',
|
||||
// decoration: InputDecoration(
|
||||
// labelText: s.server),
|
||||
// initialValue: settings.ldUrlChoice,
|
||||
// onSaved: _onChoice,
|
||||
// options: options),
|
||||
FormBuilderRadioGroup(
|
||||
orientation: OptionsOrientation.horizontal,
|
||||
name: 'themes',
|
||||
|
@ -165,6 +163,7 @@ class SettingsState extends State<SettingsPage>
|
|||
// initialValue: settings.useUA,
|
||||
// onSaved: _onUseUA)),
|
||||
]),
|
||||
|
||||
if (!simpleMode)
|
||||
FormBuilderTextField(
|
||||
decoration: InputDecoration(
|
||||
|
@ -192,6 +191,19 @@ class SettingsState extends State<SettingsPage>
|
|||
FormBuilderFieldOption(
|
||||
child: Text(s.Y1), value: '1Y'),
|
||||
]),
|
||||
if (!simpleMode) // TODO: Only Enable for UA accounts
|
||||
FormBuilderCheckboxGroup<String>(
|
||||
orientation: OptionsOrientation.horizontal,
|
||||
name: 'ua',
|
||||
decoration: InputDecoration(labelText: 'Main Address Type'),
|
||||
initialValue: uaList,
|
||||
onSaved: _onUAType,
|
||||
validator: _checkUA,
|
||||
options: [
|
||||
FormBuilderFieldOption(value: 'T'),
|
||||
FormBuilderFieldOption(value: 'S'),
|
||||
FormBuilderFieldOption(value: 'O'),
|
||||
]),
|
||||
if (!simpleMode)
|
||||
FormBuilderCheckbox(
|
||||
name: 'get_tx',
|
||||
|
@ -343,10 +355,33 @@ class SettingsState extends State<SettingsPage>
|
|||
settings.setAutoShieldThreshold(v);
|
||||
}
|
||||
|
||||
_onUseUA(v) {
|
||||
settings.setUseUA(v);
|
||||
_onUAType(List<String>? vs) {
|
||||
if (vs == null) return;
|
||||
final type = _unpackUAType(vs);
|
||||
settings.setUAType(type);
|
||||
}
|
||||
|
||||
String? _checkUA(List<String>? vs) {
|
||||
if (vs == null) return null;
|
||||
final type = _unpackUAType(vs);
|
||||
if (type < 2) return "Invalid Address Type";
|
||||
return null;
|
||||
}
|
||||
|
||||
int _unpackUAType(List<String> vs) {
|
||||
int r = 0;
|
||||
for (var v in vs) {
|
||||
switch (v) {
|
||||
case 'T': r |= 1; break;
|
||||
case 'S': r |= 2; break;
|
||||
case 'O': r |= 4; break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
_onAutoHide(v) {
|
||||
settings.setAutoHide(v);
|
||||
}
|
||||
|
|
|
@ -206,6 +206,9 @@ abstract class _Settings with Store {
|
|||
|
||||
bool instantSync = false;
|
||||
|
||||
@observable
|
||||
int uaType = 7;
|
||||
|
||||
@observable
|
||||
int developerMode = 10;
|
||||
|
||||
|
@ -250,6 +253,8 @@ abstract class _Settings with Store {
|
|||
final _developerMode = prefs.getBool('developer_mode') ?? false;
|
||||
developerMode = _developerMode ? 0 : 10;
|
||||
|
||||
uaType = prefs.getInt('ua_type') ?? 7;
|
||||
|
||||
for (var s in servers) {
|
||||
await s.loadPrefs();
|
||||
}
|
||||
|
@ -551,6 +556,13 @@ abstract class _Settings with Store {
|
|||
prefs.setString('memo_signature', v);
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> setUAType(int v) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
uaType = v;
|
||||
prefs.setInt('ua_type', v);
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> tapDeveloperMode(BuildContext context) async {
|
||||
developerMode -= 1;
|
||||
|
@ -933,6 +945,23 @@ abstract class _ContactStore with Store {
|
|||
}
|
||||
}
|
||||
|
||||
class SyncStatsStore = _SyncStatsStore with _$SyncStatsStore;
|
||||
|
||||
abstract class _SyncStatsStore with Store {
|
||||
@observable
|
||||
ObservableList<SyncDatum> syncData = ObservableList<SyncDatum>.of([]);
|
||||
|
||||
@action
|
||||
void reset() {
|
||||
syncData = ObservableList<SyncDatum>.of([]);
|
||||
}
|
||||
|
||||
@action
|
||||
void add(DateTime now, int height) {
|
||||
syncData.add(SyncDatum(now, height));
|
||||
}
|
||||
}
|
||||
|
||||
class ETACheckpoint {
|
||||
int height;
|
||||
DateTime timestamp;
|
||||
|
@ -1154,4 +1183,11 @@ class BlockInfo {
|
|||
final int height;
|
||||
final DateTime timestamp;
|
||||
BlockInfo(this.height, this.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
class SyncDatum {
|
||||
final DateTime timestamp; // elapsed time in secs
|
||||
final int height; // block time stamp
|
||||
|
||||
SyncDatum(this.timestamp, this.height);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
import 'package:YWallet/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:k_chart/k_chart_widget.dart';
|
||||
import 'package:k_chart/flutter_k_chart.dart';
|
||||
|
||||
class SyncChartPage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => SyncChartState();
|
||||
}
|
||||
|
||||
class SyncChartState extends State<SyncChartPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Sync Stats')),
|
||||
body: Column(children: [
|
||||
Expanded(child: Observer(builder: (context) {
|
||||
final syncData = syncStats.syncData;
|
||||
List<KLineEntity> datas = syncData.map((datum) {
|
||||
final h = datum.height.toDouble();
|
||||
return KLineEntity.fromCustom(
|
||||
time: datum.timestamp.millisecondsSinceEpoch,
|
||||
open: h,
|
||||
close: h,
|
||||
high: h,
|
||||
low: h,
|
||||
amount: 0,
|
||||
vol: 0);
|
||||
}).toList();
|
||||
return KChartWidget(
|
||||
datas,
|
||||
ChartStyle(),
|
||||
ChartColors(context: context),
|
||||
isLine: true,
|
||||
volHidden: true,
|
||||
showInfoDialog: true,
|
||||
mainState: MainState.MA,
|
||||
secondaryState: SecondaryState.NONE,
|
||||
);
|
||||
})),
|
||||
ButtonBar(children: [
|
||||
ElevatedButton.icon(
|
||||
onPressed: _refresh,
|
||||
label: Text('Reset'),
|
||||
icon: Icon(Icons.restart_alt)),
|
||||
ElevatedButton.icon(
|
||||
onPressed: _export,
|
||||
label: Text('Export'),
|
||||
icon: Icon(Icons.save))
|
||||
])
|
||||
]));
|
||||
}
|
||||
|
||||
_refresh() {
|
||||
syncStats.reset();
|
||||
}
|
||||
|
||||
_export() async {
|
||||
final csvData = syncStats.syncData.map((data) => [
|
||||
data.timestamp,
|
||||
data.height]).toList();
|
||||
await shareCsv(csvData, 'sync_status.csv', 'Sync Status Data');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:YWallet/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:warp_api/types.dart';
|
||||
import 'package:warp_api/warp_api.dart';
|
||||
|
||||
class TxPlanPage extends StatelessWidget {
|
||||
final String plan;
|
||||
final TxReport report;
|
||||
|
||||
TxPlanPage(this.plan, this.report);
|
||||
|
||||
factory TxPlanPage.fromPlan(String plan) {
|
||||
// final reportStr =
|
||||
// r'{"outputs":[{"id":0,"address":"zregtestsapling1qzy9wafd2axnenul6t6wav76dys6s8uatsq778mpmdvmx4k9myqxsd9m73aqdgc7gwnv53wga4j","amount":500000000,"pool":1}],"transparent":0,"sapling":500010000,"orchard":0,"net_sapling":-10000,"net_orchard":0,"fee":10000,"privacy_level":3}';
|
||||
final reportStr = WarpApi.transactionReport(active.coin, plan);
|
||||
print(reportStr);
|
||||
final json = jsonDecode(reportStr);
|
||||
final report = TxReport.fromJson(json);
|
||||
return TxPlanPage(plan, report);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final rows = report.outputs
|
||||
.map((e) => DataRow(cells: [
|
||||
DataCell(Text('...${trailing(e.address, 12)}')),
|
||||
DataCell(Text('${poolToString(e.pool)}')),
|
||||
DataCell(Text('${amountToString(e.amount, 3)}')),
|
||||
]))
|
||||
.toList();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Transaction Plan')),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: SingleChildScrollView(child: Wrap(
|
||||
direction: Axis.vertical,
|
||||
spacing: 20,
|
||||
runSpacing: 20,
|
||||
children: [
|
||||
DataTable(columns: [
|
||||
DataColumn(label: Text('Address')),
|
||||
DataColumn(label: Text('Pool')),
|
||||
DataColumn(label: Expanded(child: Text('Amount'))),
|
||||
], rows: rows),
|
||||
Text(
|
||||
'Transparent Input: ${amountToString(report.transparent, MAX_PRECISION)}'),
|
||||
Text(
|
||||
'Sapling Input: ${amountToString(report.sapling, MAX_PRECISION)}'),
|
||||
Text(
|
||||
'Orchard Input: ${amountToString(report.orchard, MAX_PRECISION)}'),
|
||||
Text(
|
||||
'Net Sapling Change: ${amountToString(report.net_sapling, MAX_PRECISION)}'),
|
||||
Text(
|
||||
'Net Orchard Change: ${amountToString(report.net_orchard, MAX_PRECISION)}'),
|
||||
Text('Fee: ${amountToString(report.fee, MAX_PRECISION)}'),
|
||||
privacyToString(report.privacy_level, theme.textTheme.titleSmall!)!,
|
||||
ButtonBar(children: confirmButtons(context, _onSend, okLabel: 'Send')),
|
||||
]))));
|
||||
}
|
||||
|
||||
_onSend() {
|
||||
final txid = WarpApi.signAndBroadcast(active.coin, active.id, this.plan);
|
||||
showSnackBar("TxID: $txid");
|
||||
navigatorKey.currentState?.pop();
|
||||
}
|
||||
}
|
||||
|
||||
String poolToString(int pool) {
|
||||
switch (pool) {
|
||||
case 0:
|
||||
return "Transparent";
|
||||
case 1:
|
||||
return "Sapling";
|
||||
}
|
||||
return "Orchard";
|
||||
}
|
||||
|
||||
Widget? privacyToString(int privacyLevel, TextStyle baseStyle) {
|
||||
switch (privacyLevel) {
|
||||
case 0: return Text("PRIVACY: VERY LOW", style: baseStyle.copyWith(color: Colors.red));
|
||||
case 1: return Text("PRIVACY: LOW", style: baseStyle.copyWith(color: Colors.orange));
|
||||
case 2: return Text("PRIVACY: MEDIUM", style: baseStyle.copyWith(color: Colors.yellow));
|
||||
case 3: return Text("PRIVACY: HIGH", style: baseStyle.copyWith(color: Colors.green));
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
id: me.hanh.zwallet.Ywallet
|
||||
runtime: org.freedesktop.Platform
|
||||
runtime-version: "22.08"
|
||||
platform-extensions:
|
||||
- org.freedesktop.Platform.GL.nvidia
|
||||
sdk: org.freedesktop.Sdk
|
||||
command: ywallet
|
||||
finish-args:
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 0f1975b0d8799d852fe62e717dad8885eec1f106
|
||||
Subproject commit 849107a56e83f150c86405df733bf87ae589811d
|
|
@ -1 +1 @@
|
|||
Subproject commit cb3904577a1e2d69112af256c603ce604bb43e18
|
||||
Subproject commit 25a2e28e7416a521ce02f606e0a930fb84422326
|
|
@ -87,3 +87,41 @@ class Progress {
|
|||
|
||||
Map<String, dynamic> toJson() => _$ProgressToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class TxOutput {
|
||||
final int id;
|
||||
final String address;
|
||||
final int amount;
|
||||
final int pool;
|
||||
|
||||
TxOutput(this.id, this.address, this.amount, this.pool);
|
||||
|
||||
factory TxOutput.fromJson(Map<String, dynamic> json) =>
|
||||
_$TxOutputFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$TxOutputToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class TxReport {
|
||||
final List<TxOutput> outputs;
|
||||
final int transparent;
|
||||
final int sapling;
|
||||
final int orchard;
|
||||
final int net_sapling;
|
||||
final int net_orchard;
|
||||
final int fee;
|
||||
final int privacy_level;
|
||||
|
||||
TxReport(this.outputs, this.transparent, this.sapling,
|
||||
this.orchard, this.net_sapling, this.net_orchard,
|
||||
this.fee, this.privacy_level);
|
||||
|
||||
factory TxReport.fromJson(Map<String, dynamic> json) =>
|
||||
_$TxReportFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$TxReportToJson(this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -86,6 +86,11 @@ class WarpApi {
|
|||
name.toNativeUtf8().cast<Int8>(), index, count);
|
||||
}
|
||||
|
||||
static String getAddress(int coin, int id, int uaType) {
|
||||
final address = warp_api_lib.get_address(coin, id, uaType);
|
||||
return unwrapResultString(address);
|
||||
}
|
||||
|
||||
static void importTransparentPath(int coin, int id, String path) {
|
||||
warp_api_lib.import_transparent_key(
|
||||
coin, id, path.toNativeUtf8().cast<Int8>());
|
||||
|
@ -176,7 +181,7 @@ class WarpApi {
|
|||
|
||||
return await compute(
|
||||
sendPaymentIsolateFn,
|
||||
PaymentParams(
|
||||
PaymentParams(coin, account,
|
||||
recipientJson, useTransparent, anchorOffset, receivePort.sendPort));
|
||||
}
|
||||
|
||||
|
@ -191,8 +196,8 @@ class WarpApi {
|
|||
return balance;
|
||||
}
|
||||
|
||||
static Future<String> shieldTAddr() async {
|
||||
final txId = await compute(shieldTAddrIsolateFn, null);
|
||||
static Future<String> shieldTAddr(int coin, int account) async {
|
||||
final txId = await compute(shieldTAddrIsolateFn, ShieldTAddrParams(coin, account));
|
||||
return txId;
|
||||
}
|
||||
|
||||
|
@ -202,17 +207,27 @@ class WarpApi {
|
|||
ScanTransparentAccountsParams(gapLimit));
|
||||
}
|
||||
|
||||
static String prepareTx(
|
||||
static String prepareTx(int coin, int account,
|
||||
List<Recipient> recipients, bool useTransparent, int anchorOffset) {
|
||||
final recipientsJson = jsonEncode(recipients);
|
||||
final res = warp_api_lib.prepare_multi_payment(
|
||||
coin, account,
|
||||
recipientsJson.toNativeUtf8().cast<Int8>(),
|
||||
useTransparent ? 1 : 0,
|
||||
anchorOffset);
|
||||
final json = unwrapResultString(res);
|
||||
return json;
|
||||
}
|
||||
|
||||
static String transactionReport(int coin, String plan) {
|
||||
final report = warp_api_lib.transaction_report(coin, plan.toNativeUtf8().cast<Int8>());
|
||||
return unwrapResultString(report);
|
||||
}
|
||||
|
||||
static String signAndBroadcast (int coin, int account, String plan) {
|
||||
final txid = warp_api_lib.sign_and_broadcast(coin, account, plan.toNativeUtf8().cast<Int8>());
|
||||
return unwrapResultString(txid);
|
||||
}
|
||||
|
||||
static Future<String> signOnly(
|
||||
int coin, int account, String tx, void Function(int) f) async {
|
||||
var receivePort = ReceivePort();
|
||||
|
@ -221,7 +236,7 @@ class WarpApi {
|
|||
});
|
||||
|
||||
return await compute(
|
||||
signOnlyIsolateFn, SignOnlyParams(tx, receivePort.sendPort));
|
||||
signOnlyIsolateFn, SignOnlyParams(coin, account, tx, receivePort.sendPort));
|
||||
}
|
||||
|
||||
static String broadcast(String txStr) {
|
||||
|
@ -453,15 +468,16 @@ class WarpApi {
|
|||
|
||||
String sendPaymentIsolateFn(PaymentParams params) {
|
||||
final txId = warp_api_lib.send_multi_payment(
|
||||
params.coin, params.account,
|
||||
params.recipientsJson.toNativeUtf8().cast<Int8>(),
|
||||
params.anchorOffset,
|
||||
params.useTransparent ? 1 : 0,
|
||||
params.port.nativePort);
|
||||
return unwrapResultString(txId);
|
||||
}
|
||||
|
||||
String signOnlyIsolateFn(SignOnlyParams params) {
|
||||
final txIdRes = warp_api_lib.sign(
|
||||
params.coin, params.account,
|
||||
params.tx.toNativeUtf8().cast<Int8>(), params.port.nativePort);
|
||||
if (txIdRes.error != nullptr) throw convertCString(txIdRes.error);
|
||||
return convertCString(txIdRes.value);
|
||||
|
@ -475,8 +491,8 @@ int mempoolSyncIsolateFn(Null n) {
|
|||
return unwrapResultI64(warp_api_lib.mempool_sync());
|
||||
}
|
||||
|
||||
String shieldTAddrIsolateFn(Null n) {
|
||||
final txId = warp_api_lib.shield_taddr();
|
||||
String shieldTAddrIsolateFn(ShieldTAddrParams params) {
|
||||
final txId = warp_api_lib.shield_taddr(params.coin, params.account);
|
||||
return unwrapResultString(txId);
|
||||
}
|
||||
|
||||
|
@ -518,20 +534,24 @@ class SyncParams {
|
|||
}
|
||||
|
||||
class PaymentParams {
|
||||
final int coin;
|
||||
final int account;
|
||||
final String recipientsJson;
|
||||
final bool useTransparent;
|
||||
final int anchorOffset;
|
||||
final SendPort port;
|
||||
|
||||
PaymentParams(
|
||||
this.recipientsJson, this.useTransparent, this.anchorOffset, this.port);
|
||||
this.coin, this.account, this.recipientsJson, this.useTransparent, this.anchorOffset, this.port);
|
||||
}
|
||||
|
||||
class SignOnlyParams {
|
||||
final int coin;
|
||||
final int account;
|
||||
final String tx;
|
||||
final SendPort port;
|
||||
|
||||
SignOnlyParams(this.tx, this.port);
|
||||
SignOnlyParams(this.coin, this.account, this.tx, this.port);
|
||||
}
|
||||
|
||||
class ShieldTAddrParams {
|
||||
|
|
|
@ -167,6 +167,23 @@ class NativeLibrary {
|
|||
late final _dart_new_sub_account _new_sub_account =
|
||||
_new_sub_account_ptr.asFunction<_dart_new_sub_account>();
|
||||
|
||||
CResult_____c_char get_address(
|
||||
int coin,
|
||||
int id_account,
|
||||
int ua_type,
|
||||
) {
|
||||
return _get_address(
|
||||
coin,
|
||||
id_account,
|
||||
ua_type,
|
||||
);
|
||||
}
|
||||
|
||||
late final _get_address_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_get_address>>('get_address');
|
||||
late final _dart_get_address _get_address =
|
||||
_get_address_ptr.asFunction<_dart_get_address>();
|
||||
|
||||
void import_transparent_key(
|
||||
int coin,
|
||||
int id_account,
|
||||
|
@ -282,14 +299,16 @@ class NativeLibrary {
|
|||
_get_latest_height_ptr.asFunction<_dart_get_latest_height>();
|
||||
|
||||
CResult_____c_char send_multi_payment(
|
||||
int coin,
|
||||
int account,
|
||||
ffi.Pointer<ffi.Int8> recipients_json,
|
||||
int use_transparent,
|
||||
int anchor_offset,
|
||||
int port,
|
||||
) {
|
||||
return _send_multi_payment(
|
||||
coin,
|
||||
account,
|
||||
recipients_json,
|
||||
use_transparent,
|
||||
anchor_offset,
|
||||
port,
|
||||
);
|
||||
|
@ -383,8 +402,14 @@ class NativeLibrary {
|
|||
late final _dart_get_taddr_balance _get_taddr_balance =
|
||||
_get_taddr_balance_ptr.asFunction<_dart_get_taddr_balance>();
|
||||
|
||||
CResult_____c_char shield_taddr() {
|
||||
return _shield_taddr();
|
||||
CResult_____c_char shield_taddr(
|
||||
int coin,
|
||||
int account,
|
||||
) {
|
||||
return _shield_taddr(
|
||||
coin,
|
||||
account,
|
||||
);
|
||||
}
|
||||
|
||||
late final _shield_taddr_ptr =
|
||||
|
@ -408,13 +433,15 @@ class NativeLibrary {
|
|||
.asFunction<_dart_scan_transparent_accounts>();
|
||||
|
||||
CResult_____c_char prepare_multi_payment(
|
||||
int coin,
|
||||
int account,
|
||||
ffi.Pointer<ffi.Int8> recipients_json,
|
||||
int use_transparent,
|
||||
int anchor_offset,
|
||||
) {
|
||||
return _prepare_multi_payment(
|
||||
coin,
|
||||
account,
|
||||
recipients_json,
|
||||
use_transparent,
|
||||
anchor_offset,
|
||||
);
|
||||
}
|
||||
|
@ -425,11 +452,30 @@ class NativeLibrary {
|
|||
late final _dart_prepare_multi_payment _prepare_multi_payment =
|
||||
_prepare_multi_payment_ptr.asFunction<_dart_prepare_multi_payment>();
|
||||
|
||||
CResult_____c_char transaction_report(
|
||||
int coin,
|
||||
ffi.Pointer<ffi.Int8> plan,
|
||||
) {
|
||||
return _transaction_report(
|
||||
coin,
|
||||
plan,
|
||||
);
|
||||
}
|
||||
|
||||
late final _transaction_report_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_transaction_report>>('transaction_report');
|
||||
late final _dart_transaction_report _transaction_report =
|
||||
_transaction_report_ptr.asFunction<_dart_transaction_report>();
|
||||
|
||||
CResult_____c_char sign(
|
||||
int coin,
|
||||
int account,
|
||||
ffi.Pointer<ffi.Int8> tx,
|
||||
int port,
|
||||
) {
|
||||
return _sign(
|
||||
coin,
|
||||
account,
|
||||
tx,
|
||||
port,
|
||||
);
|
||||
|
@ -438,6 +484,23 @@ class NativeLibrary {
|
|||
late final _sign_ptr = _lookup<ffi.NativeFunction<_c_sign>>('sign');
|
||||
late final _dart_sign _sign = _sign_ptr.asFunction<_dart_sign>();
|
||||
|
||||
CResult_____c_char sign_and_broadcast(
|
||||
int coin,
|
||||
int account,
|
||||
ffi.Pointer<ffi.Int8> tx_plan,
|
||||
) {
|
||||
return _sign_and_broadcast(
|
||||
coin,
|
||||
account,
|
||||
tx_plan,
|
||||
);
|
||||
}
|
||||
|
||||
late final _sign_and_broadcast_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_sign_and_broadcast>>('sign_and_broadcast');
|
||||
late final _dart_sign_and_broadcast _sign_and_broadcast =
|
||||
_sign_and_broadcast_ptr.asFunction<_dart_sign_and_broadcast>();
|
||||
|
||||
CResult_____c_char broadcast_tx(
|
||||
ffi.Pointer<ffi.Int8> tx_str,
|
||||
) {
|
||||
|
@ -824,15 +887,15 @@ class CResult_u32 extends ffi.Struct {
|
|||
external ffi.Pointer<ffi.Int8> error;
|
||||
}
|
||||
|
||||
class CResult_u8 extends ffi.Struct {
|
||||
@ffi.Uint8()
|
||||
external int value;
|
||||
class CResult_____c_char extends ffi.Struct {
|
||||
external ffi.Pointer<ffi.Int8> value;
|
||||
|
||||
external ffi.Pointer<ffi.Int8> error;
|
||||
}
|
||||
|
||||
class CResult_____c_char extends ffi.Struct {
|
||||
external ffi.Pointer<ffi.Int8> value;
|
||||
class CResult_u8 extends ffi.Struct {
|
||||
@ffi.Uint8()
|
||||
external int value;
|
||||
|
||||
external ffi.Pointer<ffi.Int8> error;
|
||||
}
|
||||
|
@ -949,6 +1012,18 @@ typedef _dart_new_sub_account = void Function(
|
|||
int count,
|
||||
);
|
||||
|
||||
typedef _c_get_address = CResult_____c_char Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 id_account,
|
||||
ffi.Uint8 ua_type,
|
||||
);
|
||||
|
||||
typedef _dart_get_address = CResult_____c_char Function(
|
||||
int coin,
|
||||
int id_account,
|
||||
int ua_type,
|
||||
);
|
||||
|
||||
typedef _c_import_transparent_key = ffi.Void Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 id_account,
|
||||
|
@ -1022,15 +1097,17 @@ typedef _c_get_latest_height = CResult_u32 Function();
|
|||
typedef _dart_get_latest_height = CResult_u32 Function();
|
||||
|
||||
typedef _c_send_multi_payment = CResult_____c_char Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 account,
|
||||
ffi.Pointer<ffi.Int8> recipients_json,
|
||||
ffi.Int8 use_transparent,
|
||||
ffi.Uint32 anchor_offset,
|
||||
ffi.Int64 port,
|
||||
);
|
||||
|
||||
typedef _dart_send_multi_payment = CResult_____c_char Function(
|
||||
int coin,
|
||||
int account,
|
||||
ffi.Pointer<ffi.Int8> recipients_json,
|
||||
int use_transparent,
|
||||
int anchor_offset,
|
||||
int port,
|
||||
);
|
||||
|
@ -1081,9 +1158,15 @@ typedef _dart_get_taddr_balance = CResult_u64 Function(
|
|||
int id_account,
|
||||
);
|
||||
|
||||
typedef _c_shield_taddr = CResult_____c_char Function();
|
||||
typedef _c_shield_taddr = CResult_____c_char Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 account,
|
||||
);
|
||||
|
||||
typedef _dart_shield_taddr = CResult_____c_char Function();
|
||||
typedef _dart_shield_taddr = CResult_____c_char Function(
|
||||
int coin,
|
||||
int account,
|
||||
);
|
||||
|
||||
typedef _c_scan_transparent_accounts = ffi.Void Function(
|
||||
ffi.Uint32 gap_limit,
|
||||
|
@ -1094,27 +1177,55 @@ typedef _dart_scan_transparent_accounts = void Function(
|
|||
);
|
||||
|
||||
typedef _c_prepare_multi_payment = CResult_____c_char Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 account,
|
||||
ffi.Pointer<ffi.Int8> recipients_json,
|
||||
ffi.Int8 use_transparent,
|
||||
ffi.Uint32 anchor_offset,
|
||||
);
|
||||
|
||||
typedef _dart_prepare_multi_payment = CResult_____c_char Function(
|
||||
int coin,
|
||||
int account,
|
||||
ffi.Pointer<ffi.Int8> recipients_json,
|
||||
int use_transparent,
|
||||
int anchor_offset,
|
||||
);
|
||||
|
||||
typedef _c_transaction_report = CResult_____c_char Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Pointer<ffi.Int8> plan,
|
||||
);
|
||||
|
||||
typedef _dart_transaction_report = CResult_____c_char Function(
|
||||
int coin,
|
||||
ffi.Pointer<ffi.Int8> plan,
|
||||
);
|
||||
|
||||
typedef _c_sign = CResult_____c_char Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 account,
|
||||
ffi.Pointer<ffi.Int8> tx,
|
||||
ffi.Int64 port,
|
||||
);
|
||||
|
||||
typedef _dart_sign = CResult_____c_char Function(
|
||||
int coin,
|
||||
int account,
|
||||
ffi.Pointer<ffi.Int8> tx,
|
||||
int port,
|
||||
);
|
||||
|
||||
typedef _c_sign_and_broadcast = CResult_____c_char Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 account,
|
||||
ffi.Pointer<ffi.Int8> tx_plan,
|
||||
);
|
||||
|
||||
typedef _dart_sign_and_broadcast = CResult_____c_char Function(
|
||||
int coin,
|
||||
int account,
|
||||
ffi.Pointer<ffi.Int8> tx_plan,
|
||||
);
|
||||
|
||||
typedef _c_broadcast_tx = CResult_____c_char Function(
|
||||
ffi.Pointer<ffi.Int8> tx_str,
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue