Fix Scan TAddrs
This commit is contained in:
parent
a6580baa48
commit
9b16a6b7be
|
@ -265,11 +265,33 @@ class AccountManagerState extends State<AccountManagerPage> {
|
|||
}
|
||||
|
||||
_onFullRestore() {
|
||||
Navigator.of(this.context).pushNamed('/fullRestore');
|
||||
Navigator.of(context).pushNamed('/fullRestore');
|
||||
}
|
||||
|
||||
_onScanSubAccounts() {
|
||||
Navigator.of(this.context).pushNamed('/scantaddr');
|
||||
_onScanSubAccounts() async {
|
||||
final s = S.of(context);
|
||||
final nav = Navigator.of(context);
|
||||
final gapController = TextEditingController(text: '10');
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(s.scanTransparentAddresses),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: s.gapLimit),
|
||||
controller: gapController,
|
||||
keyboardType: TextInputType.number)
|
||||
])),
|
||||
actions: confirmButtons(context, () {
|
||||
nav.pop(true);
|
||||
}))) ??
|
||||
false;
|
||||
if (confirmed) {
|
||||
final gapLimit = int.parse(gapController.text);
|
||||
Navigator.of(this.context).pushNamed('/scantaddr', arguments: gapLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -397,6 +397,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"scanQrCode": MessageLookupByLibrary.simpleMessage("Scan QR Code"),
|
||||
"scanStartingMomentarily":
|
||||
MessageLookupByLibrary.simpleMessage("Scan starting momentarily"),
|
||||
"scanTransparentAddresses":
|
||||
MessageLookupByLibrary.simpleMessage("Scan Transparent Addresses"),
|
||||
"scanningAddresses":
|
||||
MessageLookupByLibrary.simpleMessage("Scanning addresses"),
|
||||
"secondary": MessageLookupByLibrary.simpleMessage("Secondary"),
|
||||
"secretKey": MessageLookupByLibrary.simpleMessage("Secret Key"),
|
||||
"secretShare": MessageLookupByLibrary.simpleMessage("Secret Share"),
|
||||
|
|
|
@ -404,6 +404,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Escanear Código QR"),
|
||||
"scanStartingMomentarily": MessageLookupByLibrary.simpleMessage(
|
||||
"Escaneo iniciado momentáneamente"),
|
||||
"scanTransparentAddresses":
|
||||
MessageLookupByLibrary.simpleMessage("Scan Transparent Addresses"),
|
||||
"scanningAddresses":
|
||||
MessageLookupByLibrary.simpleMessage("Scanning addresses"),
|
||||
"secondary": MessageLookupByLibrary.simpleMessage("Secundario"),
|
||||
"secretKey": MessageLookupByLibrary.simpleMessage("Clave secreta"),
|
||||
"secretShare": MessageLookupByLibrary.simpleMessage("Clave secreta"),
|
||||
|
|
|
@ -408,6 +408,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Scanner le QR Code"),
|
||||
"scanStartingMomentarily": MessageLookupByLibrary.simpleMessage(
|
||||
"Le scan démarre momentanément"),
|
||||
"scanTransparentAddresses":
|
||||
MessageLookupByLibrary.simpleMessage("Scan Transparent Addresses"),
|
||||
"scanningAddresses":
|
||||
MessageLookupByLibrary.simpleMessage("Scanning addresses"),
|
||||
"secondary": MessageLookupByLibrary.simpleMessage("Secondaire"),
|
||||
"secretKey": MessageLookupByLibrary.simpleMessage("Clé secrète"),
|
||||
"secretShare": MessageLookupByLibrary.simpleMessage("Secret Share"),
|
||||
|
|
|
@ -3121,6 +3121,26 @@ class S {
|
|||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Scan Transparent Addresses`
|
||||
String get scanTransparentAddresses {
|
||||
return Intl.message(
|
||||
'Scan Transparent Addresses',
|
||||
name: 'scanTransparentAddresses',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Scanning addresses`
|
||||
String get scanningAddresses {
|
||||
return Intl.message(
|
||||
'Scanning addresses',
|
||||
name: 'scanningAddresses',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||
|
|
|
@ -305,5 +305,7 @@
|
|||
"invalidPassword": "Invalid Password",
|
||||
"databaseRestored": "Database Restored",
|
||||
"never": "Never",
|
||||
"always": "Always"
|
||||
"always": "Always",
|
||||
"scanTransparentAddresses": "Scan Transparent Addresses",
|
||||
"scanningAddresses": "Scanning addresses"
|
||||
}
|
||||
|
|
|
@ -303,5 +303,7 @@
|
|||
"invalidPassword": "Invalid Password",
|
||||
"databaseRestored": "Database Restored",
|
||||
"never": "Never",
|
||||
"always": "Always"
|
||||
"always": "Always",
|
||||
"scanTransparentAddresses": "Scan Transparent Addresses",
|
||||
"scanningAddresses": "Scanning addresses"
|
||||
}
|
||||
|
|
|
@ -304,5 +304,7 @@
|
|||
"invalidPassword": "Mot de Passe incorrect",
|
||||
"databaseRestored": "BD Récupèrée",
|
||||
"never": "Jamais",
|
||||
"always": "Toujours"
|
||||
"always": "Toujours",
|
||||
"scanTransparentAddresses": "Scan Transparent Addresses",
|
||||
"scanningAddresses": "Scanning addresses"
|
||||
}
|
||||
|
|
547
lib/main.dart
547
lib/main.dart
|
@ -93,8 +93,8 @@ void handleUri(BuildContext context, Uri uri) {
|
|||
final coin = coinDef.coin;
|
||||
final id = WarpApi.getActiveAccountId(coin);
|
||||
active.setActiveAccount(coin, id);
|
||||
Navigator.of(context).pushNamed(
|
||||
'/send', arguments: SendPageArgs(uri: uri.toString()));
|
||||
Navigator.of(context)
|
||||
.pushNamed('/send', arguments: SendPageArgs(uri: uri.toString()));
|
||||
}
|
||||
|
||||
Future<void> registerURLHandler(BuildContext context) async {
|
||||
|
@ -128,7 +128,7 @@ void handleQuickAction(BuildContext context, String type) {
|
|||
}
|
||||
|
||||
class LoadProgress extends StatefulWidget {
|
||||
LoadProgress({Key? key}): super(key: key);
|
||||
LoadProgress({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
LoadProgressState createState() => LoadProgressState();
|
||||
|
@ -154,7 +154,7 @@ class LoadProgressState extends State<LoadProgress> {
|
|||
_disposed = true;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
void cancelResetTimer() {
|
||||
_reset?.cancel();
|
||||
_reset = null;
|
||||
|
@ -165,21 +165,21 @@ class LoadProgressState extends State<LoadProgress> {
|
|||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final textTheme = theme.textTheme;
|
||||
return Scaffold(body: Container(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(height: 240, width: 200, child:
|
||||
Column(
|
||||
children: [
|
||||
Image.asset('assets/icon.png', height: 64),
|
||||
Padding(padding: EdgeInsets.all(16)),
|
||||
Text(S.of(context).loading, style: textTheme.headlineMedium),
|
||||
Padding(padding: EdgeInsets.all(16)),
|
||||
LinearProgressIndicator(value: _value),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
Text(_message, style: textTheme.labelMedium),
|
||||
]
|
||||
)
|
||||
)));
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
height: 240,
|
||||
width: 200,
|
||||
child: Column(children: [
|
||||
Image.asset('assets/icon.png', height: 64),
|
||||
Padding(padding: EdgeInsets.all(16)),
|
||||
Text(S.of(context).loading, style: textTheme.headlineMedium),
|
||||
Padding(padding: EdgeInsets.all(16)),
|
||||
LinearProgressIndicator(value: _value),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
Text(_message, style: textTheme.labelMedium),
|
||||
]))));
|
||||
}
|
||||
|
||||
void setValue(double v, String message) {
|
||||
|
@ -221,7 +221,8 @@ void main() async {
|
|||
size: size,
|
||||
backgroundColor: Colors.transparent,
|
||||
skipTaskbar: false,
|
||||
titleBarStyle: Platform.isMacOS ? TitleBarStyle.hidden : TitleBarStyle.normal,
|
||||
titleBarStyle:
|
||||
Platform.isMacOS ? TitleBarStyle.hidden : TitleBarStyle.normal,
|
||||
);
|
||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.show();
|
||||
|
@ -230,90 +231,97 @@ void main() async {
|
|||
windowManager.addListener(OnWindow());
|
||||
}
|
||||
AwesomeNotifications().initialize(
|
||||
'resource://drawable/res_notification',
|
||||
[
|
||||
NotificationChannel(
|
||||
channelKey: APP_NAME,
|
||||
channelName: APP_NAME,
|
||||
channelDescription: 'Notification channel for $APP_NAME',
|
||||
defaultColor: Color(0xFFB3F0FF),
|
||||
ledColor: Colors.white,
|
||||
)
|
||||
],
|
||||
debug: true
|
||||
);
|
||||
'resource://drawable/res_notification',
|
||||
[
|
||||
NotificationChannel(
|
||||
channelKey: APP_NAME,
|
||||
channelName: APP_NAME,
|
||||
channelDescription: 'Notification channel for $APP_NAME',
|
||||
defaultColor: Color(0xFFB3F0FF),
|
||||
ledColor: Colors.white,
|
||||
)
|
||||
],
|
||||
debug: true);
|
||||
final home = ZWalletApp();
|
||||
|
||||
runApp(FutureBuilder(
|
||||
future: settings.restore(),
|
||||
builder: (context, snapshot) {
|
||||
return snapshot.connectionState == ConnectionState.waiting
|
||||
? MaterialApp(home: Container()) :
|
||||
Observer(builder: (context) {
|
||||
final theme = settings.themeData.copyWith(
|
||||
useMaterial3: true,
|
||||
dataTableTheme: DataTableThemeData(
|
||||
headingRowColor: MaterialStateColor.resolveWith(
|
||||
(_) => settings.themeData.highlightColor)));
|
||||
return MaterialApp(
|
||||
title: APP_NAME,
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: theme,
|
||||
home: home,
|
||||
scaffoldMessengerKey: rootScaffoldMessengerKey,
|
||||
navigatorKey: navigatorKey,
|
||||
localizationsDelegates: [
|
||||
S.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: S.delegate.supportedLocales,
|
||||
onGenerateRoute: (RouteSettings routeSettings) {
|
||||
var routes = <String, WidgetBuilder>{
|
||||
'/welcome': (context) => WelcomePage(),
|
||||
'/account': (context) => HomePage(),
|
||||
'/add_account': (context) => AddAccountPage(),
|
||||
'/add_first_account': (context) => AddAccountPage(firstAccount: true),
|
||||
'/send': (context) =>
|
||||
SendPage(routeSettings.arguments as SendPageArgs?),
|
||||
'/receive': (context) =>
|
||||
PaymentURIPage(),
|
||||
'/accounts': (context) => AccountManagerPage(),
|
||||
'/settings': (context) => SettingsPage(),
|
||||
'/tx': (context) =>
|
||||
TransactionPage(routeSettings.arguments as int),
|
||||
'/message': (context) =>
|
||||
MessagePage(routeSettings.arguments as int),
|
||||
'/backup': (context) {
|
||||
final accountId = routeSettings.arguments as AccountId?;
|
||||
final accountId2 = accountId ?? active.toId();
|
||||
return BackupPage(accountId2.coin, accountId2.id);
|
||||
},
|
||||
'/pools': (context) => PoolsPage(),
|
||||
'/multipay': (context) => MultiPayPage(),
|
||||
'/edit_theme': (context) =>
|
||||
ThemeEditorPage(onSaved: settings.updateCustomThemeColors),
|
||||
'/reset': (context) => ResetPage(),
|
||||
'/fullBackup': (context) => FullBackupPage(),
|
||||
'/fullRestore': (context) => FullRestorePage(),
|
||||
'/scantaddr': (context) => ScanTAddrPage(),
|
||||
'/qroffline': (context) => QrOffline(routeSettings.arguments as String),
|
||||
'/showRawTx': (context) => ShowRawTx(routeSettings.arguments as String),
|
||||
'/keytool': (context) => KeyToolPage(),
|
||||
'/dev': (context) => DevPage(),
|
||||
'/txplan': (context) => TxPlanPage.fromPlan(routeSettings.arguments as String, false),
|
||||
'/sign': (context) => TxPlanPage.fromPlan(routeSettings.arguments as String, true),
|
||||
'/syncstats': (context) => SyncChartPage(),
|
||||
'/scanner': (context) {
|
||||
final args = routeSettings.arguments as Map<String, dynamic>;
|
||||
return QRScanner(args['onScan'], completed: args['completed'], multi: args['multi']);
|
||||
},
|
||||
};
|
||||
return MaterialPageRoute(builder: routes[routeSettings.name]!);
|
||||
},
|
||||
);
|
||||
});
|
||||
? MaterialApp(home: Container())
|
||||
: Observer(builder: (context) {
|
||||
final theme = settings.themeData.copyWith(
|
||||
useMaterial3: true,
|
||||
dataTableTheme: DataTableThemeData(
|
||||
headingRowColor: MaterialStateColor.resolveWith(
|
||||
(_) => settings.themeData.highlightColor)));
|
||||
return MaterialApp(
|
||||
title: APP_NAME,
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: theme,
|
||||
home: home,
|
||||
scaffoldMessengerKey: rootScaffoldMessengerKey,
|
||||
navigatorKey: navigatorKey,
|
||||
localizationsDelegates: [
|
||||
S.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: S.delegate.supportedLocales,
|
||||
onGenerateRoute: (RouteSettings routeSettings) {
|
||||
var routes = <String, WidgetBuilder>{
|
||||
'/welcome': (context) => WelcomePage(),
|
||||
'/account': (context) => HomePage(),
|
||||
'/add_account': (context) => AddAccountPage(),
|
||||
'/add_first_account': (context) =>
|
||||
AddAccountPage(firstAccount: true),
|
||||
'/send': (context) =>
|
||||
SendPage(routeSettings.arguments as SendPageArgs?),
|
||||
'/receive': (context) => PaymentURIPage(),
|
||||
'/accounts': (context) => AccountManagerPage(),
|
||||
'/settings': (context) => SettingsPage(),
|
||||
'/tx': (context) =>
|
||||
TransactionPage(routeSettings.arguments as int),
|
||||
'/message': (context) =>
|
||||
MessagePage(routeSettings.arguments as int),
|
||||
'/backup': (context) {
|
||||
final accountId = routeSettings.arguments as AccountId?;
|
||||
final accountId2 = accountId ?? active.toId();
|
||||
return BackupPage(accountId2.coin, accountId2.id);
|
||||
},
|
||||
'/pools': (context) => PoolsPage(),
|
||||
'/multipay': (context) => MultiPayPage(),
|
||||
'/edit_theme': (context) => ThemeEditorPage(
|
||||
onSaved: settings.updateCustomThemeColors),
|
||||
'/reset': (context) => ResetPage(),
|
||||
'/fullBackup': (context) => FullBackupPage(),
|
||||
'/fullRestore': (context) => FullRestorePage(),
|
||||
'/scantaddr': (context) =>
|
||||
ScanTAddrPage(routeSettings.arguments as int),
|
||||
'/qroffline': (context) =>
|
||||
QrOffline(routeSettings.arguments as String),
|
||||
'/showRawTx': (context) =>
|
||||
ShowRawTx(routeSettings.arguments as String),
|
||||
'/keytool': (context) => KeyToolPage(),
|
||||
'/dev': (context) => DevPage(),
|
||||
'/txplan': (context) => TxPlanPage.fromPlan(
|
||||
routeSettings.arguments as String, false),
|
||||
'/sign': (context) => TxPlanPage.fromPlan(
|
||||
routeSettings.arguments as String, true),
|
||||
'/syncstats': (context) => SyncChartPage(),
|
||||
'/scanner': (context) {
|
||||
final args =
|
||||
routeSettings.arguments as Map<String, dynamic>;
|
||||
return QRScanner(args['onScan'],
|
||||
completed: args['completed'], multi: args['multi']);
|
||||
},
|
||||
};
|
||||
return MaterialPageRoute(
|
||||
builder: routes[routeSettings.name]!);
|
||||
},
|
||||
);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -346,11 +354,14 @@ class ZWalletAppState extends State<ZWalletApp> {
|
|||
}
|
||||
// Only after at least the action method is set, the notification events are delivered
|
||||
AwesomeNotifications().setListeners(
|
||||
onActionReceivedMethod: NotificationController.onActionReceivedMethod,
|
||||
onNotificationCreatedMethod: NotificationController.onNotificationCreatedMethod,
|
||||
onNotificationDisplayedMethod: NotificationController.onNotificationDisplayedMethod,
|
||||
onDismissActionReceivedMethod: NotificationController.onDismissActionReceivedMethod
|
||||
);
|
||||
onActionReceivedMethod:
|
||||
NotificationController.onActionReceivedMethod,
|
||||
onNotificationCreatedMethod:
|
||||
NotificationController.onNotificationCreatedMethod,
|
||||
onNotificationDisplayedMethod:
|
||||
NotificationController.onNotificationDisplayedMethod,
|
||||
onDismissActionReceivedMethod:
|
||||
NotificationController.onDismissActionReceivedMethod);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -367,15 +378,14 @@ class ZWalletAppState extends State<ZWalletApp> {
|
|||
final dbPath = await getDbPath();
|
||||
for (var coin in coins) {
|
||||
coin.init(dbPath);
|
||||
final server = settings.servers.firstWhere((s) => s.coin == coin.coin);
|
||||
final server =
|
||||
settings.servers.firstWhere((s) => s.coin == coin.coin);
|
||||
final url = server.getLWDUrl();
|
||||
if (url != null)
|
||||
WarpApi.updateLWD(coin.coin, url);
|
||||
if (url != null) WarpApi.updateLWD(coin.coin, url);
|
||||
}
|
||||
|
||||
if (exportDb) {
|
||||
for (var coin in coins)
|
||||
await coin.export(context, dbPath);
|
||||
for (var coin in coins) await coin.export(context, dbPath);
|
||||
prefs.setBool('export_db', false);
|
||||
}
|
||||
if (recover) {
|
||||
|
@ -394,24 +404,24 @@ class ZWalletAppState extends State<ZWalletApp> {
|
|||
if (WarpApi.decryptDb(c.dbFullPath, '')) break; // not encrypted
|
||||
|
||||
final reset = await getDbPasswd(context, c.dbFullPath);
|
||||
if (reset) { // user didn't input the passwd and wants to reset
|
||||
if (reset) {
|
||||
// user didn't input the passwd and wants to reset
|
||||
await clearApp(context);
|
||||
}
|
||||
else break;
|
||||
} while(true);
|
||||
} else
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
for (var c in coins) {
|
||||
_setProgress(0.2 * (c.coin+1), 'Initializing ${c.ticker}');
|
||||
await compute(_initWallet, { 'coin': c, 'passwd': settings.dbPasswd });
|
||||
_setProgress(0.2 * (c.coin + 1), 'Initializing ${c.ticker}');
|
||||
await compute(_initWallet, {'coin': c, 'passwd': settings.dbPasswd});
|
||||
}
|
||||
|
||||
_setProgress(0.7, 'Restoring Active Account');
|
||||
if (recover) {
|
||||
final aid = getAvailableId(coins[0].coin);
|
||||
if (aid != null)
|
||||
active.setActiveAccount(aid.coin, aid.id);
|
||||
}
|
||||
else await active.restore();
|
||||
if (aid != null) active.setActiveAccount(aid.coin, aid.id);
|
||||
} else
|
||||
await active.restore();
|
||||
|
||||
_setProgress(0.8, 'Register URL Protocol Handlers');
|
||||
await registerURLHandler(this.context);
|
||||
|
@ -434,10 +444,12 @@ class ZWalletAppState extends State<ZWalletApp> {
|
|||
for (var c in settings.coins) {
|
||||
final coin = c.coin;
|
||||
final ticker = c.def.ticker;
|
||||
shortcuts.add(ShortcutItem(type: '$coin.receive',
|
||||
shortcuts.add(ShortcutItem(
|
||||
type: '$coin.receive',
|
||||
localizedTitle: s.receive(ticker),
|
||||
icon: 'receive'));
|
||||
shortcuts.add(ShortcutItem(type: '$coin.send',
|
||||
shortcuts.add(ShortcutItem(
|
||||
type: '$coin.send',
|
||||
localizedTitle: s.sendCointicker(ticker),
|
||||
icon: 'send'));
|
||||
}
|
||||
|
@ -468,8 +480,7 @@ class ZWalletAppState extends State<ZWalletApp> {
|
|||
WarpApi.initWallet(c.coin, c.dbFullPath);
|
||||
try {
|
||||
WarpApi.migrateData(c.coin);
|
||||
}
|
||||
catch (e) {} // do not fail on network exception
|
||||
} catch (e) {} // do not fail on network exception
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -489,10 +500,10 @@ class ZWalletAppState extends State<ZWalletApp> {
|
|||
}
|
||||
|
||||
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey =
|
||||
GlobalKey<ScaffoldMessengerState>();
|
||||
GlobalKey<ScaffoldMessengerState>();
|
||||
|
||||
List<ElevatedButton> confirmButtons(BuildContext context,
|
||||
VoidCallback? onPressed,
|
||||
List<ElevatedButton> confirmButtons(
|
||||
BuildContext context, VoidCallback? onPressed,
|
||||
{String? okLabel, Icon? okIcon, cancelValue}) {
|
||||
final s = S.of(context);
|
||||
final navigator = Navigator.of(context);
|
||||
|
@ -511,7 +522,8 @@ List<ElevatedButton> confirmButtons(BuildContext context,
|
|||
];
|
||||
}
|
||||
|
||||
List<TimeSeriesPoint<V>> sampleDaily<T, Y, V>(List<T> timeseries,
|
||||
List<TimeSeriesPoint<V>> sampleDaily<T, Y, V>(
|
||||
List<T> timeseries,
|
||||
int start,
|
||||
int end,
|
||||
int Function(T) getDay,
|
||||
|
@ -550,67 +562,73 @@ void showQR(BuildContext context, String text, String title) {
|
|||
return AlertDialog(
|
||||
content: Container(
|
||||
width: double.maxFinite,
|
||||
child: SingleChildScrollView(child: Column(children: [
|
||||
child: SingleChildScrollView(
|
||||
child: Column(children: [
|
||||
LayoutBuilder(builder: (context, constraints) {
|
||||
final size = getScreenSize(context) * 0.5;
|
||||
return QrImage(data: text, backgroundColor: Colors.white, size: size);
|
||||
return QrImage(
|
||||
data: text, backgroundColor: Colors.white, size: size);
|
||||
}),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
Text(title, style: Theme
|
||||
.of(context)
|
||||
.textTheme
|
||||
.titleSmall),
|
||||
Text(title, style: Theme.of(context).textTheme.titleSmall),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
ButtonBar(children: [
|
||||
ElevatedButton.icon(onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: text));
|
||||
showSnackBar(s.textCopiedToClipboard(title));
|
||||
Navigator.of(context).pop();
|
||||
}, icon: Icon(Icons.copy), label: Text(s.copy)),
|
||||
ElevatedButton.icon(onPressed: () => saveQRImage(text, title),
|
||||
icon: Icon(Icons.save), label: Text(s.save))
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: text));
|
||||
showSnackBar(s.textCopiedToClipboard(title));
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
icon: Icon(Icons.copy),
|
||||
label: Text(s.copy)),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => saveQRImage(text, title),
|
||||
icon: Icon(Icons.save),
|
||||
label: Text(s.save))
|
||||
])
|
||||
])))
|
||||
); });
|
||||
]))));
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> saveQRImage(String data, String title) async {
|
||||
final code = QrCode.fromData(data: data, errorCorrectLevel: QrErrorCorrectLevel.L);
|
||||
final code =
|
||||
QrCode.fromData(data: data, errorCorrectLevel: QrErrorCorrectLevel.L);
|
||||
code.make();
|
||||
final painter = QrPainter.withQr(qr: code, emptyColor: Colors.white, gapless: true);
|
||||
final painter =
|
||||
QrPainter.withQr(qr: code, emptyColor: Colors.white, gapless: true);
|
||||
final recorder = PictureRecorder();
|
||||
final canvas = Canvas(recorder);
|
||||
final size = code.moduleCount * 32;
|
||||
final whitePaint = Paint()..color = Colors.white..style = PaintingStyle.fill;
|
||||
final whitePaint = Paint()
|
||||
..color = Colors.white
|
||||
..style = PaintingStyle.fill;
|
||||
canvas.drawRect(Rect.fromLTWH(0, 0, size + 256, size + 256), whitePaint);
|
||||
canvas.translate(128, 128);
|
||||
painter.paint(canvas, Size(size.toDouble(), size.toDouble()));
|
||||
final image = await recorder.endRecording().toImage(size + 256, size + 256);
|
||||
final ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
|
||||
final ByteData? byteData =
|
||||
await image.toByteData(format: ImageByteFormat.png);
|
||||
final Uint8List pngBytes = byteData!.buffer.asUint8List();
|
||||
await saveFileBinary(pngBytes, 'qr.png', title);
|
||||
}
|
||||
|
||||
Future<bool> showMessageBox(BuildContext context, String title, String content,
|
||||
String label) async {
|
||||
Future<bool> showMessageBox(
|
||||
BuildContext context, String title, String content, String label) async {
|
||||
final confirm = await showDialog<bool>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) =>
|
||||
AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(content),
|
||||
actions: confirmButtons(context, () {
|
||||
Navigator.of(context).pop(true);
|
||||
}, okLabel: label, cancelValue: false)),
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(content),
|
||||
actions: confirmButtons(context, () {
|
||||
Navigator.of(context).pop(true);
|
||||
}, okLabel: label, cancelValue: false)),
|
||||
);
|
||||
return confirm ?? false;
|
||||
}
|
||||
|
||||
double getScreenSize(BuildContext context) {
|
||||
final size = MediaQuery
|
||||
.of(context)
|
||||
.size;
|
||||
final size = MediaQuery.of(context).size;
|
||||
return min(size.height, size.width);
|
||||
}
|
||||
|
||||
|
@ -650,8 +668,7 @@ int stringToAmount(String? s) {
|
|||
bool checkNumber(String s) {
|
||||
try {
|
||||
NumberFormat.currency().parse(s);
|
||||
}
|
||||
on FormatException {
|
||||
} on FormatException {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -664,8 +681,7 @@ Future<String?> scanCode(BuildContext context) async {
|
|||
if (!isMobile()) {
|
||||
final code = await pickDecodeQRImage();
|
||||
return code;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
final f = Completer();
|
||||
Navigator.of(context).pushNamed('/scanner', arguments: {
|
||||
'onScan': (String code) {
|
||||
|
@ -679,29 +695,30 @@ Future<String?> scanCode(BuildContext context) async {
|
|||
}
|
||||
|
||||
String centerTrim(String v) =>
|
||||
v.length >= 16 ? v.substring(0, 8) + "..." +
|
||||
v.substring(v.length - 16) : v;
|
||||
v.length >= 16 ? v.substring(0, 8) + "..." + v.substring(v.length - 16) : v;
|
||||
|
||||
String trailing(String v, int n) {
|
||||
final len = min(n, v.length);
|
||||
return v.substring(v.length - len);
|
||||
}
|
||||
|
||||
void showSnackBar(String msg, { bool autoClose = false, bool quick = false }) {
|
||||
void showSnackBar(String msg, {bool autoClose = false, bool quick = false}) {
|
||||
final duration = quick ? Duration(seconds: 1) : Duration(seconds: 4);
|
||||
final snackBar = SnackBar(content: SelectableText(msg),
|
||||
duration: autoClose ? duration : Duration(minutes: 1),
|
||||
action: SnackBarAction(label: S.current.close, onPressed: () {
|
||||
rootScaffoldMessengerKey.currentState?.hideCurrentSnackBar();
|
||||
}));
|
||||
final snackBar = SnackBar(
|
||||
content: SelectableText(msg),
|
||||
duration: autoClose ? duration : Duration(minutes: 1),
|
||||
action: SnackBarAction(
|
||||
label: S.current.close,
|
||||
onPressed: () {
|
||||
rootScaffoldMessengerKey.currentState?.hideCurrentSnackBar();
|
||||
}));
|
||||
rootScaffoldMessengerKey.currentState?.showSnackBar(snackBar);
|
||||
}
|
||||
|
||||
void showBalanceNotification(int prevBalances, int curBalances) {
|
||||
final s = S.current;
|
||||
if (syncStatus.isRescan) return;
|
||||
if (Platform.isAndroid &&
|
||||
prevBalances != curBalances) {
|
||||
if (Platform.isAndroid && prevBalances != curBalances) {
|
||||
final amount = (prevBalances - curBalances).abs();
|
||||
final amountStr = amountToString(amount, MAX_PRECISION);
|
||||
final ticker = active.coinDef.ticker;
|
||||
|
@ -714,8 +731,7 @@ void showBalanceNotification(int prevBalances, int curBalances) {
|
|||
body: s.received(amountStr, ticker),
|
||||
actionType: ActionType.Default,
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
content = NotificationContent(
|
||||
id: 1,
|
||||
channelKey: APP_NAME,
|
||||
|
@ -724,25 +740,14 @@ void showBalanceNotification(int prevBalances, int curBalances) {
|
|||
actionType: ActionType.Default,
|
||||
);
|
||||
}
|
||||
AwesomeNotifications().createNotification(
|
||||
content: content
|
||||
);
|
||||
AwesomeNotifications().createNotification(content: content);
|
||||
}
|
||||
}
|
||||
|
||||
enum DeviceWidth {
|
||||
xs,
|
||||
sm,
|
||||
md,
|
||||
lg,
|
||||
xl
|
||||
}
|
||||
enum DeviceWidth { xs, sm, md, lg, xl }
|
||||
|
||||
DeviceWidth getWidth(BuildContext context) {
|
||||
final width = MediaQuery
|
||||
.of(context)
|
||||
.size
|
||||
.width;
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
if (width < 600) return DeviceWidth.xs;
|
||||
if (width < 960) return DeviceWidth.sm;
|
||||
if (width < 1280) return DeviceWidth.md;
|
||||
|
@ -773,11 +778,13 @@ String humanizeDateTime(DateTime datetime) {
|
|||
return dateString;
|
||||
}
|
||||
|
||||
String decimalFormat(double x, int decimalDigits, { String symbol = '' }) =>
|
||||
NumberFormat.currency(decimalDigits: decimalDigits, symbol: symbol).format(
|
||||
x).trimRight();
|
||||
String decimalFormat(double x, int decimalDigits, {String symbol = ''}) =>
|
||||
NumberFormat.currency(decimalDigits: decimalDigits, symbol: symbol)
|
||||
.format(x)
|
||||
.trimRight();
|
||||
|
||||
String amountToString(int amount, int decimalDigits) => decimalFormat(amount / ZECUNIT, decimalDigits);
|
||||
String amountToString(int amount, int decimalDigits) =>
|
||||
decimalFormat(amount / ZECUNIT, decimalDigits);
|
||||
|
||||
DecodedPaymentURI decodeAddress(BuildContext context, String? v) {
|
||||
final s = S.of(context);
|
||||
|
@ -789,8 +796,7 @@ DecodedPaymentURI decodeAddress(BuildContext context, String? v) {
|
|||
final json = WarpApi.parsePaymentURI(v);
|
||||
final payment = DecodedPaymentURI.fromJson(jsonDecode(json));
|
||||
return payment;
|
||||
}
|
||||
on String catch (e) {
|
||||
} on String catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -802,8 +808,7 @@ Future<bool> authenticate(BuildContext context, String reason) async {
|
|||
final bool didAuthenticate;
|
||||
if (Platform.isAndroid && !await localAuth.canCheckBiometrics) {
|
||||
didAuthenticate = await KeyGuardmanager.authStatus == "true";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
didAuthenticate = await localAuth.authenticate(
|
||||
localizedReason: reason, options: AuthenticationOptions());
|
||||
}
|
||||
|
@ -814,10 +819,9 @@ Future<bool> authenticate(BuildContext context, String reason) async {
|
|||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
builder: (context) =>
|
||||
AlertDialog(
|
||||
title: Text(S.of(context).noAuthenticationMethod),
|
||||
content: Text(e.message ?? "")));
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(S.of(context).noAuthenticationMethod),
|
||||
content: Text(e.message ?? "")));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -827,8 +831,7 @@ Future<void> shieldTAddr(BuildContext context) async {
|
|||
final txPlan = WarpApi.shieldTAddr(
|
||||
active.coin, active.id, active.tbalance, settings.anchorOffset);
|
||||
Navigator.of(context).pushNamed('/txplan', arguments: txPlan);
|
||||
}
|
||||
on String catch (msg) {
|
||||
} on String catch (msg) {
|
||||
showSnackBar(msg);
|
||||
}
|
||||
}
|
||||
|
@ -851,7 +854,8 @@ Future<void> saveFile(String data, String filename, String title) async {
|
|||
await saveFileBinary(utf8.encode(data), filename, title);
|
||||
}
|
||||
|
||||
Future<void> saveFileBinary(List<int> data, String filename, String title) async {
|
||||
Future<void> saveFileBinary(
|
||||
List<int> data, String filename, String title) async {
|
||||
if (isMobile()) {
|
||||
final context = navigatorKey.currentContext!;
|
||||
Size size = MediaQuery.of(context).size;
|
||||
|
@ -860,10 +864,12 @@ Future<void> saveFileBinary(List<int> data, String filename, String title) async
|
|||
final xfile = XFile(path);
|
||||
final file = File(path);
|
||||
await file.writeAsBytes(data);
|
||||
await Share.shareXFiles([xfile], subject: title, sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2));
|
||||
}
|
||||
else {
|
||||
final fn = await FilePicker.platform.saveFile(dialogTitle: title, fileName: filename);
|
||||
await Share.shareXFiles([xfile],
|
||||
subject: title,
|
||||
sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2));
|
||||
} else {
|
||||
final fn = await FilePicker.platform
|
||||
.saveFile(dialogTitle: title, fileName: filename);
|
||||
if (fn != null) {
|
||||
final file = File(fn);
|
||||
await file.writeAsBytes(data);
|
||||
|
@ -872,15 +878,17 @@ Future<void> saveFileBinary(List<int> data, String filename, String title) async
|
|||
}
|
||||
|
||||
Future<void> exportFile(BuildContext context, String path, String title) async {
|
||||
final confirmed = await showMessageBox(context, title, "Exporting $path", S.of(context).ok);
|
||||
final confirmed =
|
||||
await showMessageBox(context, title, "Exporting $path", S.of(context).ok);
|
||||
if (!confirmed) return;
|
||||
if (isMobile()) {
|
||||
final context = navigatorKey.currentContext!;
|
||||
Size size = MediaQuery.of(context).size;
|
||||
final xfile = XFile(path);
|
||||
await Share.shareXFiles([xfile], subject: title, sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2));
|
||||
}
|
||||
else {
|
||||
await Share.shareXFiles([xfile],
|
||||
subject: title,
|
||||
sharePositionOrigin: Rect.fromLTWH(0, 0, size.width, size.height / 2));
|
||||
} else {
|
||||
final fn = await FilePicker.platform.saveFile();
|
||||
if (fn != null) {
|
||||
final file = File(path);
|
||||
|
@ -895,18 +903,20 @@ Future<File> getRecoveryFile() async {
|
|||
return f;
|
||||
}
|
||||
|
||||
Future<bool> showConfirmDialog(BuildContext context, String title, String body) async {
|
||||
Future<bool> showConfirmDialog(
|
||||
BuildContext context, String title, String body) async {
|
||||
final s = S.of(context);
|
||||
final confirmation = await showDialog<bool>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(body),
|
||||
actions: confirmButtons(context, () {
|
||||
Navigator.of(context).pop(true);
|
||||
}, okLabel: s.ok, cancelValue: false)),
|
||||
) ?? false;
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(body),
|
||||
actions: confirmButtons(context, () {
|
||||
Navigator.of(context).pop(true);
|
||||
}, okLabel: s.ok, cancelValue: false)),
|
||||
) ??
|
||||
false;
|
||||
return confirmation;
|
||||
}
|
||||
|
||||
|
@ -925,9 +935,12 @@ void cancelScan(BuildContext context) {
|
|||
|
||||
Future<String> getDataPath() async {
|
||||
String? home;
|
||||
if (Platform.isAndroid) home = (await getApplicationDocumentsDirectory()).parent.path;
|
||||
if (Platform.isAndroid)
|
||||
home = (await getApplicationDocumentsDirectory()).parent.path;
|
||||
if (Platform.isWindows) home = Platform.environment['LOCALAPPDATA'];
|
||||
if (Platform.isLinux) home = Platform.environment['XDG_DATA_HOME'] ?? Platform.environment['HOME'];
|
||||
if (Platform.isLinux)
|
||||
home =
|
||||
Platform.environment['XDG_DATA_HOME'] ?? Platform.environment['HOME'];
|
||||
if (Platform.isMacOS) home = Platform.environment['HOME'];
|
||||
final h = home ?? "";
|
||||
return h;
|
||||
|
@ -953,27 +966,27 @@ Future<String> getDbPath() async {
|
|||
bool isMobile() => Platform.isAndroid || Platform.isIOS;
|
||||
|
||||
class NotificationController {
|
||||
|
||||
/// Use this method to detect when a new notification or a schedule is created
|
||||
@pragma("vm:entry-point")
|
||||
static Future <void> onNotificationCreatedMethod(ReceivedNotification receivedNotification) async {
|
||||
}
|
||||
static Future<void> onNotificationCreatedMethod(
|
||||
ReceivedNotification receivedNotification) async {}
|
||||
|
||||
/// Use this method to detect every time that a new notification is displayed
|
||||
@pragma("vm:entry-point")
|
||||
static Future <void> onNotificationDisplayedMethod(ReceivedNotification receivedNotification) async {
|
||||
static Future<void> onNotificationDisplayedMethod(
|
||||
ReceivedNotification receivedNotification) async {
|
||||
FlutterRingtonePlayer.playNotification();
|
||||
}
|
||||
|
||||
/// Use this method to detect if the user dismissed a notification
|
||||
@pragma("vm:entry-point")
|
||||
static Future <void> onDismissActionReceivedMethod(ReceivedAction receivedAction) async {
|
||||
}
|
||||
static Future<void> onDismissActionReceivedMethod(
|
||||
ReceivedAction receivedAction) async {}
|
||||
|
||||
/// Use this method to detect when the user taps on a notification or action button
|
||||
@pragma("vm:entry-point")
|
||||
static Future <void> onActionReceivedMethod(ReceivedAction receivedAction) async {
|
||||
}
|
||||
static Future<void> onActionReceivedMethod(
|
||||
ReceivedAction receivedAction) async {}
|
||||
}
|
||||
|
||||
void resetApp() {
|
||||
|
@ -992,40 +1005,46 @@ Future<bool> getDbPasswd(BuildContext context, String dbPath) async {
|
|||
final formKey = GlobalKey<FormState>();
|
||||
|
||||
final reset = await showDialog<bool>(
|
||||
context: context,
|
||||
barrierColor: Colors.black,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
content: Container(
|
||||
width: double.maxFinite,
|
||||
child: SingleChildScrollView(child: Form(key: formKey, child: Column(children: [
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: s.databasePassword),
|
||||
controller: passwdController,
|
||||
validator: checkPasswd,
|
||||
onSaved: (v) { settings.dbPasswd = v!; },
|
||||
obscureText: true,
|
||||
),
|
||||
])))),
|
||||
actions:
|
||||
<ElevatedButton>[
|
||||
ElevatedButton.icon(
|
||||
icon: Icon(Icons.lock_reset),
|
||||
label: Text(s.reset),
|
||||
onPressed: () => navigator.pop(true)),
|
||||
ElevatedButton.icon(
|
||||
icon: Icon(Icons.done),
|
||||
label: Text(s.ok),
|
||||
onPressed: () {
|
||||
final fs = formKey.currentState!;
|
||||
if (fs.validate()) {
|
||||
fs.save();
|
||||
navigator.pop(false);
|
||||
}
|
||||
})
|
||||
]);
|
||||
}) ?? false;
|
||||
context: context,
|
||||
barrierColor: Colors.black,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
content: Container(
|
||||
width: double.maxFinite,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: Column(children: [
|
||||
TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: s.databasePassword),
|
||||
controller: passwdController,
|
||||
validator: checkPasswd,
|
||||
onSaved: (v) {
|
||||
settings.dbPasswd = v!;
|
||||
},
|
||||
obscureText: true,
|
||||
),
|
||||
])))),
|
||||
actions: <ElevatedButton>[
|
||||
ElevatedButton.icon(
|
||||
icon: Icon(Icons.lock_reset),
|
||||
label: Text(s.reset),
|
||||
onPressed: () => navigator.pop(true)),
|
||||
ElevatedButton.icon(
|
||||
icon: Icon(Icons.done),
|
||||
label: Text(s.ok),
|
||||
onPressed: () {
|
||||
final fs = formKey.currentState!;
|
||||
if (fs.validate()) {
|
||||
fs.save();
|
||||
navigator.pop(false);
|
||||
}
|
||||
})
|
||||
]);
|
||||
}) ??
|
||||
false;
|
||||
|
||||
return reset;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ import 'generated/l10n.dart';
|
|||
import 'main.dart';
|
||||
|
||||
class ScanTAddrPage extends StatefulWidget {
|
||||
final int gapLimit;
|
||||
ScanTAddrPage(this.gapLimit);
|
||||
|
||||
@override
|
||||
ScanTAddrPageState createState() => ScanTAddrPageState();
|
||||
}
|
||||
|
@ -16,7 +19,8 @@ class ScanTAddrPageState extends State<ScanTAddrPage> {
|
|||
void initState() {
|
||||
super.initState();
|
||||
Future(() async {
|
||||
final _addresses = await WarpApi.scanTransparentAccounts(active.coin, active.id, settings.gapLimit);
|
||||
final _addresses = await WarpApi.scanTransparentAccounts(
|
||||
active.coin, active.id, widget.gapLimit);
|
||||
setState(() {
|
||||
addresses = _addresses;
|
||||
});
|
||||
|
@ -25,23 +29,25 @@ class ScanTAddrPageState extends State<ScanTAddrPage> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
final _addresses = addresses;
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Scan Transparent Addresses')),
|
||||
body: (_addresses == null) ?
|
||||
Center(child: Text('Scanning addresses'))
|
||||
: Column(
|
||||
children: [
|
||||
Expanded(child: ListView.builder(
|
||||
itemCount: _addresses.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final a = _addresses[index];
|
||||
return ListTile(title: Text(a.address!), subtitle: Text(amountToString(a.balance, MAX_PRECISION)));
|
||||
})),
|
||||
ButtonBar(children: confirmButtons(this.context, onPressed))
|
||||
]
|
||||
)
|
||||
);
|
||||
appBar: AppBar(title: Text(s.scanTransparentAddresses)),
|
||||
body: (_addresses == null)
|
||||
? Center(child: Text(s.scanningAddresses))
|
||||
: Column(children: [
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: _addresses.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final a = _addresses[index];
|
||||
return ListTile(
|
||||
title: Text(a.address!),
|
||||
subtitle: Text(
|
||||
amountToString(a.balance, MAX_PRECISION)));
|
||||
})),
|
||||
ButtonBar(children: confirmButtons(this.context, onPressed))
|
||||
]));
|
||||
}
|
||||
|
||||
onPressed() async {
|
||||
|
@ -54,4 +60,3 @@ class ScanTAddrPageState extends State<ScanTAddrPage> {
|
|||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ class SettingsState extends State<SettingsPage>
|
|||
var _anchorController =
|
||||
TextEditingController(text: "${settings.anchorOffset}");
|
||||
var _memoController = TextEditingController();
|
||||
var _gapLimitController = TextEditingController(text: "${settings.gapLimit}");
|
||||
var _currency = settings.currency;
|
||||
var _needAuth = false;
|
||||
var _messageView = settings.messageView;
|
||||
|
@ -50,7 +49,6 @@ class SettingsState extends State<SettingsPage>
|
|||
final simpleMode = settings.simpleMode;
|
||||
_memoController.text = settings.memoSignature ?? s.sendFrom(APP_NAME);
|
||||
|
||||
|
||||
final hasUA = active.coinDef.supportsUA;
|
||||
final uaType = settings.uaType;
|
||||
List<String> uaList = [];
|
||||
|
@ -153,7 +151,6 @@ class SettingsState extends State<SettingsPage>
|
|||
},
|
||||
onSaved: _onProtectOpen)),
|
||||
]),
|
||||
|
||||
if (!simpleMode)
|
||||
FormBuilderCheckbox(
|
||||
name: 'use_millis',
|
||||
|
@ -191,7 +188,8 @@ class SettingsState extends State<SettingsPage>
|
|||
FormBuilderCheckboxGroup<String>(
|
||||
orientation: OptionsOrientation.horizontal,
|
||||
name: 'ua',
|
||||
decoration: InputDecoration(labelText: 'Main Address Type'),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Main Address Type'),
|
||||
initialValue: uaList,
|
||||
onSaved: _onUAType,
|
||||
validator: _checkUA,
|
||||
|
@ -207,19 +205,23 @@ class SettingsState extends State<SettingsPage>
|
|||
initialValue: settings.getTx,
|
||||
onSaved: _onGetTx),
|
||||
FormBuilderRadioGroup<int>(
|
||||
orientation: OptionsOrientation.horizontal,
|
||||
name: 'auto_hide',
|
||||
decoration: InputDecoration(labelText: s.autoHideBalance),
|
||||
initialValue: settings.autoHide,
|
||||
onSaved: _onAutoHide,
|
||||
options: [
|
||||
FormBuilderFieldOption(child: Text(s.never), value: 0),
|
||||
FormBuilderFieldOption(child: Text(s.auto), value: 1),
|
||||
FormBuilderFieldOption(child: Text(s.always), value: 2),
|
||||
]),
|
||||
orientation: OptionsOrientation.horizontal,
|
||||
name: 'auto_hide',
|
||||
decoration:
|
||||
InputDecoration(labelText: s.autoHideBalance),
|
||||
initialValue: settings.autoHide,
|
||||
onSaved: _onAutoHide,
|
||||
options: [
|
||||
FormBuilderFieldOption(
|
||||
child: Text(s.never), value: 0),
|
||||
FormBuilderFieldOption(
|
||||
child: Text(s.auto), value: 1),
|
||||
FormBuilderFieldOption(
|
||||
child: Text(s.always), value: 2),
|
||||
]),
|
||||
DropdownButtonFormField<int>(
|
||||
decoration:
|
||||
InputDecoration(labelText: s.minPrivacy),
|
||||
InputDecoration(labelText: s.minPrivacy),
|
||||
value: _minPrivacy,
|
||||
items: getPrivacyOptions(context),
|
||||
onChanged: (v) {
|
||||
|
@ -235,41 +237,60 @@ class SettingsState extends State<SettingsPage>
|
|||
title: Text(s.includeReplyTo),
|
||||
initialValue: settings.includeReplyTo,
|
||||
onSaved: _onIncludeReplyTo),
|
||||
if (!simpleMode) Row(children: [
|
||||
Expanded(child: DropdownButtonFormField<ViewStyle>(
|
||||
decoration: InputDecoration(labelText: s.messages),
|
||||
value: _messageView,
|
||||
items: ViewStyle.values.map((v) => DropdownMenuItem(
|
||||
child: Text(v.name), value: v)).toList(),
|
||||
onChanged: (v) {
|
||||
setState(() { _messageView = v!; });
|
||||
},
|
||||
onSaved: (_) {
|
||||
settings.setMessageView(_messageView);
|
||||
})),
|
||||
Expanded(child: DropdownButtonFormField<ViewStyle>(
|
||||
decoration: InputDecoration(labelText: s.notes),
|
||||
value: _noteView,
|
||||
items: ViewStyle.values.map((v) => DropdownMenuItem(
|
||||
child: Text(v.name), value: v)).toList(),
|
||||
onChanged: (v) {
|
||||
setState(() { _noteView = v!; });
|
||||
},
|
||||
onSaved: (_) {
|
||||
settings.setNoteView(_noteView);
|
||||
})),
|
||||
Expanded(child: DropdownButtonFormField<ViewStyle>(
|
||||
decoration: InputDecoration(labelText: s.transactions),
|
||||
value: _txView,
|
||||
items: ViewStyle.values.map((v) => DropdownMenuItem(
|
||||
child: Text(v.name), value: v)).toList(),
|
||||
onChanged: (v) {
|
||||
setState(() { _txView = v!; });
|
||||
},
|
||||
onSaved: (_) {
|
||||
settings.setTxView(_txView);
|
||||
})),
|
||||
]),
|
||||
if (!simpleMode)
|
||||
Row(children: [
|
||||
Expanded(
|
||||
child: DropdownButtonFormField<ViewStyle>(
|
||||
decoration: InputDecoration(
|
||||
labelText: s.messages),
|
||||
value: _messageView,
|
||||
items: ViewStyle.values
|
||||
.map((v) => DropdownMenuItem(
|
||||
child: Text(v.name), value: v))
|
||||
.toList(),
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
_messageView = v!;
|
||||
});
|
||||
},
|
||||
onSaved: (_) {
|
||||
settings.setMessageView(_messageView);
|
||||
})),
|
||||
Expanded(
|
||||
child: DropdownButtonFormField<ViewStyle>(
|
||||
decoration:
|
||||
InputDecoration(labelText: s.notes),
|
||||
value: _noteView,
|
||||
items: ViewStyle.values
|
||||
.map((v) => DropdownMenuItem(
|
||||
child: Text(v.name), value: v))
|
||||
.toList(),
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
_noteView = v!;
|
||||
});
|
||||
},
|
||||
onSaved: (_) {
|
||||
settings.setNoteView(_noteView);
|
||||
})),
|
||||
Expanded(
|
||||
child: DropdownButtonFormField<ViewStyle>(
|
||||
decoration: InputDecoration(
|
||||
labelText: s.transactions),
|
||||
value: _txView,
|
||||
items: ViewStyle.values
|
||||
.map((v) => DropdownMenuItem(
|
||||
child: Text(v.name), value: v))
|
||||
.toList(),
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
_txView = v!;
|
||||
});
|
||||
},
|
||||
onSaved: (_) {
|
||||
settings.setTxView(_txView);
|
||||
})),
|
||||
]),
|
||||
if (!simpleMode)
|
||||
FormBuilderCheckbox(
|
||||
name: 'use_cold_qr',
|
||||
|
@ -295,14 +316,6 @@ class SettingsState extends State<SettingsPage>
|
|||
name: 'memo',
|
||||
controller: _memoController,
|
||||
onSaved: _onMemo),
|
||||
if (!simpleMode)
|
||||
FormBuilderTextField(
|
||||
decoration:
|
||||
InputDecoration(labelText: s.gapLimit),
|
||||
name: 'gap_limit',
|
||||
keyboardType: TextInputType.number,
|
||||
controller: _gapLimitController,
|
||||
onSaved: _onGapLimit),
|
||||
Padding(padding: EdgeInsets.symmetric(vertical: 8)),
|
||||
ButtonBar(children: confirmButtons(context, _onSave))
|
||||
]))))));
|
||||
|
@ -345,9 +358,15 @@ class SettingsState extends State<SettingsPage>
|
|||
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;
|
||||
case 'T':
|
||||
r |= 1;
|
||||
break;
|
||||
case 'S':
|
||||
r |= 2;
|
||||
break;
|
||||
case 'O':
|
||||
r |= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
|
@ -393,10 +412,6 @@ class SettingsState extends State<SettingsPage>
|
|||
settings.setAnchorOffset(int.parse(v));
|
||||
}
|
||||
|
||||
_onGapLimit(v) {
|
||||
settings.setGapLimit(int.parse(v));
|
||||
}
|
||||
|
||||
_onGetTx(v) {
|
||||
settings.updateGetTx(v);
|
||||
}
|
||||
|
|
|
@ -173,9 +173,6 @@ abstract class _Settings with Store {
|
|||
@observable
|
||||
bool qrOffline = true;
|
||||
|
||||
@observable
|
||||
int gapLimit = 10;
|
||||
|
||||
@observable
|
||||
int primaryColorValue = 0;
|
||||
@observable
|
||||
|
@ -244,7 +241,6 @@ abstract class _Settings with Store {
|
|||
messageView = ViewStyle.values[(prefs.getInt('message_view') ?? 0)];
|
||||
noteView = ViewStyle.values[(prefs.getInt('note_view') ?? 0)];
|
||||
txView = ViewStyle.values[(prefs.getInt('tx_view') ?? 0)];
|
||||
gapLimit = prefs.getInt('gap_limit') ?? 10;
|
||||
qrOffline = prefs.getBool('qr_offline') ?? true;
|
||||
|
||||
primaryColorValue = prefs.getInt('primary') ?? Colors.blue.value;
|
||||
|
@ -347,13 +343,6 @@ abstract class _Settings with Store {
|
|||
WarpApi.useGPU(v);
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> setGapLimit(int _gapLimit) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
gapLimit = _gapLimit;
|
||||
prefs.setInt('gap_limit', gapLimit);
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> setTheme(String thm) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 09f2c1093027be54cc316a758a687f9a3f58ad08
|
||||
Subproject commit ee7672569560ba1367f6449dd7a12347d42402f0
|
|
@ -179,9 +179,7 @@ class WarpApi {
|
|||
}
|
||||
|
||||
static bool validAddress(int coin, String address) {
|
||||
return warp_api_lib.valid_address(
|
||||
coin, toNative(address)) !=
|
||||
0;
|
||||
return warp_api_lib.valid_address(coin, toNative(address)) != 0;
|
||||
}
|
||||
|
||||
static String getDiversifiedAddress(int uaType, int time) {
|
||||
|
@ -230,50 +228,62 @@ class WarpApi {
|
|||
return balance;
|
||||
}
|
||||
|
||||
static Future<String> transferPools(int coin, int account, int fromPool, int toPool,
|
||||
int amount, bool includeFee, String memo, int splitAmount, int anchorOffset) async {
|
||||
final txId = await compute(transferPoolsIsolateFn, TransferPoolsParams(coin, account, fromPool, toPool, amount,
|
||||
includeFee, memo, splitAmount, anchorOffset));
|
||||
static Future<String> transferPools(
|
||||
int coin,
|
||||
int account,
|
||||
int fromPool,
|
||||
int toPool,
|
||||
int amount,
|
||||
bool includeFee,
|
||||
String memo,
|
||||
int splitAmount,
|
||||
int anchorOffset) async {
|
||||
final txId = await compute(
|
||||
transferPoolsIsolateFn,
|
||||
TransferPoolsParams(coin, account, fromPool, toPool, amount, includeFee,
|
||||
memo, splitAmount, anchorOffset));
|
||||
return txId;
|
||||
}
|
||||
|
||||
static String shieldTAddr(int coin, int account, int amount, int anchorOffset) {
|
||||
final txPlan = warp_api_lib.shield_taddr(coin, account, amount, anchorOffset);
|
||||
static String shieldTAddr(
|
||||
int coin, int account, int amount, int anchorOffset) {
|
||||
final txPlan =
|
||||
warp_api_lib.shield_taddr(coin, account, amount, anchorOffset);
|
||||
return unwrapResultString(txPlan);
|
||||
}
|
||||
|
||||
static Future<List<AddressBalance>> scanTransparentAccounts(
|
||||
int coin, int account, int gapLimit) async {
|
||||
return await compute(scanTransparentAccountsParamsIsolateFn,
|
||||
ScanTransparentAccountsParams(gapLimit));
|
||||
{'coin': coin, 'account': account, 'gapLimit': gapLimit});
|
||||
}
|
||||
|
||||
static Future<String> prepareTx(int coin, int account,
|
||||
List<Recipient> recipients, int anchorOffset) async {
|
||||
final builder = Builder();
|
||||
final builder = Builder();
|
||||
final rs = recipients.map((r) => r.unpack()).toList();
|
||||
int root = RecipientsT(values: rs).pack(builder);
|
||||
builder.finish(root);
|
||||
return await compute((_) {
|
||||
final res = warp_api_lib.prepare_multi_payment(
|
||||
coin, account,
|
||||
toNativeBytes(builder.buffer),
|
||||
builder.size(),
|
||||
anchorOffset);
|
||||
final res = warp_api_lib.prepare_multi_payment(coin, account,
|
||||
toNativeBytes(builder.buffer), builder.size(), anchorOffset);
|
||||
final json = unwrapResultString(res);
|
||||
return json;
|
||||
}, null);
|
||||
}
|
||||
|
||||
static TxReport transactionReport(int coin, String plan) {
|
||||
final data = unwrapResultBytes(warp_api_lib.transaction_report(coin, toNative(plan)));
|
||||
final data = unwrapResultBytes(
|
||||
warp_api_lib.transaction_report(coin, toNative(plan)));
|
||||
final report = TxReport(data);
|
||||
return report;
|
||||
}
|
||||
|
||||
static Future<String> signAndBroadcast (int coin, int account, String plan) async {
|
||||
static Future<String> signAndBroadcast(
|
||||
int coin, int account, String plan) async {
|
||||
return await compute((_) {
|
||||
final txid = warp_api_lib.sign_and_broadcast(coin, account, plan.toNativeUtf8().cast<Int8>());
|
||||
final txid = warp_api_lib.sign_and_broadcast(
|
||||
coin, account, plan.toNativeUtf8().cast<Int8>());
|
||||
return unwrapResultString(txid);
|
||||
}, null);
|
||||
}
|
||||
|
@ -285,8 +295,8 @@ class WarpApi {
|
|||
f(progress);
|
||||
});
|
||||
|
||||
return await compute(
|
||||
signOnlyIsolateFn, SignOnlyParams(coin, account, tx, receivePort.sendPort));
|
||||
return await compute(signOnlyIsolateFn,
|
||||
SignOnlyParams(coin, account, tx, receivePort.sendPort));
|
||||
}
|
||||
|
||||
static String broadcast(String txStr) {
|
||||
|
@ -298,9 +308,11 @@ class WarpApi {
|
|||
return warp_api_lib.is_valid_tkey(toNative(key)) != 0;
|
||||
}
|
||||
|
||||
static Future<String> sweepTransparent(int latestHeight, String sk, int pool, int confirmations) async {
|
||||
static Future<String> sweepTransparent(
|
||||
int latestHeight, String sk, int pool, int confirmations) async {
|
||||
return await compute((_) {
|
||||
final txid = warp_api_lib.sweep_tkey(latestHeight, toNative(sk), pool, confirmations);
|
||||
final txid = warp_api_lib.sweep_tkey(
|
||||
latestHeight, toNative(sk), pool, confirmations);
|
||||
return unwrapResultString(txid);
|
||||
}, null);
|
||||
}
|
||||
|
@ -344,7 +356,8 @@ class WarpApi {
|
|||
}
|
||||
|
||||
static String commitUnsavedContacts(int anchorOffset) {
|
||||
return unwrapResultString(warp_api_lib.commit_unsaved_contacts(anchorOffset));
|
||||
return unwrapResultString(
|
||||
warp_api_lib.commit_unsaved_contacts(anchorOffset));
|
||||
}
|
||||
|
||||
static void markMessageAsRead(int messageId, bool read) {
|
||||
|
@ -367,12 +380,10 @@ class WarpApi {
|
|||
warp_api_lib.delete_account(coin, account);
|
||||
}
|
||||
|
||||
static String makePaymentURI(int coin, String address, int amount, String memo) {
|
||||
static String makePaymentURI(
|
||||
int coin, String address, int amount, String memo) {
|
||||
final uri = warp_api_lib.make_payment_uri(
|
||||
coin,
|
||||
toNative(address),
|
||||
amount,
|
||||
memo.toNativeUtf8().cast<Int8>());
|
||||
coin, toNative(address), amount, memo.toNativeUtf8().cast<Int8>());
|
||||
return unwrapResultString(uri);
|
||||
}
|
||||
|
||||
|
@ -394,7 +405,8 @@ class WarpApi {
|
|||
}
|
||||
|
||||
static void unzipBackup(String key, String path, String tmpDir) {
|
||||
unwrapResultU8(warp_api_lib.unzip_backup(toNative(key), toNative(path), toNative(tmpDir)));
|
||||
unwrapResultU8(warp_api_lib.unzip_backup(
|
||||
toNative(key), toNative(path), toNative(tmpDir)));
|
||||
}
|
||||
|
||||
static List<String> splitData(int id, String data) {
|
||||
|
@ -477,7 +489,8 @@ class WarpApi {
|
|||
}
|
||||
|
||||
static Balance getBalance(int coin, int id, int confirmedHeight) {
|
||||
final r = unwrapResultBytes(warp_api_lib.get_balances(coin, id, confirmedHeight));
|
||||
final r =
|
||||
unwrapResultBytes(warp_api_lib.get_balances(coin, id, confirmedHeight));
|
||||
final b = Balance(r);
|
||||
return b;
|
||||
}
|
||||
|
@ -507,8 +520,10 @@ class WarpApi {
|
|||
return msgs.messages!;
|
||||
}
|
||||
|
||||
static PrevNext getPrevNextMessage(int coin, int id, String subject, int height) {
|
||||
final r = unwrapResultBytes(warp_api_lib.get_prev_next_message(coin, id, toNative(subject), height));
|
||||
static PrevNext getPrevNextMessage(
|
||||
int coin, int id, String subject, int height) {
|
||||
final r = unwrapResultBytes(warp_api_lib.get_prev_next_message(
|
||||
coin, id, toNative(subject), height));
|
||||
final pn = PrevNext(r);
|
||||
return pn;
|
||||
}
|
||||
|
@ -535,7 +550,8 @@ class WarpApi {
|
|||
print("templ $t");
|
||||
final data = toNativeBytes(template);
|
||||
|
||||
return unwrapResultU32(warp_api_lib.save_send_template(coin, data, template.length));
|
||||
return unwrapResultU32(
|
||||
warp_api_lib.save_send_template(coin, data, template.length));
|
||||
}
|
||||
|
||||
static void deleteSendTemplate(int coin, int id) {
|
||||
|
@ -555,13 +571,15 @@ class WarpApi {
|
|||
}
|
||||
|
||||
static List<Quote> getQuotes(int coin, int timestamp, String currency) {
|
||||
final r = unwrapResultBytes(warp_api_lib.get_historical_prices(coin, timestamp, toNative(currency)));
|
||||
final r = unwrapResultBytes(warp_api_lib.get_historical_prices(
|
||||
coin, timestamp, toNative(currency)));
|
||||
final quotes = QuoteVec(r);
|
||||
return quotes.values!;
|
||||
}
|
||||
|
||||
static List<Spending> getSpendings(int coin, int id, int timestamp) {
|
||||
final r = unwrapResultBytes(warp_api_lib.get_spendings(coin, id, timestamp));
|
||||
final r =
|
||||
unwrapResultBytes(warp_api_lib.get_spendings(coin, id, timestamp));
|
||||
final quotes = SpendingVec(r);
|
||||
return quotes.values!;
|
||||
}
|
||||
|
@ -585,17 +603,18 @@ class WarpApi {
|
|||
}
|
||||
|
||||
static void cloneDbWithPasswd(int coin, String tempPath, String passwd) {
|
||||
warp_api_lib.clone_db_with_passwd(coin, toNative(tempPath), toNative(passwd));
|
||||
warp_api_lib.clone_db_with_passwd(
|
||||
coin, toNative(tempPath), toNative(passwd));
|
||||
}
|
||||
|
||||
static bool decryptDb(String dbPath, String passwd) {
|
||||
return unwrapResultBool(warp_api_lib.decrypt_db(toNative(dbPath), toNative(passwd)));
|
||||
return unwrapResultBool(
|
||||
warp_api_lib.decrypt_db(toNative(dbPath), toNative(passwd)));
|
||||
}
|
||||
}
|
||||
|
||||
String signOnlyIsolateFn(SignOnlyParams params) {
|
||||
final txIdRes = warp_api_lib.sign(
|
||||
params.coin, params.account,
|
||||
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);
|
||||
|
@ -606,8 +625,16 @@ int getLatestHeightIsolateFn(Null n) {
|
|||
}
|
||||
|
||||
String transferPoolsIsolateFn(TransferPoolsParams params) {
|
||||
final txId = warp_api_lib.transfer_pools(params.coin, params.account, params.fromPool, params.toPool,
|
||||
params.amount, params.takeFee ? 1 : 0, toNative(params.memo), params.splitAmount, params.anchorOffset);
|
||||
final txId = warp_api_lib.transfer_pools(
|
||||
params.coin,
|
||||
params.account,
|
||||
params.fromPool,
|
||||
params.toPool,
|
||||
params.amount,
|
||||
params.takeFee ? 1 : 0,
|
||||
toNative(params.memo),
|
||||
params.splitAmount,
|
||||
params.anchorOffset);
|
||||
return unwrapResultString(txId);
|
||||
}
|
||||
|
||||
|
@ -621,7 +648,8 @@ int syncHistoricalPricesIsolateFn(SyncHistoricalPricesParams params) {
|
|||
}
|
||||
|
||||
int getTBalanceIsolateFn(GetTBalanceParams params) {
|
||||
return unwrapResultU64(warp_api_lib.get_taddr_balance(params.coin, params.account));
|
||||
return unwrapResultU64(
|
||||
warp_api_lib.get_taddr_balance(params.coin, params.account));
|
||||
}
|
||||
|
||||
int getBlockHeightByTimeIsolateFn(BlockHeightByTimeParams params) {
|
||||
|
@ -629,8 +657,11 @@ int getBlockHeightByTimeIsolateFn(BlockHeightByTimeParams params) {
|
|||
}
|
||||
|
||||
List<AddressBalance> scanTransparentAccountsParamsIsolateFn(
|
||||
ScanTransparentAccountsParams params) {
|
||||
final r = unwrapResultBytes(warp_api_lib.scan_transparent_accounts(params.gapLimit));
|
||||
Map<String, Object> params) {
|
||||
final r = unwrapResultBytes(warp_api_lib.scan_transparent_accounts(
|
||||
params['coin'] as int,
|
||||
params['account'] as int,
|
||||
params['gapLimit'] as int));
|
||||
final v = AddressBalanceVec(r);
|
||||
return v.values!;
|
||||
}
|
||||
|
@ -653,8 +684,8 @@ class PaymentParams {
|
|||
final int anchorOffset;
|
||||
final SendPort port;
|
||||
|
||||
PaymentParams(
|
||||
this.coin, this.account, this.recipientsJson, this.useTransparent, this.anchorOffset, this.port);
|
||||
PaymentParams(this.coin, this.account, this.recipientsJson,
|
||||
this.useTransparent, this.anchorOffset, this.port);
|
||||
}
|
||||
|
||||
class SignOnlyParams {
|
||||
|
@ -677,8 +708,16 @@ class TransferPoolsParams {
|
|||
final int splitAmount;
|
||||
final int anchorOffset;
|
||||
|
||||
TransferPoolsParams(this.coin, this.account, this.fromPool, this.toPool, this.amount, this.takeFee, this.memo,
|
||||
this.splitAmount, this.anchorOffset);
|
||||
TransferPoolsParams(
|
||||
this.coin,
|
||||
this.account,
|
||||
this.fromPool,
|
||||
this.toPool,
|
||||
this.amount,
|
||||
this.takeFee,
|
||||
this.memo,
|
||||
this.splitAmount,
|
||||
this.anchorOffset);
|
||||
}
|
||||
|
||||
class SyncHistoricalPricesParams {
|
||||
|
@ -700,12 +739,6 @@ class BlockHeightByTimeParams {
|
|||
BlockHeightByTimeParams(this.time);
|
||||
}
|
||||
|
||||
class ScanTransparentAccountsParams {
|
||||
final int gapLimit;
|
||||
|
||||
ScanTransparentAccountsParams(this.gapLimit);
|
||||
}
|
||||
|
||||
String convertCString(Pointer<Int8> s) {
|
||||
final str = s.cast<Utf8>().toDartString();
|
||||
warp_api_lib.deallocate_str(s);
|
||||
|
@ -713,9 +746,9 @@ String convertCString(Pointer<Int8> s) {
|
|||
}
|
||||
|
||||
List<int> convertBytes(Pointer<Uint8> s, int len) {
|
||||
final bytes = [...s.asTypedList(len)];
|
||||
warp_api_lib.deallocate_bytes(s, len);
|
||||
return bytes;
|
||||
final bytes = [...s.asTypedList(len)];
|
||||
warp_api_lib.deallocate_bytes(s, len);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void mempoolRunIsolateFn(int port) {
|
||||
|
|
|
@ -512,9 +512,13 @@ class NativeLibrary {
|
|||
_shield_taddr_ptr.asFunction<_dart_shield_taddr>();
|
||||
|
||||
CResult______u8 scan_transparent_accounts(
|
||||
int coin,
|
||||
int account,
|
||||
int gap_limit,
|
||||
) {
|
||||
return _scan_transparent_accounts(
|
||||
coin,
|
||||
account,
|
||||
gap_limit,
|
||||
);
|
||||
}
|
||||
|
@ -1906,10 +1910,14 @@ typedef _dart_shield_taddr = CResult_____c_char Function(
|
|||
);
|
||||
|
||||
typedef _c_scan_transparent_accounts = CResult______u8 Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Uint32 account,
|
||||
ffi.Uint32 gap_limit,
|
||||
);
|
||||
|
||||
typedef _dart_scan_transparent_accounts = CResult______u8 Function(
|
||||
int coin,
|
||||
int account,
|
||||
int gap_limit,
|
||||
);
|
||||
|
||||
|
|
|
@ -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.3.6+408
|
||||
version: 1.3.6+409
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
|
Loading…
Reference in New Issue