user setitngs
This commit is contained in:
parent
52091044e4
commit
4042871ae6
|
@ -1,5 +1,7 @@
|
|||
from typing import Optional
|
||||
from typing import Any
|
||||
import aiosqlite
|
||||
|
||||
from src.util.byte_types import hexstr_to_bytes
|
||||
from src.util.streamable import Streamable
|
||||
|
||||
|
||||
|
@ -36,7 +38,7 @@ class KeyValStore:
|
|||
await cursor.close()
|
||||
await self.db_connection.commit()
|
||||
|
||||
async def get(self, key: str) -> Optional[str]:
|
||||
async def get_object(self, key: str, type: Any) -> Any:
|
||||
"""
|
||||
Return bytes representation of stored object
|
||||
"""
|
||||
|
@ -50,9 +52,9 @@ class KeyValStore:
|
|||
if row is None:
|
||||
return None
|
||||
|
||||
return row[1]
|
||||
return type.from_bytes(hexstr_to_bytes(row[1]))
|
||||
|
||||
async def set(self, key: str, obj: Streamable):
|
||||
async def set_object(self, key: str, obj: Streamable):
|
||||
"""
|
||||
Adds object to key val store
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
from src.wallet.settings.settings_objects import BackupInitialized
|
||||
|
||||
default_backup_initialized = BackupInitialized(False, False, False, True)
|
||||
|
||||
default_settings = {BackupInitialized.__name__: default_backup_initialized}
|
|
@ -0,0 +1,16 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
from src.util.streamable import streamable, Streamable
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@streamable
|
||||
class BackupInitialized(Streamable):
|
||||
"""
|
||||
Stores user decision regarding import of backup info
|
||||
"""
|
||||
|
||||
user_initialized: bool # Stores if user made a selection in UI. (Skip vs Import backup)
|
||||
user_skipped: bool # Stores if user decided to skip import of backup info
|
||||
backup_info_imported: bool # Stores if backup info has been imported
|
||||
new_wallet: bool # Stores if this wallet is newly created / not restored from backup
|
|
@ -0,0 +1,82 @@
|
|||
from typing import Any, Dict
|
||||
|
||||
from src.util.byte_types import hexstr_to_bytes
|
||||
from src.wallet.key_val_store import KeyValStore
|
||||
import logging
|
||||
|
||||
from src.wallet.settings.default_settings import default_settings
|
||||
from src.wallet.settings.settings_objects import BackupInitialized
|
||||
|
||||
|
||||
class UserSettings:
|
||||
settings: Dict[str, Any]
|
||||
basic_store: KeyValStore
|
||||
|
||||
@staticmethod
|
||||
async def create(
|
||||
store: KeyValStore, name: str = None,
|
||||
):
|
||||
self = UserSettings()
|
||||
self.basic_store = store
|
||||
if name:
|
||||
self.log = logging.getLogger(name)
|
||||
else:
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.settings = {}
|
||||
await self.load_store()
|
||||
return self
|
||||
|
||||
def _keys(self):
|
||||
all_keys = [BackupInitialized]
|
||||
return all_keys
|
||||
|
||||
async def load_store(self):
|
||||
keys = self._keys()
|
||||
for setting in keys:
|
||||
name = setting.__name__
|
||||
hex_str = await self.basic_store.get_object(name, BackupInitialized)
|
||||
if hex_str is None:
|
||||
object = default_settings[name]
|
||||
else:
|
||||
bytes = hexstr_to_bytes(hex_str)
|
||||
object = setting.from_bytes(bytes)
|
||||
|
||||
self.settings[name] = object
|
||||
|
||||
async def setting_updated(self, setting: Any):
|
||||
name = setting.__class__.__name__
|
||||
await self.basic_store.set_object(name, setting)
|
||||
self.settings[name] = setting
|
||||
|
||||
async def user_skipped_backup_import(self):
|
||||
new = BackupInitialized(
|
||||
user_initialized=True,
|
||||
user_skipped=True,
|
||||
backup_info_imported=False,
|
||||
new_wallet=False,
|
||||
)
|
||||
await self.setting_updated(new)
|
||||
return new
|
||||
|
||||
async def user_imported_backup(self):
|
||||
new = BackupInitialized(
|
||||
user_initialized=True,
|
||||
user_skipped=False,
|
||||
backup_info_imported=True,
|
||||
new_wallet=False,
|
||||
)
|
||||
await self.setting_updated(new)
|
||||
return new
|
||||
|
||||
async def user_created_new_wallet(self):
|
||||
new = BackupInitialized(
|
||||
user_initialized=True,
|
||||
user_skipped=False,
|
||||
backup_info_imported=False,
|
||||
new_wallet=True,
|
||||
)
|
||||
await self.setting_updated(new)
|
||||
return new
|
||||
|
||||
def get_backup_settings(self):
|
||||
return self.settings[BackupInitialized.__name__]
|
|
@ -27,6 +27,7 @@ from src.util.ints import uint32, uint64
|
|||
from src.types.sized_bytes import bytes32
|
||||
from src.util.api_decorators import api_request
|
||||
from src.wallet.derivation_record import DerivationRecord
|
||||
from src.wallet.settings.settings_objects import BackupInitialized
|
||||
from src.wallet.transaction_record import TransactionRecord
|
||||
from src.wallet.util.wallet_types import WalletType
|
||||
from src.wallet.wallet_action import WalletAction
|
||||
|
@ -110,10 +111,13 @@ class WalletNode:
|
|||
self.potential_header_hashes = {}
|
||||
self.state_changed_callback = None
|
||||
self.wallet_state_manager = None
|
||||
self.backup_initialized = False # Delay first launch sync after user imports backup info or decides to skip
|
||||
self.sync_generator_task = None
|
||||
self.server = None
|
||||
|
||||
async def _start(self, public_key_fingerprint: Optional[int] = None) -> bool:
|
||||
async def _start(
|
||||
self, public_key_fingerprint: Optional[int] = None, new_wallet: bool = False
|
||||
) -> bool:
|
||||
self._shut_down = False
|
||||
private_keys = self.keychain.get_all_private_keys()
|
||||
if len(private_keys) == 0:
|
||||
|
@ -142,7 +146,19 @@ class WalletNode:
|
|||
self.wallet_state_manager = await WalletStateManager.create(
|
||||
private_key, self.config, path, self.constants
|
||||
)
|
||||
|
||||
assert self.wallet_state_manager is not None
|
||||
|
||||
if new_wallet is True:
|
||||
await self.wallet_state_manager.user_settings.user_created_new_wallet()
|
||||
|
||||
backup_settings: BackupInitialized = self.wallet_state_manager.user_settings.get_backup_settings()
|
||||
if backup_settings.user_initialized is False:
|
||||
self.backup_initialized = False
|
||||
return False
|
||||
|
||||
self.backup_initialized = True
|
||||
|
||||
if self.state_changed_callback is not None:
|
||||
self.wallet_state_manager.set_callback(self.state_changed_callback)
|
||||
|
||||
|
@ -151,7 +167,7 @@ class WalletNode:
|
|||
|
||||
def _close(self):
|
||||
self._shut_down = True
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
self.wsm_close_task = asyncio.create_task(
|
||||
self.wallet_state_manager.close_all_stores()
|
||||
|
@ -161,7 +177,7 @@ class WalletNode:
|
|||
async def _await_closed(self):
|
||||
if self.sync_generator_task is not None:
|
||||
await self.sync_generator_task.aclose()
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
await self.wsm_close_task
|
||||
|
||||
|
@ -175,12 +191,12 @@ class WalletNode:
|
|||
self.wallet_state_manager.set_pending_callback(self._pending_tx_handler)
|
||||
|
||||
def _pending_tx_handler(self):
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
asyncio.ensure_future(self._resend_queue())
|
||||
|
||||
async def _action_messages(self) -> List[OutboundMessage]:
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return []
|
||||
actions: List[
|
||||
WalletAction
|
||||
|
@ -202,7 +218,7 @@ class WalletNode:
|
|||
return result
|
||||
|
||||
async def _resend_queue(self):
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
if self._shut_down:
|
||||
return
|
||||
|
@ -216,7 +232,7 @@ class WalletNode:
|
|||
self.server.push_message(msg)
|
||||
|
||||
async def _messages_to_resend(self) -> List[OutboundMessage]:
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return []
|
||||
messages: List[OutboundMessage] = []
|
||||
|
||||
|
@ -246,7 +262,7 @@ class WalletNode:
|
|||
self.server = server
|
||||
|
||||
async def _on_connect(self) -> AsyncGenerator[OutboundMessage, None]:
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
messages = await self._messages_to_resend()
|
||||
|
||||
|
@ -254,7 +270,7 @@ class WalletNode:
|
|||
yield msg
|
||||
|
||||
def _num_needed_peers(self) -> int:
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return 0
|
||||
assert self.server is not None
|
||||
diff = self.config["target_peer_count"] - len(
|
||||
|
@ -327,7 +343,7 @@ class WalletNode:
|
|||
Wallet has fallen far behind (or is starting up for the first time), and must be synced
|
||||
up to the LCA of the blockchain.
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
|
||||
# 1. Get all header hashes
|
||||
|
@ -648,7 +664,7 @@ class WalletNode:
|
|||
This is called when we have finished a block (which means we have downloaded the header,
|
||||
as well as the relevant additions and removals for the wallets).
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return None
|
||||
self.log.info(
|
||||
f"Finishing block {block_record.header_hash} at height {block_record.height}"
|
||||
|
@ -703,7 +719,7 @@ class WalletNode:
|
|||
This is an ack for our previous SendTransaction call. This removes the transaction from
|
||||
the send queue if we have sent it to enough nodes.
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
if ack.status == MempoolInclusionStatus.SUCCESS:
|
||||
self.log.info(
|
||||
|
@ -731,7 +747,7 @@ class WalletNode:
|
|||
"""
|
||||
Receipt of proof hashes, used during sync for interactive weight verification protocol.
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
if not self.wallet_state_manager.sync_mode:
|
||||
self.log.warning("Receiving proof hashes while not syncing.")
|
||||
|
@ -746,7 +762,7 @@ class WalletNode:
|
|||
Response containing all header hashes after a point. This is used to find the fork
|
||||
point between our current blockchain, and the current heaviest tip.
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
if not self.wallet_state_manager.sync_mode:
|
||||
self.log.warning("Receiving header hashes while not syncing.")
|
||||
|
@ -761,7 +777,7 @@ class WalletNode:
|
|||
Error in requesting all header hashes.
|
||||
"""
|
||||
self.log.error("All header hashes after request rejected")
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
self.header_hashes_error = True
|
||||
|
||||
|
@ -771,7 +787,7 @@ class WalletNode:
|
|||
Notification from full node that a new LCA (Least common ancestor of the three blockchain
|
||||
tips) has been added to the full node.
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
if self._shut_down:
|
||||
return
|
||||
|
@ -817,7 +833,7 @@ class WalletNode:
|
|||
The full node responds to our RequestHeader call. We cannot finish this block
|
||||
until we have the required additions / removals for our wallets.
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
while True:
|
||||
if self._shut_down:
|
||||
|
@ -927,7 +943,7 @@ class WalletNode:
|
|||
The full node has rejected our request for a header.
|
||||
"""
|
||||
# TODO(mariano): implement
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
self.log.error("Header request rejected")
|
||||
|
||||
|
@ -937,7 +953,7 @@ class WalletNode:
|
|||
The full node has responded with the additions for a block. We will use this
|
||||
to try to finish the block, and add it to the state.
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
if self._shut_down:
|
||||
return
|
||||
|
@ -1080,7 +1096,7 @@ class WalletNode:
|
|||
The full node has responded with the removals for a block. We will use this
|
||||
to try to finish the block, and add it to the state.
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
if self._shut_down:
|
||||
return
|
||||
|
@ -1172,7 +1188,7 @@ class WalletNode:
|
|||
The full node has rejected our request for removals.
|
||||
"""
|
||||
# TODO(mariano): implement
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
self.log.error("Removals request rejected")
|
||||
|
||||
|
@ -1184,7 +1200,7 @@ class WalletNode:
|
|||
The full node has rejected our request for additions.
|
||||
"""
|
||||
# TODO(mariano): implement
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
self.log.error("Additions request rejected")
|
||||
|
||||
|
@ -1193,7 +1209,7 @@ class WalletNode:
|
|||
"""
|
||||
The full node respond with transaction generator
|
||||
"""
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
wrapper = response.generatorResponse
|
||||
if wrapper.generator is not None:
|
||||
|
@ -1210,6 +1226,6 @@ class WalletNode:
|
|||
The full node rejected our request for generator
|
||||
"""
|
||||
# TODO (Straya): implement
|
||||
if self.wallet_state_manager is None:
|
||||
if self.wallet_state_manager is None or self.backup_initialized is False:
|
||||
return
|
||||
self.log.info("generator rejected")
|
||||
|
|
|
@ -23,6 +23,7 @@ from src.util.hash import std_hash
|
|||
from src.wallet.cc_wallet.cc_wallet import CCWallet
|
||||
from src.wallet.cc_wallet import cc_wallet_puzzles
|
||||
from src.wallet.key_val_store import KeyValStore
|
||||
from src.wallet.settings.user_settings import UserSettings
|
||||
from src.wallet.trade_manager import TradeManager
|
||||
from src.wallet.transaction_record import TransactionRecord
|
||||
from src.wallet.block_record import BlockRecord
|
||||
|
@ -86,6 +87,7 @@ class WalletStateManager:
|
|||
|
||||
trade_manager: TradeManager
|
||||
generate_count: int
|
||||
user_settings: UserSettings
|
||||
|
||||
@staticmethod
|
||||
async def create(
|
||||
|
@ -115,6 +117,7 @@ class WalletStateManager:
|
|||
self.basic_store = await KeyValStore.create(self.db_connection)
|
||||
self.trade_manager = await TradeManager.create(self, self.db_connection)
|
||||
|
||||
self.user_settings = await UserSettings.create(self.basic_store)
|
||||
self.lca = None
|
||||
self.sync_mode = False
|
||||
self.height_to_hash = {}
|
||||
|
|
|
@ -181,7 +181,7 @@ async def setup_wallet_node(
|
|||
started = asyncio.Event()
|
||||
|
||||
async def start_callback():
|
||||
await api._start()
|
||||
await api._start(new_wallet=True)
|
||||
nonlocal started
|
||||
started.set()
|
||||
|
||||
|
|
Loading…
Reference in New Issue