From 8b416d99188578fc41e94d1da2a8a070200fbb97 Mon Sep 17 00:00:00 2001 From: minibits-cash Date: Mon, 27 Jan 2025 17:01:19 +0100 Subject: [PATCH] Fixes: correct mint fees update and rare crash after NWC payment --- package.json | 2 +- src/models/Mint.ts | 13 +++++++++++++ src/models/NwcStore.ts | 16 ++++++++++++---- src/models/helpers/setupRootStore.ts | 2 -- src/services/minibitsService.ts | 24 +----------------------- src/services/notificationService.ts | 19 +++++++++++++++---- src/services/syncQueueService.ts | 4 ++-- src/services/walletService.ts | 6 +++--- 8 files changed, 47 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index 11643a35..613eba89 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minibits_wallet", - "version": "0.1.11-beta.2", + "version": "0.1.11-beta.3", "private": true, "scripts": { "android:clean": "cd android && ./gradlew clean", diff --git a/src/models/Mint.ts b/src/models/Mint.ts index 33034d16..b2bd6c8e 100644 --- a/src/models/Mint.ts +++ b/src/models/Mint.ts @@ -123,6 +123,14 @@ export const MintModel = types self.keysets = cast(self.keysets) } }, + setInputFeePpk(keysetId: string, inputFeePpk: number) { + const keyset = self.keysets.find(k => k.id === keysetId) + + if(keyset) { + keyset.input_fee_ppk = inputFeePpk + self.keysets = cast(self.keysets) + } + }, addKeys(keys: CashuMintKeys) { const alreadyExists = self.keys.some(k => k.id === keys.id) @@ -223,6 +231,11 @@ export const MintModel = types if (existing.unit !== keyset.unit) { throw new AppError(Err.VALIDATION_ERROR, `Keyset unit mismatch, got ${keyset.unit}, expected ${existing.unit}`) } + + if(keyset.input_fee_ppk && existing.input_fee_ppk !== keyset.input_fee_ppk) { + self.setInputFeePpk(existing.id, keyset.input_fee_ppk) + } + return existing } diff --git a/src/models/NwcStore.ts b/src/models/NwcStore.ts index 98c9ec84..3d3d5c18 100644 --- a/src/models/NwcStore.ts +++ b/src/models/NwcStore.ts @@ -513,7 +513,12 @@ export const NwcConnectionModel = types.model('NwcConnection', { handleNwcRequestTask: flow(function* handleNwcRequestTask(requestEvent: NostrEvent, decryptedNwcRequest?: NwcRequest) { let nwcRequest: NwcRequest if(!decryptedNwcRequest) { - const decryptedContent = yield NostrClient.decryptNip04(requestEvent.pubkey, requestEvent.content) + + const decryptedContent = yield NostrClient.decryptNip04( + requestEvent.pubkey, + requestEvent.content + ) + nwcRequest = JSON.parse(decryptedContent) } else { nwcRequest = decryptedNwcRequest @@ -535,13 +540,13 @@ export const NwcConnectionModel = types.model('NwcConnection', { nwcResponse = self.handleGetBalance(nwcRequest) break case 'make_invoice': - nwcResponse = yield self.handleMakeInvoice(nwcRequest, requestEvent) as Promise + nwcResponse = yield self.handleMakeInvoice(nwcRequest, requestEvent) break case 'lookup_invoice': nwcResponse = self.handleLookupInvoice(nwcRequest) break case 'pay_invoice': - nwcResponse = yield self.handlePayInvoice(nwcRequest, requestEvent) as Promise + nwcResponse = yield self.handlePayInvoice(nwcRequest, requestEvent) break default: const message = `NWC method ${nwcRequest.method} is unknown or not yet supported.` @@ -553,7 +558,7 @@ export const NwcConnectionModel = types.model('NwcConnection', { log.error(message, {nwcRequest}) } - // needs to be set before sendResponse but after switch / pay_invoice + yield self.sendResponse(nwcResponse, requestEvent) return nwcResponse @@ -768,6 +773,9 @@ export const NwcStoreModel = types const nwcResponse: NwcResponse | NwcError = yield targetConnection.handleNwcRequestTask(event, decryptedNwcRequest) + // prevent rare cases where this might not be called in SyncQueue._handleTaskResult + yield NotificationService.stopForegroundService() + return { taskFunction: HANDLE_NWC_REQUEST_TASK, message: (nwcResponse as NwcResponse).result || undefined , diff --git a/src/models/helpers/setupRootStore.ts b/src/models/helpers/setupRootStore.ts index a5f3cb2c..92c6c9ca 100644 --- a/src/models/helpers/setupRootStore.ts +++ b/src/models/helpers/setupRootStore.ts @@ -42,8 +42,6 @@ export async function setupRootStore(rootStore: RootStore) { // let latestSnapshot: any try { - // Give an option to encrypt storage as it might slow down app start on some Android devices - // User settings are mastered in sqlite so we can get the encryption setting before loading root store log.trace('[setupRootStore]', `Create Database instance and get UserSettings`) const userSettings = Database.getUserSettings() diff --git a/src/services/minibitsService.ts b/src/services/minibitsService.ts index 6ba9e793..a59e8b82 100644 --- a/src/services/minibitsService.ts +++ b/src/services/minibitsService.ts @@ -141,27 +141,6 @@ const recoverProfile = async function (seedHash: string, update: {currentPubkey: } -// Serves for migration from pre-seed wallet version -const migrateSeedHash = async function (pubkey: string, update: {seedHash: string}) { - const url = MINIBITS_SERVER_API_HOST + '/profile' - const method = 'PUT' - const { seedHash } = update - - const body = { - seedHash, - } - - const walletProfile: WalletProfile = await fetchApi(url + `/migrate/pubkey/${pubkey}`, { - method, - body, - }) - - log.info('[migrateSeedHash]', `Migrated seedHash`, seedHash) - - return walletProfile -} - - const getWalletProfile = async function (pubkey: string) { const url = MINIBITS_SERVER_API_HOST + '/profile' const method = 'GET' @@ -354,8 +333,7 @@ export const MinibitsClient = { updateWalletProfile, updateWalletProfileNip05, updateDeviceToken, - recoverProfile, - migrateSeedHash, + recoverProfile, getRandomPictures, getWalletProfileByWalletId, getWalletProfileByNip05, diff --git a/src/services/notificationService.ts b/src/services/notificationService.ts index 9b389523..d2a4e2d5 100644 --- a/src/services/notificationService.ts +++ b/src/services/notificationService.ts @@ -309,12 +309,23 @@ const areNotificationsEnabled = async function (): Promise { return false } -const isNotificationDispayed = async function (): Promise { +const isNotificationDisplayed = async function (options: { foregroundServiceOnly?: boolean }): Promise { + const { foregroundServiceOnly } = options const notifications = await notifee.getDisplayedNotifications() - if(notifications.length > 0) { - return true + + for (const notification of notifications) { + if (foregroundServiceOnly) { + // Assuming `foreground` is a property that indicates if the notification is in the foreground + if (notification.notification.android?.asForegroundService === true) { + return true + } + } else { + // If foregroundOnly is false, return true as soon as we find any notification + return true + } } + // If no matching notification is found, return false return false } @@ -328,6 +339,6 @@ export const NotificationService = { onBackgroundNotification, onForegroundNotification, areNotificationsEnabled, - isNotificationDispayed, + isNotificationDisplayed, stopForegroundService } \ No newline at end of file diff --git a/src/services/syncQueueService.ts b/src/services/syncQueueService.ts index 927f0911..1ac50eb6 100644 --- a/src/services/syncQueueService.ts +++ b/src/services/syncQueueService.ts @@ -62,9 +62,9 @@ const _handleTaskResult = async (taskId: TaskId, result: WalletTaskResult | Tran if(queue.getAllTasksDetails(['idle', 'running']).length === 0) { - if(await NotificationService.isNotificationDispayed()) { + if(await NotificationService.isNotificationDisplayed({foregroundServiceOnly: true})) { log.trace('[_handleTaskResult] stopForegroundService') - NotificationService.stopForegroundService() + await NotificationService.stopForegroundService() } } } diff --git a/src/services/walletService.ts b/src/services/walletService.ts index f27fc620..cc9090d1 100644 --- a/src/services/walletService.ts +++ b/src/services/walletService.ts @@ -13,7 +13,7 @@ import {rootStoreInstance} from '../models' import {CashuProof, CashuUtils} from './cashu/cashuUtils' import {LightningUtils} from './lightning/lightningUtils' import AppError, {Err} from '../utils/AppError' -import {InFlightRequest, MintBalance, MintProofsCounter, MintStatus} from '../models/Mint' +import {MintBalance, MintStatus} from '../models/Mint' import {MeltQuoteResponse, MintQuoteState, Token, getDecodedToken, getEncodedToken} from '@cashu/cashu-ts' import {Mint} from '../models/Mint' import {pollerExists, stopPolling} from '../utils/poller' @@ -24,12 +24,12 @@ import { IncomingDataType, IncomingParser } from './incomingParser' import { Contact } from '../models/Contact' import { SyncQueue } from './syncQueueService' import { receiveTask, receiveOfflinePrepareTask, receiveOfflineCompleteTask} from './wallet/receiveTask' -import { sendFromMintSync, sendTask } from './wallet/sendTask' +import { sendTask } from './wallet/sendTask' import { topupTask } from './wallet/topupTask' import { transferTask } from './wallet/transferTask' import { revertTask } from './wallet/revertTask' import { WalletUtils } from './wallet/utils' -import { NotificationService, TASK_QUEUE_CHANNEL_ID, TASK_QUEUE_CHANNEL_NAME } from './notificationService' +import { NotificationService } from './notificationService' import { MintUnit, formatCurrency, getCurrency } from './wallet/currency' import { MinibitsClient } from './minibitsService' import { KeyChain } from './keyChain'