mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-20 17:54:41 +00:00
last upd
This commit is contained in:
parent
e4c775bffe
commit
141867930a
3 changed files with 0 additions and 743 deletions
|
@ -158,7 +158,6 @@ bool setupNode({
|
||||||
}) {
|
}) {
|
||||||
final addressPointer = address.toNativeUtf8();
|
final addressPointer = address.toNativeUtf8();
|
||||||
Pointer<Utf8>? loginPointer;
|
Pointer<Utf8>? loginPointer;
|
||||||
Pointer<Utf8>? socksProxyAddressPointer;
|
|
||||||
Pointer<Utf8>? passwordPointer;
|
Pointer<Utf8>? passwordPointer;
|
||||||
|
|
||||||
if (login != null) {
|
if (login != null) {
|
||||||
|
|
273
lib/zano.dart
273
lib/zano.dart
|
@ -1,273 +0,0 @@
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:cake_wallet/core/generate_wallet_password.dart';
|
|
||||||
import 'package:cake_wallet/core/key_service.dart';
|
|
||||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
|
||||||
import 'package:cake_wallet/zano_connected_widget.dart';
|
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
|
||||||
import 'package:cw_core/wallet_type.dart';
|
|
||||||
import 'package:cw_zano/api/calls.dart' as calls;
|
|
||||||
import 'package:cw_zano/api/model/balance.dart';
|
|
||||||
import 'package:cw_zano/api/model/create_wallet_result.dart';
|
|
||||||
import 'package:cw_zano/api/wallet.dart' as zano_wallet;
|
|
||||||
import 'package:cw_zano/zano_wallet_service.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
||||||
import 'package:get_it/get_it.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
Future<void> main() async {
|
|
||||||
await runZonedGuarded(() async {
|
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
|
||||||
|
|
||||||
FlutterError.onError = ExceptionHandler.onError;
|
|
||||||
|
|
||||||
/// A callback that is invoked when an unhandled error occurs in the root
|
|
||||||
/// isolate.
|
|
||||||
PlatformDispatcher.instance.onError = (error, stack) {
|
|
||||||
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
await setup();
|
|
||||||
runApp(App());
|
|
||||||
}, (error, stackTrace) async {
|
|
||||||
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stackTrace));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
final getIt = GetIt.instance;
|
|
||||||
|
|
||||||
Future<void> setup() async {
|
|
||||||
getIt.registerFactory<KeyService>(() => KeyService(getIt.get<FlutterSecureStorage>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
class App extends StatefulWidget {
|
|
||||||
const App({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<App> createState() => _AppState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// class HomeWidget extends StatefulWidget {
|
|
||||||
// const HomeWidget({super.key});
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// State<HomeWidget> createState() => _HomeWidgetState();
|
|
||||||
// }
|
|
||||||
|
|
||||||
class _AppState extends State<App> {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return MaterialApp(
|
|
||||||
home: DisconnectedWidget(), //HomeWidget(),
|
|
||||||
routes: {
|
|
||||||
ConnectedWidget.route: (context) {
|
|
||||||
final address = ModalRoute.of(context)!.settings.arguments! as String;
|
|
||||||
return ConnectedWidget(address: address);
|
|
||||||
},
|
|
||||||
DisconnectedWidget.route: (context) => DisconnectedWidget(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int hWallet = 0;
|
|
||||||
CreateWalletResult? lwr;
|
|
||||||
List<Balance> balances = [];
|
|
||||||
String seed = '', version = '';
|
|
||||||
final assetIds = <String, String>{};
|
|
||||||
const walletWrongId = 'WALLET_WRONG_ID';
|
|
||||||
const walletName = 'walletName';
|
|
||||||
|
|
||||||
Future<void> init() async {
|
|
||||||
version = calls.getVersion();
|
|
||||||
final setupNode = await calls.setupNode(
|
|
||||||
address: '195.201.107.230:33336',
|
|
||||||
login: '',
|
|
||||||
password: '',
|
|
||||||
useSSL: false,
|
|
||||||
isLightWallet: false);
|
|
||||||
if (!setupNode) {
|
|
||||||
debugPrint('error setting up node!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> create(String name) async {
|
|
||||||
debugPrint('create $name');
|
|
||||||
await init();
|
|
||||||
final path = await pathForWallet(name: name, type: WalletType.zano);
|
|
||||||
final credentials = ZanoNewWalletCredentials(name: name);
|
|
||||||
final keyService = KeyService(FlutterSecureStorage());
|
|
||||||
final password = generateWalletPassword();
|
|
||||||
credentials.password = password;
|
|
||||||
await keyService.saveWalletPassword(password: password, walletName: credentials.name);
|
|
||||||
debugPrint('path $path password $password');
|
|
||||||
final result = calls.createWallet(path: path, password: password, language: '');
|
|
||||||
debugPrint('create result $result');
|
|
||||||
return _parseResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> connect(String name) async {
|
|
||||||
debugPrint('connect');
|
|
||||||
await init();
|
|
||||||
final path = await pathForWallet(name: name, type: WalletType.zano);
|
|
||||||
final credentials = ZanoNewWalletCredentials(name: name);
|
|
||||||
final keyService = KeyService(FlutterSecureStorage());
|
|
||||||
final password = await keyService.getWalletPassword(walletName: credentials.name);
|
|
||||||
debugPrint('path $path password $password');
|
|
||||||
final result = await calls.loadWallet(path, password, 0);
|
|
||||||
return _parseResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> restore(String name, String seed) async {
|
|
||||||
debugPrint("restore");
|
|
||||||
await init();
|
|
||||||
final path = await pathForWallet(name: name, type: WalletType.zano);
|
|
||||||
final credentials = ZanoNewWalletCredentials(name: name);
|
|
||||||
final keyService = KeyService(FlutterSecureStorage());
|
|
||||||
final password = generateWalletPassword();
|
|
||||||
credentials.password = password;
|
|
||||||
await keyService.saveWalletPassword(password: password, walletName: credentials.name);
|
|
||||||
debugPrint('path $path password $password');
|
|
||||||
var result = calls.restoreWalletFromSeed(path, password, seed);
|
|
||||||
debugPrint('restore result $result');
|
|
||||||
//result = await calls.loadWallet(path, password, 0);
|
|
||||||
return _parseResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
String? _parseResult(String result) {
|
|
||||||
final map = json.decode(result) as Map<String, dynamic>;
|
|
||||||
if (map['result'] != null) {
|
|
||||||
lwr = CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
|
|
||||||
balances = lwr!.wi.balances;
|
|
||||||
hWallet = lwr!.walletId;
|
|
||||||
assetIds.clear();
|
|
||||||
for (final balance in lwr!.wi.balances) {
|
|
||||||
assetIds[balance.assetInfo.assetId] = balance.assetInfo.ticker;
|
|
||||||
}
|
|
||||||
return lwr!.wi.address;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void close() {
|
|
||||||
calls.closeWallet(hWallet);
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisconnectedWidget extends StatefulWidget {
|
|
||||||
const DisconnectedWidget({super.key});
|
|
||||||
static const route = 'disconnected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<DisconnectedWidget> createState() => _DisconnectedWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _DisconnectedWidgetState extends State<DisconnectedWidget> {
|
|
||||||
late final TextEditingController _name = TextEditingController(text: "wallet");
|
|
||||||
late final TextEditingController _seed = TextEditingController(
|
|
||||||
text:
|
|
||||||
"palm annoy brush task almost through here sent doll guilty smart horse mere canvas flirt advice fruit known shower happiness steel autumn beautiful approach anymore canvas");
|
|
||||||
bool _loading = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
() async {
|
|
||||||
final preferences = await SharedPreferences.getInstance();
|
|
||||||
final value = preferences.getString(walletName);
|
|
||||||
if (value != null && value.isNotEmpty) _name.text = value;
|
|
||||||
}();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(title: Text('Disconnected')),
|
|
||||||
body: SafeArea(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(32.0),
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
Opacity(
|
|
||||||
opacity: _loading ? 0.5 : 1,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
TextField(
|
|
||||||
controller: _name, decoration: InputDecoration(labelText: 'Wallet name')),
|
|
||||||
TextButton(
|
|
||||||
child: Text('Connect and Open Wallet'),
|
|
||||||
onPressed: () async {
|
|
||||||
//setState(() => _loading = true);
|
|
||||||
final preferences = await SharedPreferences.getInstance();
|
|
||||||
await preferences.setString(walletName, _name.text);
|
|
||||||
final result = await connect(_name.text);
|
|
||||||
//setState(() => _loading = false);
|
|
||||||
if (result != null) {
|
|
||||||
debugPrint("navigated to connected");
|
|
||||||
Navigator.of(context).pushReplacementNamed(
|
|
||||||
ConnectedWidget.route,
|
|
||||||
arguments: result,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
debugPrint('connect no result');
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: Text('Create and Open Wallet'),
|
|
||||||
onPressed: () async {
|
|
||||||
//setState(() => _loading = true);
|
|
||||||
final preferences = await SharedPreferences.getInstance();
|
|
||||||
await preferences.setString(walletName, _name.text);
|
|
||||||
final result = await create(_name.text);
|
|
||||||
//setState(() => _loading = false);
|
|
||||||
if (result != null) {
|
|
||||||
debugPrint("navigating to connected");
|
|
||||||
Navigator.of(context).pushReplacementNamed(
|
|
||||||
ConnectedWidget.route,
|
|
||||||
arguments: result,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
debugPrint('create no result');
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
TextField(
|
|
||||||
controller: _seed, decoration: InputDecoration(labelText: 'Wallet seed')),
|
|
||||||
TextButton(
|
|
||||||
child: Text('Restore from seed'),
|
|
||||||
onPressed: () async {
|
|
||||||
final preferences = await SharedPreferences.getInstance();
|
|
||||||
await preferences.setString(walletName, _name.text);
|
|
||||||
final result = await restore(_name.text, _seed.text);
|
|
||||||
if (result != null) {
|
|
||||||
Navigator.of(context).pushReplacementNamed(
|
|
||||||
ConnectedWidget.route,
|
|
||||||
arguments: result,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
debugPrint('restore no result');
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
TextButton(child: Text('Close Wallet'), onPressed: close),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (_loading) Center(child: CircularProgressIndicator()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,469 +0,0 @@
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:cake_wallet/zano.dart';
|
|
||||||
import 'package:cw_zano/api/model/destination.dart';
|
|
||||||
import 'package:cw_zano/api/model/get_wallet_info_result.dart';
|
|
||||||
import 'package:cw_zano/api/model/get_wallet_status_result.dart';
|
|
||||||
import 'package:cw_zano/api/model/history.dart';
|
|
||||||
import 'package:cw_zano/api/model/transfer_params.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:cw_zano/api/calls.dart' as calls;
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
class ConnectedWidget extends StatefulWidget {
|
|
||||||
final String address;
|
|
||||||
const ConnectedWidget({super.key, required this.address});
|
|
||||||
static const route = 'connected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<ConnectedWidget> createState() => _ConnectedWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ConnectedWidgetState extends State<ConnectedWidget> {
|
|
||||||
Timer? _longRefreshTimer;
|
|
||||||
GetWalletStatusResult? _gwsr;
|
|
||||||
int? _txFee;
|
|
||||||
final int _mixin = 10;
|
|
||||||
late final TextEditingController _destinationAddress =
|
|
||||||
TextEditingController(text: widget.address);
|
|
||||||
static const defaultAmount = 1.0;
|
|
||||||
late final TextEditingController _amount = TextEditingController(text: defaultAmount.toString());
|
|
||||||
late String _amountFormatted = _mulBy10_12(defaultAmount);
|
|
||||||
late final TextEditingController _paymentId = TextEditingController();
|
|
||||||
late final TextEditingController _comment = TextEditingController(text: "test");
|
|
||||||
bool _pushPayer = false;
|
|
||||||
bool _hideReceiver = true;
|
|
||||||
String _transferResult = '';
|
|
||||||
List<History>? _transactions;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
// _getWalletStatus returning true if it's in long refresh
|
|
||||||
// in a long refresh we keep requesting _getWalletStatus until we get false
|
|
||||||
if (_getWalletStatus()) {
|
|
||||||
_longRefreshTimer = Timer.periodic(Duration(milliseconds: 1000), (timer) {
|
|
||||||
if (!_getWalletStatus()) {
|
|
||||||
_longRefreshTimer!.cancel();
|
|
||||||
debugPrint('cancelling get wallet status timer');
|
|
||||||
_getWalletInfo();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//_getWalletInfo();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
//_timer.cancel();
|
|
||||||
// _myAddress.dispose();
|
|
||||||
// _seed.dispose();
|
|
||||||
_destinationAddress.dispose();
|
|
||||||
_amount.dispose();
|
|
||||||
_paymentId.dispose();
|
|
||||||
_comment.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return DefaultTabController(
|
|
||||||
length: 4,
|
|
||||||
child: Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Version $version'),
|
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.close),
|
|
||||||
onPressed: () {
|
|
||||||
close();
|
|
||||||
Navigator.of(context).pushReplacementNamed(DisconnectedWidget.route);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
bottom: TabBar(
|
|
||||||
tabs: [
|
|
||||||
Tab(text: 'Main'),
|
|
||||||
Tab(text: 'Transfer'),
|
|
||||||
Builder(builder: (context) {
|
|
||||||
if (lwr != null && lwr!.recentHistory.history != null) {
|
|
||||||
return Tab(text: 'History (${lwr!.recentHistory.history!.length})');
|
|
||||||
}
|
|
||||||
return Tab(text: 'History');
|
|
||||||
}),
|
|
||||||
Tab(text: 'Transactions')
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
body: SafeArea(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: TabBarView(
|
|
||||||
children: [
|
|
||||||
_mainTab(context),
|
|
||||||
_transferTab(context),
|
|
||||||
_historyTab(),
|
|
||||||
_transactionsTab(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _transactionsTab() {
|
|
||||||
return Column(children: [
|
|
||||||
TextButton(onPressed: _getTransactions, child: Text('Update list of Transactions')),
|
|
||||||
Expanded(child: _transactionsListView(_transactions)),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _historyTab() {
|
|
||||||
if (lwr == null) return Text("Empty");
|
|
||||||
return _transactionsListView(lwr!.recentHistory.history);
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView _transactionsListView(List<History>? list) {
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: list != null ? list.length : 0,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final item = list![index];
|
|
||||||
late String addr;
|
|
||||||
if (item.remoteAddresses.isNotEmpty) {
|
|
||||||
addr = _shorten(item.remoteAddresses.first);
|
|
||||||
} else {
|
|
||||||
addr = "???";
|
|
||||||
}
|
|
||||||
return Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text("${index + 1}. ${_dateTime(item.timestamp)} Remote addr: $addr"),
|
|
||||||
if (item.remoteAddresses.isNotEmpty)
|
|
||||||
IconButton(
|
|
||||||
onPressed: () =>
|
|
||||||
Clipboard.setData(ClipboardData(text: item.remoteAddresses.first)),
|
|
||||||
icon: Icon(Icons.copy),
|
|
||||||
),
|
|
||||||
if (item.remoteAliases.isNotEmpty) Text(" (${item.remoteAliases.first})"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Text(" txHash: ${item.txHash} comment: ${item.comment}"),
|
|
||||||
Text(
|
|
||||||
" paymentId: ${item.paymentId} height: ${item.height} fee: ${_divBy10_12(item.fee)}"),
|
|
||||||
if (item.employedEntries.receive.isNotEmpty)
|
|
||||||
Text(" Receive", style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
for (int i = 0; i < item.employedEntries.receive.length; i++)
|
|
||||||
Text(
|
|
||||||
' ${item.employedEntries.receive[i].index}. ${_assetName(item.employedEntries.receive[i].assetId)} ${_divBy10_12(item.employedEntries.receive[i].amount)}'),
|
|
||||||
if (item.employedEntries.send.isNotEmpty)
|
|
||||||
Text(" Spent", style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
for (int i = 0; i < item.employedEntries.send.length; i++)
|
|
||||||
Text(
|
|
||||||
' ${item.employedEntries.send[i].index}. ${_assetName(item.employedEntries.send[i].assetId)} ${_divBy10_12(item.employedEntries.send[i].amount)}'),
|
|
||||||
if (item.subtransfers.isNotEmpty)
|
|
||||||
Text(" Subtransfers", style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
for (int i = 0; i < item.subtransfers.length; i++)
|
|
||||||
Text(
|
|
||||||
' ${item.subtransfers[i].isIncome ? 'In' : 'Out'}. ${_assetName(item.subtransfers[i].assetId)} ${_divBy10_12(item.subtransfers[i].amount)}'),
|
|
||||||
Divider(),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _transferTab(BuildContext context) {
|
|
||||||
return SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text('Remote Address ', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Expanded(
|
|
||||||
child: TextField(
|
|
||||||
controller: _destinationAddress,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => Clipboard.setData(ClipboardData(text: _destinationAddress.text)),
|
|
||||||
icon: Icon(Icons.copy)),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () async {
|
|
||||||
final clipboard = await Clipboard.getData("text/plain");
|
|
||||||
if (clipboard == null || clipboard.text == null) return;
|
|
||||||
setState(() {
|
|
||||||
_destinationAddress.text = clipboard.text!;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon: Icon(Icons.paste)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
// ${lwr!.wi.address}
|
|
||||||
Text('Amount ', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Expanded(
|
|
||||||
child: TextField(
|
|
||||||
controller: _amount,
|
|
||||||
onChanged: (value) => setState(() {
|
|
||||||
_amountFormatted = _mulBy10_12(double.parse(value));
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text("= ${_amountFormatted}"),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => Clipboard.setData(ClipboardData(text: _amount.text)),
|
|
||||||
icon: Icon(Icons.copy)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (_txFee != null)
|
|
||||||
Text('Fee: ${_divBy10_12(_txFee!)} (${_txFee!})')
|
|
||||||
else
|
|
||||||
Text("Pls get Tx Fee before transfer!"),
|
|
||||||
Text('Mixin: $_mixin'),
|
|
||||||
Row(children: [
|
|
||||||
Text('Payment Id ', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Expanded(child: TextField(controller: _paymentId)),
|
|
||||||
]),
|
|
||||||
Row(children: [
|
|
||||||
Text('Comment ', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Expanded(child: TextField(controller: _comment)),
|
|
||||||
]),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text('Push Payer ', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Checkbox(
|
|
||||||
value: _pushPayer,
|
|
||||||
onChanged: (value) => setState(() => _pushPayer = value ?? false)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text('Hide Receiver ', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Checkbox(
|
|
||||||
value: _hideReceiver,
|
|
||||||
onChanged: (value) => setState(() => _hideReceiver = value ?? false)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
TextButton(onPressed: _transfer, child: Text('Transfer')),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text('Transfer result $_transferResult'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _mainTab(BuildContext context) {
|
|
||||||
return SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text('Wallet Info', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
TextButton(onPressed: _getWalletInfo, child: Text('Update WI & TxFee')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text('My Address ', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
widget.address,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
)),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => Clipboard.setData(ClipboardData(text: widget.address)),
|
|
||||||
icon: Icon(Icons.copy)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
for (final balance in balances)
|
|
||||||
Text(
|
|
||||||
'Balance (${balance.assetInfo.ticker}) total: ${_divBy10_12(balance.total)}, unlocked: ${_divBy10_12(balance.unlocked)}'),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text('Seed ', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Expanded(child: Text(seed, maxLines: 1, overflow: TextOverflow.ellipsis)),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => Clipboard.setData(ClipboardData(text: seed)),
|
|
||||||
icon: Icon(Icons.copy)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text('Wallet Status', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
TextButton(onPressed: _getWalletStatus, child: Text('Update')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (_gwsr != null) ...[
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text('Daemon Height ${_gwsr!.currentDaemonHeight}')),
|
|
||||||
Expanded(child: Text('Wallet Height ${_gwsr!.currentWalletHeight}')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text('Daemon Connected ${_gwsr!.isDaemonConnected}')),
|
|
||||||
Expanded(child: Text('In Long Refresh ${_gwsr!.isInLongRefresh}')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text('Progress ${_gwsr!.progress}')),
|
|
||||||
Expanded(child: Text('WalletState ${_gwsr!.walletState}')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
if (_txFee != null) Text('Tx Fee: ${_divBy10_12(_txFee!)} (${_txFee!})'),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
close();
|
|
||||||
Navigator.of(context).pushReplacementNamed(DisconnectedWidget.route);
|
|
||||||
},
|
|
||||||
child: Text('Disconnect')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _transfer() async {
|
|
||||||
final result = await calls.transfer(
|
|
||||||
hWallet,
|
|
||||||
TransferParams(
|
|
||||||
destinations: [
|
|
||||||
Destination(
|
|
||||||
amount: _mulBy10_12(double.parse(_amount.text)),
|
|
||||||
address: _destinationAddress.text,
|
|
||||||
assetId: assetIds.keys.first,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
fee: _txFee!,
|
|
||||||
mixin: _mixin,
|
|
||||||
paymentId: _paymentId.text,
|
|
||||||
comment: _comment.text,
|
|
||||||
pushPayer: _pushPayer,
|
|
||||||
hideReceiver: _hideReceiver,
|
|
||||||
));
|
|
||||||
debugPrint('transfer result $result');
|
|
||||||
final map = jsonDecode(result);
|
|
||||||
if (map['result'] == null) {
|
|
||||||
setState(() => _transferResult = 'empty result');
|
|
||||||
} else {
|
|
||||||
if (map['result']['error'] != null) {
|
|
||||||
setState(() => _transferResult =
|
|
||||||
"error code ${map['result']['error']['code']} message ${map['result']['error']['message']} ");
|
|
||||||
} else if (map['result']['result'] != null) {
|
|
||||||
setState(() => _transferResult =
|
|
||||||
"transfer tx hash ${map['result']['result']['tx_hash']} size ${map['result']['result']['tx_size']} ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _getWalletStatus() {
|
|
||||||
final json = calls.getWalletStatus(hWallet);
|
|
||||||
if (json == walletWrongId) {
|
|
||||||
debugPrint('error $walletWrongId');
|
|
||||||
setState(() => _gwsr = null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
setState(() {
|
|
||||||
_gwsr = GetWalletStatusResult.fromJson(jsonDecode(json) as Map<String, dynamic>);
|
|
||||||
});
|
|
||||||
return _gwsr!.isInLongRefresh;
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint('exception $e');
|
|
||||||
setState(() => _gwsr = null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _getWalletInfo() {
|
|
||||||
final result = GetWalletInfoResult.fromJson(
|
|
||||||
jsonDecode(calls.getWalletInfo(hWallet)) as Map<String, dynamic>);
|
|
||||||
final fee = calls.getCurrentTxFee(0);
|
|
||||||
setState(() {
|
|
||||||
balances = result.wi.balances;
|
|
||||||
seed = result.wiExtended.seed;
|
|
||||||
_txFee = fee;
|
|
||||||
});
|
|
||||||
// setState(() {
|
|
||||||
// _gwsr = GetWalletStatusResult.fromJson(
|
|
||||||
// jsonDecode(calls.getWalletStatus(hWallet)) as Map<String, dynamic>);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _getTransactions() async {
|
|
||||||
final result = await calls.getRecentTxsAndInfo(hWallet: hWallet, offset: 0, count: 30);
|
|
||||||
final map = jsonDecode(result);
|
|
||||||
if (map == null || map["result"] == null || map["result"]["result"] == null) {
|
|
||||||
setState(() => _transactions = null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setState(() => _transactions = map["result"]["result"]["transfers"] == null
|
|
||||||
? null
|
|
||||||
: (map["result"]["result"]["transfers"] as List<dynamic>)
|
|
||||||
.map((e) => History.fromJson(e as Map<String, dynamic>))
|
|
||||||
.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
String _divBy10_12(int value) {
|
|
||||||
return (value / pow(10, 12)).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String _mulBy10_12(double value) {
|
|
||||||
var str = (value * pow(10, 12)).toString();
|
|
||||||
if (str.contains('.')) str = str.split('.')[0];
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
String _shorten(String someId) {
|
|
||||||
if (someId.length < 9) return someId;
|
|
||||||
return '${someId.substring(0, 4).toUpperCase()}...${someId.substring(someId.length - 2)}';
|
|
||||||
}
|
|
||||||
|
|
||||||
String _assetName(String assetId) {
|
|
||||||
if (assetIds[assetId] != null) {
|
|
||||||
return assetIds[assetId]!;
|
|
||||||
} else {
|
|
||||||
return _shorten(assetId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String _dateTime(int timestamp) {
|
|
||||||
DateTime date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
|
|
||||||
return '${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')} ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}';
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _row(
|
|
||||||
String first, String second, String third, String forth, String fifth, String sixth) =>
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text(first)),
|
|
||||||
Expanded(flex: 2, child: Text(second)),
|
|
||||||
Expanded(flex: 2, child: Text(third)),
|
|
||||||
Expanded(flex: 3, child: Text(forth)),
|
|
||||||
Expanded(flex: 3, child: Text(fifth)),
|
|
||||||
Expanded(child: Text(sixth)),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
Reference in a new issue