From 234a35d2a0145aced04ff187e5d50833bf2ca5f6 Mon Sep 17 00:00:00 2001 From: minibits-cash Date: Tue, 12 Nov 2024 15:15:20 +0100 Subject: [PATCH] Fix spent proofs might remain in wallet after a lightning payment, fix pending tx count --- output.log | Bin 0 -> 532214 bytes package.json | 2 +- src/models/Mint.ts | 6 ++-- src/models/TransactionsStore.ts | 2 +- src/models/helpers/setupRootStore.ts | 7 +++-- src/screens/TranHistoryScreen.tsx | 2 +- src/screens/WalletScreen.tsx | 40 +++++++++++++-------------- src/services/mmkvStorage.ts | 2 +- src/services/wallet/sendTask.ts | 10 +++---- src/services/wallet/transferTask.ts | 36 ++++++++++-------------- src/services/walletService.ts | 26 +++++++++++------ 11 files changed, 66 insertions(+), 67 deletions(-) create mode 100644 output.log diff --git a/output.log b/output.log new file mode 100644 index 0000000000000000000000000000000000000000..b21a667bf09bc57122e291fd5712aa769bbdc218 GIT binary patch literal 532214 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 Q@tx-~Fw&i`vqh8qe^gD-?*IS* literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 9acbe3c..210aded 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minibits_wallet", - "version": "0.1.9-beta.30", + "version": "0.1.9-beta.31", "private": true, "scripts": { "android:clean": "cd android && ./gradlew clean", diff --git a/src/models/Mint.ts b/src/models/Mint.ts index 90bbd14..30f2ab4 100644 --- a/src/models/Mint.ts +++ b/src/models/Mint.ts @@ -15,9 +15,7 @@ import { MintUnit, MintUnits } from '../services/wallet/currency' import { getRootStore } from './helpers/getRootStore' import { generateId } from '../utils/utils' import { ProofV3 } from '../services/cashu/cashuUtils' -import { RootStoreModel } from './RootStore' -import { MintsStoreModel } from './MintsStore' -import { WalletStoreModel } from './WalletStore' +import { Proof } from './Proof' export type MintBalance = { @@ -367,7 +365,7 @@ export const MintModel = types self.proofsCounters = cast(self.proofsCounters) }, - getMintFeeReserve(proofs: ProofV3[]): number { + getMintFeeReserve(proofs: ProofV3[] | Proof[]): number { // Find the corresponding keyset for each proof and sum the input fees const totalInputFees = proofs.reduce((sum, proof) => { const keyset = self.keysets.find(k => k.id === proof.id) diff --git a/src/models/TransactionsStore.ts b/src/models/TransactionsStore.ts index 0b8f4aa..3999903 100644 --- a/src/models/TransactionsStore.ts +++ b/src/models/TransactionsStore.ts @@ -304,7 +304,7 @@ export const TransactionsStoreModel = types transactionsMap: prunedTransactionsMap } - console.log('[postProcessSnapshot]', {prunedSnapshot}) + // console.log('[postProcessSnapshot]', {prunedSnapshot}) return prunedSnapshot }) diff --git a/src/models/helpers/setupRootStore.ts b/src/models/helpers/setupRootStore.ts index fef2c5f..a5f3cb2 100644 --- a/src/models/helpers/setupRootStore.ts +++ b/src/models/helpers/setupRootStore.ts @@ -59,7 +59,7 @@ export async function setupRootStore(rootStore: RootStore) { const mmkvLoaded = performance.now() const dataSize = Buffer.byteLength(JSON.stringify(restoredState), 'utf8') - log.trace({restoredState}) + // log.trace({restoredState}) log.trace('[setupRootStore]', `Loading ${dataSize.toLocaleString()} bytes of state from MMKV took ${(mmkvLoaded - start).toLocaleString()} ms.`) applySnapshot(rootStore, restoredState) @@ -83,11 +83,12 @@ export async function setupRootStore(rootStore: RootStore) { } // track changes & save snapshot to the storage not more then once per second - const saveSnapshot = debounce((snapshot) => { + const saveSnapshot = debounce((snapshot) => { MMKVStorage.save(ROOT_STORAGE_KEY, snapshot) }, 1000) - _disposer = onSnapshot(rootStore, snapshot => { + _disposer = onSnapshot(rootStore, snapshot => { + // log.trace('[setupRootStore] onSnapshot *** MMKV SHOULD SAVE ***') saveSnapshot(snapshot) // log.trace('[setupRootStore] saved', {walletStore: snapshot.walletStore}) }) diff --git a/src/screens/TranHistoryScreen.tsx b/src/screens/TranHistoryScreen.tsx index 8b453b5..adf6130 100644 --- a/src/screens/TranHistoryScreen.tsx +++ b/src/screens/TranHistoryScreen.tsx @@ -267,7 +267,7 @@ export const TranHistoryScreen: FC> /> {} @@ -98,8 +100,8 @@ export const WalletScreen: FC = observer( const [defaultMintUrl, setDefaultMintUrl] = useState(MINIBITS_MINT_URL) const [error, setError] = useState() const [isLoading, setIsLoading] = useState(false) - const [lastClaimCheck, setLastClaimCheck] = useState(getUnixTime(new Date())) - const [lastPendingCheck, setLastPendingCheck] = useState(getUnixTime(new Date())) + const [lastClaimCheck, setLastClaimCheck] = useState(0) + const [lastPendingCheck, setLastPendingCheck] = useState(0) const [isMintsModalVisible, setIsMintsModalVisible] = useState(false) const [isUpdateAvailable, setIsUpdateAvailable] = useState(false) const [isUpdateModalVisible, setIsUpdateModalVisible] = useState(false) @@ -165,17 +167,12 @@ export const WalletScreen: FC = observer( if(groupedMints.length === 0) { await addMint() } - - // check lnaddress claims on app start and set timestamp to trigger focus updates - WalletTask.handleClaim().catch(e => setInfo(e.message)) - // Auto-recover inflight proofs - do only on startup and before checkPendingReceived to prevent conflicts + + // Only once on startup - auto-recover inflight proofs WalletTask.handleInFlight().catch(e => false) - // Create websocket subscriptions to receive tokens or payment requests by NOSTR DMs - WalletTask.receiveEventsFromRelays().catch(e => false) - // Get exchange rate - if(userSettingsStore.exchangeCurrency) { - walletStore.refreshExchangeRate(userSettingsStore.exchangeCurrency!) - } + // Only once on startup - Create websocket subscriptions to receive tokens or payment requests by NOSTR DMs + WalletTask.receiveEventsFromRelays().catch(e => false) + // Set wallet tab to preferred unit const preferredUnit: MintUnit = userSettingsStore.preferredUnit const preferredTabIndex = routes.findIndex(route => route.key === preferredUnit) @@ -253,16 +250,18 @@ export const WalletScreen: FC = observer( } const nowInSec = getUnixTime(new Date()) - // log.trace('[useFocusEffect]', {nowInSec, lastClaimCheck, delay: lastClaimCheck ? nowInSec - lastClaimCheck : undefined}) + log.trace('[useFocusEffect] Start', {secsFromLastPending: nowInSec - lastPendingCheck, secsFromLastClaim: nowInSec - lastClaimCheck}) - if(lastPendingCheck && nowInSec - lastPendingCheck > 10) { + // On startup and on re-focus if some secs passed + if(nowInSec - lastPendingCheck > PENDING_CHECK_INTERVAL) { + setLastPendingCheck(nowInSec) WalletTask.syncPendingStateWithMints().catch(e => false) WalletTask.handlePendingTopups().catch(e => false) } else { log.trace('[useFocusEffect] Skipping pending checks...') } - if(lastClaimCheck && nowInSec - lastClaimCheck > 60) { + if(nowInSec - lastClaimCheck > CLAIM_CHECK_INTERVAL) { setLastClaimCheck(nowInSec) WalletTask.handleClaim().catch(e => false) @@ -276,7 +275,7 @@ export const WalletScreen: FC = observer( } - }, [lastClaimCheck, isInternetReachable, userSettingsStore.exchangeCurrency]) + }, [lastPendingCheck, lastClaimCheck, isInternetReachable, userSettingsStore.exchangeCurrency]) ) @@ -303,16 +302,17 @@ export const WalletScreen: FC = observer( const nowInSec = getUnixTime(new Date()) - // log.trace('[appState]', { nowInSec, lastClaimCheck, delay: lastClaimCheck ? nowInSec - lastClaimCheck : undefined }); + log.trace('[handleAppStateChange] Start', {secsFromLastPending: nowInSec - lastPendingCheck, secsFromLastClaim: nowInSec - lastClaimCheck}) - if (lastPendingCheck && nowInSec - lastPendingCheck > 10) { + if (nowInSec - lastPendingCheck > PENDING_CHECK_INTERVAL) { + setLastPendingCheck(nowInSec) WalletTask.syncPendingStateWithMints().catch(e => false) WalletTask.handlePendingTopups().catch(e => false) } else { log.trace('[handleAppStateChange] Skipping pending checks...') } - if(lastClaimCheck && nowInSec - lastClaimCheck > 60) { + if(nowInSec - lastClaimCheck > CLAIM_CHECK_INTERVAL) { setLastClaimCheck(nowInSec) WalletTask.handleClaim().catch(e => false) @@ -336,7 +336,7 @@ export const WalletScreen: FC = observer( return () => { subscription.remove(); // Ensure cleanup to avoid multiple listeners }; - }, [lastClaimCheck, lastPendingCheck, isInternetReachable, userSettingsStore.exchangeCurrency]) + }, [lastPendingCheck, lastClaimCheck, isInternetReachable, userSettingsStore.exchangeCurrency]) const toggleMintsModal = () => { diff --git a/src/services/mmkvStorage.ts b/src/services/mmkvStorage.ts index e054e17..3bfec34 100644 --- a/src/services/mmkvStorage.ts +++ b/src/services/mmkvStorage.ts @@ -212,7 +212,7 @@ const save = function (key: string, value: any): boolean { const end = performance.now() // const dataSize = Buffer.byteLength(JSON.stringify(value), 'utf8') - // log.trace(`[mmkvStorage.save] Took ${end - start} ms to save ${dataSize} bytes.`) + // log.trace(`[mmkvStorage.save] *** MMKV REAL SAVE *** Took ${end - start} ms to save ${dataSize} bytes.`) return true } catch (e: any) { diff --git a/src/services/wallet/sendTask.ts b/src/services/wallet/sendTask.ts index 1dfffd1..8c5dfcb 100644 --- a/src/services/wallet/sendTask.ts +++ b/src/services/wallet/sendTask.ts @@ -140,7 +140,7 @@ export const sendTask = async function ( log.trace('[send] totalBalance after', balanceAfter) - // Start polling for accepted payment is it is not offline send + // Start polling for accepted payment it is not an offline send if(selectedProofs.length === 0) { const proofsToSync = proofsStore.getByMint(mintUrl, {isPending: true}) @@ -214,7 +214,7 @@ export const sendFromMintSync = async function ( ) } - const proofsFromMint = proofsStore.getByMint(mintUrl, {isPending: false, unit}) as Proof[] + const proofsFromMint = proofsStore.getByMint(mintUrl, {isPending: false, unit}) log.debug('[sendFromMintSync]', 'proofsFromMint count', {mintBalance: mintBalance.balances[unit], amountToSend}) @@ -399,7 +399,7 @@ export const sendFromMintSync = async function ( // release lock lockedProofsCounter.resetInFlight(transactionId) - } else if (returnedAmount === 0) { + } else { /* * SWAP is NOT needed, we've found denominations that match exact amount * @@ -416,9 +416,7 @@ export const sendFromMintSync = async function ( proofsToSend = [...proofsToSendFrom] - } else { - throw new AppError(Err.VALIDATION_ERROR, 'Amount to keep can not be negative') - } + } // remove used proofs and move sent proofs to pending proofsStore.removeProofs(proofsToSendFrom) diff --git a/src/services/wallet/transferTask.ts b/src/services/wallet/transferTask.ts index 03b7058..d92d3ae 100644 --- a/src/services/wallet/transferTask.ts +++ b/src/services/wallet/transferTask.ts @@ -97,7 +97,7 @@ export const transferTask = async function ( } // calculate fees charged by mint for melt transaction to prepare enough proofs - const proofsFromMint = proofsStore.getByMint(mintUrl, {isPending: false, unit}) as Proof[] + const proofsFromMint = proofsStore.getByMint(mintUrl, {isPending: false, unit}) let proofsToMelt = CashuUtils.getProofsToSend( amountToTransfer + meltQuote.fee_reserve, @@ -120,9 +120,14 @@ export const transferTask = async function ( [], transaction.id, ) + + const { + proofs: proofsToPay, + mintFeePaid, + mintFeeReserve, + isSwapNeeded + } = swapResult - proofsToPay = swapResult.proofs - const {mintFeePaid, mintFeeReserve, isSwapNeeded} = swapResult proofsToPayAmount = CashuUtils.getProofsAmount(proofsToPay) // TODO in case of swap from inactive keysets, different meltFees might apply than above calculated meltFeeReserve @@ -135,6 +140,7 @@ export const transferTask = async function ( status: TransactionStatus.PREPARED, mintFeeReserve, mintFeePaid, + proofsToPayAmount, isSwapNeeded, createdAt: new Date(), }) @@ -182,28 +188,14 @@ export const transferTask = async function ( lockedProofsCounter.decreaseProofsCounter(countOfInFlightProofs) - // update transaction status and proofs state based on sync with the mint - // proofsToPay are clean ProofV3, not Proof models so we send all pending from state - /* const proofsToSync = proofsStore.getByMint(mintUrl, {isPending: true}) - const { completedTransactionIds, transactionStateUpdates } = await WalletTask.syncStateWithMintSync( - { - proofsToSync, - mintUrl, - isPending: true - } - ) - - if(!completedTransactionIds.includes(transaction.id)) { - // silent - log.warn('[transfer] payLightningMelt call suceeded but proofs were not spent by mint', {transactionStateUpdates}) - }*/ - - // If real fees were less then estimated, cash the returned savings. - if (state === MeltQuoteState.PAID) { + log.trace('[transfer] Invoice PAID', {state, preimage}) + // Spend pending proofs that were used to settle the lightning invoice + proofsStore.removeProofs(proofsToPay as Proof[], true, false) + let lightningFeePaid = meltQuote.fee_reserve - if (feeSavedProofs.length) { + if (feeSavedProofs.length > 0) { const {addedAmount: feeSaved} = WalletUtils.addCashuProofs( mintUrl, feeSavedProofs, diff --git a/src/services/walletService.ts b/src/services/walletService.ts index 8276926..b539924 100644 --- a/src/services/walletService.ts +++ b/src/services/walletService.ts @@ -434,7 +434,7 @@ const syncPendingStateWithMints = async function (): Promise { } const isPending = true - // const maxBatchSize = MAX_CHECK_INPUT_SIZE + const maxBatchSize = MAX_SYNC_INPUT_SIZE // group proofs by mint so that we do max one call per mint for (const mint of mintsStore.allMints) { @@ -445,8 +445,17 @@ const syncPendingStateWithMints = async function (): Promise { } const proofsToSync = proofsStore.getByMint(mint.mintUrl, {isPending}) - const totalProofs = proofsToSync.length - syncStateWithMint({ proofsToSync, mintUrl: mint.mintUrl, isPending }) + const totalProofsCount = proofsToSync.length + + if (totalProofsCount > maxBatchSize) { + for (let i = 0; i < totalProofsCount; i += maxBatchSize) { + const batch = proofsToSync.slice(i, i + maxBatchSize) + syncStateWithMint({ proofsToSync: batch, mintUrl: mint.mintUrl, isPending }) + } + } else { + // If the length is less than or equal to 100, run syncStateWithMint with all proofs. + syncStateWithMint({ proofsToSync, mintUrl: mint.mintUrl, isPending }); + } } } @@ -473,7 +482,7 @@ const syncSpendableStateWithMints = async function (): Promise { if (totalProofsCount > maxBatchSize) { for (let i = 0; i < totalProofsCount; i += maxBatchSize) { const batch = proofsToSync.slice(i, i + maxBatchSize) - syncStateWithMint({ proofsToSync: batch, mintUrl: mint.mintUrl, isPending }); + syncStateWithMint({ proofsToSync: batch, mintUrl: mint.mintUrl, isPending }) } } else { // If the length is less than or equal to 100, run syncStateWithMint with all proofs. @@ -495,7 +504,7 @@ const syncStateWithMint = async function ( } ): Promise { const {mintUrl, isPending, proofsToSync} = options - log.trace('[syncStateWithMint] start', {mintUrl, isPending}) + log.trace('[syncStateWithMint] start', {mintUrl, isPending, proofsToSyncCount: proofsToSync.length}) const now = new Date().getTime() return SyncQueue.addTask( @@ -516,7 +525,7 @@ const syncStateWithMintSync = async function ( ): Promise { const {mintUrl, isPending, proofsToSync} = options - log.trace('[syncStateWithMintSync] start', {mintUrl, isPending, proofsToSyncCount: proofsToSync?.length}) + log.trace('[syncStateWithMintSync] start', {mintUrl, isPending, proofsToSyncCount: proofsToSync.length}) return await _syncStateWithMintTask({proofsToSync, mintUrl, isPending}) } @@ -636,7 +645,7 @@ const _syncStateWithMintTask = async function ( if (tx) { // spent amount does not cover matched tx amount - // means that some spent proofs were used as inputs into the send + // means that some spent proofs were used as inputs into the swap / melt if(spentByMintTxAmount < tx.amount) { errorTransactionIds.push(Number(tId)) @@ -679,7 +688,8 @@ const _syncStateWithMintTask = async function ( return { tId: Number(tId), - updatedStatus: TransactionStatus.ERROR + updatedStatus: TransactionStatus.ERROR, + message: 'Could not find transaction in the database.' } as TransactionStateUpdate })