From 0dea6a2e4669341107de5300ebfd1dda7ca62d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Olav?= Date: Sat, 11 Nov 2023 19:53:58 +0100 Subject: [PATCH 1/8] tabs: change theme when changing coins --- .../tabs/sidechain_explorer_tab_page.dart | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/pages/tabs/sidechain_explorer_tab_page.dart b/lib/pages/tabs/sidechain_explorer_tab_page.dart index e67ee2e7..7b4994c2 100644 --- a/lib/pages/tabs/sidechain_explorer_tab_page.dart +++ b/lib/pages/tabs/sidechain_explorer_tab_page.dart @@ -2,11 +2,14 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:sail_ui/sail_ui.dart'; +import 'package:sidesail/app.dart'; import 'package:sidesail/config/sidechains.dart'; import 'package:sidesail/providers/balance_provider.dart'; import 'package:sidesail/rpc/rpc_ethereum.dart'; import 'package:sidesail/rpc/rpc_sidechain.dart'; import 'package:sidesail/rpc/rpc_testchain.dart'; +import 'package:sidesail/storage/client_settings.dart'; +import 'package:sidesail/storage/sail_settings/theme_settings.dart'; import 'package:sidesail/widgets/containers/chain_overview_card.dart'; import 'package:sidesail/widgets/containers/tabs/dashboard_tab_widgets.dart'; import 'package:stacked/stacked.dart'; @@ -20,6 +23,8 @@ class SidechainExplorerTabPage extends StatelessWidget { @override Widget build(BuildContext context) { + final app = SailApp.of(context); + return ViewModelBuilder.reactive( viewModelBuilder: () => SidechainExplorerTabViewModel(), builder: ((context, viewModel, child) { @@ -41,7 +46,7 @@ class SidechainExplorerTabPage extends StatelessWidget { unconfirmedBalance: viewModel.pendingBalance, highlighted: false, currentChain: viewModel.chain.type == SidechainType.testChain, - onPressed: () => viewModel.setSidechainRPC(test), + onPressed: () => viewModel.setSidechainRPC(test, app), ), ChainOverviewCard( chain: EthereumSidechain(), @@ -49,7 +54,7 @@ class SidechainExplorerTabPage extends StatelessWidget { unconfirmedBalance: viewModel.pendingBalance, highlighted: false, currentChain: viewModel.chain.type == SidechainType.ethereum, - onPressed: () => viewModel.setSidechainRPC(eth), + onPressed: () => viewModel.setSidechainRPC(eth, app), ), ], ), @@ -67,6 +72,8 @@ class SidechainExplorerTabPage extends StatelessWidget { class SidechainExplorerTabViewModel extends BaseViewModel { BalanceProvider get _balanceProvider => GetIt.I.get(); SidechainRPC get _sideRPC => GetIt.I.get(); + ClientSettings get _clientSettings => GetIt.I.get(); + SailThemeValues theme = SailThemeValues.light; double get balance => _balanceProvider.balance; double get pendingBalance => _balanceProvider.pendingBalance; @@ -80,11 +87,17 @@ class SidechainExplorerTabViewModel extends BaseViewModel { // pass notifyListeners of this view model directly _balanceProvider.addListener(notifyListeners); _sideRPC.addListener(notifyListeners); + _init(); + } + + Future _init() async { + theme = (await _clientSettings.getValue(ThemeSetting())).value; } - void setSidechainRPC(SidechainSubRPC sideSubRPC) { + void setSidechainRPC(SidechainSubRPC sideSubRPC, SailAppState sailApp) { _sideRPC.setSubRPC(sideSubRPC); notifyListeners(); + sailApp.loadTheme(theme); } @override From 7f797df40e679aaaf9fa73e5fd2f3ff74b79fade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Olav?= Date: Sat, 11 Nov 2023 19:54:23 +0100 Subject: [PATCH 2/8] tabs/ethereum: add create account button if none exist --- .../tabs/ethereum/ethereum_rpc_tab_page.dart | 74 ++++++++++++++++--- lib/rpc/rpc_ethereum.dart | 37 ++++++++-- 2 files changed, 92 insertions(+), 19 deletions(-) diff --git a/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart b/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart index fc1d1c59..c01b448a 100644 --- a/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart +++ b/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart @@ -2,8 +2,12 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:sail_ui/sail_ui.dart'; +import 'package:sail_ui/widgets/core/sail_text.dart'; import 'package:sidesail/routing/router.dart'; +import 'package:sidesail/rpc/rpc_ethereum.dart'; import 'package:sidesail/widgets/containers/tabs/console.dart'; +import 'package:stacked/stacked.dart'; +import 'package:web3dart/web3dart.dart'; @RoutePage() class EthereumRPCTabPage extends StatelessWidget { @@ -13,18 +17,64 @@ class EthereumRPCTabPage extends StatelessWidget { @override Widget build(BuildContext context) { - return const SailPage( - scrollable: true, - title: 'Ethereum RPC', - subtitle: 'Call RPCs directly to the Ethereum sidechain. Try typing in "eth_blockNumber" in the input below.', - body: Padding( - padding: EdgeInsets.only(bottom: SailStyleValues.padding30), - child: Column( - children: [ - RPCWidget(), - ], - ), - ), + return ViewModelBuilder.reactive( + viewModelBuilder: () => EthereumRPCTabPageViewModel(), + builder: ((context, viewModel, child) { + return SailPage( + scrollable: true, + title: 'Ethereum RPC', + subtitle: 'Call RPCs directly to the Ethereum sidechain. Try typing in "eth_blockNumber" in the input below.', + widgetTitle: SailRow( + spacing: SailStyleValues.padding08, + children: [ + if (viewModel.account == null) + SailButton.primary( + 'Create account', + onPressed: viewModel.createAccount, + size: ButtonSize.small, + ), + if (viewModel.account == null) + SailText.secondary12('You need an account to deposit and withdraw sidechain-coins'), + if (viewModel.account != null) SailText.secondary13('Your ETH-address: ${viewModel.account!.toString()}'), + Expanded(child: Container()), + ], + ), + body: const Padding( + padding: EdgeInsets.only(bottom: SailStyleValues.padding30), + child: Column( + children: [ + RPCWidget(), + ], + ), + ), + ); + }), ); } } + +class EthereumRPCTabPageViewModel extends BaseViewModel { + EthereumRPC get _rpc => GetIt.I.get(); + + EthereumAddress? get account => _rpc.account; + + EthereumRPCTabPageViewModel() { + _rpc.addListener(notifyListeners); + } + + bool running = false; + + void createAccount() async { + if (account != null) { + throw Exception('you can only make one account using the GUI'); + } + + await _rpc.newAccount(); + } + + @override + void dispose() { + super.dispose(); + _rpc.removeListener(notifyListeners); + } +} diff --git a/lib/rpc/rpc_ethereum.dart b/lib/rpc/rpc_ethereum.dart index b89270e9..71bea766 100644 --- a/lib/rpc/rpc_ethereum.dart +++ b/lib/rpc/rpc_ethereum.dart @@ -5,7 +5,10 @@ import 'package:sidesail/rpc/models/core_transaction.dart'; import 'package:sidesail/rpc/rpc_sidechain.dart'; import 'package:web3dart/web3dart.dart'; -abstract class EthereumRPC extends SidechainSubRPC {} +abstract class EthereumRPC extends SidechainSubRPC { + EthereumAddress? account; + Future newAccount(); +} class EthereumRPCLive extends EthereumRPC { final sgweiPerSat = 1000000000; @@ -26,6 +29,11 @@ class EthereumRPCLive extends EthereumRPC { EthereumRPCLive._create() { chain = EthereumSidechain(); + try { + _setAndGetAccount(); + } catch (error) { + // + } } static Future create() async { @@ -40,7 +48,6 @@ class EthereumRPCLive extends EthereumRPC { connectionSettings = SingleNodeConnectionSettings('', 'localhost', 8545, '', ''); await createClient(); - await testConnection(); } @@ -52,12 +59,16 @@ class EthereumRPCLive extends EthereumRPC { @override Future<(double, double)> getBalance() async { - final account = await _account(); + final account = await _setAndGetAccount(); final balance = await _client.getBalance(account); return (balance.getInEther.toDouble(), 0.0); } - Future _account() async { + Future _setAndGetAccount() async { + if (account != null) { + return account!; + } + final accountFut = await callRAW('eth_accounts'); final accounts = await accountFut as List; @@ -65,15 +76,27 @@ class EthereumRPCLive extends EthereumRPC { throw Exception('Create account from cli using personal.newAccount before getting balance'); } - return EthereumAddress.fromHex(accounts[0] as String); + account = EthereumAddress.fromHex(accounts[0] as String); + return account!; + } + + @override + Future newAccount() async { + final accountFut = await callRAW('personal_newAccount', ['passphrase', 'passphrase']); + final accountStr = await accountFut as String; + + if (accountStr.isEmpty) { + throw Exception('Could not create account. Try using cli with personal.newAccount'); + } + + account = EthereumAddress.fromHex(accountStr); } // ignore: unused_element Future _deposit(int amountSat, int feeSat) async { final amount = sgweiPerSat * amountSat; final fee = sgweiPerSat * feeSat; - final account = await _account(); - final deposit = await callRAW('eth_deposit', [account.hex, _toHex(amount), _toHex(fee)]); + final deposit = await callRAW('eth_deposit', [account!.hex, _toHex(amount), _toHex(fee)]); return deposit as bool; } From 55fe2fb68c8152a2f0ab2feee44daf277a650ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Olav?= Date: Sat, 11 Nov 2023 19:59:59 +0100 Subject: [PATCH 3/8] tabs/console: make ether console slightly better --- lib/widgets/containers/tabs/console.dart | 6 +++--- .../containers/single_value_container.dart | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/widgets/containers/tabs/console.dart b/lib/widgets/containers/tabs/console.dart index 887b1d1d..0abdc49f 100644 --- a/lib/widgets/containers/tabs/console.dart +++ b/lib/widgets/containers/tabs/console.dart @@ -193,13 +193,13 @@ class ResultView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ SingleValueContainer( - width: 95, + width: 0, icon: result.error == null ? SailSVG.icon(SailSVGAsset.iconConfirmed, width: 13) : SailSVG.icon(SailSVGAsset.iconFailed, width: 13), copyable: true, - label: result.command.split(' ').first, - value: result.error ?? result.success, + customCopyValue: result.error ?? result.success, + value: '> ${result.command}\n${result.error ?? result.success}', ), ], ), diff --git a/packages/sail_ui/lib/widgets/containers/single_value_container.dart b/packages/sail_ui/lib/widgets/containers/single_value_container.dart index 356b9467..5621f266 100644 --- a/packages/sail_ui/lib/widgets/containers/single_value_container.dart +++ b/packages/sail_ui/lib/widgets/containers/single_value_container.dart @@ -5,21 +5,23 @@ import 'package:sail_ui/widgets/core/sail_snackbar.dart'; import 'package:sail_ui/widgets/core/sail_text.dart'; class SingleValueContainer extends StatelessWidget { - final String label; + final String? label; final dynamic value; final double width; final String? trailingText; final Widget? icon; final bool copyable; + final String? customCopyValue; const SingleValueContainer({ super.key, - required this.label, required this.value, required this.width, + this.label, this.trailingText, this.icon, this.copyable = true, + this.customCopyValue, }); @override @@ -33,16 +35,17 @@ class SingleValueContainer extends StatelessWidget { const SizedBox( width: 13, ), - SizedBox( - width: width, - child: SailText.secondary12(label), - ), + if (label != null) + SizedBox( + width: width, + child: SailText.secondary12(label!), + ), Expanded( child: SailScaleButton( onPressed: copyable ? () { - Clipboard.setData(ClipboardData(text: value.toString())); - showSnackBar(context, 'Copied $label'); + Clipboard.setData(ClipboardData(text: customCopyValue ?? value.toString())); + showSnackBar(context, 'Copied ${label ?? customCopyValue ?? value.toString()}'); } : null, child: SailText.primary12(value.toString()), From 943cc00fe61e93973d7d2406daf317e2a8136cb6 Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Mon, 13 Nov 2023 08:57:14 +0100 Subject: [PATCH 4/8] multi: add dialog util --- lib/pages/tabs/dashboard_tab_page.dart | 10 +++------- .../mainchain/transfer_mainchain_tab_route.dart | 11 +++-------- .../containers/tabs/dashboard_tab_widgets.dart | 13 ++++--------- .../tabs/transfer_mainchain_tab_widgets.dart | 15 ++++----------- lib/widgets/dialog.dart | 14 ++++++++++++++ 5 files changed, 28 insertions(+), 35 deletions(-) create mode 100644 lib/widgets/dialog.dart diff --git a/lib/pages/tabs/dashboard_tab_page.dart b/lib/pages/tabs/dashboard_tab_page.dart index b5a57c81..aa81bc37 100644 --- a/lib/pages/tabs/dashboard_tab_page.dart +++ b/lib/pages/tabs/dashboard_tab_page.dart @@ -6,7 +6,6 @@ import 'package:get_it/get_it.dart'; import 'package:intl/intl.dart'; import 'package:logger/logger.dart'; import 'package:sail_ui/sail_ui.dart'; -import 'package:sail_ui/theme/theme.dart'; import 'package:sail_ui/widgets/core/sail_text.dart'; import 'package:sidesail/config/sidechains.dart'; import 'package:sidesail/providers/transactions_provider.dart'; @@ -14,6 +13,7 @@ import 'package:sidesail/routing/router.dart'; import 'package:sidesail/rpc/models/core_transaction.dart'; import 'package:sidesail/rpc/rpc_sidechain.dart'; import 'package:sidesail/widgets/containers/tabs/dashboard_tab_widgets.dart'; +import 'package:sidesail/widgets/dialog.dart'; import 'package:stacked/stacked.dart'; @RoutePage() @@ -199,10 +199,8 @@ class DashboardTabViewModel extends BaseViewModel { } void send(BuildContext context) async { - final theme = SailTheme.of(context); - await showDialog( + await showThemedDialog( context: context, - barrierColor: theme.colors.background.withOpacity(0.4), builder: (BuildContext context) { return const SendOnSidechainAction(); }, @@ -210,10 +208,8 @@ class DashboardTabViewModel extends BaseViewModel { } void receive(BuildContext context) async { - final theme = SailTheme.of(context); - await showDialog( + await showThemedDialog( context: context, - barrierColor: theme.colors.background.withOpacity(0.4), builder: (BuildContext context) { return const ReceiveOnSidechainAction(); }, diff --git a/lib/pages/tabs/testchain/mainchain/transfer_mainchain_tab_route.dart b/lib/pages/tabs/testchain/mainchain/transfer_mainchain_tab_route.dart index dc3c6a9c..7e3ff408 100644 --- a/lib/pages/tabs/testchain/mainchain/transfer_mainchain_tab_route.dart +++ b/lib/pages/tabs/testchain/mainchain/transfer_mainchain_tab_route.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:logger/logger.dart'; import 'package:sail_ui/sail_ui.dart'; -import 'package:sail_ui/theme/theme.dart'; import 'package:sail_ui/widgets/core/sail_text.dart'; import 'package:sidesail/pages/tabs/dashboard_tab_page.dart'; import 'package:sidesail/providers/transactions_provider.dart'; @@ -11,6 +10,7 @@ import 'package:sidesail/routing/router.dart'; import 'package:sidesail/rpc/models/core_transaction.dart'; import 'package:sidesail/widgets/containers/tabs/dashboard_tab_widgets.dart'; import 'package:sidesail/widgets/containers/tabs/transfer_mainchain_tab_widgets.dart'; +import 'package:sidesail/widgets/dialog.dart'; import 'package:stacked/stacked.dart'; @RoutePage() @@ -95,11 +95,8 @@ class TransferMainchainTabViewModel extends BaseViewModel { } void pegOut(BuildContext context) async { - final theme = SailTheme.of(context); - - await showDialog( + await showThemedDialog( context: context, - barrierColor: theme.colors.background.withOpacity(0.4), builder: (BuildContext context) { return const PegOutAction(); }, @@ -107,10 +104,8 @@ class TransferMainchainTabViewModel extends BaseViewModel { } void pegIn(BuildContext context) async { - final theme = SailTheme.of(context); - await showDialog( + await showThemedDialog( context: context, - barrierColor: theme.colors.background.withOpacity(0.4), builder: (BuildContext context) { return const PegInAction(); }, diff --git a/lib/widgets/containers/tabs/dashboard_tab_widgets.dart b/lib/widgets/containers/tabs/dashboard_tab_widgets.dart index 4ac8a892..3ab7abc1 100644 --- a/lib/widgets/containers/tabs/dashboard_tab_widgets.dart +++ b/lib/widgets/containers/tabs/dashboard_tab_widgets.dart @@ -11,6 +11,7 @@ import 'package:sidesail/providers/transactions_provider.dart'; import 'package:sidesail/routing/router.dart'; import 'package:sidesail/rpc/rpc_testchain.dart'; import 'package:sidesail/widgets/containers/dashboard_action_modal.dart'; +import 'package:sidesail/widgets/dialog.dart'; import 'package:stacked/stacked.dart'; class DashboardGroup extends StatelessWidget { @@ -169,11 +170,9 @@ class SendOnSidechainViewModel extends BaseViewModel { return; } - final theme = SailTheme.of(context); - await showDialog( + await showThemedDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: theme.colors.background.withOpacity(0.9), title: SailText.primary13( 'Confirm send', ), @@ -232,11 +231,9 @@ class SendOnSidechainViewModel extends BaseViewModel { return; } - final theme = SailTheme.of(context); - await showDialog( + await showThemedDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: theme.colors.background.withOpacity(0.9), title: SailText.primary13( 'Success', ), @@ -256,11 +253,9 @@ class SendOnSidechainViewModel extends BaseViewModel { return; } - final theme = SailTheme.of(context); - await showDialog( + await showThemedDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: theme.colors.background.withOpacity(0.9), title: SailText.primary13( 'Failed', ), diff --git a/lib/widgets/containers/tabs/transfer_mainchain_tab_widgets.dart b/lib/widgets/containers/tabs/transfer_mainchain_tab_widgets.dart index 5bc63543..94b3e869 100644 --- a/lib/widgets/containers/tabs/transfer_mainchain_tab_widgets.dart +++ b/lib/widgets/containers/tabs/transfer_mainchain_tab_widgets.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:logger/logger.dart'; import 'package:sail_ui/sail_ui.dart'; -import 'package:sail_ui/theme/theme.dart'; import 'package:sail_ui/widgets/core/sail_text.dart'; import 'package:sidesail/providers/balance_provider.dart'; import 'package:sidesail/providers/transactions_provider.dart'; @@ -12,6 +11,7 @@ import 'package:sidesail/routing/router.dart'; import 'package:sidesail/rpc/rpc_mainchain.dart'; import 'package:sidesail/rpc/rpc_testchain.dart'; import 'package:sidesail/widgets/containers/dashboard_action_modal.dart'; +import 'package:sidesail/widgets/dialog.dart'; import 'package:stacked/stacked.dart'; class PegOutAction extends StatelessWidget { @@ -128,12 +128,9 @@ class PegOutViewModel extends BaseViewModel { return; } - final theme = SailTheme.of(context); - - await showDialog( + await showThemedDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: theme.colors.background.withOpacity(0.9), title: SailText.primary13( 'Confirm withdrawal', ), @@ -200,11 +197,9 @@ class PegOutViewModel extends BaseViewModel { // refresh transactions, but don't await, so dialog is showed instantly unawaited(_transactionsProvider.fetch()); - final theme = SailTheme.of(context); - await showDialog( + await showThemedDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: theme.colors.background.withOpacity(0.9), title: SailText.primary13( 'Success', ), @@ -226,11 +221,9 @@ class PegOutViewModel extends BaseViewModel { return; } - final theme = SailTheme.of(context); - await showDialog( + await showThemedDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: theme.colors.background.withOpacity(0.9), title: SailText.primary13( 'Failed', ), diff --git a/lib/widgets/dialog.dart b/lib/widgets/dialog.dart new file mode 100644 index 00000000..a49a63d3 --- /dev/null +++ b/lib/widgets/dialog.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; +import 'package:sail_ui/theme/theme.dart'; + +Future showThemedDialog({ + required BuildContext context, + required WidgetBuilder builder, +}) { + final theme = SailTheme.of(context); + return showDialog( + context: context, + barrierColor: theme.colors.background.withOpacity(0.4), + builder: builder, + ); +} From ecb97efcfda763a5e2aedf3a842d159250330aa1 Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Mon, 13 Nov 2023 08:57:39 +0100 Subject: [PATCH 5/8] eth: enable personal API in Docker node, give proper error message --- docker-compose.yml | 7 ++++++- lib/rpc/rpc_ethereum.dart | 32 +++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7aecd9cc..70fba457 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,7 +56,12 @@ services: - 8551:8551 # Authenticated RPC command: - --http # enable HTTP RPC - - --http.addr=0.0.0.0 # TODO: add auth config? --authrpc.jwtsecret, --authrpc.addr=0.0.0.0, --authrpc.vhosts=* + # 'personal' API is needed for replicating the old ETH tutorial + # made by Paul. Think it's some sort of wallet functionality? Not sure, + # tbh. Went looking for a list of available APIs, without finding + # anything. + - --http.api=net,eth,personal,web3 + - --http.addr=0.0.0.0 - --main.host=mainchain - --main.password=password - --main.user=user diff --git a/lib/rpc/rpc_ethereum.dart b/lib/rpc/rpc_ethereum.dart index 71bea766..d2840de4 100644 --- a/lib/rpc/rpc_ethereum.dart +++ b/lib/rpc/rpc_ethereum.dart @@ -4,6 +4,7 @@ import 'package:sidesail/pages/tabs/settings/node_settings_tab.dart'; import 'package:sidesail/rpc/models/core_transaction.dart'; import 'package:sidesail/rpc/rpc_sidechain.dart'; import 'package:web3dart/web3dart.dart'; +import 'package:web3dart/json_rpc.dart' as jsonrpc; abstract class EthereumRPC extends SidechainSubRPC { EthereumAddress? account; @@ -17,7 +18,16 @@ class EthereumRPCLive extends EthereumRPC { @override Future callRAW(String method, [params]) async { - return _client.makeRPCCall(method, params); + try { + final res = await _client.makeRPCCall(method, params); + return res; + } on jsonrpc.RPCError catch (err) { + const magicErrCode = -32601; // no clue what this is + if (err.errorCode == magicErrCode && method.startsWith('personal')) { + throw "The 'personal' API is not enabled on your Ethereum node. Add the \n`--http.api=personal` argument, and try again."; + } + rethrow; + } } // Apparently Ethereum doesn't have a conf file? @@ -82,11 +92,11 @@ class EthereumRPCLive extends EthereumRPC { @override Future newAccount() async { - final accountFut = await callRAW('personal_newAccount', ['passphrase', 'passphrase']); + final accountFut = await callRAW('personal_newAccount', ['passphrase']); final accountStr = await accountFut as String; if (accountStr.isEmpty) { - throw Exception('Could not create account. Try using cli with personal.newAccount'); + throw Exception('Could not create account. Try using CLI with personal.newAccount'); } account = EthereumAddress.fromHex(accountStr); @@ -156,6 +166,22 @@ final ethRpcMethods = [ 'eth_getFilterLogs', 'eth_getLogs', + // Wallet (?) stuff + 'personal_newAccount', + 'personal_importRawKey', + 'personal_unlockAccount', + 'personal_ecRecover', + 'personal_sign', + 'personal_sendTransaction', + 'personal_lockAccount', + 'personal_listAccounts', + 'personal_openWallet', + 'personal_deriveAccount', + 'personal_signTransaction', + 'personal_unpair', + 'personal_initializeWallet', + 'personal_listWallets', + // Sidechain specific RPC calls 'eth_deposit', 'eth_withdraw', From 8c51228dfc6b604ee4d269a56998dfd3fd32e7d7 Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Mon, 13 Nov 2023 08:58:19 +0100 Subject: [PATCH 6/8] eth: show dialog with error message on create account --- .../tabs/ethereum/ethereum_rpc_tab_page.dart | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart b/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart index c01b448a..2907decc 100644 --- a/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart +++ b/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart @@ -12,6 +12,7 @@ import 'package:web3dart/web3dart.dart'; @RoutePage() class EthereumRPCTabPage extends StatelessWidget { AppRouter get router => GetIt.I.get(); + AppRouter get _router => GetIt.I.get(); const EthereumRPCTabPage({super.key}); @@ -30,7 +31,29 @@ class EthereumRPCTabPage extends StatelessWidget { if (viewModel.account == null) SailButton.primary( 'Create account', - onPressed: viewModel.createAccount, + onPressed: () async { + try { + await viewModel.createAccount(); + } catch (err) { + if (!context.mounted) { + return; + } + + await showDialog( + context: context, + builder: (context) => AlertDialog( + title: SailText.primary20('Could not create account'), + content: SailText.secondary13(err.toString()), + actions: [ + TextButton( + onPressed: () => _router.popUntilRoot(), + child: SailText.primary13('OK'), + ), + ], + ), + ); + } + }, size: ButtonSize.small, ), if (viewModel.account == null) @@ -64,7 +87,7 @@ class EthereumRPCTabPageViewModel extends BaseViewModel { bool running = false; - void createAccount() async { + Future createAccount() async { if (account != null) { throw Exception('you can only make one account using the GUI'); } From 948ade8822e0771851ef20d5bb60ebc51c061f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Olav?= Date: Mon, 13 Nov 2023 17:02:33 +0100 Subject: [PATCH 7/8] rpc/ethereum: add all rpc endpoints found in attach --- docker-compose.yml | 2 +- lib/rpc/rpc_ethereum.dart | 89 ++++++++++++++++++++++++++++++--------- 2 files changed, 71 insertions(+), 20 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 70fba457..17964cef 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -60,7 +60,7 @@ services: # made by Paul. Think it's some sort of wallet functionality? Not sure, # tbh. Went looking for a list of available APIs, without finding # anything. - - --http.api=net,eth,personal,web3 + - --http.api=eth,web3,personal,admin,jeth,miner,net,txpool - --http.addr=0.0.0.0 - --main.host=mainchain - --main.password=password diff --git a/lib/rpc/rpc_ethereum.dart b/lib/rpc/rpc_ethereum.dart index d2840de4..bfd566a8 100644 --- a/lib/rpc/rpc_ethereum.dart +++ b/lib/rpc/rpc_ethereum.dart @@ -3,8 +3,8 @@ import 'package:sidesail/config/sidechains.dart'; import 'package:sidesail/pages/tabs/settings/node_settings_tab.dart'; import 'package:sidesail/rpc/models/core_transaction.dart'; import 'package:sidesail/rpc/rpc_sidechain.dart'; -import 'package:web3dart/web3dart.dart'; import 'package:web3dart/json_rpc.dart' as jsonrpc; +import 'package:web3dart/web3dart.dart'; abstract class EthereumRPC extends SidechainSubRPC { EthereumAddress? account; @@ -123,11 +123,15 @@ class EthereumRPCLive extends EthereumRPC { /// List of all known RPC methods available / final ethRpcMethods = [ + // Sidechain specific RPC calls + 'eth_deposit', + 'eth_withdraw', + 'eth_getUnspentWithdrawals', + 'eth_refund', + 'web3_clientVersion', 'web3_sha3', - 'net_version', - 'net_listening', - 'net_peerCount', + 'eth_syncing', 'eth_coinbase', 'eth_chainId', @@ -167,24 +171,71 @@ final ethRpcMethods = [ 'eth_getLogs', // Wallet (?) stuff - 'personal_newAccount', - 'personal_importRawKey', - 'personal_unlockAccount', - 'personal_ecRecover', - 'personal_sign', - 'personal_sendTransaction', - 'personal_lockAccount', + 'personal_getListAccounts', 'personal_listAccounts', 'personal_openWallet', - 'personal_deriveAccount', - 'personal_signTransaction', + 'personal_unlockAccount', + 'personal_getListWallets', + 'personal_listWallets', + 'personal_sendTransaction', 'personal_unpair', + 'personal_deriveAccount', + 'personal_importRawKey', + 'personal_lockAccount', + 'personal_sign', + 'personal_ecRecover', 'personal_initializeWallet', - 'personal_listWallets', + 'personal_newAccount', + 'personal_signTransaction', - // Sidechain specific RPC calls - 'eth_deposit', - 'eth_withdraw', - 'eth_getUnspentWithdrawals', - 'eth_refund', + 'admin_startHTTP', + 'admin_addPeer', + 'admin_importChain', + 'admin_startRPC', + 'admin_addTrustedPeer', + 'admin_startWS', + 'admin_nodeInfo', + 'admin_stopHTTP', + 'admin_peers', + 'admin_stopRPC', + 'admin_datadir', + 'admin_stopWS', + 'admin_exportChain', + 'admin_removePeer', + 'admin_getDatadir', + 'admin_removeTrustedPeer', + 'admin_getNodeInfo', + 'admin_sleep', + 'admin_getPeers', + 'admin_sleepBlocks', + 'admin_clearHistory', + + 'jeth_newAccount', + 'jeth_sign', + 'jeth_unlockAccount', + 'jeth_openWallet', + + 'miner_setGasLimit', + 'miner_stop', + 'miner_getHashrate', + 'miner_setGasPrice', + 'miner_setEtherbase', + 'miner_setRecommitInterval', + 'miner_setExtra', + 'miner_start', + + 'net_getListening', + 'net_getVersion', + 'net_peerCount', + 'net_getPeerCount', + 'net_listening', + 'net_version', + + 'txpool_contentFrom', + 'txpool_getStatus', + 'txpool_getContent', + 'txpool_content', + 'txpool_getInspect', + 'txpool_inspect', + 'txpool_status', ]; From 28ca24d9cb4081be197b5f974b4a8b7966754755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Olav?= Date: Mon, 13 Nov 2023 17:16:59 +0100 Subject: [PATCH 8/8] tabs/ethereum: show loader when creating account --- lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart | 4 ++++ lib/rpc/rpc_ethereum.dart | 3 +++ 2 files changed, 7 insertions(+) diff --git a/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart b/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart index 2907decc..bed3b92e 100644 --- a/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart +++ b/lib/pages/tabs/ethereum/ethereum_rpc_tab_page.dart @@ -54,6 +54,7 @@ class EthereumRPCTabPage extends StatelessWidget { ); } }, + loading: viewModel.isBusy, size: ButtonSize.small, ), if (viewModel.account == null) @@ -88,11 +89,14 @@ class EthereumRPCTabPageViewModel extends BaseViewModel { bool running = false; Future createAccount() async { + setBusy(true); if (account != null) { throw Exception('you can only make one account using the GUI'); } await _rpc.newAccount(); + setBusy(false); + notifyListeners(); } @override diff --git a/lib/rpc/rpc_ethereum.dart b/lib/rpc/rpc_ethereum.dart index bfd566a8..891ef1a0 100644 --- a/lib/rpc/rpc_ethereum.dart +++ b/lib/rpc/rpc_ethereum.dart @@ -71,6 +71,8 @@ class EthereumRPCLive extends EthereumRPC { Future<(double, double)> getBalance() async { final account = await _setAndGetAccount(); final balance = await _client.getBalance(account); + + notifyListeners(); return (balance.getInEther.toDouble(), 0.0); } @@ -100,6 +102,7 @@ class EthereumRPCLive extends EthereumRPC { } account = EthereumAddress.fromHex(accountStr); + notifyListeners(); } // ignore: unused_element