From 25c7376ccc635b963bd94e1b797cb97b174c878e Mon Sep 17 00:00:00 2001 From: William Swanson Date: Tue, 10 Feb 2026 16:50:33 -0800 Subject: [PATCH 1/2] Remove some dead code The items in the list are already known to need these changes, so there is no need to double-check. --- src/core/login/splitting.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/core/login/splitting.ts b/src/core/login/splitting.ts index 1a059137..0fac7ca6 100644 --- a/src/core/login/splitting.ts +++ b/src/core/login/splitting.ts @@ -172,18 +172,14 @@ export async function splitWalletInfo( // Restore anything that has simply been deleted: if (toRestore.length > 0) { const newStates: EdgeWalletStates = {} - let hasChanges = false for (const existingWalletInfo of toRestore) { - if (existingWalletInfo.archived || existingWalletInfo.deleted) { - hasChanges = true - newStates[existingWalletInfo.id] = { - archived: false, - deleted: false, - migratedFromWalletId: existingWalletInfo.migratedFromWalletId - } + newStates[existingWalletInfo.id] = { + archived: false, + deleted: false, + migratedFromWalletId: existingWalletInfo.migratedFromWalletId } } - if (hasChanges) await changeWalletStates(ai, accountId, newStates) + await changeWalletStates(ai, accountId, newStates) } // Add the keys to the login: From 1c29f4875727ca433ca6dcd9e58994bf3051d41e Mon Sep 17 00:00:00 2001 From: William Swanson Date: Wed, 11 Feb 2026 15:10:57 -0800 Subject: [PATCH 2/2] Add an `EdgeCurrencyWallet.walletSettings` property This lets us control settings on a per-wallet basis, instead of per-chain (which is that the old userSettings property handles). --- CHANGELOG.md | 2 + src/core/account/memory-wallet.ts | 3 +- src/core/actions.ts | 17 ++++++- .../currency/wallet/currency-wallet-api.ts | 15 +++++- .../wallet/currency-wallet-cleaners.ts | 4 ++ .../currency/wallet/currency-wallet-files.ts | 49 ++++++++++++++++++- .../currency/wallet/currency-wallet-pixie.ts | 42 +++++++++++++--- .../wallet/currency-wallet-reducer.ts | 16 +++++- src/types/types.ts | 8 +++ 9 files changed, 144 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90afd00b..c8890677 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- added: `EdgeCurrencyWallet.walletSettings` and `EdgeCurrencyWallet.changeWalletSettings`, plus matching engine plumbing. + ## 2.42.0 (2026-02-10) - added: `EdgeCurrencyEngineCallbacks.onSyncStatusChanged` callback. diff --git a/src/core/account/memory-wallet.ts b/src/core/account/memory-wallet.ts index e7595608..9ee57ea4 100644 --- a/src/core/account/memory-wallet.ts +++ b/src/core/account/memory-wallet.ts @@ -28,7 +28,7 @@ export const makeMemoryWalletInner = async ( walletType: string, opts: EdgeCreateCurrencyWalletOptions = {} ): Promise => { - const { keys } = opts + const { keys, walletSettings = {} } = opts if (keys == null) throw new Error('No keys provided') const walletId = `memorywallet-${memoryWalletCount++}` @@ -113,6 +113,7 @@ export const makeMemoryWalletInner = async ( lightMode: true, log, userSettings: { ...(config.userSettings ?? {}) }, + walletSettings, walletLocalDisklet: makeMemoryDisklet(), walletLocalEncryptedDisklet: makeMemoryDisklet() }) diff --git a/src/core/actions.ts b/src/core/actions.ts index 59bdf34c..dfb685e4 100644 --- a/src/core/actions.ts +++ b/src/core/actions.ts @@ -11,7 +11,8 @@ import { EdgeTokenMap, EdgeTransaction, EdgeWalletInfo, - EdgeWalletStates + EdgeWalletStates, + JsonObject } from '../types/types' import { SwapSettings } from './account/account-types' import { ClientInfo } from './context/client-file' @@ -359,6 +360,20 @@ export type RootAction = walletId: string } } + | { + type: 'CURRENCY_WALLET_CHANGED_WALLET_SETTINGS' + payload: { + walletId: string + walletSettings: JsonObject + } + } + | { + type: 'CURRENCY_WALLET_LOADED_WALLET_SETTINGS_FILE' + payload: { + walletId: string + walletSettings: JsonObject + } + } | { type: 'INFO_CACHE_FETCHED' payload: InfoCacheFile diff --git a/src/core/currency/wallet/currency-wallet-api.ts b/src/core/currency/wallet/currency-wallet-api.ts index a3da9d3f..9d20432a 100644 --- a/src/core/currency/wallet/currency-wallet-api.ts +++ b/src/core/currency/wallet/currency-wallet-api.ts @@ -40,7 +40,8 @@ import { EdgeTokenId, EdgeTokenIdOptions, EdgeTransaction, - EdgeWalletInfo + EdgeWalletInfo, + JsonObject } from '../../../types/types' import { makeMetaTokens } from '../../account/custom-tokens' import { splitWalletInfo } from '../../login/splitting' @@ -63,6 +64,7 @@ import { loadTxFiles, renameCurrencyWallet, saveTxMetadataFile, + saveWalletSettingsFile, setCurrencyWalletFiat, setupNewTxMetadata, updateCurrencyWalletTxMetadata @@ -193,6 +195,17 @@ export function makeCurrencyWalletApi( return div(nativeAmount, multiplier, multiplier.length) }, + // User settings for this wallet: + get walletSettings(): JsonObject { + return input.props.walletState.walletSettings + }, + async changeWalletSettings(settings: JsonObject): Promise { + if (input.props.walletState.currencyInfo.hasWalletSettings !== true) { + throw new Error('Wallet settings unsupported') + } + await saveWalletSettingsFile(input, settings) + }, + // Chain state: get balances(): EdgeBalances { return input.props.walletState.balances diff --git a/src/core/currency/wallet/currency-wallet-cleaners.ts b/src/core/currency/wallet/currency-wallet-cleaners.ts index 5aac3b4c..b3ef6e2c 100644 --- a/src/core/currency/wallet/currency-wallet-cleaners.ts +++ b/src/core/currency/wallet/currency-wallet-cleaners.ts @@ -306,6 +306,10 @@ export const asTokensFile = asObject({ detectedTokenIds: asArray(asString) }) +export const asWalletSettingsFile = asObject({ + walletSettings: asOptional(asJsonObject, () => ({})) +}) + const asTransactionAsset = asObject({ assetAction: asOptional(asEdgeAssetAction), metadata: asEdgeMetadata, diff --git a/src/core/currency/wallet/currency-wallet-files.ts b/src/core/currency/wallet/currency-wallet-files.ts index e0960577..6476c1fb 100644 --- a/src/core/currency/wallet/currency-wallet-files.ts +++ b/src/core/currency/wallet/currency-wallet-files.ts @@ -8,7 +8,8 @@ import { EdgeSubscribedAddress, EdgeTokenId, EdgeTransaction, - EdgeTxAction + EdgeTxAction, + JsonObject } from '../../../types/types' import { makeJsonFile } from '../../../util/file-helpers' import { fetchAppIdInfo } from '../../account/lobby-api' @@ -30,6 +31,7 @@ import { asTransactionFile, asWalletFiatFile, asWalletNameFile, + asWalletSettingsFile, LegacyTransactionFile, TransactionAsset, TransactionFile @@ -45,6 +47,7 @@ const LEGACY_TOKENS_FILE = 'EnabledTokens.json' const SEEN_TX_CHECKPOINT_FILE = 'seenTxCheckpoint.json' const TOKENS_FILE = 'Tokens.json' const WALLET_NAME_FILE = 'WalletName.json' +const WALLET_SETTINGS_FILE = 'WalletSettings.json' const legacyAddressFile = makeJsonFile(asLegacyAddressFile) const legacyMapFile = makeJsonFile(asLegacyMapFile) @@ -55,6 +58,7 @@ const tokensFile = makeJsonFile(asTokensFile) const transactionFile = makeJsonFile(asTransactionFile) const walletFiatFile = makeJsonFile(asWalletFiatFile) const walletNameFile = makeJsonFile(asWalletNameFile) +const walletSettingsFile = makeJsonFile(asWalletSettingsFile) /** * Updates the enabled tokens on a wallet. @@ -284,6 +288,45 @@ export async function loadTokensFile( }) } +/** + * Loads wallet-specific settings. + */ +export async function loadWalletSettingsFile( + input: CurrencyWalletInput +): Promise { + const { dispatch, state, walletId } = input.props + const disklet = getStorageWalletDisklet(state, walletId) + + const clean = await walletSettingsFile.load(disklet, WALLET_SETTINGS_FILE) + dispatch({ + type: 'CURRENCY_WALLET_LOADED_WALLET_SETTINGS_FILE', + payload: { + walletId, + walletSettings: clean?.walletSettings ?? {} + } + }) +} + +/** + * Persists wallet settings to disk. + */ +export async function saveWalletSettingsFile( + input: CurrencyWalletInput, + walletSettings: JsonObject +): Promise { + const { dispatch, state, walletId } = input.props + const disklet = getStorageWalletDisklet(state, walletId) + + await walletSettingsFile.save(disklet, WALLET_SETTINGS_FILE, { + walletSettings + }) + + dispatch({ + type: 'CURRENCY_WALLET_CHANGED_WALLET_SETTINGS', + payload: { walletId, walletSettings } + }) +} + /** * Loads transaction metadata files. */ @@ -697,6 +740,10 @@ export async function reloadWalletFiles( if (changes.includes(TOKENS_FILE) || changes.includes(LEGACY_TOKENS_FILE)) { await loadTokensFile(input) } + const { hasWalletSettings = false } = input.props.walletState.currencyInfo + if (hasWalletSettings && changes.includes(WALLET_SETTINGS_FILE)) { + await loadWalletSettingsFile(input) + } if (changes.includes(CURRENCY_FILE)) { await loadFiatFile(input) } diff --git a/src/core/currency/wallet/currency-wallet-pixie.ts b/src/core/currency/wallet/currency-wallet-pixie.ts index 2b310532..919d4323 100644 --- a/src/core/currency/wallet/currency-wallet-pixie.ts +++ b/src/core/currency/wallet/currency-wallet-pixie.ts @@ -14,7 +14,8 @@ import { EdgeCurrencyTools, EdgeCurrencyWallet, EdgeTokenMap, - EdgeWalletInfo + EdgeWalletInfo, + JsonObject } from '../../../types/types' import { makeJsonFile } from '../../../util/file-helpers' import { makePeriodicTask, PeriodicTask } from '../../../util/periodic-task' @@ -45,9 +46,14 @@ import { loadSeenTxCheckpointFile, loadTokensFile, loadTxFileNames, + loadWalletSettingsFile, writeTokensFile } from './currency-wallet-files' -import { CurrencyWalletState, initialTokenIds } from './currency-wallet-reducer' +import { + CurrencyWalletState, + initialTokenIds, + initialWalletSettings +} from './currency-wallet-reducer' import { tokenIdsToCurrencyCodes, uniqueStrings } from './enabled-tokens' export interface CurrencyWalletOutput { @@ -118,6 +124,11 @@ export const walletPixie: TamePixie = combinePixies({ // so the engine can start in the right state: await loadTokensFile(input) + const { hasWalletSettings = false } = walletState.currencyInfo + if (hasWalletSettings) { + await loadWalletSettingsFile(input) + } + // Start the engine: const accountState = state.accounts[accountId] const engine = await plugin.makeCurrencyEngine(publicWalletInfo, { @@ -138,7 +149,8 @@ export const walletPixie: TamePixie = combinePixies({ // User settings: customTokens: accountState.customTokens[pluginId] ?? {}, enabledTokenIds: input.props.walletState.allEnabledTokenIds, - userSettings: accountState.userSettings[pluginId] ?? {} + userSettings: accountState.userSettings[pluginId] ?? {}, + walletSettings: input.props.walletState.walletSettings }) input.onOutput(engine) @@ -462,7 +474,8 @@ export const walletPixie: TamePixie = combinePixies({ watcher(input: CurrencyWalletInput) { let lastState: CurrencyWalletState | undefined - let lastSettings: object = {} + let lastUserSettings: object = {} + let lastWalletSettings: JsonObject = initialWalletSettings let lastTokens: EdgeTokenMap = {} let lastEnabledTokenIds: string[] = initialTokenIds @@ -480,11 +493,12 @@ export const walletPixie: TamePixie = combinePixies({ lastState = walletState // Update engine settings: - const userSettings = accountState.userSettings[pluginId] ?? lastSettings - if (lastSettings !== userSettings && engine != null) { + const userSettings = + accountState.userSettings[pluginId] ?? lastUserSettings + if (lastUserSettings !== userSettings && engine != null) { await engine.changeUserSettings(userSettings) } - lastSettings = userSettings + lastUserSettings = userSettings // Update the custom tokens: const customTokens = accountState.customTokens[pluginId] ?? lastTokens @@ -505,6 +519,20 @@ export const walletPixie: TamePixie = combinePixies({ } lastTokens = customTokens + // Update wallet-scoped settings: + const { hasWalletSettings = false } = walletState.currencyInfo + const { walletSettings } = walletState + if ( + lastWalletSettings !== walletSettings && + engine?.changeWalletSettings != null && + hasWalletSettings + ) { + await engine + .changeWalletSettings(walletSettings) + .catch(error => input.props.onError(error)) + } + lastWalletSettings = walletSettings + // Update enabled tokens: const { allEnabledTokenIds } = walletState if (lastEnabledTokenIds !== allEnabledTokenIds && engine != null) { diff --git a/src/core/currency/wallet/currency-wallet-reducer.ts b/src/core/currency/wallet/currency-wallet-reducer.ts index b9912277..1cf017ae 100644 --- a/src/core/currency/wallet/currency-wallet-reducer.ts +++ b/src/core/currency/wallet/currency-wallet-reducer.ts @@ -13,7 +13,8 @@ import { EdgeTransaction, EdgeTxAction, EdgeWalletInfo, - EdgeWalletInfoFull + EdgeWalletInfoFull, + JsonObject } from '../../../types/types' import { compare } from '../../../util/compare' import { RootAction } from '../../actions' @@ -75,6 +76,7 @@ export interface CurrencyWalletState { readonly enabledTokenIds: string[] readonly tokenFileDirty: boolean readonly tokenFileLoaded: boolean + readonly walletSettings: JsonObject readonly engineFailure: Error | null readonly engineStarted: boolean readonly fiat: string @@ -118,6 +120,8 @@ export interface CurrencyWalletNext { readonly self: CurrencyWalletState } +export const initialWalletSettings: JsonObject = {} + // Used for detectedTokenIds & enabledTokenIds: export const initialTokenIds: string[] = [] @@ -250,6 +254,16 @@ const currencyWalletInner = buildReducer< } }, + walletSettings(state = initialWalletSettings, action): JsonObject { + switch (action.type) { + case 'CURRENCY_WALLET_LOADED_WALLET_SETTINGS_FILE': + case 'CURRENCY_WALLET_CHANGED_WALLET_SETTINGS': + return action.payload.walletSettings + default: + return state + } + }, + engineFailure(state = null, action): Error | null { if (action.type === 'CURRENCY_ENGINE_FAILED') { const { error } = action.payload diff --git a/src/types/types.ts b/src/types/types.ts index 998426c9..9f275ace 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -541,6 +541,7 @@ export interface EdgeCurrencyInfo { unsafeMakeSpend?: boolean unsafeSyncNetwork?: boolean usesChangeServer?: boolean + hasWalletSettings?: boolean /** Show the total sync percentage with this many decimal digits */ syncDisplayPrecision?: number @@ -1041,10 +1042,12 @@ export interface EdgeCurrencyEngineOptions { customTokens: EdgeTokenMap enabledTokenIds: string[] userSettings: JsonObject | undefined + walletSettings: JsonObject } export interface EdgeCurrencyEngine { readonly changeUserSettings: (settings: JsonObject) => Promise + readonly changeWalletSettings?: (settings: JsonObject) => Promise /** * Starts any persistent resources the engine needs, such as WebSockets. @@ -1344,6 +1347,10 @@ export interface EdgeCurrencyWallet { readonly currencyConfig: EdgeCurrencyConfig // eslint-disable-line no-use-before-define readonly currencyInfo: EdgeCurrencyInfo + // User settings for this wallet: + readonly walletSettings: JsonObject + readonly changeWalletSettings: (settings: JsonObject) => Promise + // Chain state: readonly balanceMap: EdgeBalanceMap readonly balances: EdgeBalances @@ -1649,6 +1656,7 @@ export interface EdgeCreateCurrencyWalletOptions { enabledTokenIds?: string[] fiatCurrencyCode?: string name?: string + walletSettings?: JsonObject // Create a private key from some text: importText?: string