Skip to content

Commit

Permalink
Merge c41fc14 into d0aad8c
Browse files Browse the repository at this point in the history
  • Loading branch information
jessopb committed Oct 18, 2022
2 parents d0aad8c + c41fc14 commit 8dbeadd
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 13 deletions.
19 changes: 9 additions & 10 deletions lbry/extras/daemon/daemon.py
Expand Up @@ -1330,7 +1330,7 @@ async def jsonrpc_wallet_create(
@requires("wallet")
async def jsonrpc_wallet_export(self, password=None, wallet_id=None):
"""
Export wallet data
Exports encrypted wallet data if password is supplied; otherwise plain JSON.
Wallet must be unlocked to perform this operation.
Expand All @@ -1342,18 +1342,19 @@ async def jsonrpc_wallet_export(self, password=None, wallet_id=None):
--wallet_id=<wallet_id> : (str) wallet being exported
Returns:
(str) data
(str) data: base64-encoded encrypted wallet, or cleartext JSON
"""
assert password is not None, "passwordless use is not implemented yet"
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
encrypted = wallet.pack(password)
return encrypted.decode()
if password:
return wallet.pack(password).decode()
return wallet.to_json()

@requires("wallet")
async def jsonrpc_wallet_import(self, data, password=None, wallet_id=None, blocking=False):
"""
Import wallet data and merge accounts, preferences.
Import wallet data and merge accounts and preferences. Data is expected to be JSON if
password is not supplied.
Wallet must be unlocked to perform this operation.
Expand All @@ -1368,9 +1369,8 @@ async def jsonrpc_wallet_import(self, data, password=None, wallet_id=None, block
--blocking : (bool) wait until any new accounts have merged
Returns:
(str) data
(str) base64-encoded encrypted wallet, or cleartext JSON
"""
assert not data.strip().startswith("{"), "unencrypted wallet import is not implemented yet"
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
added_accounts, merged_accounts = wallet.merge(self.wallet_manager, password, data)
for new_account in itertools.chain(added_accounts, merged_accounts):
Expand All @@ -1384,8 +1384,7 @@ async def jsonrpc_wallet_import(self, data, password=None, wallet_id=None, block
for new_account in added_accounts:
asyncio.create_task(self.ledger.subscribe_account(new_account))
wallet.save()
encrypted = wallet.pack(password)
return encrypted.decode()
return await self.jsonrpc_wallet_export(password=password, wallet_id=wallet_id)

@requires("wallet")
async def jsonrpc_wallet_add(self, wallet_id):
Expand Down
12 changes: 9 additions & 3 deletions lbry/wallet/wallet.py
Expand Up @@ -139,6 +139,10 @@ def to_dict(self, encrypt_password: str = None):
'accounts': [a.to_dict(encrypt_password) for a in self.accounts]
}

def to_json(self):
assert not self.is_locked, "Cannot serialize a wallet with locked/encrypted accounts."
return json.dumps(self.to_dict())

def save(self):
if self.preferences.get(ENCRYPT_ON_DISK, False):
if self.encryption_password is not None:
Expand All @@ -165,8 +169,7 @@ def hash(self) -> bytes:

def pack(self, password):
assert not self.is_locked, "Cannot pack a wallet with locked/encrypted accounts."
new_data = json.dumps(self.to_dict())
new_data_compressed = zlib.compress(new_data.encode())
new_data_compressed = zlib.compress(self.to_json().encode())
return better_aes_encrypt(password, new_data_compressed)

@classmethod
Expand All @@ -186,7 +189,10 @@ def merge(self, manager: 'WalletManager',
password: str, data: str) -> (List['Account'], List['Account']):
assert not self.is_locked, "Cannot sync apply on a locked wallet."
added_accounts, merged_accounts = [], []
decrypted_data = self.unpack(password, data)
if password:
decrypted_data = self.unpack(password, data)
else:
decrypted_data = json.loads(data)
self.preferences.merge(decrypted_data.get('preferences', {}))
for account_dict in decrypted_data['accounts']:
ledger = manager.get_or_create_ledger(account_dict['ledger'])
Expand Down
10 changes: 10 additions & 0 deletions tests/integration/blockchain/test_wallet_commands.py
Expand Up @@ -491,3 +491,13 @@ async def test_wallet_import_and_export(self):
daemon2.wallet_manager.default_account.channel_keys,
daemon.wallet_manager.default_wallet.accounts[1].channel_keys
)

# test without passwords
data = await daemon2.jsonrpc_wallet_export()
json_data = json.loads(data)
self.assertEqual(json_data["name"], "Wallet")
self.assertNotIn("four", json_data["preferences"])

json_data["preferences"]["four"] = {"value": 4, "ts": 0}
await daemon.jsonrpc_wallet_import(data=json.dumps(json_data), blocking=True)
self.assertEqual(daemon.jsonrpc_preference_get("four"), {"four": 4})

0 comments on commit 8dbeadd

Please sign in to comment.