Electrum: How to manage two wallets using JSON RPC? (multiple wallets, specify wallet on RPC, switch wallets)

Created on 23 Jan 2018  Â·  10Comments  Â·  Source: spesmilo/electrum

Hello,
I am making a service which using two wallets. How can I use JSON RPC for switching between the wallets?
For example, I can use key "w" in cmd:
./electrum listaddresses -w ~/.electrum/wallets/wallet_2
In this case, I receive the addresses of the second wallet.
But, how can I pass the key using JSON RPC?
{"id":1,"method":"listaddresses","params":[{"w": "/home/superdevX/.electrum/wallets/wallet_2"}]}
This does not work. In this case, I receive the addresses of the first default wallet.
What am I doing wrong?

CLRPC ▶ enhancement ✨

Most helpful comment

ahh.. I was testing on python 3.5.3.

$ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04) 
[GCC 6.3.0 20170118] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os; os.path.join(None, "/asd/qwe")
'/asd/qwe'
> python3.5
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os; os.path.join(None, "/asd/qwe")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\ntpath.py", line 113, in join
    genericpath._check_arg_types('join', path, *paths)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\genericpath.py", line 143, in _check_arg_types
    (funcname, s.__class__.__name__)) from None
TypeError: join() argument must be str or bytes, not 'NoneType'

All 10 comments

I am not sure whether this is implemented as a single command; as in, specifying the wallet as an extra argument in a call.
However, you can use load_wallet to switch between wallets.

curl --data-binary '{"id":"curltext","method":"daemon","params":{"config_options":{"subcommand":"load_wallet", "wallet_path":"/home/user/.electrum/testnet/wallets/test_std_asdasd", "password":"1234"}}}' http://user:[email protected]:7778
curl --data-binary '{"id":"curltext","method":"getseed"}' http://user:[email protected]:7778

curl --data-binary '{"id":"curltext","method":"daemon","params":{"config_options":{"subcommand":"load_wallet", "wallet_path":"/home/user/.electrum/testnet/wallets/test_segwit_asdasd", "password":"1234"}}}' http://user:[email protected]:7778
curl --data-binary '{"id":"curltext","method":"getseed"}' http://user:[email protected]:7778

@SomberNight

I've tried your suggestion but I get an error:

curl --data-binary '{"id":"curltext","method":"daemon","params":{"config_options":{"subcommand":"load_wallet", "wallet_path":"/Users/ilijatovilo/.electrum/testnet/wallets/default_wallet_2"}}}' http://username:[email protected]:7777

Invalid call parameters:

{"result": null, "id": "curltext", "error": {"code": -32602, "message": "Invalid parameters: expected str, bytes or os.PathLike object, not NoneType"}}

The wallet is not encrypted. Adding an empty password property doesn't help.

But since this is a workaround I would rather contribute to support the -w parameter. Can you give me some information on where (what files) this should be added?

I've just tested it again, and it still works for me -- on linux; maybe it fails on Mac?

Can you give me some information on where (what files) this should be added?

You should look at the main script and commands.py and daemon.py

Start here:
https://github.com/spesmilo/electrum/blob/e7ef4aa4f6fa34fc8a96dcc9def198b76a6b9b22/electrum/daemon.py#L261

Interesting. Shouldn't running electrum daemon load_wallet -w ... do exactly the same thing? Because that is working just fine.

I found out why this isn't working for me. It's this line:

https://github.com/spesmilo/electrum/blob/master/electrum/simple_config.py#L244

For some reason self.get('cwd') returns None for me which is why os.path.join gives me a type error. This happens even though in run_electrum.py config_options['cwd'] = os.getcwd() is executed. I was able to make it work by changing the line to to:

if self.get('wallet_path'):
    return self.get('wallet_path')

@SomberNight Do you know why this is happening? This makes no sense to me. If electrum tries to combine the path with cwd every time your example shouldn't work. Do you have a suggestion on what to do here?

@SomberNight I've just tested this on a colleagues Windows machine, same issue. There's currently no way to run this without modifying the line above. Can you comment on this? I'll gladly make a pull request but first I need to understand what the behaviour is supposed to be.

I have the same problem as @iluuu1994 on Windows. I did some research and here are results:

  1. As @iluuu1994 explained, error occurs inside config.get_wallet_path function (simple_config.py, line 244)
    Key 'cwd' is not defined in the config, so self.get('cwd') returns None and exception is fired.
  2. Key 'cwd' is not defined if config is created by run_daemon function (daemon.py, line 169) since config there is created from config_options, received by JSONRPC request, and no extra keys are added. Config, created in run_electrum, where config_options['cwd'] = os.getcwd() is executed is not passed to the run_daemon function.
  3. So, as a workaround i`d recommend to add 'cwd' key to the 'config_options' of the JSONRPC request:
curl --data-binary '{"id":1,"method":"daemon","params":{"config_options":{"subcommand":"load_wallet", "wallet_path":"/home/user/.electrum/wallets/test_std_asdasd", "password":"123", "cwd":""}}}' http://user:[email protected]:7778

If you provide absolute path for 'wallet_path', empty string for 'cwd' would be ok. It works for me on Windows.

  1. One of the possible fixes of this issue could be moving setting 'cwd' key from run_electrum (line 377) to the SimpleConfig __init__ function (simple_config.py, line 83):
self.cmdline_options['cwd'] = os.getcwd()

or even direct use of os.getcwd() inside config.get_wallet_path (simple_config.py, line 244):

return os.path.join(os.getcwd(), self.get('wallet_path'))

because this function is the only place, where the value of config key 'cwd' is used.

ahh.. I was testing on python 3.5.3.

$ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04) 
[GCC 6.3.0 20170118] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os; os.path.join(None, "/asd/qwe")
'/asd/qwe'
> python3.5
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os; os.path.join(None, "/asd/qwe")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\ntpath.py", line 113, in join
    genericpath._check_arg_types('join', path, *paths)
  File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\genericpath.py", line 143, in _check_arg_types
    (funcname, s.__class__.__name__)) from None
TypeError: join() argument must be str or bytes, not 'NoneType'

@SomberNight It's working now, thanks!

Note that on current master you can specify the wallet as an argument to most RPCs:

curl --data-binary '{"id":"curltext","jsonrpc":"2.0","method":"getseed","params":{"password":"123456", "wallet":"~/.electrum/testnet/wallets/test_segwit_2"}}' http://user:[email protected]:7777
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Kixunil picture Kixunil  Â·  4Comments

cculianu picture cculianu  Â·  5Comments

Giszmo picture Giszmo  Â·  5Comments

GuestInCorle picture GuestInCorle  Â·  3Comments

ZoZoRocks picture ZoZoRocks  Â·  4Comments