mirror of
https://github.com/mollyim/monero-wallet-sdk.git
synced 2024-12-25 23:49:28 -05:00
demo: autosave wallet state
This commit is contained in:
parent
529184abaf
commit
5cf5c71b90
@ -20,13 +20,23 @@ class MoneroSdkClient(
|
|||||||
val provider = providerDeferred.await()
|
val provider = providerDeferred.await()
|
||||||
return withContext(ioDispatcher) {
|
return withContext(ioDispatcher) {
|
||||||
val wallet = provider.createNewWallet(moneroNetwork)
|
val wallet = provider.createNewWallet(moneroNetwork)
|
||||||
walletDataFileStorage.tryWriteData(wallet.publicAddress, false) { output ->
|
saveToFile(wallet, provider, false)
|
||||||
provider.saveWallet(wallet, output)
|
|
||||||
}
|
|
||||||
wallet
|
wallet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun saveWallet(wallet: MoneroWallet) {
|
||||||
|
withContext(ioDispatcher) {
|
||||||
|
saveToFile(wallet, providerDeferred.await(), true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveToFile(wallet: MoneroWallet, provider: WalletProvider, canOverwrite: Boolean) {
|
||||||
|
walletDataFileStorage.tryWriteData(wallet.publicAddress, canOverwrite) { output ->
|
||||||
|
provider.saveWallet(wallet, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun openWallet(
|
suspend fun openWallet(
|
||||||
publicAddress: String,
|
publicAddress: String,
|
||||||
remoteNodes: Flow<List<RemoteNode>>,
|
remoteNodes: Flow<List<RemoteNode>>,
|
||||||
|
@ -58,7 +58,7 @@ class WalletRepository(
|
|||||||
moneroNetwork: MoneroNetwork,
|
moneroNetwork: MoneroNetwork,
|
||||||
name: String,
|
name: String,
|
||||||
remoteNodeIds: List<Long>,
|
remoteNodeIds: List<Long>,
|
||||||
): Pair<Long, IWallet> {
|
): Pair<Long, MoneroWallet> {
|
||||||
val wallet = moneroSdkClient.createWallet(moneroNetwork)
|
val wallet = moneroSdkClient.createWallet(moneroNetwork)
|
||||||
val walletId = walletDataSource.createWalletConfig(
|
val walletId = walletDataSource.createWalletConfig(
|
||||||
publicAddress = wallet.publicAddress,
|
publicAddress = wallet.publicAddress,
|
||||||
@ -68,6 +68,9 @@ class WalletRepository(
|
|||||||
return walletId to wallet
|
return walletId to wallet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun saveWallet(wallet: MoneroWallet) =
|
||||||
|
moneroSdkClient.saveWallet(wallet)
|
||||||
|
|
||||||
suspend fun updateWalletConfig(walletConfig: WalletConfig) =
|
suspend fun updateWalletConfig(walletConfig: WalletConfig) =
|
||||||
walletDataSource.updateWalletConfig(walletConfig)
|
walletDataSource.updateWalletConfig(walletConfig)
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,39 @@ import androidx.lifecycle.LifecycleService
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import im.molly.monero.demo.AppModule
|
import im.molly.monero.demo.AppModule
|
||||||
import im.molly.monero.demo.data.WalletRepository
|
import im.molly.monero.demo.data.WalletRepository
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.isActive
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
const val TAG = "SyncService"
|
const val TAG = "SyncService"
|
||||||
|
|
||||||
class SyncService(
|
class SyncService(
|
||||||
private val walletRepository: WalletRepository = AppModule.walletRepository,
|
private val walletRepository: WalletRepository = AppModule.walletRepository,
|
||||||
|
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
|
||||||
) : LifecycleService() {
|
) : LifecycleService() {
|
||||||
|
|
||||||
|
private suspend fun doSync() = coroutineScope {
|
||||||
|
val syncedWalletIds = mutableSetOf<Long>()
|
||||||
|
|
||||||
|
walletRepository.getWalletIdList().collect {
|
||||||
|
val idSet = it.toSet()
|
||||||
|
val toSync = idSet subtract syncedWalletIds
|
||||||
|
toSync.forEach { walletId ->
|
||||||
|
val wallet = walletRepository.getWallet(walletId)
|
||||||
|
launch {
|
||||||
|
while (isActive) {
|
||||||
|
val result = wallet.awaitRefresh()
|
||||||
|
if (result.isError()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
walletRepository.saveWallet(wallet)
|
||||||
|
delay(10.seconds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
syncedWalletIds.addAll(toSync)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val binder: IBinder = LocalBinder()
|
private val binder: IBinder = LocalBinder()
|
||||||
|
|
||||||
inner class LocalBinder : Binder() {
|
inner class LocalBinder : Binder() {
|
||||||
@ -41,25 +64,8 @@ class SyncService(
|
|||||||
Log.d(TAG, "onCreate")
|
Log.d(TAG, "onCreate")
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch(ioDispatcher) {
|
||||||
val syncedWalletIds = mutableSetOf<Long>()
|
doSync()
|
||||||
walletRepository.getWalletIdList().collect {
|
|
||||||
val idSet = it.toSet()
|
|
||||||
val toSync = idSet subtract syncedWalletIds
|
|
||||||
toSync.forEach { walletId ->
|
|
||||||
val wallet = walletRepository.getWallet(walletId)
|
|
||||||
lifecycleScope.launch {
|
|
||||||
while (isActive) {
|
|
||||||
val result = wallet.awaitRefresh()
|
|
||||||
if (result.isError()) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
delay(10.seconds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
syncedWalletIds.addAll(toSync)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ interface IWallet {
|
|||||||
String getPrimaryAccountAddress();
|
String getPrimaryAccountAddress();
|
||||||
void addBalanceListener(in IBalanceListener listener);
|
void addBalanceListener(in IBalanceListener listener);
|
||||||
void removeBalanceListener(in IBalanceListener listener);
|
void removeBalanceListener(in IBalanceListener listener);
|
||||||
void save(in ParcelFileDescriptor destination);
|
oneway void save(in ParcelFileDescriptor destination);
|
||||||
oneway void resumeRefresh(boolean skipCoinbaseOutputs, in IRefreshCallback callback);
|
oneway void resumeRefresh(boolean skipCoinbaseOutputs, in IRefreshCallback callback);
|
||||||
void cancelRefresh();
|
void cancelRefresh();
|
||||||
void setRefreshSince(long heightOrTimestamp);
|
void setRefreshSince(long heightOrTimestamp);
|
||||||
|
@ -88,6 +88,7 @@ bool Wallet::parseFrom(std::istream& input) {
|
|||||||
return false;
|
return false;
|
||||||
if (!serialization::serialize(ar, m_wallet))
|
if (!serialization::serialize(ar, m_wallet))
|
||||||
return false;
|
return false;
|
||||||
|
m_blockchain_height = m_wallet.get_blockchain_current_height();
|
||||||
m_wallet.get_transfers(m_tx_outs);
|
m_wallet.get_transfers(m_tx_outs);
|
||||||
m_account_ready = true;
|
m_account_ready = true;
|
||||||
return true;
|
return true;
|
||||||
@ -130,31 +131,30 @@ void Wallet::handleBalanceChanged(uint64_t at_block_height) {
|
|||||||
m_wallet.get_transfers(m_tx_outs);
|
m_wallet.get_transfers(m_tx_outs);
|
||||||
m_tx_outs_mutex.unlock();
|
m_tx_outs_mutex.unlock();
|
||||||
m_blockchain_height = at_block_height;
|
m_blockchain_height = at_block_height;
|
||||||
JNIEnv* env = getJniEnv();
|
callOnRefresh(true);
|
||||||
m_callback.callVoidMethod(env, WalletNative_onRefresh, at_block_height, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::handleNewBlock(uint64_t height, bool debounce) {
|
void Wallet::handleNewBlock(uint64_t height) {
|
||||||
m_blockchain_height = height;
|
m_blockchain_height = height;
|
||||||
bool notify = false;
|
// Notify the blockchain height once every 200 ms if the height is a multiple of 100.
|
||||||
if (debounce) {
|
bool debounce = true;
|
||||||
// Notify the blockchain height once every 200 ms if the height is a multiple of 100.
|
if (height % 100 == 0) {
|
||||||
if (height % 100 == 0) {
|
static std::chrono::steady_clock::time_point last_time;
|
||||||
static std::chrono::steady_clock::time_point last_time;
|
auto now = std::chrono::steady_clock::now();
|
||||||
auto now = std::chrono::steady_clock::now();
|
if (now - last_time >= 200.ms) {
|
||||||
if (now - last_time >= 200.ms) {
|
last_time = now;
|
||||||
last_time = now;
|
debounce = false;
|
||||||
notify = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
notify = true;
|
|
||||||
}
|
}
|
||||||
if (notify) {
|
if (!debounce) {
|
||||||
m_callback.callVoidMethod(getJniEnv(), WalletNative_onRefresh, height, false);
|
callOnRefresh(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wallet::callOnRefresh(bool balance_changed) {
|
||||||
|
m_callback.callVoidMethod(getJniEnv(), WalletNative_onRefresh, m_blockchain_height, balance_changed);
|
||||||
|
}
|
||||||
|
|
||||||
Wallet::Status Wallet::nonReentrantRefresh(bool skip_coinbase) {
|
Wallet::Status Wallet::nonReentrantRefresh(bool skip_coinbase) {
|
||||||
LOG_FATAL_IF(m_refresh_running.exchange(true),
|
LOG_FATAL_IF(m_refresh_running.exchange(true),
|
||||||
"Refresh should not be called concurrently");
|
"Refresh should not be called concurrently");
|
||||||
@ -187,7 +187,7 @@ Wallet::Status Wallet::nonReentrantRefresh(bool skip_coinbase) {
|
|||||||
}
|
}
|
||||||
m_refresh_running.store(false);
|
m_refresh_running.store(false);
|
||||||
// Always notify the last block height.
|
// Always notify the last block height.
|
||||||
handleNewBlock(m_blockchain_height, false);
|
callOnRefresh(false);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,9 @@ class Wallet : tools::i_wallet2_callback {
|
|||||||
auto suspendRefreshAndRunLocked(T block) -> decltype(block());
|
auto suspendRefreshAndRunLocked(T block) -> decltype(block());
|
||||||
|
|
||||||
void handleBalanceChanged(uint64_t at_block_height);
|
void handleBalanceChanged(uint64_t at_block_height);
|
||||||
void handleNewBlock(uint64_t height, bool debounce = true);
|
void handleNewBlock(uint64_t height);
|
||||||
|
|
||||||
|
void callOnRefresh(bool balance_changed);
|
||||||
|
|
||||||
// Implementation of i_wallet2_callback follows.
|
// Implementation of i_wallet2_callback follows.
|
||||||
private:
|
private:
|
||||||
|
2
vendor/monero
vendored
2
vendor/monero
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 1bfa33ad2b4b2b4bd752a6dda74102defabba063
|
Subproject commit 4ba282d12182bc3c907e3e77ef1091e2e806f086
|
Loading…
Reference in New Issue
Block a user