diff --git a/src/i18n_messages/en.json b/src/i18n_messages/en.json index 7937faba..eec2feb0 100644 --- a/src/i18n_messages/en.json +++ b/src/i18n_messages/en.json @@ -513,6 +513,8 @@ "from": "From %{sender}", "paidFrom": "Paid from", "paidTo": "Paid to %{receiver}", + "payTo": "Pay to %{receiver}", + "payNow": "Pay now", "receivedFrom": "Received from %{sender}", "receivedTo": "Received to", "receiveFailed": "Receive failed", diff --git a/src/models/Proof.ts b/src/models/Proof.ts index 8176b5a9..80fbec71 100644 --- a/src/models/Proof.ts +++ b/src/models/Proof.ts @@ -3,10 +3,10 @@ import {withSetPropAction} from './helpers/withSetPropAction' import { MintUnit } from '../services/wallet/currency' /** - * Proof type saved in database backup + * Proof db record */ -export type BackupProof = Proof & { +export type ProofRecord = Proof & { isPending: boolean isSpent: boolean updatedAt: Date diff --git a/src/models/ProofsStore.ts b/src/models/ProofsStore.ts index 739a88c7..6d686d51 100644 --- a/src/models/ProofsStore.ts +++ b/src/models/ProofsStore.ts @@ -7,7 +7,7 @@ import { flow, } from 'mobx-state-tree' import {withSetPropAction} from './helpers/withSetPropAction' -import {ProofModel, Proof, BackupProof} from './Proof' +import {ProofModel, Proof, ProofRecord} from './Proof' import {log} from '../services/logService' import {getRootStore} from './helpers/getRootStore' import AppError, {Err} from '../utils/AppError' @@ -110,7 +110,7 @@ export const ProofsStoreModel = types // Group into isUnspent and isPending const groupedProofs = unspentAndPendingProofs.reduce( - (acc: {isPending: BackupProof[], isUnspent: BackupProof[]}, proof: BackupProof) => { + (acc: {isPending: ProofRecord[], isUnspent: ProofRecord[]}, proof: ProofRecord) => { if (proof.isPending) { acc.isPending.push(proof); } else { @@ -121,7 +121,7 @@ export const ProofsStoreModel = types { isUnspent: [], isPending: [] } // Initialize the groups ) - const cleanProofs = (proofs: BackupProof[]) => { + const cleanProofs = (proofs: ProofRecord[]) => { return proofs.map(p => { // Destructure the unwanted properties and collect the rest in `cleaned` const { isPending, isSpent, updatedAt, ...cleaned } = p @@ -165,7 +165,7 @@ export const ProofsStoreModel = types throw new AppError(Err.STORAGE_ERROR, 'Could not find mint', {mintUrl: newProofs[0].mintUrl}) } - for (const [keysetId, keysetProofs] of proofsByKeysetId.entries()) { + for (const [keysetId, keysetProofs] of Array.from(proofsByKeysetId.entries())) { for (const proof of keysetProofs) { if(self.alreadyExists(proof)) { diff --git a/src/models/Transaction.ts b/src/models/Transaction.ts index 625415b9..411422e2 100644 --- a/src/models/Transaction.ts +++ b/src/models/Transaction.ts @@ -3,37 +3,6 @@ import { log } from '../services/logService' import { MintUnit } from '../services/wallet/currency' import { Database } from '../services' -/** - * Transaction model with MST actions for database updates. - * Note: Individual setter actions (setStatus, setFee, etc.) are deprecated. - * Use the generic update() action instead for all mutations. - */ -export interface TransactionRecord { - id: number - type: TransactionType - amount: number - fee: number - unit: MintUnit - data: string - sentFrom?: string | null - sentTo?: string | null - profile?: string | null - memo?: string | null - paymentId?: string | null - quote?: string | null - paymentRequest?: string | null - zapRequest?: string | null - inputToken?: string | null - outputToken?: string | null - proof?: string | null - mint: string - balanceAfter?: number | null - noteToSelf?: string | null - tags?: Array | null - status: TransactionStatus - expiresAt?: Date | null - createdAt: Date -} export type TransactionData = { status: TransactionStatus @@ -100,16 +69,16 @@ export const TransactionModel = types self.outputToken = outputToken.slice(0, 40) log.trace('[pruneOutputToken]', 'Transaction outputToken pruned in store', { id: self.id }) }, - update(fields: Partial) { + update(fields: Partial) { // Update multiple fields in database with a single query - Database.updateTransaction(self.id!, fields) + const updatedTransaction = Database.updateTransaction(self.id, fields) // Update the model to keep store in sync - Object.keys(fields).forEach(key => { - ;(self as any)[key] = (fields as any)[key] + Object.keys(updatedTransaction).forEach(key => { + ;(self as any)[key] = (updatedTransaction as any)[key] }) - log.trace('[update]', 'Transaction updated', { id: self.id, fields: Object.keys(fields) }) + log.trace('[update]', 'Transaction updated', { id: self.id, updatedData: fields}) }, })) diff --git a/src/models/TransactionsStore.ts b/src/models/TransactionsStore.ts index 2e21c905..1503c598 100644 --- a/src/models/TransactionsStore.ts +++ b/src/models/TransactionsStore.ts @@ -3,14 +3,12 @@ import { SnapshotOut, types, flow, - detach, } from 'mobx-state-tree' import {withSetPropAction} from './helpers/withSetPropAction' import { TransactionModel, Transaction, TransactionStatus, - TransactionRecord, } from './Transaction' import {Database} from '../services' import {log} from '../services/logService' @@ -76,16 +74,14 @@ import { .filter(t => t.unit === unit) }, getPendingTopups() { - const dbTopups: TransactionRecord[] = Database.getPendingTopups() + const dbTopups: Transaction[] = Database.getPendingTopups() if(dbTopups.length > 0) { const pendingTopups: Transaction[] = [] for(const topup of dbTopups) { - const createdAt = new Date(topup.createdAt) - const expiresAt = topup.expiresAt ? new Date(topup.expiresAt) : null - const inStoreTransaction = {...topup, createdAt, expiresAt} + const inStoreTransaction = {...topup} const topupInstance = TransactionModel.create(inStoreTransaction) pendingTopups.push(topupInstance) @@ -98,8 +94,26 @@ import { return [] }, - getPendingTopupsCount() { - return Database.getPendingTopupsCount() + getPendingTransfers() { + const dbTransfers: Transaction[] = Database.getPendingTopups() + + if(dbTransfers.length > 0) { + + const pendingTransfers: Transaction[] = [] + + for(const transfer of dbTransfers) { + const inStoreTransaction = {...transfer} + + const transferInstance = TransactionModel.create(inStoreTransaction) + pendingTransfers.push(transferInstance) + } + + return pendingTransfers + + } + + return [] + }, countRecentByUnit(unit: MintUnit) { return this.getRecentByUnit(unit).length @@ -115,9 +129,7 @@ import { const dbTransaction = Database.getTransactionById(id) if(dbTransaction) { - const createdAt = new Date(dbTransaction.createdAt) - const expiresAt = dbTransaction.expiresAt ? new Date(dbTransaction.expiresAt) : null - const inStoreTransaction = {...dbTransaction, createdAt} + const inStoreTransaction = {...dbTransaction} const {id} = dbTransaction if(!loadTokens) { @@ -143,9 +155,7 @@ import { const dbTransaction = Database.getTransactionByPaymentId(paymentId) if(dbTransaction) { - const createdAt = new Date(dbTransaction.createdAt) - const expiresAt = dbTransaction.expiresAt ? new Date(dbTransaction.expiresAt) : null - const inStoreTransaction = {...dbTransaction, createdAt, expiresAt} + const inStoreTransaction = {...dbTransaction} const {id} = dbTransaction // Shorten for performance reasons @@ -169,9 +179,7 @@ import { const dbTransaction = Database.getTransactionByQuote(quote) if(dbTransaction) { - const createdAt = new Date(dbTransaction.createdAt) - const expiresAt = dbTransaction.expiresAt ? new Date(dbTransaction.expiresAt) : null - const inStoreTransaction = {...dbTransaction, createdAt, expiresAt} + const inStoreTransaction = {...dbTransaction} const {id} = dbTransaction // Shorten for performance reasons @@ -195,9 +203,7 @@ import { const dbTransaction = Database.getTransactionByPaymentRequest(pr) if(dbTransaction) { - const createdAt = new Date(dbTransaction.createdAt) - const expiresAt = dbTransaction.expiresAt ? new Date(dbTransaction.expiresAt) : null - const inStoreTransaction = {...dbTransaction, createdAt, expiresAt} + const inStoreTransaction = {...dbTransaction} const {id} = dbTransaction // Shorten for performance reasons @@ -276,11 +282,10 @@ import { .actions(self => ({ addTransaction: flow(function* addTransaction(newTransaction){ // First let's store the transaction into the database - const dbTransaction: TransactionRecord = yield Database.addTransactionAsync(newTransaction) + const dbTransaction: Transaction = yield Database.addTransactionAsync(newTransaction) // Add the new transaction to the transactions store - const createdAt = new Date(dbTransaction.createdAt) - const inStoreTransaction = {...dbTransaction, createdAt} + const inStoreTransaction = {...dbTransaction} const {id} = dbTransaction if (!self.transactionsMap.has(id)) { @@ -301,14 +306,12 @@ import { }), addToHistory(limit: number, offset: number, onlyPending: boolean){ // Appends transaction to the map and adds reference to history from database. - const result = Database.getTransactions(limit, offset, onlyPending) - log.trace('[addToHistory] dbResult ids', {ids: result?._array.map(t => t.id)}) + const transactions = Database.getTransactions(limit, offset, onlyPending) + log.trace('[addToHistory] transactions ids', {ids: transactions ? transactions.map(t => t.id) : []}) - if (result && result.length > 0) { - for (const dbTransaction of result._array) { - const createdAt = new Date(dbTransaction.createdAt) - const expiresAt = dbTransaction.expiresAt ? new Date(dbTransaction.expiresAt) : null - const inStoreTransaction = {...dbTransaction, createdAt, expiresAt} + if (transactions && transactions.length > 0) { + for (const dbTransaction of transactions) { + const inStoreTransaction = {...dbTransaction} // Shorten for performance reasons if(inStoreTransaction.inputToken && inStoreTransaction.inputToken.length > 0) { @@ -337,13 +340,11 @@ import { }, addRecentByUnit() { // Rehydrates recent from database. - const dbTransactions = Database.getRecentTransactionsByUnit(maxTransactionsByUnit) + const transactions = Database.getRecentTransactionsByUnit(maxTransactionsByUnit) - if (dbTransactions && dbTransactions.length > 0) { - for (const dbTransaction of dbTransactions) { - const createdAt = new Date(dbTransaction.createdAt) - const expiresAt = dbTransaction.expiresAt ? new Date(dbTransaction.expiresAt) : null - const inStoreTransaction = {...dbTransaction, createdAt, expiresAt} + if (transactions && transactions.length > 0) { + for (const dbTransaction of transactions) { + const inStoreTransaction = {...dbTransaction} // Shorten for performance reasons if(inStoreTransaction.inputToken && inStoreTransaction.inputToken.length > 0) { @@ -431,17 +432,10 @@ import { return prunedSnapshot }) - - const getHostname = function (mintUrl: string) { - try { - return new URL(mintUrl).hostname - } catch (e) { - return false - } - } + // refresh export interface TransactionsStore extends Instance {} export interface TransactionsStoreSnapshot - extends SnapshotOut {} \ No newline at end of file + extends SnapshotOut {} diff --git a/src/screens/TranDetailScreen.tsx b/src/screens/TranDetailScreen.tsx index 6106f649..6862cd6f 100644 --- a/src/screens/TranDetailScreen.tsx +++ b/src/screens/TranDetailScreen.tsx @@ -102,7 +102,7 @@ export const TranDetailScreen = observer(function TranDetailScreen({ route }: Pr useFocusEffect(useCallback(() => { try { const tx = transactionsStore.findById(id, true) // load full tokens - log.trace('Transaction loaded', {id: tx?.id, unit: tx?.unit, note: tx?.noteToSelf, inputToken: tx?.inputToken, outputToken: tx?.inputToken}) + log.trace('Transaction loaded', {tx}) if (!tx) { throw new AppError( @@ -1385,10 +1385,12 @@ const TopupInfoBlock = function (props: { useFocusEffect(useCallback(() => { log.trace('[TopupInfoBlock] useFocusEffect start') - if (transaction.status === TransactionStatus.ERROR || - transaction.status === TransactionStatus.PENDING || - transaction.status === TransactionStatus.EXPIRED) { - setIsPendingTopupRetriable(true) + if ([ + TransactionStatus.ERROR, + TransactionStatus.PENDING, + TransactionStatus.EXPIRED + ].includes(transaction.status)) { + setIsPendingTopupRetriable(true) } }, [])) @@ -1530,7 +1532,7 @@ const TopupInfoBlock = function (props: { label="tranDetailScreen.createdAt" value={(transaction.createdAt as Date).toLocaleString()} /> - {transaction.expiresAt && ( + {transaction.expiresAt && transaction.status !== TransactionStatus.COMPLETED && (