Skip to content

Commit

Permalink
Allow deleting of metadata params with null
Browse files Browse the repository at this point in the history
  • Loading branch information
paullinator committed Dec 12, 2023
1 parent b76f7f6 commit 3ed9d40
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 27 deletions.
11 changes: 6 additions & 5 deletions src/core/currency/wallet/currency-wallet-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
EdgeTxAction,
EdgeWalletInfo
} from '../../../types/types'
import { mergeDeeply } from '../../../util/util'
import { mergeDeeply, mergeDeeplyNull } from '../../../util/util'
import { makeMetaTokens } from '../../account/custom-tokens'
import { toApiInput } from '../../root-pixie'
import { makeStorageWalletApi } from '../../storage/storage-api'
Expand Down Expand Up @@ -718,10 +718,11 @@ export function combineTxWithFile(
if (file != null) {
if (file.creationDate < out.date) out.date = file.creationDate

const merged: TransactionFile['currencies']['currencyCode'] = mergeDeeply(
file.currencies[walletCurrency],
file.currencies[currencyCode]
)
const merged: TransactionFile['currencies']['currencyCode'] =
mergeDeeplyNull(
file.currencies[walletCurrency],
file.currencies[currencyCode]
)
if (merged.metadata != null) {
out.metadata = {
...out.metadata,
Expand Down
22 changes: 16 additions & 6 deletions src/core/currency/wallet/currency-wallet-cleaners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ import { asJsonObject } from '../../../util/file-helpers'
*/
export interface DiskMetadata {
bizId?: number
category?: string
category?: string | null
exchangeAmount: { [fiatCurrencyCode: string]: number }
name?: string
notes?: string
name?: string | null
notes?: string | null
}

/**
Expand Down Expand Up @@ -130,6 +130,16 @@ interface LegacyMapFile {
// building-block cleaners
// ---------------------------------------------------------------------

/**
* Like `asOptional`, but explicitly preserves `null`.
*/
function asNullable<T>(cleaner: Cleaner<T>): Cleaner<T | null | undefined> {
return raw => {
if (raw === undefined) return undefined
if (raw === null) return null
return cleaner(raw)
}
}
/**
* Turns user-provided metadata into its on-disk format.
*/
Expand Down Expand Up @@ -194,10 +204,10 @@ export const asEdgeTxSwap = asObject<EdgeTxSwap>({

const asDiskMetadata = asObject<DiskMetadata>({
bizId: asOptional(asNumber),
category: asOptional(asString),
category: asNullable(asString),
exchangeAmount: asOptional(asObject(asNumber), () => ({})),
name: asOptional(asString),
notes: asOptional(asString)
name: asNullable(asString),
notes: asNullable(asString)
})

export function asIntegerString(raw: unknown): string {
Expand Down
13 changes: 4 additions & 9 deletions src/core/currency/wallet/currency-wallet-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,13 @@ export function searchStringFilter(

if (checkNullTypeAndIndex(tx.nativeAmount)) return true
if (tx.metadata != null) {
const {
category = '',
name = '',
notes = '',
exchangeAmount = {}
} = tx.metadata
const { category, name, notes, exchangeAmount = {} } = tx.metadata
const txCurrencyWalletState =
tx.walletId != null ? currencyState.wallets[tx.walletId] : undefined
if (
checkNullTypeAndIndex(category) ||
checkNullTypeAndIndex(name) ||
checkNullTypeAndIndex(notes) ||
checkNullTypeAndIndex(category ?? '') ||
checkNullTypeAndIndex(name ?? '') ||
checkNullTypeAndIndex(notes ?? '') ||
(txCurrencyWalletState != null &&
checkNullTypeAndIndex(exchangeAmount[txCurrencyWalletState.fiat]))
)
Expand Down
4 changes: 2 additions & 2 deletions src/core/currency/wallet/currency-wallet-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
EdgeTxAction
} from '../../../types/types'
import { makeJsonFile } from '../../../util/file-helpers'
import { mergeDeeply } from '../../../util/util'
import { mergeDeeplyNull } from '../../../util/util'
import { fetchAppIdInfo } from '../../account/lobby-api'
import { toApiInput } from '../../root-pixie'
import { RootState } from '../../root-reducer'
Expand Down Expand Up @@ -479,7 +479,7 @@ export async function setCurrencyWalletTxMetadata(
}
}

const json = mergeDeeply(oldFile, newFile)
const json = mergeDeeplyNull(oldFile, newFile)

// Save the new file:
dispatch({
Expand Down
8 changes: 4 additions & 4 deletions src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,13 +490,13 @@ export interface EdgeCurrencyInfo {

export interface EdgeMetadata {
bizId?: number
category?: string
category?: string | null
exchangeAmount?: { [fiatCurrencyCode: string]: number }
name?: string
notes?: string
name?: string | null
notes?: string | null

/** @deprecated Use exchangeAmount instead */
amountFiat?: number
amountFiat?: number | null
}

// Would prefer a better name than EdgeNetworkFee2 but can't think of one
Expand Down
28 changes: 28 additions & 0 deletions src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,34 @@ export function mergeDeeply(...objects: any[]): any {
return out
}

/**
* Merges several Javascript objects deeply,
* preferring the items from later objects. Includes
* null as a valid to stomp on older data
*/
export function mergeDeeplyNull(...objects: any[]): any {
const out: any = {}

for (const o of objects) {
if (o === undefined) continue

for (const key of Object.keys(o)) {
if (o[key] === undefined) continue
if (o[key] === null) {
out[key] = null
continue
}

out[key] =
out[key] !== undefined && typeof o[key] === 'object'
? mergeDeeplyNull(out[key], o[key])
: o[key]
}
}

return out
}

/**
* Like `Object.assign`, but makes the properties non-enumerable.
*/
Expand Down
40 changes: 40 additions & 0 deletions test/core/currency/wallet/currency-wallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,46 @@ describe('currency wallets', function () {
expect(txs[0].savedAction).deep.equals(savedAction)
})

it('can delete metadata', async function () {
const { wallet, config } = await makeFakeCurrencyWallet()

const metadata: EdgeMetadata = {
bizId: 1234,
name: 'me',
amountFiat: 0.75,
category: 'expense:Foot Massage',
notes: 'Hello World'
}
const newMetadata: EdgeMetadata = {
bizId: 1234,
name: 'me',
amountFiat: 0.75,
category: null,
notes: null
}

await config.changeUserSettings({
txs: { a: { nativeAmount: '25', metadata } }
})

const txs = await wallet.getTransactions({})
expect(txs.length).equals(1)
expect(txs[0].nativeAmount).equals('25')
expect(txs[0].metadata).deep.equals({
exchangeAmount: { 'iso:USD': 0.75 },
...metadata
})

await wallet.saveTxMetadata('a', 'FAKE', newMetadata)
const txs2 = await wallet.getTransactions({})
expect(txs2.length).equals(1)
expect(txs2[0].nativeAmount).equals('25')
expect(txs2[0].metadata).deep.equals({
exchangeAmount: { 'iso:USD': 0.75 },
...newMetadata
})
})

it('can be paused and un-paused', async function () {
const { wallet, context } = await makeFakeCurrencyWallet(true)
const isEngineRunning = async (): Promise<boolean> => {
Expand Down
19 changes: 18 additions & 1 deletion test/util/util.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect } from 'chai'
import { describe, it } from 'mocha'

import { mergeDeeply } from '../../src/util/util'
import { mergeDeeply, mergeDeeplyNull } from '../../src/util/util'

describe('utilities', function () {
it('mergeDeeply', function () {
Expand All @@ -20,4 +20,21 @@ describe('utilities', function () {
z: 5
})
})
it('mergeDeeplyNull', function () {
const a = {
x: 1,
y: { a: -1, c: 4 }
}
const b = {
x: null,
y: { a: 2, b: 3 },
z: 5
}

expect(mergeDeeplyNull(a, b)).deep.equals({
x: null,
y: { a: 2, b: 3, c: 4 },
z: 5
})
})
})

0 comments on commit 3ed9d40

Please sign in to comment.